protected static function buildTableWrapper($permissions_table, $modules, $user_roles, $actions_output) { $renderer = \Drupal::service('renderer'); // TODO: find out if there is a sf way to do this $same_page = trim(parse_url($_SERVER['HTTP_REFERER'], PHP_URL_PATH), '/') == $_GET['q']; $render = array('#type' => 'container', '#attributes' => array('class' => array('fpa-container'))); $hiders = array('fpa-hide-descriptions' => array('hide' => t('Hide descriptions'), 'show' => t('Show descriptions')), 'fpa-hide-system-names' => array('hide' => t('Hide system names'), 'show' => t('Show system names'))); $render['#attributes']['class'][] = 'fpa-hide-system-names'; $hide_container = array('#type' => 'container', '#attributes' => array('class' => array('fpa-toggle-container'))); foreach ($hiders as $hide_class => $labels) { $hide_container[$hide_class] = array('#theme' => 'link', '#text' => '', '#path' => '', '#options' => array('attributes' => array_merge($labels, array('fpa-toggle-class' => $hide_class)), 'html' => TRUE, 'fragment' => ' ', 'external' => TRUE)); } $render['hide_container'] = $hide_container; $wrapper = array('#type' => 'container', '#attributes' => array('class' => array('fpa-wrapper'))); $render['wrapper'] =& $wrapper; /** * <style /> block template. */ $style_template = array('#type' => 'container', '#attributes' => array('class' => array('style-wrapper-class-name'))); $style_template['style'] = array('#type' => 'html_tag', '#tag' => 'style', '#attributes' => array('type' => array('text/css')), '#value' => ''); /** * <style /> block for role filtering. */ $wrapper['role_styles'] = $style_template; $wrapper['role_styles']['#attributes']['class'][0] = 'fpa-role-styles'; /** * <style /> block for permission filtering. */ $wrapper['perm_styles'] = $style_template; $wrapper['perm_styles']['#attributes']['class'][0] = 'fpa-perm-styles'; /** * Left section contains module list and form submission button. */ $left_section = array('#type' => 'container', '#attributes' => array('class' => array('fpa-left-section'))); $wrapper['left_section'] =& $left_section; /** * Right section contains filter form and permissions table. */ $right_section = array('#type' => 'container', '#attributes' => array('class' => array('fpa-right-section'))); $wrapper['right_section'] =& $right_section; $module_template = array('#wrapper_attributes' => array(FPA_ATTR_MODULE => array(), FPA_ATTR_PERMISSION => array()), 'data' => array('#type' => 'container', '#attributes' => array(), 'link' => NULL, 'counters' => array(), 'total' => array('#type' => 'html_tag', '#tag' => 'span', '#attributes' => array('class' => array('fpa-perm-total'), 'fpa-total' => 0), '#value' => ''))); $counter_template = array('#type' => 'html_tag', '#tag' => 'span', '#attributes' => array('class' => array('fpa-perm-counter'), FPA_ATTR_PERMISSION => array()), '#value' => ''); $items = array(); $all_modules = array('text' => t('All modules'), FPA_ATTR_MODULE => array(), FPA_ATTR_PERMISSION => array()); array_unshift($modules, $all_modules); $all_modules_counters = array(); foreach ($modules as $module) { $module_item = $module_template; $module_item['#wrapper_attributes'][FPA_ATTR_MODULE] = $module[FPA_ATTR_MODULE]; $module_item['#wrapper_attributes'][FPA_ATTR_PERMISSION] = array_reduce($module[FPA_ATTR_PERMISSION], 'array_merge', array()); // Use link for accessibility and tabability. $options = array('fragment' => 'all'); if (!empty($module['title'])) { $options['fragment'] = 'module-' . $module['title'][0]; $options['attributes']['title'] = $module['title'][0]; } $module_item['data']['link'] = Link::createFromRoute($module['text'], 'user.admin_permissions', array(), $options)->toRenderable(); foreach ($module[FPA_ATTR_PERMISSION] as $module_perm) { $counter_item = $counter_template; $counter_item['#attributes'][FPA_ATTR_PERMISSION] = $module_perm; $all_modules_counters[] = $counter_item; $module_item['data']['counters'][] = $counter_item; } $module_item['data']['total']['#attributes']['fpa-total'] = count($module[FPA_ATTR_PERMISSION]); $items[] = $module_item; } $items[0]['data']['counters'] = $all_modules_counters; $items[0]['data']['total']['#attributes']['fpa-total'] = count($all_modules_counters); $left_section['list'] = array('#items' => $items, '#theme' => 'item_list'); $left_section['buttons'] = $actions_output; $filter_form = array('#type' => 'container', '#attributes' => array('class' => array('fpa-filter-form'))); $clear_button = array('#type' => 'html_tag', '#tag' => 'input', '#attributes' => array('type' => array('button'), 'class' => array('fpa-clear-search', 'form-submit'), 'value' => 'Clear filter')); $default_filter = ''; if (!empty($_GET['fpa_perm'])) { $default_filter = $_GET['fpa_perm']; } if (!empty($_COOKIE['fpa_filter']) && $same_page) { $default_filter = $_COOKIE['fpa_filter']; } $filter_form['permission_module_filter'] = array('#type' => 'textfield', '#title' => t('Filter:'), '#size' => 25, '#field_suffix' => $renderer->render($clear_button), '#attributes' => array('placeholder' => array('permission@module'), 'autofocus' => 'autofocus'), '#value' => $default_filter, '#description' => t('<p>Enter in the format of "permission@module",</p><p>e.g. <em>admin@system</em> will show only permissions with the<br>text "admin" in modules with the text "system".</p><p>This will also match on system name of a permission.</p>')); /* * Populate the permission filter styles. */ $matches = array(); preg_match('/^\\s*([^@]*)@?(.*?)\\s*$/i', $filter_form['permission_module_filter']['#value'], $matches); array_shift($matches); // Remove whole match item. $safe_matches = array(); foreach ($matches as $match) { $safe_matches[] = Html::getClass($match); } $module_match = !empty($_COOKIE['module_match']) ? $_COOKIE['module_match'] : '*='; $filters = array(Unicode::strlen($safe_matches[0]) > 0 ? '[' . FPA_ATTR_PERMISSION . '*="' . $safe_matches[0] . '"]' : '', Unicode::strlen($safe_matches[1]) > 0 ? '[' . FPA_ATTR_MODULE . $module_match . '"' . $safe_matches[1] . '"]' : ''); $filter_styles = array('.fpa-table-wrapper tr[' . FPA_ATTR_MODULE . ']{display: none;}', '.fpa-table-wrapper tr[' . FPA_ATTR_MODULE . ']', $filters[0], $filters[1], '{display: table-row;}', '.fpa-perm-counter{display: none;}', '.fpa-perm-counter', $filters[0], '{display: inline;}', '.fpa-left-section li[' . FPA_ATTR_MODULE . ']', Unicode::strlen($filters[1]) > 0 ? $filters[1] : '[' . FPA_ATTR_MODULE . '=""]', '{margin-right:-1px; background-color: white; border-right: solid 1px transparent;}'); $wrapper['perm_styles']['style']['#value'] = implode('', $filter_styles); $cookie_roles = !empty($_COOKIE['fpa_roles']) && $same_page ? json_decode($_COOKIE['fpa_roles']) : array(); $options = array('*' => t('--All Roles')); if (!empty($user_roles)) { $options += $user_roles; // Preserves keys. } if (in_array('*', $cookie_roles)) { $cookie_roles = array('*'); } $filter_form['role_filter'] = array('#type' => 'select', '#title' => t('Roles:'), '#description' => t('Select which roles to display.<br>Ctrl+click to select multiple.'), '#size' => 5, '#options' => $options, '#attributes' => array('multiple' => 'multiple', 'autocomplete' => 'off'), '#value' => count(array_intersect($cookie_roles, array_keys($options))) > 0 ? $cookie_roles : array('*')); /* * Populate the roles styles. */ if (!in_array('*', $filter_form['role_filter']['#value'])) { $role_styles = array('.fpa-table-wrapper [' . FPA_ATTR_ROLE . '] {display: none;}'); foreach ($filter_form['role_filter']['#value'] as $value) { $role_styles[] = '.fpa-table-wrapper [' . FPA_ATTR_ROLE . '="' . $value . '"] {display: table-cell;}'; } $role_styles[] = '.fpa-table-wrapper [' . FPA_ATTR_ROLE . '="' . end($filter_form['role_filter']['#value']) . '"] {border-right: 1px solid #bebfb9;}'; $wrapper['role_styles']['style']['#value'] = implode('', $role_styles); } $checked_status = array('#type' => 'checkboxes', '#title' => t('Display permissions that are:'), '#options' => array(FPA_ATTR_CHECKED => t('Checked'), FPA_ATTR_NOT_CHECKED => t('Not Checked')), '#attributes' => array(), '#title_display' => 'before', '#description' => t('Applies to all visible roles.<br />Unsaved changes are not counted.<br />Most effective when a single role is visible.<br />Empty module rows sometimes display when used with permission filter.')); $checked_status_keys = array_keys($checked_status['#options']); $checked_status['#value'] = array_combine($checked_status_keys, $checked_status_keys); $pseudo_form = array(); $filter_form['checked_status'] = Checkboxes::processCheckboxes($checked_status, new FormState(), $pseudo_form); foreach (Element::children($filter_form['checked_status']) as $key) { $filter_form['checked_status'][$key]['#checked'] = TRUE; } $right_section['filter_form'] = $filter_form; $table_wrapper = array('#type' => 'container', '#attributes' => array('class' => array('fpa-table-wrapper'))); $table_wrapper['table'] = array('#theme' => 'table', '#header' => $permissions_table['header'], '#rows' => $permissions_table['rows'], '#attributes' => array('id' => 'permissions')); // Show after full table HTML is loaded. Reduces progressive table load reflow/repaint. $table_wrapper['show_table'] = array('#type' => 'html_tag', '#tag' => 'style', '#attributes' => array('type' => array('text/css')), '#value' => '#permissions {display: table;} .fpa-table-wrapper {background: none;}'); $table_wrapper['buttons'] = $actions_output; $right_section['table_wrapper'] = $table_wrapper; return $render; }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { // Form input keys that will not be included in $view->exposed_raw_data. $exclude = array('submit', 'form_build_id', 'form_id', 'form_token', 'exposed_form_plugin', 'reset'); $values = $form_state->getValues(); foreach (array('field', 'filter') as $type) { /** @var \Drupal\views\Plugin\views\ViewsHandlerInterface[] $handlers */ $handlers =& $form_state->get('view')->{$type}; foreach ($handlers as $key => $info) { if ($handlers[$key]->acceptExposedInput($values)) { $handlers[$key]->submitExposed($form, $form_state); } else { // The input from the form did not validate, exclude it from the // stored raw data. $exclude[] = $key; } } } $view = $form_state->get('view'); $view->exposed_data = $values; $view->exposed_raw_input = []; $exclude = array('submit', 'form_build_id', 'form_id', 'form_token', 'exposed_form_plugin', 'reset'); /** @var \Drupal\views\Plugin\views\exposed_form\ExposedFormPluginBase $exposed_form_plugin */ $exposed_form_plugin = $view->display_handler->getPlugin('exposed_form'); $exposed_form_plugin->exposedFormSubmit($form, $form_state, $exclude); foreach ($values as $key => $value) { if (!empty($key) && !in_array($key, $exclude)) { if (is_array($value)) { // Handle checkboxes, we only want to include the checked options. // @todo: revisit the need for this when // https://www.drupal.org/node/342316 is resolved. $checked = Checkboxes::getCheckedCheckboxes($value); foreach ($checked as $option_id) { $view->exposed_raw_input[$option_id] = $value[$option_id]; } } else { $view->exposed_raw_input[$key] = $value; } } } }
/** * Determines if the input from a filter should change the generated query. * * @param array $input * The exposed data for this view. * * @return bool * TRUE if the input for this filter should be included in the view query. * FALSE otherwise. */ public function acceptExposedInput($input) { if (empty($this->options['exposed'])) { return TRUE; } if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator_id']) && isset($input[$this->options['expose']['operator_id']])) { $this->operator = $input[$this->options['expose']['operator_id']]; } if (!empty($this->options['expose']['identifier'])) { $value = $input[$this->options['expose']['identifier']]; // Various ways to check for the absence of non-required input. if (empty($this->options['expose']['required'])) { if (($this->operator == 'empty' || $this->operator == 'not empty') && $value === '') { $value = ' '; } if ($this->operator != 'empty' && $this->operator != 'not empty') { if ($value == 'All' || $value === array()) { return FALSE; } // If checkboxes are used to render this filter, do not include the // filter if no options are checked. if (is_array($value) && Checkboxes::detectEmptyCheckboxes($value)) { return FALSE; } } if (!empty($this->alwaysMultiple) && $value === '') { return FALSE; } } if (isset($value)) { $this->value = $value; if (empty($this->alwaysMultiple) && empty($this->options['expose']['multiple']) && !is_array($value)) { $this->value = array($value); } } else { return FALSE; } } return TRUE; }