diff --git a/core/lib/Drupal/Core/Config/Entity/Query/Condition.php b/core/lib/Drupal/Core/Config/Entity/Query/Condition.php index d231f0b..132ebc1 100644 --- a/core/lib/Drupal/Core/Config/Entity/Query/Condition.php +++ b/core/lib/Drupal/Core/Config/Entity/Query/Condition.php @@ -162,6 +162,8 @@ protected function match(array $condition, $value) { return $value >= $condition['value']; case '<=': return $value <= $condition['value']; + case '<>': + return $value != $condition['value']; case 'IN': return array_search($value, $condition['value']) !== FALSE; case 'NOT IN': diff --git a/core/lib/Drupal/Core/Entity/EntityFormController.php b/core/lib/Drupal/Core/Entity/EntityFormController.php index 7c5f7ed..f5c01a9 100644 --- a/core/lib/Drupal/Core/Entity/EntityFormController.php +++ b/core/lib/Drupal/Core/Entity/EntityFormController.php @@ -391,6 +391,10 @@ protected function submitEntityLanguage(array $form, array &$form_state) { */ public function buildEntity(array $form, array &$form_state) { $entity = clone $this->entity; + // If you submit a form, the form state comes from caching, which forces + // the controller to be the one before caching. Ensure to have the + // controller of the current request. + $form_state['controller'] = $this; // @todo Move entity_form_submit_build_entity() here. // @todo Exploit the Field API to process the submitted entity field. entity_form_submit_build_entity($entity->entityType(), $entity, $form, $form_state); diff --git a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorAdminTest.php b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorAdminTest.php index 4d07526..c0bc012 100644 --- a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorAdminTest.php +++ b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorAdminTest.php @@ -51,7 +51,7 @@ function testAdmin() { $ckeditor = $manager->createInstance('ckeditor'); $this->drupalLogin($this->admin_user); - $this->drupalGet('admin/config/content/formats/filtered_html'); + $this->drupalGet('admin/config/content/formats/manage/filtered_html'); // Ensure no Editor config entity exists yet. $editor = entity_load('editor', 'filtered_html'); @@ -118,7 +118,7 @@ function testAdmin() { $this->assertIdentical($expected_settings, $editor->settings, 'The Editor config entity has the correct settings.'); // Configure the Styles plugin, and ensure the updated settings are saved. - $this->drupalGet('admin/config/content/formats/filtered_html'); + $this->drupalGet('admin/config/content/formats/manage/filtered_html'); $edit = array( 'editor[settings][plugins][stylescombo][styles]' => "h1.title|Title\np.callout|Callout\n\n", ); @@ -131,7 +131,7 @@ function testAdmin() { // Change the buttons that appear on the toolbar (in JavaScript, this is // done via drag and drop, but here we can only emulate the end result of // that interaction). Test multiple toolbar rows and a divider within a row. - $this->drupalGet('admin/config/content/formats/filtered_html'); + $this->drupalGet('admin/config/content/formats/manage/filtered_html'); $expected_settings['toolbar']['buttons'] = array( array('Undo', '|', 'Redo'), array('JustifyCenter'), @@ -148,7 +148,7 @@ function testAdmin() { // CKEditor plugin — this should not affect the Editor config entity. module_enable(array('ckeditor_test')); drupal_container()->get('plugin.manager.ckeditor.plugin')->clearCachedDefinitions(); - $this->drupalGet('admin/config/content/formats/filtered_html'); + $this->drupalGet('admin/config/content/formats/manage/filtered_html'); $ultra_llama_mode_checkbox = $this->xpath('//input[@type="checkbox" and @name="editor[settings][plugins][llama_contextual_and_button][ultra_llama_mode]" and not(@checked)]'); $this->assertTrue(count($ultra_llama_mode_checkbox) === 1, 'The "Ultra llama mode" checkbox exists and is not checked.'); $editor = entity_load('editor', 'filtered_html'); @@ -156,12 +156,12 @@ function testAdmin() { $this->assertIdentical($expected_settings, $editor->settings, 'The Editor config entity has the correct settings.'); // Finally, check the "Ultra llama mode" checkbox. - $this->drupalGet('admin/config/content/formats/filtered_html'); + $this->drupalGet('admin/config/content/formats/manage/filtered_html'); $edit = array( 'editor[settings][plugins][llama_contextual_and_button][ultra_llama_mode]' => '1', ); $this->drupalPost(NULL, $edit, t('Save configuration')); - $this->drupalGet('admin/config/content/formats/filtered_html'); + $this->drupalGet('admin/config/content/formats/manage/filtered_html'); $ultra_llama_mode_checkbox = $this->xpath('//input[@type="checkbox" and @name="editor[settings][plugins][llama_contextual_and_button][ultra_llama_mode]" and @checked="checked"]'); $this->assertTrue(count($ultra_llama_mode_checkbox) === 1, 'The "Ultra llama mode" checkbox exists and is checked.'); $expected_settings['plugins']['llama_contextual_and_button']['ultra_llama_mode'] = '1'; diff --git a/core/modules/editor/editor.module b/core/modules/editor/editor.module index a0e78a6..5a75c57 100644 --- a/core/modules/editor/editor.module +++ b/core/modules/editor/editor.module @@ -156,11 +156,11 @@ function editor_form_filter_admin_overview_alter(&$form, $form_state) { } /** - * Implements hook_form_FORM_ID_alter(). + * Implements hook_form_BASE_FORM_ID_alter() for 'filter_format_form'. */ -function editor_form_filter_admin_format_form_alter(&$form, &$form_state) { +function editor_form_filter_format_form_alter(&$form, &$form_state) { if (!isset($form_state['editor'])) { - $format_id = $form['#format']->format; + $format_id = $form_state['controller']->getEntity()->id(); $form_state['editor'] = editor_load($format_id); $form_state['editor_manager'] = Drupal::service('plugin.manager.editor'); } @@ -226,15 +226,15 @@ function editor_form_filter_admin_format_form_alter(&$form, &$form_state) { $settings_form['#element_validate'][] = array($plugin, 'settingsFormValidate'); $form['editor']['settings']['subform'] = $plugin->settingsForm($settings_form, $form_state, $editor); $form['editor']['settings']['subform']['#parents'] = array('editor', 'settings'); - $form['#submit'][] = array($plugin, 'settingsFormSubmit'); + $form['actions']['submit']['#submit'][] = array($plugin, 'settingsFormSubmit'); } $form['#validate'][] = 'editor_form_filter_admin_format_validate'; - $form['#submit'][] = 'editor_form_filter_admin_format_submit'; + $form['actions']['submit']['#submit'][] = 'editor_form_filter_admin_format_submit'; } /** - * Button submit handler for filter_admin_format_form()'s 'editor_configure' button. + * Button submit handler for filter_format_form()'s 'editor_configure' button. */ function editor_form_filter_admin_format_editor_configure($form, &$form_state) { $editor = $form_state['editor']; @@ -244,7 +244,7 @@ function editor_form_filter_admin_format_editor_configure($form, &$form_state) { } elseif (empty($editor) || $form_state['values']['editor']['editor'] !== $editor->editor) { $editor = entity_create('editor', array( - 'format' => $form['#format']->format, + 'format' => $form_state['controller']->getEntity()->id(), 'editor' => $form_state['values']['editor']['editor'], )); $form_state['editor'] = $editor; @@ -254,14 +254,14 @@ function editor_form_filter_admin_format_editor_configure($form, &$form_state) { } /** - * AJAX callback handler for filter_admin_format_form(). + * AJAX callback handler for filter_format_form(). */ function editor_form_filter_admin_form_ajax($form, &$form_state) { return $form['editor']['settings']; } /** - * Additional validate handler for filter_admin_format_form(). + * Additional validate handler for filter_format_form(). */ function editor_form_filter_admin_format_validate($form, &$form_state) { // This validate handler is not applicable when using the 'Configure' button. @@ -279,11 +279,11 @@ function editor_form_filter_admin_format_validate($form, &$form_state) { } /** - * Additional submit handler for filter_admin_format_form(). + * Additional submit handler for filter_format_form(). */ function editor_form_filter_admin_format_submit($form, &$form_state) { // Delete the existing editor if disabling or switching between editors. - $format_id = $form['#format']->format; + $format_id = $form_state['controller']->getEntity()->id(); $original_editor = editor_load($format_id); if ($original_editor && $original_editor->editor != $form_state['values']['editor']) { $original_editor->delete(); @@ -293,7 +293,7 @@ function editor_form_filter_admin_format_submit($form, &$form_state) { if ($form_state['editor'] !== FALSE) { // Ensure the text format is set: when creating a new text format, this // would equal the empty string. - $form_state['editor']->format = $form['#format']->format; + $form_state['editor']->format = $format_id; $form_state['editor']->settings = $form_state['values']['editor']['settings']; $form_state['editor']->save(); } diff --git a/core/modules/editor/lib/Drupal/editor/Tests/EditorAdminTest.php b/core/modules/editor/lib/Drupal/editor/Tests/EditorAdminTest.php index 27cc458..0bc89e1 100644 --- a/core/modules/editor/lib/Drupal/editor/Tests/EditorAdminTest.php +++ b/core/modules/editor/lib/Drupal/editor/Tests/EditorAdminTest.php @@ -50,7 +50,7 @@ function setUp() { */ function testNoEditorAvailable() { $this->drupalLogin($this->admin_user); - $this->drupalGet('admin/config/content/formats/filtered_html'); + $this->drupalGet('admin/config/content/formats/manage/filtered_html'); // Ensure the form field order is correct. $roles_pos = strpos($this->drupalGetContent(), 'Roles'); @@ -75,7 +75,7 @@ function testNoEditorAvailable() { function testAddEditorToExistingFormat() { $this->enableUnicornEditor(); $this->drupalLogin($this->admin_user); - $this->drupalGet('admin/config/content/formats/filtered_html'); + $this->drupalGet('admin/config/content/formats/manage/filtered_html'); $edit = $this->selectUnicornEditor(); // Configure Unicorn Editor's setting to another value. $edit['editor[settings][foo]'] = 'baz'; @@ -155,7 +155,7 @@ protected function verifyUnicornEditorConfiguration($format_id, $foo = 'bar') { $this->assertIdentical($editor->settings['ponies too'], true, 'The text editor defaults are retrieved correctly.'); $this->assertIdentical($editor->settings['rainbows'], true, 'The text editor defaults added by hook_editor_settings_defaults() are retrieved correctly.'); $this->assertIdentical($editor->settings['sparkles'], false, 'The text editor defaults modified by hook_editor_settings_defaults_alter() are retrieved correctly.'); - $this->drupalGet('admin/config/content/formats/'. $format_id); + $this->drupalGet('admin/config/content/formats/manage/'. $format_id); $select = $this->xpath('//select[@name="editor[editor]"]'); $select_is_disabled = $this->xpath('//select[@name="editor[editor]" and @disabled="disabled"]'); $options = $this->xpath('//select[@name="editor[editor]"]/option'); diff --git a/core/modules/filter/filter.admin.inc b/core/modules/filter/filter.admin.inc deleted file mode 100644 index a4493a9..0000000 --- a/core/modules/filter/filter.admin.inc +++ /dev/null @@ -1,348 +0,0 @@ - 'table', - '#header' => array(t('Name'), t('Roles'), t('Weight'), t('Operations')), - '#tabledrag' => array( - array('order', 'sibling', 'text-format-order-weight'), - ), - ); - foreach ($formats as $id => $format) { - $form['formats'][$id]['#attributes']['class'][] = 'draggable'; - $form['formats'][$id]['#weight'] = $format->weight; - - $links = array(); - $links['configure'] = array( - 'title' => t('configure'), - 'href' => "admin/config/content/formats/$id", - ); - // Check whether this is the fallback text format. This format is available - // to all roles and cannot be disabled via the admin interface. - $form['formats'][$id]['#is_fallback'] = ($id == $fallback_format); - if ($form['formats'][$id]['#is_fallback']) { - $form['formats'][$id]['name'] = array('#markup' => drupal_placeholder($format->name)); - if (config('filter.settings')->get('always_show_fallback_choice')) { - $roles_markup = drupal_placeholder(t('All roles may use this format')); - } - else { - $roles_markup = drupal_placeholder(t('This format is shown when no other formats are available')); - } - } - else { - $form['formats'][$id]['name'] = array('#markup' => check_plain($format->name)); - $roles = array_map('check_plain', filter_get_roles_by_format($format)); - $roles_markup = $roles ? implode(', ', $roles) : t('No roles may use this format'); - $links['disable'] = array( - 'title' => t('disable'), - 'href' => "admin/config/content/formats/$id/disable", - ); - } - - $form['formats'][$id]['roles'] = array('#markup' => $roles_markup); - - $form['formats'][$id]['weight'] = array( - '#type' => 'weight', - '#title' => t('Weight for @title', array('@title' => $format->name)), - '#title_display' => 'invisible', - '#default_value' => $format->weight, - '#attributes' => array('class' => array('text-format-order-weight')), - ); - - $form['formats'][$id]['operations'] = array( - '#type' => 'operations', - '#links' => $links, - ); - } - $form['actions'] = array('#type' => 'actions'); - $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save changes')); - return $form; -} - -/** - * Form submission handler for filter_admin_overview(). - */ -function filter_admin_overview_submit($form, &$form_state) { - $filter_formats = filter_formats(); - foreach ($form_state['values']['formats'] as $id => $data) { - // Only update if this is a form element with weight. - if (is_array($data) && isset($data['weight'])) { - $filter_formats[$id]->set('weight', $data['weight']); - $filter_formats[$id]->save(); - } - } - filter_formats_reset(); - drupal_set_message(t('The text format ordering has been saved.')); -} - -/** - * Page callback: Displays the text format add/edit form. - * - * @param object|null $format - * (optional) An object representing a format, with the following properties: - * - format: A machine-readable name representing the ID of the text format - * to save. If this corresponds to an existing text format, that format - * will be updated; otherwise, a new format will be created. - * - name: The title of the text format. - * - cache: An integer indicating whether the text format is cacheable (1) or - * not (0). Defaults to 1. - * - status: (optional) An integer indicating whether the text format is - * enabled (1) or not (0). Defaults to 1. - * - weight: (optional) The weight of the text format, which controls its - * placement in text format lists. If omitted, the weight is set to 0. - * Defaults to NULL. - * - * @return - * A form array. - * - * @see filter_menu() - */ -function filter_admin_format_page($format = NULL) { - if (!isset($format->name)) { - drupal_set_title(t('Add text format')); - - $format = entity_create('filter_format', array()); - } - return drupal_get_form('filter_admin_format_form', $format); -} - -/** - * Form constructor for the text format add/edit form. - * - * @param $format - * A format object having the properties: - * - format: A machine-readable name representing the ID of the text format to - * save. If this corresponds to an existing text format, that format will be - * updated; otherwise, a new format will be created. - * - name: The title of the text format. - * - cache: (optional) An integer indicating whether the text format is - * cacheable (1) or not (0). Defaults to 1. - * - status: (optional) An integer indicating whether the text format is - * enabled (1) or not (0). Defaults to 1. - * - weight: (optional) The weight of the text format, which controls its - * placement in text format lists. If omitted, the weight is set to 0. - * - * @see filter_admin_format_form_validate() - * @see filter_admin_format_form_submit() - * @ingroup forms - */ -function filter_admin_format_form($form, &$form_state, $format) { - $is_fallback = ($format->format == filter_fallback_format()); - - $form['#format'] = $format; - $form['#tree'] = TRUE; - $form['#attached']['library'][] = array('filter', 'drupal.filter.admin'); - - $form['name'] = array( - '#type' => 'textfield', - '#title' => t('Name'), - '#default_value' => $format->name, - '#required' => TRUE, - '#weight' => -30, - ); - $form['format'] = array( - '#type' => 'machine_name', - '#required' => TRUE, - '#default_value' => $format->format, - '#maxlength' => 255, - '#machine_name' => array( - 'exists' => 'filter_format_exists', - 'source' => array('name'), - ), - '#disabled' => !empty($format->format), - '#weight' => -20, - ); - // @todo Remove once moved to FilterFormatFormController. - $form['langcode'] = array( - '#type' => 'value', - '#value' => !$format->isNew() ? $format->langcode : language_default()->langcode, - ); - - // Add user role access selection. - $form['roles'] = array( - '#type' => 'checkboxes', - '#title' => t('Roles'), - '#options' => array_map('check_plain', user_role_names()), - '#disabled' => $is_fallback, - '#weight' => -10, - ); - if ($is_fallback) { - $form['roles']['#description'] = t('All roles for this text format must be enabled and cannot be changed.'); - } - if (!empty($format->format)) { - // If editing an existing text format, pre-select its current permissions. - $form['roles']['#default_value'] = array_keys(filter_get_roles_by_format($format)); - } - elseif ($admin_role = config('user.settings')->get('admin_role')) { - // If adding a new text format and the site has an administrative role, - // pre-select that role so as to grant administrators access to the new - // text format permission by default. - $form['roles']['#default_value'] = array($admin_role); - } - - // Create filter plugin instances for all available filters, including both - // enabled/configured ones as well as new and not yet unconfigured ones. - $filters = $format->filters()->sort(); - - // Filter status. - $form['filters']['status'] = array( - '#type' => 'item', - '#title' => t('Enabled filters'), - '#prefix' => '
', - '#suffix' => '
', - // This item is used as a pure wrapping container with heading. Ignore its - // value, since 'filters' should only contain filter definitions. - // @see http://drupal.org/node/1829202 - '#input' => FALSE, - ); - // Filter order (tabledrag). - $form['filters']['order'] = array( - '#type' => 'table', - // For filter.admin.js - '#attributes' => array('id' => 'filter-order'), - '#title' => t('Filter processing order'), - '#tabledrag' => array( - array('order', 'sibling', 'filter-order-weight'), - ), - '#tree' => FALSE, - '#input' => FALSE, - '#theme_wrappers' => array('form_element'), - ); - // Filter settings. - $form['filter_settings'] = array( - '#type' => 'vertical_tabs', - '#title' => t('Filter settings'), - ); - - foreach ($filters as $name => $filter) { - $form['filters']['status'][$name] = array( - '#type' => 'checkbox', - '#title' => $filter->getLabel(), - '#default_value' => $filter->status, - '#parents' => array('filters', $name, 'status'), - '#description' => $filter->getDescription(), - '#weight' => $filter->weight, - ); - - $form['filters']['order'][$name]['#attributes']['class'][] = 'draggable'; - $form['filters']['order'][$name]['#weight'] = $filter->weight; - $form['filters']['order'][$name]['filter'] = array( - '#markup' => $filter->getLabel(), - ); - $form['filters']['order'][$name]['weight'] = array( - '#type' => 'weight', - '#title' => t('Weight for @title', array('@title' => $filter->getLabel())), - '#title_display' => 'invisible', - '#delta' => 50, - '#default_value' => $filter->weight, - '#parents' => array('filters', $name, 'weight'), - '#attributes' => array('class' => array('filter-order-weight')), - ); - - // Retrieve the settings form of the filter plugin. The plugin should not be - // aware of the text format. Therefore, it only receives a set of minimal - // base properties to allow advanced implementations to work. - $settings_form = array( - '#parents' => array('filters', $name, 'settings'), - '#tree' => TRUE, - ); - $settings_form = $filter->settingsForm($settings_form, $form_state); - if (!empty($settings_form)) { - $form['filters']['settings'][$name] = array( - '#type' => 'details', - '#title' => $filter->getLabel(), - '#weight' => $filter->weight, - '#parents' => array('filters', $name, 'settings'), - '#group' => 'filter_settings', - ); - $form['filters']['settings'][$name] += $settings_form; - } - } - - $form['actions'] = array('#type' => 'actions'); - $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save configuration')); - - return $form; -} - -/** - * Form validation handler for filter_admin_format_form(). - * - * @see filter_admin_format_form_submit() - */ -function filter_admin_format_form_validate($form, &$form_state) { - $format_format = trim($form_state['values']['format']); - $format_name = trim($form_state['values']['name']); - - // Ensure that the values to be saved later are exactly the ones validated. - form_set_value($form['format'], $format_format, $form_state); - form_set_value($form['name'], $format_name, $form_state); - - $filter_formats = entity_load_multiple('filter_format'); - foreach ($filter_formats as $format) { - if ($format->name == $format_name && $format->format != $format_format) { - form_set_error('name', t('Text format names must be unique. A format named %name already exists.', array('%name' => $format_name))); - break; - } - } -} - -/** - * Form submission handler for filter_admin_format_form(). - * - * @see filter_admin_format_form_validate() - */ -function filter_admin_format_form_submit($form, &$form_state) { - // Remove unnecessary values. - form_state_values_clean($form_state); - - // Add the submitted form values to the text format, and save it. - $format = $form['#format']; - foreach ($form_state['values'] as $key => $value) { - if ($key != 'filters') { - $format->set($key, $value); - } - else { - foreach ($value as $instance_id => $config) { - $format->setFilterConfig($instance_id, $config); - } - } - } - $status = $format->save(); - - // Save user permissions. - if ($permission = filter_permission_name($format)) { - foreach ($form_state['values']['roles'] as $rid => $enabled) { - user_role_change_permissions($rid, array($permission => $enabled)); - } - } - - switch ($status) { - case SAVED_NEW: - drupal_set_message(t('Added text format %format.', array('%format' => $format->name))); - break; - - case SAVED_UPDATED: - drupal_set_message(t('The text format %format has been updated.', array('%format' => $format->name))); - break; - } - - $form_state['redirect'] = 'admin/config/content/formats'; -} diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module index 1b90cde..675fc6b 100644 --- a/core/modules/filter/filter.module +++ b/core/modules/filter/filter.module @@ -65,7 +65,7 @@ function filter_help($path, $arg) { $output .= '

' . t('Text formats are presented on content editing pages in the order defined on this page. The first format available to a user will be selected by default.') . '

'; return $output; - case 'admin/config/content/formats/%': + case 'admin/config/content/formats/manage/%': $output = '

' . t('A text format contains filters that change the user input, for example stripping out malicious HTML or making URLs clickable. Filters are executed from top to bottom and the order is important, since one filter may prevent another filter from doing its job. For example, when URLs are converted into links before disallowed HTML tags are removed, all links may be removed. When this happens, the order of filters may need to be re-arranged.') . '

'; return $output; } @@ -123,10 +123,7 @@ function filter_menu() { $items['admin/config/content/formats'] = array( 'title' => 'Text formats', 'description' => 'Configure how content input by users is filtered, including allowed HTML tags. Also allows enabling of module-provided filters.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('filter_admin_overview'), - 'access arguments' => array('administer filters'), - 'file' => 'filter.admin.inc', + 'route_name' => 'filter_admin_overview', ); $items['admin/config/content/formats/list'] = array( 'title' => 'List', @@ -134,20 +131,15 @@ function filter_menu() { ); $items['admin/config/content/formats/add'] = array( 'title' => 'Add text format', - 'page callback' => 'filter_admin_format_page', - 'access arguments' => array('administer filters'), + 'route_name' => 'filter_format_add', 'type' => MENU_LOCAL_ACTION, - 'file' => 'filter.admin.inc', ); - $items['admin/config/content/formats/%filter_format'] = array( + $items['admin/config/content/formats/manage/%'] = array( 'title callback' => 'filter_admin_format_title', - 'title arguments' => array(4), - 'page callback' => 'filter_admin_format_page', - 'page arguments' => array(4), - 'access arguments' => array('administer filters'), - 'file' => 'filter.admin.inc', + 'title arguments' => array(5), + 'route_name' => 'filter_format_edit', ); - $items['admin/config/content/formats/%filter_format/disable'] = array( + $items['admin/config/content/formats/manage/%/disable'] = array( 'title' => 'Disable text format', 'route_name' => 'filter_admin_disable', ); @@ -194,16 +186,16 @@ function filter_format_exists($format_id) { /** * Displays a text format form title. * - * @param object $format_id - * A format object. + * @param string $format_id + * A format ID. * * @return string * The name of the format. - * - * @see filter_menu() */ -function filter_admin_format_title($format) { - return $format->name; +function filter_admin_format_title($format_id) { + if ($format = filter_format_load($format_id)) { + return $format->label(); + } } /** @@ -225,7 +217,7 @@ function filter_permission() { if (!empty($permission)) { // Only link to the text format configuration page if the user who is // viewing this will have access to that page. - $format_name_replacement = user_access('administer filters') ? l($format->name, 'admin/config/content/formats/' . $format->format) : drupal_placeholder($format->name); + $format_name_replacement = user_access('administer filters') ? l($format->name, 'admin/config/content/formats/manage/' . $format->format) : drupal_placeholder($format->name); $perms[$permission] = array( 'title' => t("Use the !text_format text format", array('!text_format' => $format_name_replacement,)), 'description' => drupal_placeholder(t('Warning: This permission may have security implications depending on how the text format is configured.')), diff --git a/core/modules/filter/filter.routing.yml b/core/modules/filter/filter.routing.yml index 0b9d357..5442fb0 100644 --- a/core/modules/filter/filter.routing.yml +++ b/core/modules/filter/filter.routing.yml @@ -1,10 +1,3 @@ -filter_admin_disable: - pattern: '/admin/config/content/formats/{filter_format}/disable' - defaults: - _entity_form: 'filter_format.disable' - requirements: - _filter_disable_format_access: 'TRUE' - filter_tips_all: pattern: '/filter/tips' defaults: @@ -18,3 +11,32 @@ filter_tips: _content: '\Drupal\filter\Controller\FilterController::filterTips' requirements: _filter_access: 'TRUE' + +filter_admin_overview: + pattern: '/admin/config/content/formats' + defaults: + _content: '\Drupal\Core\Entity\Controller\EntityListController::listing' + entity_type: 'filter_format' + requirements: + _permission: 'administer filters' + +filter_format_add: + pattern: '/admin/config/content/formats/add' + defaults: + _entity_form: filter_format.add + requirements: + _permission: 'administer filters' + +filter_format_edit: + pattern: '/admin/config/content/formats/manage/{filter_format}' + defaults: + _entity_form: filter_format.edit + requirements: + _permission: 'administer filters' + +filter_admin_disable: + pattern: '/admin/config/content/formats/manage/{filter_format}/disable' + defaults: + _entity_form: 'filter_format.disable' + requirements: + _filter_disable_format_access: 'TRUE' diff --git a/core/modules/filter/lib/Drupal/filter/FilterFormatAddFormController.php b/core/modules/filter/lib/Drupal/filter/FilterFormatAddFormController.php new file mode 100644 index 0000000..6180ef7 --- /dev/null +++ b/core/modules/filter/lib/Drupal/filter/FilterFormatAddFormController.php @@ -0,0 +1,32 @@ + $this->entity->label()))); + return $this->entity; + } + +} diff --git a/core/modules/filter/lib/Drupal/filter/FilterFormatEditFormController.php b/core/modules/filter/lib/Drupal/filter/FilterFormatEditFormController.php new file mode 100644 index 0000000..09a62dd --- /dev/null +++ b/core/modules/filter/lib/Drupal/filter/FilterFormatEditFormController.php @@ -0,0 +1,40 @@ +entity->status()) { + throw new NotFoundHttpException(); + } + + drupal_set_title($this->entity->label()); + $form = parent::form($form, $form_state); + $form['roles']['#default_value'] = array_keys(filter_get_roles_by_format($this->entity)); + return $form; + } + + /** + * {@inheritdoc} + */ + public function submit(array $form, array &$form_state) { + parent::submit($form, $form_state); + drupal_set_message(t('The text format %format has been updated.', array('%format' => $this->entity->label()))); + return $this->entity; + } + +} diff --git a/core/modules/filter/lib/Drupal/filter/FilterFormatFormControllerBase.php b/core/modules/filter/lib/Drupal/filter/FilterFormatFormControllerBase.php new file mode 100644 index 0000000..f9d4965 --- /dev/null +++ b/core/modules/filter/lib/Drupal/filter/FilterFormatFormControllerBase.php @@ -0,0 +1,257 @@ +configFactory = $config_factory; + $this->queryFactory = $query_factory; + } + + /** + * {@inheritdoc} + */ + public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + return new static( + $container->get('config.factory'), + $container->get('entity.query') + ); + } + + /** + * {@inheritdoc} + */ + public function form(array $form, array &$form_state) { + $format = $this->entity; + $is_fallback = ($format->id() == $this->configFactory->get('filter.settings')->get('fallback_format')); + + $form['#tree'] = TRUE; + $form['#attached']['library'][] = array('filter', 'drupal.filter.admin'); + + $form['name'] = array( + '#type' => 'textfield', + '#title' => t('Name'), + '#default_value' => $format->label(), + '#required' => TRUE, + '#weight' => -30, + ); + $form['format'] = array( + '#type' => 'machine_name', + '#required' => TRUE, + '#default_value' => $format->id(), + '#maxlength' => 255, + '#machine_name' => array( + 'exists' => 'filter_format_exists', + 'source' => array('name'), + ), + '#disabled' => !$format->isNew(), + '#weight' => -20, + ); + + // Add user role access selection. + $form['roles'] = array( + '#type' => 'checkboxes', + '#title' => t('Roles'), + '#options' => array_map('\Drupal\Component\Utility\String::checkPlain', user_role_names()), + '#disabled' => $is_fallback, + '#weight' => -10, + ); + if ($is_fallback) { + $form['roles']['#description'] = t('All roles for this text format must be enabled and cannot be changed.'); + } + if (!$format->isNew()) { + // If editing an existing text format, pre-select its current permissions. + $form['roles']['#default_value'] = array_keys(filter_get_roles_by_format($format)); + } + elseif ($admin_role = $this->configFactory->get('user.settings')->get('admin_role')) { + // If adding a new text format and the site has an administrative role, + // pre-select that role so as to grant administrators access to the new + // text format permission by default. + $form['roles']['#default_value'] = array($admin_role); + } + + // Create filter plugin instances for all available filters, including both + // enabled/configured ones as well as new and not yet unconfigured ones. + $filters = $format->filters()->sort(); + + // Filter status. + $form['filters']['status'] = array( + '#type' => 'item', + '#title' => t('Enabled filters'), + '#prefix' => '
', + '#suffix' => '
', + // This item is used as a pure wrapping container with heading. Ignore its + // value, since 'filters' should only contain filter definitions. + // @see http://drupal.org/node/1829202 + '#input' => FALSE, + ); + // Filter order (tabledrag). + $form['filters']['order'] = array( + '#type' => 'table', + // For filter.admin.js + '#attributes' => array('id' => 'filter-order'), + '#title' => t('Filter processing order'), + '#tabledrag' => array( + array('order', 'sibling', 'filter-order-weight'), + ), + '#tree' => FALSE, + '#input' => FALSE, + '#theme_wrappers' => array('form_element'), + ); + // Filter settings. + $form['filter_settings'] = array( + '#type' => 'vertical_tabs', + '#title' => t('Filter settings'), + ); + + foreach ($filters as $name => $filter) { + $form['filters']['status'][$name] = array( + '#type' => 'checkbox', + '#title' => $filter->getLabel(), + '#default_value' => $filter->status, + '#parents' => array('filters', $name, 'status'), + '#description' => $filter->getDescription(), + '#weight' => $filter->weight, + ); + + $form['filters']['order'][$name]['#attributes']['class'][] = 'draggable'; + $form['filters']['order'][$name]['#weight'] = $filter->weight; + $form['filters']['order'][$name]['filter'] = array( + '#markup' => $filter->getLabel(), + ); + $form['filters']['order'][$name]['weight'] = array( + '#type' => 'weight', + '#title' => t('Weight for @title', array('@title' => $filter->getLabel())), + '#title_display' => 'invisible', + '#delta' => 50, + '#default_value' => $filter->weight, + '#parents' => array('filters', $name, 'weight'), + '#attributes' => array('class' => array('filter-order-weight')), + ); + + // Retrieve the settings form of the filter plugin. The plugin should not be + // aware of the text format. Therefore, it only receives a set of minimal + // base properties to allow advanced implementations to work. + $settings_form = array( + '#parents' => array('filters', $name, 'settings'), + '#tree' => TRUE, + ); + $settings_form = $filter->settingsForm($settings_form, $form_state); + if (!empty($settings_form)) { + $form['filters']['settings'][$name] = array( + '#type' => 'details', + '#title' => $filter->getLabel(), + '#weight' => $filter->weight, + '#parents' => array('filters', $name, 'settings'), + '#group' => 'filter_settings', + ); + $form['filters']['settings'][$name] += $settings_form; + } + } + return parent::form($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function validate(array $form, array &$form_state) { + parent::validate($form, $form_state); + + // @todo Move trimming upstream. + $format_format = trim($form_state['values']['format']); + $format_name = trim($form_state['values']['name']); + + // Ensure that the values to be saved later are exactly the ones validated. + form_set_value($form['format'], $format_format, $form_state); + form_set_value($form['name'], $format_name, $form_state); + + $format_exists = $this->queryFactory + ->get('filter_format') + ->condition('format', $format_format, '<>') + ->condition('name', $format_name) + ->execute(); + if ($format_exists) { + form_set_error('name', t('Text format names must be unique. A format named %name already exists.', array('%name' => $format_name))); + } + } + + /** + * {@inheritdoc} + */ + public function submit(array $form, array &$form_state) { + parent::submit($form, $form_state); + + // Add the submitted form values to the text format, and save it. + $format = $this->entity; + foreach ($form_state['values'] as $key => $value) { + if ($key != 'filters') { + $format->set($key, $value); + } + else { + foreach ($value as $instance_id => $config) { + $format->setFilterConfig($instance_id, $config); + } + } + } + $format->save(); + + // Save user permissions. + if ($permission = filter_permission_name($format)) { + foreach ($form_state['values']['roles'] as $rid => $enabled) { + user_role_change_permissions($rid, array($permission => $enabled)); + } + } + + $form_state['redirect'] = 'admin/config/content/formats'; + + return $this->entity; + } + + /** + * {@inheritdoc} + */ + protected function actions(array $form, array &$form_state) { + $actions = parent::actions($form, $form_state); + $actions['submit']['#value'] = t('Save configuration'); + unset($actions['delete']); + return $actions; + } + +} diff --git a/core/modules/filter/lib/Drupal/filter/FilterFormatListController.php b/core/modules/filter/lib/Drupal/filter/FilterFormatListController.php new file mode 100644 index 0000000..43c4940 --- /dev/null +++ b/core/modules/filter/lib/Drupal/filter/FilterFormatListController.php @@ -0,0 +1,184 @@ +configFactory = $config_factory; + } + + /** + * {@inheritdoc} + */ + public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + return new static( + $entity_type, + $entity_info, + $container->get('plugin.manager.entity')->getStorageController($entity_type), + $container->get('module_handler'), + $container->get('config.factory') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormID() { + return 'filter_admin_overview'; + } + + /** + * {@inheritdoc} + */ + public function render() { + return drupal_get_form($this); + } + + /** + * {@inheritdoc} + */ + public function load() { + // Only list enabled filters. + return array_filter(parent::load(), function ($entity) { + return $entity->status(); + }); + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, array &$form_state) { + // Overview of all formats. + $this->entities = $this->load(); + $filter_settings = $this->configFactory->get('filter.settings'); + $fallback_format = $filter_settings->get('fallback_format'); + + $form['#tree'] = TRUE; + $form['formats'] = array( + '#type' => 'table', + '#header' => array(t('Name'), t('Roles'), t('Weight'), t('Operations')), + '#tabledrag' => array( + array('order', 'sibling', 'text-format-order-weight'), + ), + ); + $fallback_choice = $filter_settings->get('always_show_fallback_choice'); + foreach ($this->entities as $id => $format) { + $form['formats'][$id]['#attributes']['class'][] = 'draggable'; + $form['formats'][$id]['#weight'] = $format->weight; + + $links = array(); + $links['configure'] = array( + 'title' => t('configure'), + 'href' => "admin/config/content/formats/manage/$id", + ); + // Check whether this is the fallback text format. This format is available + // to all roles and cannot be disabled via the admin interface. + $form['formats'][$id]['#is_fallback'] = ($id == $fallback_format); + if ($form['formats'][$id]['#is_fallback']) { + $form['formats'][$id]['name'] = array('#markup' => String::placeholder($format->name)); + if ($fallback_choice) { + $roles_markup = String::placeholder(t('All roles may use this format')); + } + else { + $roles_markup = String::placeholder(t('This format is shown when no other formats are available')); + } + } + else { + $form['formats'][$id]['name'] = array('#markup' => String::checkPlain($format->name)); + $roles = array_map('\Drupal\Component\Utility\String::checkPlain', filter_get_roles_by_format($format)); + $roles_markup = $roles ? implode(', ', $roles) : t('No roles may use this format'); + $links['disable'] = array( + 'title' => t('disable'), + 'href' => "admin/config/content/formats/manage/$id/disable", + ); + } + + $form['formats'][$id]['roles'] = array('#markup' => $roles_markup); + + $form['formats'][$id]['weight'] = array( + '#type' => 'weight', + '#title' => t('Weight for @title', array('@title' => $format->name)), + '#title_display' => 'invisible', + '#default_value' => $format->weight, + '#attributes' => array('class' => array('text-format-order-weight')), + ); + + $form['formats'][$id]['operations'] = array( + '#type' => 'operations', + '#links' => $links, + ); + } + $form['actions'] = array('#type' => 'actions'); + $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save changes')); + return $form; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, array &$form_state) { + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, array &$form_state) { + foreach ($form_state['values']['formats'] as $id => $data) { + // Only update if this is a form element with weight. + if (is_array($data) && isset($data['weight'])) { + $this->entities[$id]->set('weight', $data['weight']); + $this->entities[$id]->save(); + } + } + filter_formats_reset(); + drupal_set_message(t('The text format ordering has been saved.')); + } + +} diff --git a/core/modules/filter/lib/Drupal/filter/Plugin/Core/Entity/FilterFormat.php b/core/modules/filter/lib/Drupal/filter/Plugin/Core/Entity/FilterFormat.php index b3224b9..7336b03 100644 --- a/core/modules/filter/lib/Drupal/filter/Plugin/Core/Entity/FilterFormat.php +++ b/core/modules/filter/lib/Drupal/filter/Plugin/Core/Entity/FilterFormat.php @@ -23,8 +23,11 @@ * module = "filter", * controllers = { * "form" = { + * "add" = "Drupal\filter\FilterFormatAddFormController", + * "edit" = "Drupal\filter\FilterFormatEditFormController", * "disable" = "Drupal\filter\Form\FilterDisableForm" * }, + * "list" = "Drupal\filter\FilterFormatListController", * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController" * }, * config_prefix = "filter.format", diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterAdminTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterAdminTest.php index 6dc2f4c..abce5dd 100644 --- a/core/modules/filter/lib/Drupal/filter/Tests/FilterAdminTest.php +++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterAdminTest.php @@ -76,8 +76,8 @@ function testFormatAdmin() { // Edit text format. $this->drupalGet('admin/config/content/formats'); - $this->assertLinkByHref('admin/config/content/formats/' . $format_id); - $this->drupalGet('admin/config/content/formats/' . $format_id); + $this->assertLinkByHref('admin/config/content/formats/manage/' . $format_id); + $this->drupalGet('admin/config/content/formats/manage/' . $format_id); $this->drupalPost(NULL, array(), t('Save configuration')); // Verify that the custom weight of the text format has been retained. @@ -85,12 +85,12 @@ function testFormatAdmin() { $this->assertFieldByName("formats[$format_id][weight]", 5, 'Text format weight was retained.'); // Disable text format. - $this->assertLinkByHref('admin/config/content/formats/' . $format_id . '/disable'); - $this->drupalGet('admin/config/content/formats/' . $format_id . '/disable'); + $this->assertLinkByHref('admin/config/content/formats/manage/' . $format_id . '/disable'); + $this->drupalGet('admin/config/content/formats/manage/' . $format_id . '/disable'); $this->drupalPost(NULL, array(), t('Disable')); // Verify that disabled text format no longer exists. - $this->drupalGet('admin/config/content/formats/' . $format_id); + $this->drupalGet('admin/config/content/formats/manage/' . $format_id); $this->assertResponse(404, 'Disabled text format no longer exists.'); // Attempt to create a format of the same machine name as the disabled @@ -129,8 +129,8 @@ function testFilterAdmin() { // Check that the fallback format exists and cannot be disabled. $this->assertTrue($plain == filter_fallback_format(), 'The fallback format is set to plain text.'); $this->drupalGet('admin/config/content/formats'); - $this->assertNoRaw('admin/config/content/formats/' . $plain . '/disable', 'Disable link for the fallback format not found.'); - $this->drupalGet('admin/config/content/formats/' . $plain . '/disable'); + $this->assertNoRaw('admin/config/content/formats/manage/' . $plain . '/disable', 'Disable link for the fallback format not found.'); + $this->drupalGet('admin/config/content/formats/manage/' . $plain . '/disable'); $this->assertResponse(403, 'The fallback format cannot be disabled.'); // Verify access permissions to Full HTML format. @@ -140,9 +140,9 @@ function testFilterAdmin() { // Add an additional tag. $edit = array(); $edit['filters[filter_html][settings][allowed_html]'] = '