/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { $types = ViewExecutable::getHandlerTypes(); $view = $form_state->get('view'); $display =& $view->getExecutable()->displayHandlers->get($form_state->get('display_id')); $remember_groups = array(); if (!empty($view->form_cache)) { $old_fields = $view->form_cache['handlers']; } else { $old_fields = $display->getOption($types['filter']['plural']); } $groups = $form_state->getValue('filter_groups'); // Whatever button was clicked, re-calculate field information. $new_fields = $order = array(); // Make an array with the weights foreach ($form_state->getValue('filters') as $field => $info) { // add each value that is a field with a weight to our list, but only if // it has had its 'removed' checkbox checked. if (is_array($info) && empty($info['removed'])) { if (isset($info['weight'])) { $order[$field] = $info['weight']; } if (isset($info['group'])) { $old_fields[$field]['group'] = $info['group']; $remember_groups[$info['group']][] = $field; } } } // Sort the array asort($order); // Create a new list of fields in the new order. foreach (array_keys($order) as $field) { $new_fields[$field] = $old_fields[$field]; } // If the #group property is set on the clicked button, that means we are // either adding or removing a group, not actually updating the filters. $triggering_element = $form_state->getTriggeringElement(); if (!empty($triggering_element['#group'])) { if ($triggering_element['#group'] == 'add') { // Add a new group $groups['groups'][] = 'AND'; } else { // Renumber groups above the removed one down. foreach (array_keys($groups['groups']) as $group_id) { if ($group_id >= $triggering_element['#group']) { $old_group = $group_id + 1; if (isset($groups['groups'][$old_group])) { $groups['groups'][$group_id] = $groups['groups'][$old_group]; if (isset($remember_groups[$old_group])) { foreach ($remember_groups[$old_group] as $id) { $new_fields[$id]['group'] = $group_id; } } } else { // If this is the last one, just unset it. unset($groups['groups'][$group_id]); } } } } // Update our cache with values so that cancel still works the way // people expect. $view->form_cache = ['key' => 'rearrange-filter', 'groups' => $groups, 'handlers' => $new_fields]; // Return to this form except on actual Update. $view->addFormToStack('rearrange-filter', $form_state->get('display_id'), 'filter'); } else { // The actual update button was clicked. Remove the empty groups, and // renumber them sequentially. ksort($remember_groups); $groups['groups'] = static::arrayKeyPlus(array_values(array_intersect_key($groups['groups'], $remember_groups))); // Change the 'group' key on each field to match. Here, $mapping is an // array whose keys are the old group numbers and whose values are the new // (sequentially numbered) ones. $mapping = array_flip(static::arrayKeyPlus(array_keys($remember_groups))); foreach ($new_fields as &$new_field) { $new_field['group'] = $mapping[$new_field['group']]; } // Write the changed handler values. $display->setOption($types['filter']['plural'], $new_fields); $display->setOption('filter_groups', $groups); if (isset($view->form_cache)) { unset($view->form_cache); } } // Store in cache. $view->cacheSet(); }
/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { $view = $form_state->get('view'); $display_id = $form_state->get('display_id'); $type = $form_state->get('type'); $id = $form_state->get('id'); $form = array('options' => array('#tree' => TRUE, '#theme_wrappers' => array('container'), '#attributes' => array('class' => array('scroll'), 'data-drupal-views-scroll' => TRUE))); $executable = $view->getExecutable(); if (!$executable->setDisplay($display_id)) { $form['markup'] = array('#markup' => $this->t('Invalid display id @display', array('@display' => $display_id))); return $form; } $executable->initQuery(); $item = $executable->getHandler($display_id, $type, $id); if ($item) { $handler = $executable->display_handler->getHandler($type, $id); if (empty($handler)) { $form['markup'] = array('#markup' => $this->t("Error: handler for @table > @field doesn't exist!", array('@table' => $item['table'], '@field' => $item['field']))); } else { $handler->init($executable, $executable->display_handler, $item); $types = ViewExecutable::getHandlerTypes(); $form['#title'] = $this->t('Configure aggregation settings for @type %item', array('@type' => $types[$type]['lstitle'], '%item' => $handler->adminLabel())); $handler->buildGroupByForm($form['options'], $form_state); $form_state->set('handler', $handler); } $view->getStandardButtons($form, $form_state, 'views_ui_config_item_group_form'); } return $form; }
/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { $view = $form_state['view']; $display_id = $form_state['display_id']; $type = $form_state['type']; $id = $form_state['id']; $form = array('options' => array('#tree' => true, '#theme_wrappers' => array('container'), '#attributes' => array('class' => array('scroll'), 'data-drupal-views-scroll' => TRUE))); $executable = $view->getExecutable(); $executable->setDisplay($display_id); $item = $executable->getHandler($display_id, $type, $id); if ($item) { $handler = $executable->display_handler->getHandler($type, $id); if (empty($handler)) { $form['markup'] = array('#markup' => $this->t("Error: handler for @table > @field doesn't exist!", array('@table' => $item['table'], '@field' => $item['field']))); } else { $handler->init($executable, $executable->display_handler, $item); $types = ViewExecutable::getHandlerTypes(); $form['#title'] = $this->t('Configure extra settings for @type %item', array('@type' => $types[$type]['lstitle'], '%item' => $handler->adminLabel())); $form['#section'] = $display_id . '-' . $type . '-' . $id; // Get form from the handler. $handler->buildExtraOptionsForm($form['options'], $form_state); $form_state['handler'] = $handler; } $view->getStandardButtons($form, $form_state, 'views_ui_config_item_extra_form'); } return $form; }
/** * Tests most of the handlers. */ public function testHandlers() { $this->drupalCreateContentType(array('type' => 'article')); $this->addDefaultCommentField('node', 'article'); $object_types = array_keys(ViewExecutable::getHandlerTypes()); foreach ($this->container->get('views.views_data')->get() as $base_table => $info) { if (!isset($info['table']['base'])) { continue; } $view = entity_create('view', array('base_table' => $base_table)); $view = $view->getExecutable(); // @todo The groupwise relationship is currently broken. $exclude[] = 'taxonomy_term_field_data:tid_representative'; $exclude[] = 'users_field_data:uid_representative'; // Go through all fields and there through all handler types. foreach ($info as $field => $field_info) { // Table is a reserved key for the metainformation. if ($field != 'table' && !in_array("{$base_table}:{$field}", $exclude)) { $item = array('table' => $base_table, 'field' => $field); foreach ($object_types as $type) { if (isset($field_info[$type]['id'])) { $options = array(); if ($type == 'filter') { $handler = $this->container->get("plugin.manager.views.{$type}")->getHandler($item); // Set the value to use for the filter based on the filter type. if ($handler instanceof InOperator) { $options['value'] = array(1); } else { $options['value'] = 1; } } $view->addHandler('default', $type, $base_table, $field, $options); } } } } // Go through each step individually to see whether some parts are // failing. $view->build(); $view->preExecute(); $view->execute(); $view->render(); // Make sure all handlers extend the HandlerBase. foreach ($object_types as $type) { if (isset($view->{$type})) { foreach ($view->{$type} as $handler) { $this->assertTrue($handler instanceof HandlerBase, format_string('@type handler of class %class is an instance of HandlerBase', array('@type' => $type, '%class' => get_class($handler)))); } } } } }
/** * {@inheritdoc} */ protected function viewsData() { $data = parent::viewsData(); // Override the name handler to be able to call placeholder() from outside. $data['views_test_data']['name']['field']['id'] = 'test_field'; // Setup one field with an access callback and one with an access callback // and arguments. $data['views_test_data']['access_callback'] = $data['views_test_data']['id']; $data['views_test_data']['access_callback_arguments'] = $data['views_test_data']['id']; foreach (ViewExecutable::getHandlerTypes() as $type => $info) { if (isset($data['views_test_data']['access_callback'][$type]['id'])) { $data['views_test_data']['access_callback'][$type]['access callback'] = 'views_test_data_handler_test_access_callback'; $data['views_test_data']['access_callback_arguments'][$type]['access callback'] = 'views_test_data_handler_test_access_callback_argument'; $data['views_test_data']['access_callback_arguments'][$type]['access arguments'] = array(TRUE); } } return $data; }
/** * Lists all instances of fields on any views. * * @return array * The Views fields report page. */ public function reportFields() { $views = $this->entityManager()->getStorage('view')->loadMultiple(); // Fetch all fieldapi fields which are used in views // Therefore search in all views, displays and handler-types. $fields = array(); $handler_types = ViewExecutable::getHandlerTypes(); foreach ($views as $view) { $executable = $view->getExecutable(); $executable->initDisplay(); foreach ($executable->displayHandlers as $display_id => $display) { if ($executable->setDisplay($display_id)) { foreach ($handler_types as $type => $info) { foreach ($executable->getHandlers($type, $display_id) as $item) { $table_data = $this->viewsData->get($item['table']); if (isset($table_data[$item['field']]) && isset($table_data[$item['field']][$type]) && ($field_data = $table_data[$item['field']][$type])) { // The final check that we have a fieldapi field now. if (isset($field_data['field_name'])) { $fields[$field_data['field_name']][$view->id()] = $view->id(); } } } } } } } $header = array(t('Field name'), t('Used in')); $rows = array(); foreach ($fields as $field_name => $views) { $rows[$field_name]['data'][0]['data']['#plain_text'] = $field_name; foreach ($views as $view) { $rows[$field_name]['data'][1][] = $this->l($view, new Url('entity.view.edit_form', array('view' => $view))); } $item_list = ['#theme' => 'item_list', '#items' => $rows[$field_name]['data'][1], '#context' => ['list_style' => 'comma-list']]; $rows[$field_name]['data'][1] = ['data' => $item_list]; } // Sort rows by field name. ksort($rows); $output = array('#type' => 'table', '#header' => $header, '#rows' => $rows, '#empty' => t('No fields have been used in views yet.')); return $output; }
/** * Lists all instances of fields on any views. * * @return array * The Views fields report page. */ public function reportFields() { $views = $this->entityManager()->getStorage('view')->loadMultiple(); // Fetch all fieldapi fields which are used in views // Therefore search in all views, displays and handler-types. $fields = array(); $handler_types = ViewExecutable::getHandlerTypes(); foreach ($views as $view) { $executable = $view->getExecutable(); $executable->initDisplay(); foreach ($executable->displayHandlers as $display_id => $display) { if ($executable->setDisplay($display_id)) { foreach ($handler_types as $type => $info) { foreach ($executable->getHandlers($type, $display_id) as $item) { $table_data = $this->viewsData->get($item['table']); if (isset($table_data[$item['field']]) && isset($table_data[$item['field']][$type]) && ($field_data = $table_data[$item['field']][$type])) { // The final check that we have a fieldapi field now. if (isset($field_data['field_name'])) { $fields[$field_data['field_name']][$view->id()] = $view->id(); } } } } } } } $header = array(t('Field name'), t('Used in')); $rows = array(); foreach ($fields as $field_name => $views) { $rows[$field_name]['data'][0] = String::checkPlain($field_name); foreach ($views as $view) { $rows[$field_name]['data'][1][] = $this->l($view, 'views_ui.edit', array('view' => $view)); } $rows[$field_name]['data'][1] = SafeMarkup::set(implode(', ', $rows[$field_name]['data'][1])); } // Sort rows by field name. ksort($rows); $output = array('#type' => 'table', '#header' => $header, '#rows' => $rows, '#empty' => t('No fields have been used in views yet.')); return $output; }
/** * Submit handler for adding new item(s) to a view. */ public function submitItemAdd($form, FormStateInterface $form_state) { $type = $form_state->get('type'); $types = ViewExecutable::getHandlerTypes(); $section = $types[$type]['plural']; $display_id = $form_state->get('display_id'); // Handle the override select. list($was_defaulted, $is_defaulted) = $this->getOverrideValues($form, $form_state); if ($was_defaulted && !$is_defaulted) { // We were using the default display's values, but we're now overriding // the default display and saving values specific to this display. $display =& $this->getExecutable()->displayHandlers->get($display_id); // setOverride toggles the override of this section. $display->setOverride($section); } elseif (!$was_defaulted && $is_defaulted) { // We used to have an override for this display, but the user now wants // to go back to the default display. // Overwrite the default display with the current form values, and make // the current display use the new default values. $display =& $this->getExecutable()->displayHandlers->get($display_id); // optionsOverride toggles the override of this section. $display->setOverride($section); } if (!$form_state->isValueEmpty('name') && is_array($form_state->getValue('name'))) { // Loop through each of the items that were checked and add them to the view. foreach (array_keys(array_filter($form_state->getValue('name'))) as $field) { list($table, $field) = explode('.', $field, 2); if ($cut = strpos($field, '$')) { $field = substr($field, 0, $cut); } $id = $this->getExecutable()->addHandler($display_id, $type, $table, $field); // check to see if we have group by settings $key = $type; // Footer,header and empty text have a different internal handler type(area). if (isset($types[$type]['type'])) { $key = $types[$type]['type']; } $item = array('table' => $table, 'field' => $field); $handler = Views::handlerManager($key)->getHandler($item); if ($this->getExecutable()->displayHandlers->get('default')->useGroupBy() && $handler->usesGroupBy()) { $this->addFormToStack('handler-group', $display_id, $type, $id); } // check to see if this type has settings, if so add the settings form first if ($handler && $handler->hasExtraOptions()) { $this->addFormToStack('handler-extra', $display_id, $type, $id); } // Then add the form to the stack $this->addFormToStack('handler', $display_id, $type, $id); } } if (isset($this->form_cache)) { unset($this->form_cache); } // Store in cache $this->cacheSet(); }
/** * {@inheritdoc} */ public function submitForm(array &$form, array &$form_state) { // Run it through the handler's submit function. $form_state['handler']->submitOptionsForm($form['options'], $form_state); $item = $form_state['handler']->options; $types = ViewExecutable::getHandlerTypes(); // For footer/header $handler_type is area but $type is footer/header. // For all other handle types it's the same. $handler_type = $type = $form_state['type']; if (!empty($types[$type]['type'])) { $handler_type = $types[$type]['type']; } $override = NULL; $executable = $form_state['view']->getExecutable(); if ($executable->display_handler->useGroupBy() && !empty($item['group_type'])) { if (empty($executable->query)) { $executable->initQuery(); } $aggregate = $executable->query->getAggregationInfo(); if (!empty($aggregate[$item['group_type']]['handler'][$type])) { $override = $aggregate[$item['group_type']]['handler'][$type]; } } // Create a new handler and unpack the options from the form onto it. We // can use that for storage. $handler = Views::handlerManager($handler_type)->getHandler($item, $override); $handler->init($executable, $executable->display_handler, $item); // Add the incoming options to existing options because items using // the extra form may not have everything in the form here. $options = $form_state['values']['options'] + $form_state['handler']->options; // This unpacks only options that are in the definition, ensuring random // extra stuff on the form is not sent through. $handler->unpackOptions($handler->options, $options, NULL, FALSE); // Add any dependencies as the handler is saved. Put it here so // it does not need to be declared in defineOptions(). if ($dependencies = $handler->getDependencies()) { $handler->options['dependencies'] = $dependencies; } // Add the module providing the handler as a dependency as well. $handler->options['dependencies']['module'][] = $handler->definition['provider']; // Store the item back on the view $executable->setHandler($form_state['display_id'], $form_state['type'], $form_state['id'], $handler->options); // Ensure any temporary options are removed. if (isset($form_state['view']->temporary_options[$type][$form_state['id']])) { unset($form_state['view']->temporary_options[$type][$form_state['id']]); } // Write to cache $form_state['view']->cacheSet(); }
/** * A submit handler that is used for storing temporary items when using * multi-step changes, such as ajax requests. */ public function submitTemporaryForm($form, FormStateInterface $form_state) { // Run it through the handler's submit function. $this->submitOptionsForm($form['options'], $form_state); $item = $this->options; $types = ViewExecutable::getHandlerTypes(); // For footer/header $handler_type is area but $type is footer/header. // For all other handle types it's the same. $handler_type = $type = $form_state->get('type'); if (!empty($types[$type]['type'])) { $handler_type = $types[$type]['type']; } $override = NULL; $view = $form_state->get('view'); $executable = $view->getExecutable(); if ($executable->display_handler->useGroupBy() && !empty($item['group_type'])) { if (empty($executable->query)) { $executable->initQuery(); } $aggregate = $executable->query->getAggregationInfo(); if (!empty($aggregate[$item['group_type']]['handler'][$type])) { $override = $aggregate[$item['group_type']]['handler'][$type]; } } // Create a new handler and unpack the options from the form onto it. We // can use that for storage. $handler = Views::handlerManager($handler_type)->getHandler($item, $override); $handler->init($executable, $executable->display_handler, $item); // Add the incoming options to existing options because items using // the extra form may not have everything in the form here. $options = $form_state->getValue('options') + $this->options; // This unpacks only options that are in the definition, ensuring random // extra stuff on the form is not sent through. $handler->unpackOptions($handler->options, $options, NULL, FALSE); // Store the item back on the view. $executable = $view->getExecutable(); $executable->temporary_options[$type][$form_state->get('id')] = $handler->options; // @todo Decide if \Drupal\views_ui\Form\Ajax\ViewsFormBase::getForm() is // perhaps the better place to fix the issue. // \Drupal\views_ui\Form\Ajax\ViewsFormBase::getForm() drops the current // form from the stack, even if it's an #ajax. So add the item back to the top // of the stack. $view->addFormToStack($form_state->get('form_key'), $form_state->get('display_id'), $type, $item['id'], TRUE); $form_state->get('rerender', TRUE); $form_state->setRebuild(); // Write to cache $view->cacheSet(); }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { $view = $form_state->get('view'); $display_id = $form_state->get('display_id'); $type = $form_state->get('type'); $types = ViewExecutable::getHandlerTypes(); $display =& $view->getExecutable()->displayHandlers->get($display_id); $old_fields = $display->getOption($types[$type]['plural']); $new_fields = $order = array(); // Make an array with the weights foreach ($form_state->getValue('fields') as $field => $info) { // add each value that is a field with a weight to our list, but only if // it has had its 'removed' checkbox checked. if (is_array($info) && isset($info['weight']) && empty($info['removed'])) { $order[$field] = $info['weight']; } } // Sort the array asort($order); // Create a new list of fields in the new order. foreach (array_keys($order) as $field) { $new_fields[$field] = $old_fields[$field]; } $display->setOption($types[$type]['plural'], $new_fields); // Store in cache $view->cacheSet(); }
/** * Tests optional handlers. */ public function testOptionalHandlers() { $handler_types = ViewExecutable::getHandlerTypes(); foreach ($handler_types as $type => $type_info) { $this->drupalGet('admin/structure/views/view/test_view_optional/edit'); $href = "admin/structure/views/nojs/handler/test_view_optional/default/{$type}/id_optional"; $result = $this->xpath('//a[contains(@href, :href)]', array(':href' => $href)); $this->assertEqual(count($result), 1, String::format('Handler (%type) edit link found.', array('%type' => $type))); $text = t('Optional handler is missing (Module: @module) …', array('@module' => 'views')); $this->assertIdentical((string) $result[0], $text, 'Ensure the optional handler link text was found.'); $this->drupalGet($href); $result = $this->xpath('//h1'); $this->assertTrue(strpos((string) $result[0], $text) !== FALSE, 'Ensure the optional handler title was found.'); $description_args = array('@module' => 'views', '@table' => 'views_test_data', '@field' => 'id_optional'); foreach ($description_args as $token => $value) { $this->assertNoText($token, String::format('Raw @token token placeholder not found.', array('@token' => $token))); $this->assertText($value, String::format('Replaced @token value found.', array('@token' => $token))); } } }
/** * Tests ViewExecutable::getHandlerTypes(). */ public function testGetHandlerTypes() { $types = ViewExecutable::getHandlerTypes(); foreach (array('field', 'filter', 'argument', 'sort', 'header', 'footer', 'empty') as $type) { $this->assertTrue(isset($types[$type])); // @todo The key on the display should be footers, headers and empties // or something similar instead of the singular, but so long check for // this special case. if (isset($types[$type]['type']) && $types[$type]['type'] == 'area') { $this->assertEqual($types[$type]['plural'], $type); } else { $this->assertEqual($types[$type]['plural'], $type . 's'); } } }
/** * Setups a view executable and default display. * * @return array * Returns the view executable and default display. */ protected function setupBaseViewAndDisplay() { $config = array('id' => 'test_view', 'tag' => 'OnE, TWO, and three', 'display' => ['default' => ['id' => 'default', 'display_plugin' => 'default', 'display_title' => 'Default']]); $storage = new View($config, 'view'); $view = new ViewExecutable($storage, $this->user, $this->viewsData, $this->routeProvider); $display = $this->getMockBuilder('Drupal\\views\\Plugin\\views\\display\\DisplayPluginBase')->disableOriginalConstructor()->getMock(); $display->expects($this->any())->method('getPlugin')->with($this->equalTo('cache'))->willReturn($this->successCache); $display->display = $config['display']['default']; $view->current_display = 'default'; $view->display_handler = $display; $view->displayHandlers = $this->displayHandlers; $view->displayHandlers->expects($this->any())->method('get')->with('default')->willReturn($display); $view->displayHandlers->expects($this->any())->method('has')->with('default')->willReturn(TRUE); foreach (array_keys($view->getHandlerTypes()) as $type) { $view->{$type} = []; } return array($view, $display); }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { $view = $form_state->get('view'); $display_id = $form_state->get('display_id'); $id = $form_state->get('id'); $handler = $form_state->get('handler'); // Run it through the handler's submit function. $handler->submitOptionsForm($form['options'], $form_state); $item = $handler->options; $types = ViewExecutable::getHandlerTypes(); // For footer/header $handler_type is area but $type is footer/header. // For all other handle types it's the same. $handler_type = $type = $form_state->get('type'); if (!empty($types[$type]['type'])) { $handler_type = $types[$type]['type']; } $override = NULL; $executable = $view->getExecutable(); if ($executable->display_handler->useGroupBy() && !empty($item['group_type'])) { if (empty($executable->query)) { $executable->initQuery(); } $aggregate = $executable->query->getAggregationInfo(); if (!empty($aggregate[$item['group_type']]['handler'][$type])) { $override = $aggregate[$item['group_type']]['handler'][$type]; } } // Create a new handler and unpack the options from the form onto it. We // can use that for storage. $handler = Views::handlerManager($handler_type)->getHandler($item, $override); $handler->init($executable, $executable->display_handler, $item); // Add the incoming options to existing options because items using // the extra form may not have everything in the form here. $options = $form_state->getValue('options') + $handler->options; // This unpacks only options that are in the definition, ensuring random // extra stuff on the form is not sent through. $handler->unpackOptions($handler->options, $options, NULL, FALSE); // Store the item back on the view $executable->setHandler($display_id, $type, $id, $handler->options); // Ensure any temporary options are removed. if (isset($view->temporary_options[$type][$id])) { unset($view->temporary_options[$type][$id]); } // Write to cache $view->cacheSet(); }
/** * Merges handlers default values. * * @param string $type * The name of the handler type option. */ protected function mergeHandler($type) { $types = ViewExecutable::getHandlerTypes(); $options = $this->getOption($types[$type]['plural']); foreach ($this->getHandlers($type) as $id => $handler) { if (isset($options[$id])) { $options[$id] = $options[$id] + $handler->options; } } $this->setOption($types[$type]['plural'], $options); }
/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { $view = $form_state->get('view'); $display_id = $form_state->get('display_id'); $type = $form_state->get('type'); $form = array('options' => array('#theme_wrappers' => array('container'), '#attributes' => array('class' => array('scroll'), 'data-drupal-views-scroll' => TRUE))); $executable = $view->getExecutable(); $executable->setDisplay($display_id); $display =& $executable->displayHandlers->get($display_id); $types = ViewExecutable::getHandlerTypes(); $ltitle = $types[$type]['ltitle']; $section = $types[$type]['plural']; if (!empty($types[$type]['type'])) { $type = $types[$type]['type']; } $form['#title'] = $this->t('Add @type', array('@type' => $ltitle)); $form['#section'] = $display_id . 'add-handler'; // Add the display override dropdown. views_ui_standard_display_dropdown($form, $form_state, $section); // Figure out all the base tables allowed based upon what the relationships provide. $base_tables = $executable->getBaseTables(); $options = Views::viewsDataHelper()->fetchFields(array_keys($base_tables), $type, $display->useGroupBy(), $form_state->get('type')); if (!empty($options)) { $form['override']['controls'] = array('#theme_wrappers' => array('container'), '#id' => 'views-filterable-options-controls', '#attributes' => array('class' => array('container-inline'))); $form['override']['controls']['options_search'] = array('#type' => 'textfield', '#title' => $this->t('Search')); $groups = array('all' => $this->t('- All -')); $form['override']['controls']['group'] = array('#type' => 'select', '#title' => $this->t('Type'), '#options' => array()); $form['options']['name'] = array('#prefix' => '<div class="views-radio-box form-checkboxes views-filterable-options">', '#suffix' => '</div>', '#tree' => TRUE, '#default_value' => 'all'); // Group options first to simplify the usage of #states. $grouped_options = array(); foreach ($options as $key => $option) { $group = preg_replace('/[^a-z0-9]/', '-', strtolower($option['group'])); $groups[$group] = $option['group']; $grouped_options[$group][$key] = $option; if (!empty($option['aliases']) && is_array($option['aliases'])) { foreach ($option['aliases'] as $id => $alias) { if (empty($alias['base']) || !empty($base_tables[$alias['base']])) { $copy = $option; $copy['group'] = $alias['group']; $copy['title'] = $alias['title']; if (isset($alias['help'])) { $copy['help'] = $alias['help']; } $group = preg_replace('/[^a-z0-9]/', '-', strtolower($copy['group'])); $groups[$group] = $copy['group']; $grouped_options[$group][$key . '$' . $id] = $copy; } } } } foreach ($grouped_options as $group => $group_options) { foreach ($group_options as $key => $option) { $form['options']['name'][$key] = array('#type' => 'checkbox', '#title' => $this->t('!group: !field', array('!group' => $option['group'], '!field' => $option['title'])), '#description' => $option['help'], '#return_value' => $key, '#prefix' => "<div class='filterable-option'>", '#suffix' => '</div>', '#states' => array('visible' => array(array(':input[name="override[controls][group]"]' => array('value' => 'all')), array(':input[name="override[controls][group]"]' => array('value' => $group))))); } } $form['override']['controls']['group']['#options'] = $groups; } else { $form['options']['markup'] = array('#markup' => '<div class="form-item">' . $this->t('There are no @types available to add.', array('@types' => $ltitle)) . '</div>'); } // Add a div to show the selected items $form['selected'] = array('#type' => 'item', '#markup' => '<span class="views-ui-view-title">' . $this->t('Selected:') . '</span> ' . '<div class="views-selected-options"></div>', '#theme_wrappers' => array('form_element', 'views_ui_container'), '#attributes' => array('class' => array('container-inline', 'views-add-form-selected'), 'data-drupal-views-offset' => 'bottom')); $view->getStandardButtons($form, $form_state, 'views_ui_add_handler_form', $this->t('Add and configure @types', array('@types' => $ltitle))); // Remove the default submit function. $form['actions']['submit']['#submit'] = array_filter($form['actions']['submit']['#submit'], function ($var) { return !(is_array($var) && isset($var[1]) && $var[1] == 'standardSubmit'); }); $form['actions']['submit']['#submit'][] = array($view, 'submitItemAdd'); return $form; }
/** * Tests broken handlers. */ public function testBrokenHandlers() { $handler_types = ViewExecutable::getHandlerTypes(); foreach ($handler_types as $type => $type_info) { $this->drupalGet('admin/structure/views/view/test_view_broken/edit'); $href = "admin/structure/views/nojs/handler/test_view_broken/default/{$type}/id_broken"; $result = $this->xpath('//a[contains(@href, :href)]', array(':href' => $href)); $this->assertEqual(count($result), 1, SafeMarkup::format('Handler (%type) edit link found.', array('%type' => $type))); $text = 'Broken/missing handler'; $this->assertIdentical((string) $result[0], $text, 'Ensure the broken handler text was found.'); $this->drupalGet($href); $result = $this->xpath('//h1[@class="page-title"]'); $this->assertTrue(strpos((string) $result[0], $text) !== FALSE, 'Ensure the broken handler text was found.'); $original_configuration = ['field' => 'id_broken', 'id' => 'id_broken', 'relationship' => 'none', 'table' => 'views_test_data', 'plugin_id' => 'numeric']; foreach ($original_configuration as $key => $value) { $this->assertText(SafeMarkup::format('@key: @value', array('@key' => $key, '@value' => $value))); } } }