diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockTest.php index 6a3dd0c..4f3aacd 100644 --- a/core/modules/block/lib/Drupal/block/Tests/BlockTest.php +++ b/core/modules/block/lib/Drupal/block/Tests/BlockTest.php @@ -36,12 +36,11 @@ function setUp() { config('system.site')->set('page.front', 'test-page')->save(); // Create Full HTML text format. - $full_html_format = array( + $full_html_format = entity_create('filter_format', array( 'format' => 'full_html', 'name' => 'Full HTML', - ); - $full_html_format = (object) $full_html_format; - filter_format_save($full_html_format); + )); + $full_html_format->save(); $this->checkPermissions(array(), TRUE); // Create and log in an administrative user having access to the Full HTML diff --git a/core/modules/filter/config/filter.format.plain_text.yml b/core/modules/filter/config/filter.format.plain_text.yml new file mode 100644 index 0000000..a7f72cd --- /dev/null +++ b/core/modules/filter/config/filter.format.plain_text.yml @@ -0,0 +1,26 @@ +# Every site requires at least one text format as fallback format that +# - is accessible to all users. +# - is secure, using very basic formatting only. +# - may be modified by installation profiles to have other properties. +format: plain_text +name: 'Plain text' +status: '1' +weight: '10' +roles: + - anonymous + - authenticated +cache: '1' +filters: + # Escape all HTML. + filter_html_escape: + module: filter + status: '1' + # Convert URLs into links. + filter_url: + module: filter + status: '1' + # Convert linebreaks into paragraphs. + filter_autop: + module: filter + status: '1' +langcode: und diff --git a/core/modules/filter/filter.admin.inc b/core/modules/filter/filter.admin.inc index a62f8e3..b9fb91c 100644 --- a/core/modules/filter/filter.admin.inc +++ b/core/modules/filter/filter.admin.inc @@ -75,13 +75,12 @@ function filter_admin_overview($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'])) { - // Only update if this is a form element with weight. - db_update('filter_format') - ->fields(array('weight' => $data['weight'])) - ->condition('format', $id) - ->execute(); + $filter_formats[$id]->set('weight', $data['weight']); + $filter_formats[$id]->save(); } } filter_formats_reset(); @@ -112,10 +111,8 @@ function filter_admin_overview_submit($form, &$form_state) { function filter_admin_format_page($format = NULL) { if (!isset($format->name)) { drupal_set_title(t('Add text format')); - $format = (object) array( - 'format' => NULL, - 'name' => '', - ); + + $format = entity_create('filter_format', array()); } return drupal_get_form('filter_admin_format_form', $format); } @@ -212,6 +209,10 @@ function filter_admin_format_form($form, &$form_state, $format) { '#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, ); foreach ($filter_info as $name => $filter) { $form['filters']['status'][$name] = array( @@ -229,6 +230,10 @@ function filter_admin_format_form($form, &$form_state, $format) { '#type' => 'item', '#title' => t('Filter processing order'), '#theme' => 'filter_admin_format_filter_order', + // 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, ); foreach ($filter_info as $name => $filter) { $form['filters']['order'][$name]['filter'] = array( @@ -259,8 +264,7 @@ function filter_admin_format_form($form, &$form_state, $format) { $function = $filter['settings callback']; // Pass along stored filter settings and default settings, but also the // format object and all filters to allow for complex implementations. - $defaults = (isset($filter['default settings']) ? $filter['default settings'] : array()); - $settings_form = $function($form, $form_state, $filters[$name], $format, $defaults, $filters); + $settings_form = $function($form, $form_state, $filters[$name], $format, $filter['default settings'], $filters); if (!empty($settings_form)) { $form['filters']['settings'][$name] = array( '#type' => 'details', @@ -324,9 +328,12 @@ function filter_admin_format_form_validate($form, &$form_state) { form_set_value($form['format'], $format_format, $form_state); form_set_value($form['name'], $format_name, $form_state); - $result = db_query("SELECT format FROM {filter_format} WHERE name = :name AND format <> :format", array(':name' => $format_name, ':format' => $format_format))->fetchField(); - if ($result) { - form_set_error('name', t('Text format names must be unique. A format named %name already exists.', array('%name' => $format_name))); + $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; + } } } @@ -339,19 +346,15 @@ function filter_admin_format_form_submit($form, &$form_state) { // Remove unnecessary values. form_state_values_clean($form_state); + // Reduce roles to a simple list of enabled roles. + $form_state['values']['roles'] = array_keys(array_filter($form_state['values']['roles'])); + // Add the submitted form values to the text format, and save it. $format = $form['#format']; foreach ($form_state['values'] as $key => $value) { - $format->$key = $value; - } - $status = filter_format_save($format); - - // Save user permissions. - if ($permission = filter_permission_name($format)) { - foreach ($format->roles as $rid => $enabled) { - user_role_change_permissions($rid, array($permission => $enabled)); - } + $format->set($key, $value); } + $status = $format->save(); switch ($status) { case SAVED_NEW: diff --git a/core/modules/filter/filter.api.php b/core/modules/filter/filter.api.php index f11a528..c041eb4 100644 --- a/core/modules/filter/filter.api.php +++ b/core/modules/filter/filter.api.php @@ -277,43 +277,10 @@ function hook_filter_FILTER_tips($filter, $format, $long) { */ /** - * Perform actions when a new text format has been created. - * - * @param $format - * The format object of the format being updated. - * - * @see hook_filter_format_update() - * @see hook_filter_format_disable() - */ -function hook_filter_format_insert($format) { - mymodule_cache_rebuild(); -} - -/** - * Perform actions when a text format has been updated. - * - * This hook allows modules to act when a text format has been updated in any - * way. For example, when filters have been reconfigured, disabled, or - * re-arranged in the text format. - * - * @param $format - * The format object of the format being updated. - * - * @see hook_filter_format_insert() - * @see hook_filter_format_disable() - */ -function hook_filter_format_update($format) { - mymodule_cache_rebuild(); -} - -/** * Perform actions when a text format has been disabled. * * @param $format * The format object of the format being disabled. - * - * @see hook_filter_format_insert() - * @see hook_filter_format_update() */ function hook_filter_format_disable($format) { mymodule_cache_rebuild(); diff --git a/core/modules/filter/filter.install b/core/modules/filter/filter.install index f3c29a5..39ef59b 100644 --- a/core/modules/filter/filter.install +++ b/core/modules/filter/filter.install @@ -5,106 +5,12 @@ * Install, update, and uninstall functions for the Filter module. */ +use Drupal\Component\Uuid\Uuid; + /** * Implements hook_schema(). */ function filter_schema() { - $schema['filter'] = array( - 'description' => 'Table that maps filters (HTML corrector) to text formats (Filtered HTML).', - 'fields' => array( - 'format' => array( - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'description' => 'Foreign key: The {filter_format}.format to which this filter is assigned.', - ), - 'module' => array( - 'type' => 'varchar', - 'length' => 64, - 'not null' => TRUE, - 'default' => '', - 'description' => 'The origin module of the filter.', - ), - 'name' => array( - 'type' => 'varchar', - 'length' => 32, - 'not null' => TRUE, - 'default' => '', - 'description' => 'Name of the filter being referenced.', - ), - 'weight' => array( - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - 'description' => 'Weight of filter within format.', - ), - 'status' => array( - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - 'description' => 'Filter enabled status. (1 = enabled, 0 = disabled)', - ), - 'settings' => array( - 'type' => 'blob', - 'not null' => FALSE, - 'size' => 'big', - 'serialize' => TRUE, - 'description' => 'A serialized array of name value pairs that store the filter settings for the specific format.', - ), - ), - 'primary key' => array('format', 'name'), - 'indexes' => array( - 'list' => array('weight', 'module', 'name'), - ), - ); - $schema['filter_format'] = array( - 'description' => 'Stores text formats: custom groupings of filters, such as Filtered HTML.', - 'fields' => array( - 'format' => array( - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'description' => 'Primary Key: Unique machine name of the format.', - ), - 'name' => array( - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - 'description' => 'Name of the text format (Filtered HTML).', - 'translatable' => TRUE, - ), - 'cache' => array( - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - 'size' => 'tiny', - 'description' => 'Flag to indicate whether format is cacheable. (1 = cacheable, 0 = not cacheable)', - ), - 'status' => array( - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 1, - 'size' => 'tiny', - 'description' => 'The status of the text format. (1 = enabled, 0 = disabled)', - ), - 'weight' => array( - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - 'description' => 'Weight of text format to use when listing.', - ), - ), - 'primary key' => array('format'), - 'unique keys' => array( - 'name' => array('name'), - ), - 'indexes' => array( - 'status_weight' => array('status', 'weight'), - ), - ); - $schema['cache_filter'] = drupal_get_schema_unprocessed('system', 'cache'); $schema['cache_filter']['description'] = 'Cache table for the Filter module to store already filtered pieces of text, identified by text format and hash of the text.'; @@ -112,40 +18,6 @@ function filter_schema() { } /** - * Implements hook_install(). - */ -function filter_install() { - // All sites require at least one text format (the fallback format) that all - // users have access to, so add it here. We initialize it as a simple, safe - // plain text format with very basic formatting, but it can be modified by - // installation profiles to have other properties. - $plain_text_format = array( - 'format' => 'plain_text', - 'name' => 'Plain text', - 'weight' => 10, - 'filters' => array( - // Escape all HTML. - 'filter_html_escape' => array( - 'weight' => 0, - 'status' => 1, - ), - // URL filter. - 'filter_url' => array( - 'weight' => 1, - 'status' => 1, - ), - // Line break filter. - 'filter_autop' => array( - 'weight' => 2, - 'status' => 1, - ), - ), - ); - $plain_text_format = (object) $plain_text_format; - filter_format_save($plain_text_format); -} - -/** * @addtogroup updates-7.x-to-8.x * @{ */ @@ -162,6 +34,42 @@ function filter_update_8000() { } /** + * Migrate filter formats into configuration. + * + * @ingroup config_upgrade + */ +function filter_update_8001() { + $uuid = new Uuid(); + $result = db_query('SELECT format, name, cache, status, weight FROM {filter_format}', array(), array('fetch' => PDO::FETCH_ASSOC)); + foreach ($result as $format) { + $id = $format['format']; + + // Generate a UUID. + $format['uuid'] = $uuid->generate(); + + // Add user roles. + $format['roles'] = array_keys(user_roles(FALSE, 'use text format ' . $format['format'])); + + // Retrieve and prepare all filters. + $filters = db_query('SELECT name, module, status, weight, settings FROM {filter} WHERE format = :format ORDER BY weight, module, name', array( + ':format' => $id, + ), array('fetch' => PDO::FETCH_ASSOC))->fetchAllAssoc('name'); + foreach ($filters as $name => &$filter) { + // The filter name is used as key only. + unset($filter['name']); + $filter['settings'] = unserialize($filter['settings']); + } + $format['filters'] = $filters; + + // Save the config object. + $config = config('filter.format.' . $id); + $config->setData($format); + $config->save(); + update_config_manifest_add('filter.format', array($id)); + } +} + +/** * @} End of "defgroup updates-7.x-to-8.x". * The next series of updates should start at 9000. */ diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module index c4b596a..18f4ed4 100644 --- a/core/modules/filter/filter.module +++ b/core/modules/filter/filter.module @@ -7,6 +7,7 @@ use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Template\Attribute; +use Drupal\filter\Plugin\Core\Entity\FilterFormat; /** * Non-HTML markup language filters that generate HTML. @@ -205,116 +206,6 @@ function filter_format_load($format_id) { } /** - * Saves a text format object to the database. - * - * @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. - * - 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. - * - filters: (optional) An associative, multi-dimensional array of filters - * assigned to the text format, keyed by the name of each filter and using - * the properties: - * - weight: (optional) The weight of the filter in the text format. If - * omitted, either the currently stored weight is retained (if there is - * one), or the filter is assigned a weight of 10, which will usually - * put it at the bottom of the list. - * - status: (optional) A Boolean indicating whether the filter is - * enabled in the text format. If omitted, the filter will be disabled. - * - settings: (optional) An array of configured settings for the filter. - * See hook_filter_info() for details. - * - * @return - * SAVED_NEW or SAVED_UPDATED. - */ -function filter_format_save($format) { - $format->name = trim($format->name); - $format->cache = _filter_format_is_cacheable($format); - if (!isset($format->status)) { - $format->status = 1; - } - if (!isset($format->weight)) { - $format->weight = 0; - } - - // Insert or update the text format. - $return = db_merge('filter_format') - ->key(array('format' => $format->format)) - ->fields(array( - 'name' => $format->name, - 'cache' => (int) $format->cache, - 'status' => (int) $format->status, - 'weight' => (int) $format->weight, - )) - ->execute(); - - // Programmatic saves may not contain any filters. - if (!isset($format->filters)) { - $format->filters = array(); - } - $filter_info = filter_get_filters(); - foreach ($filter_info as $name => $filter) { - // If the format does not specify an explicit weight for a filter, assign - // a default weight, either defined in hook_filter_info(), or the default of - // 0 by filter_get_filters(). - if (!isset($format->filters[$name]['weight'])) { - $format->filters[$name]['weight'] = $filter['weight']; - } - $format->filters[$name]['status'] = isset($format->filters[$name]['status']) ? $format->filters[$name]['status'] : 0; - $format->filters[$name]['module'] = $filter['module']; - - // If settings were passed, only ensure default settings. - if (isset($format->filters[$name]['settings'])) { - if (isset($filter['default settings'])) { - $format->filters[$name]['settings'] = array_merge($filter['default settings'], $format->filters[$name]['settings']); - } - } - // Otherwise, use default settings or fall back to an empty array. - else { - $format->filters[$name]['settings'] = isset($filter['default settings']) ? $filter['default settings'] : array(); - } - - $fields = array(); - $fields['weight'] = $format->filters[$name]['weight']; - $fields['status'] = $format->filters[$name]['status']; - $fields['module'] = $format->filters[$name]['module']; - $fields['settings'] = serialize($format->filters[$name]['settings']); - - db_merge('filter') - ->key(array( - 'format' => $format->format, - 'name' => $name, - )) - ->fields($fields) - ->execute(); - } - - if ($return == SAVED_NEW) { - module_invoke_all('filter_format_insert', $format); - } - else { - module_invoke_all('filter_format_update', $format); - // Explicitly indicate that the format was updated. We need to do this - // since if the filters were updated but the format object itself was not, - // the merge query above would not return an indication that anything had - // changed. - $return = SAVED_UPDATED; - - // Clear the filter cache whenever a text format is updated. - cache('filter')->deleteTags(array('filter_format' => $format->format)); - } - - filter_formats_reset(); - - return $return; -} - -/** * Disables a text format. * * There is no core facility to re-enable a disabled format. It is not deleted @@ -326,10 +217,8 @@ function filter_format_save($format) { * The text format object to be disabled. */ function filter_format_disable($format) { - db_update('filter_format') - ->fields(array('status' => 0)) - ->condition('format', $format->format) - ->execute(); + $format->status = 0; + $format->save(); // Allow modules to react on text format deletion. module_invoke_all('filter_format_disable', $format); @@ -353,7 +242,7 @@ function filter_format_disable($format) { * @see filter_format_load() */ function filter_format_exists($format_id) { - return (bool) db_query_range('SELECT 1 FROM {filter_format} WHERE format = :format', 0, 1, array(':format' => $format_id))->fetchField(); + return entity_load('filter_format', $format_id); } /** @@ -452,13 +341,14 @@ function filter_formats($account = NULL) { $formats['all'] = $cache->data; } else { - $formats['all'] = db_select('filter_format', 'ff') - ->addTag('translatable') - ->fields('ff') - ->condition('status', 1) - ->orderBy('weight') - ->execute() - ->fetchAllAssoc('format'); + $filter_formats = entity_load_multiple('filter_format'); + $formats['all'] = array(); + foreach ($filter_formats as $format_name => $filter_format) { + if (!empty($filter_format->status)) { + $formats['all'][$format_name] = $filter_format; + } + } + uasort($formats['all'], 'Drupal\Core\Config\Entity\ConfigEntityBase::sort'); cache()->set("filter_formats:{$language_interface->langcode}", $formats['all'], CacheBackendInterface::CACHE_PERMANENT, array('filter_formats' => TRUE)); } @@ -663,6 +553,7 @@ function filter_get_filters() { $info[$name] += array( 'description' => '', 'weight' => 0, + 'default settings' => array(), ); } $filters = array_merge($filters, $info); @@ -717,7 +608,7 @@ function filter_format_allowcache($format_id) { * TRUE if all the filters enabled in the given text format allow caching, * FALSE otherwise. * - * @see filter_format_save() + * @see Drupal\filter\Plugin\Core\Entity\FilterFormat::save() */ function _filter_format_is_cacheable($format) { if (empty($format->filters)) { @@ -757,9 +648,18 @@ function filter_list_format($format_id) { $filters['all'] = $cache->data; } else { - $result = db_query('SELECT * FROM {filter} ORDER BY weight, module, name'); - foreach ($result as $record) { - $filters['all'][$record->format][$record->name] = $record; + $filter_formats = filter_formats(); + foreach ($filter_formats as $filter_format) { + foreach ($filter_format->filters as $filter_name => $filter) { + $filter['name'] = $filter_name; + $filters['all'][$filter_format->format][$filter_name] = $filter; + } + uasort($filters['all'][$filter_format->format], 'Drupal\filter\Plugin\Core\Entity\FilterFormat::sortFilters'); + // Convert filters into objects. + // @todo Retain filters as arrays or convert to plugins. + foreach ($filters['all'][$filter_format->format] as $filter_name => $filter) { + $filters['all'][$filter_format->format][$filter_name] = (object) $filter; + } } cache()->set('filter_list_format', $filters['all']); } @@ -771,12 +671,10 @@ function filter_list_format($format_id) { foreach ($filter_map as $name => $filter) { if (isset($filter_info[$name])) { $filter->title = $filter_info[$name]['title']; - // Unpack stored filter settings. - $filter->settings = (isset($filter->settings) ? unserialize($filter->settings) : array()); + + $filter->settings = isset($filter->settings) ? $filter->settings : array(); // Merge in default settings. - if (isset($filter_info[$name]['default settings'])) { - $filter->settings += $filter_info[$name]['default settings']; - } + $filter->settings += $filter_info[$name]['default settings']; $format_filters[$name] = $filter; } @@ -885,7 +783,7 @@ function check_markup($text, $format_id = NULL, $langcode = '', $cache = FALSE, // Cache the filtered text. This cache is infinitely valid. It becomes // obsolete when $text changes (which leads to a new $cache_id). It is // automatically flushed when the text format is updated. - // @see filter_format_save() + // @see Drupal\filter\Plugin\Core\Entity\FilterFormat::save() if ($cache) { cache('filter')->set($cache_id, $text, CacheBackendInterface::CACHE_PERMANENT, array('filter_format' => $format->format)); } diff --git a/core/modules/filter/lib/Drupal/filter/FilterFormatStorageController.php b/core/modules/filter/lib/Drupal/filter/FilterFormatStorageController.php new file mode 100644 index 0000000..a2aec32 --- /dev/null +++ b/core/modules/filter/lib/Drupal/filter/FilterFormatStorageController.php @@ -0,0 +1,97 @@ +name = trim($entity->label()); + $entity->cache = _filter_format_is_cacheable($entity); + $filter_info = filter_get_filters(); + foreach ($filter_info as $name => $filter) { + // Ensure a consistent definition and order of properties for all filters + // by merging the actual filter definition into defaults. + $defaults = array( + 'module' => $filter['module'], + // The filter ID has to be temporarily injected into the properties, in + // order to sort all filters below. + // @todo Rethink filter sorting to remove dependency on filter IDs. + 'name' => $name, + // Unless explicitly enabled, all filters are disabled by default. + 'status' => 0, + // If no explicit weight was defined for a filter, assign either the + // default weight defined in hook_filter_info() or the default of 0 by + // filter_get_filters(). + 'weight' => $filter['weight'], + 'settings' => $filter['default settings'], + ); + // All available filters are saved for each format, in order to retain all + // filter properties regardless of whether a filter is currently enabled + // or not, since some filters require extensive configuration. + // @todo Do not save disabled filters whose properties are identical to + // all default properties. + if (isset($entity->filters[$name])) { + $entity->filters[$name] = array_merge($defaults, $entity->filters[$name]); + } + else { + $entity->filters[$name] = $defaults; + } + // The module definition from hook_filter_info() always takes precedence + // and needs to be updated in case it changes. + $entity->filters[$name]['module'] = $filter['module']; + } + + // Sort all filters. + uasort($entity->filters, 'Drupal\filter\Plugin\Core\Entity\FilterFormat::sortFilters'); + // Remove the 'name' property from all filters that was added above. + foreach ($entity->filters as &$filter) { + unset($filter['name']); + } + } + + /** + * Overrides \Drupal\Core\Config\Entity\ConfigStorageController::postSave(). + */ + protected function postSave(EntityInterface $entity, $update) { + parent::postSave($entity, $update); + + if ($update) { + // Clear the filter cache whenever a text format is updated. + cache('filter')->deleteTags(array('filter_format' => $entity->id())); + } + filter_formats_reset(); + + // Save user role permissions. + // The format was already disabled and saved. filter_formats() does not + // include disabled formats. user_role_change_permissions() calls into + // user_permission_get_modules() which calls into hook_permission() in order + // to determine the module that defines a user permission. + // filter_permission() uses filter_formats(), so the disabled format is no + // longer contained and consequently the user permission is not found, + // leading to an error. Therefore, permissions cannot be updated for + // disabled formats. + if (!empty($entity->status) && $permission = filter_permission_name($entity)) { + foreach (user_roles() as $rid => $name) { + $enabled = in_array($rid, $entity->roles); + user_role_change_permissions($rid, array($permission => $enabled)); + } + } + } + +} 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 new file mode 100644 index 0000000..2f6e6d4 --- /dev/null +++ b/core/modules/filter/lib/Drupal/filter/Plugin/Core/Entity/FilterFormat.php @@ -0,0 +1,138 @@ +format; + } + + /** + * Helper callback for uasort() to sort filters by status, weight, module, and name. + * + * @see Drupal\filter\FilterFormatStorageController::preSave() + * @see filter_list_format() + */ + public static function sortFilters($a, $b) { + if ($a['status'] != $b['status']) { + return !empty($a['status']) ? -1 : 1; + } + if ($a['weight'] != $b['weight']) { + return ($a['weight'] < $b['weight']) ? -1 : 1; + } + if ($a['module'] != $b['module']) { + return strnatcasecmp($a['module'], $b['module']); + } + return strnatcasecmp($a['name'], $b['name']); + } + +} diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php index e355f2d..3918ea9 100644 --- a/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php +++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php @@ -26,7 +26,7 @@ function setUp() { parent::setUp(); // Create Filtered HTML format. - $filtered_html_format = array( + $filtered_html_format = entity_create('filter_format', array( 'format' => 'filtered_html', 'name' => 'Filtered HTML', 'filters' => array( @@ -40,12 +40,11 @@ function setUp() { 'status' => 1, ), ) - ); - $filtered_html_format = (object) $filtered_html_format; - filter_format_save($filtered_html_format); + )); + $filtered_html_format->save(); // Create Full HTML format. - $full_html_format = array( + $full_html_format = entity_create('filter_format', array( 'format' => 'full_html', 'name' => 'Full HTML', 'weight' => 1, @@ -55,9 +54,8 @@ function setUp() { 'status' => 1, ), ), - ); - $full_html_format = (object) $full_html_format; - filter_format_save($full_html_format); + )); + $full_html_format->save(); } /** diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterAdminTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterAdminTest.php index 9a09a76..0b9d30f 100644 --- a/core/modules/filter/lib/Drupal/filter/Tests/FilterAdminTest.php +++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterAdminTest.php @@ -152,14 +152,13 @@ function testFilterAdmin() { )); $this->assertTrue(!empty($elements), 'Reorder confirmed in admin interface.'); - $result = db_query('SELECT * FROM {filter} WHERE format = :format ORDER BY weight ASC', array(':format' => $filtered)); - $filters = array(); - foreach ($result as $filter) { - if ($filter->name == $second_filter || $filter->name == $first_filter) { - $filters[] = $filter; + $filter_format = entity_load('filter_format', $filtered); + foreach ($filter_format->filters as $filter_name => $filter) { + if ($filter_name == $second_filter || $filter_name == $first_filter) { + $filters[] = $filter_name; } } - $this->assertTrue(($filters[0]->name == $second_filter && $filters[1]->name == $first_filter), 'Order confirmed in database.'); + $this->assertTrue(($filters[0] == $second_filter && $filters[1] == $first_filter), t('Order confirmed in database.')); // Add format. $edit = array(); diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterCrudTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterCrudTest.php index 766736f..2fa330b 100644 --- a/core/modules/filter/lib/Drupal/filter/Tests/FilterCrudTest.php +++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterCrudTest.php @@ -35,15 +35,15 @@ public static function getInfo() { */ function testTextFormatCrud() { // Add a text format with minimum data only. - $format = new stdClass(); + $format = entity_create('filter_format', array()); $format->format = 'empty_format'; $format->name = 'Empty format'; - filter_format_save($format); + $format->save(); $this->verifyTextFormat($format); $this->verifyFilters($format); // Add another text format specifying all possible properties. - $format = new stdClass(); + $format = entity_create('filter_format', array()); $format->format = 'custom_format'; $format->name = 'Custom format'; $format->filters = array( @@ -54,7 +54,7 @@ function testTextFormatCrud() { ), ), ); - filter_format_save($format); + $format->save(); $this->verifyTextFormat($format); $this->verifyFilters($format); @@ -62,21 +62,19 @@ function testTextFormatCrud() { $format->name = 'Altered format'; $format->filters['filter_url']['status'] = 0; $format->filters['filter_autop']['status'] = 1; - filter_format_save($format); + $format->save(); $this->verifyTextFormat($format); $this->verifyFilters($format); // Add a uncacheable filter and save again. $format->filters['filter_test_uncacheable']['status'] = 1; - filter_format_save($format); + $format->save(); $this->verifyTextFormat($format); $this->verifyFilters($format); // Disable the text format. filter_format_disable($format); - $db_format = db_query("SELECT * FROM {filter_format} WHERE format = :format", array(':format' => $format->format))->fetchObject(); - $this->assertFalse($db_format->status, 'Database: Disabled text format is marked as disabled.'); $formats = filter_formats(); $this->assertTrue(!isset($formats[$format->format]), 'filter_formats: Disabled text format no longer exists.'); } @@ -86,16 +84,6 @@ function testTextFormatCrud() { */ function verifyTextFormat($format) { $t_args = array('%format' => $format->name); - // Verify text format database record. - $db_format = db_select('filter_format', 'ff') - ->fields('ff') - ->condition('format', $format->format) - ->execute() - ->fetchObject(); - $this->assertEqual($db_format->format, $format->format, format_string('Database: Proper format id for text format %format.', $t_args)); - $this->assertEqual($db_format->name, $format->name, format_string('Database: Proper title for text format %format.', $t_args)); - $this->assertEqual($db_format->cache, $format->cache, format_string('Database: Proper cache indicator for text format %format.', $t_args)); - $this->assertEqual($db_format->weight, $format->weight, format_string('Database: Proper weight for text format %format.', $t_args)); // Verify filter_format_load(). $filter_format = filter_format_load($format->format); @@ -123,27 +111,7 @@ function verifyTextFormat($format) { * Verify that filters are properly stored for a text format. */ function verifyFilters($format) { - // Verify filter database records. - $filters = db_query("SELECT * FROM {filter} WHERE format = :format", array(':format' => $format->format))->fetchAllAssoc('name'); $format_filters = $format->filters; - foreach ($filters as $name => $filter) { - $t_args = array('%format' => $format->name, '%filter' => $name); - - // Verify that filter status is properly stored. - $this->assertEqual($filter->status, $format_filters[$name]['status'], format_string('Database: Proper status for %filter in text format %format.', $t_args)); - - // Verify that filter settings were properly stored. - $this->assertEqual(unserialize($filter->settings), isset($format_filters[$name]['settings']) ? $format_filters[$name]['settings'] : array(), format_string('Database: Proper filter settings for %filter in text format %format.', $t_args)); - - // Verify that each filter has a module name assigned. - $this->assertTrue(!empty($filter->module), format_string('Database: Proper module name for %filter in text format %format.', $t_args)); - - // Remove the filter from the copy of saved $format to check whether all - // filters have been processed later. - unset($format_filters[$name]); - } - // Verify that all filters have been processed. - $this->assertTrue(empty($format_filters), 'Database contains values for all filters in the saved format.'); // Verify filter_list_format(). $filters = filter_list_format($format->format); diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterDefaultFormatTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterDefaultFormatTest.php index 04fa520..cbeecd0 100644 --- a/core/modules/filter/lib/Drupal/filter/Tests/FilterDefaultFormatTest.php +++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterDefaultFormatTest.php @@ -42,7 +42,10 @@ function testDefaultTextFormats() { // Adjust the weights so that the first and second formats (in that order) // are the two lowest weighted formats available to any user. - $minimum_weight = db_query("SELECT MIN(weight) FROM {filter_format}")->fetchField(); + $minimum_weight = 0; + foreach (entity_load_multiple('filter_format') as $format) { + $minimum_weight = min($minimum_weight, $format->weight); + } $edit = array(); $edit['formats[' . $first_format->format . '][weight]'] = $minimum_weight - 2; $edit['formats[' . $second_format->format . '][weight]'] = $minimum_weight - 1; diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterHooksTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterHooksTest.php index f01b4d2..eab7e79 100644 --- a/core/modules/filter/lib/Drupal/filter/Tests/FilterHooksTest.php +++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterHooksTest.php @@ -29,10 +29,6 @@ public static function getInfo() { ); } - function setUp() { - parent::setUp(); - } - /** * Tests hooks on format management. * @@ -55,8 +51,8 @@ function testFilterHooks() { $edit['name'] = $name; $edit['roles[' . DRUPAL_ANONYMOUS_RID . ']'] = 1; $this->drupalPost('admin/config/content/formats/add', $edit, t('Save configuration')); - $this->assertRaw(t('Added text format %format.', array('%format' => $name)), 'New format created.'); - $this->assertText('hook_filter_format_insert invoked.', 'hook_filter_format_insert was invoked.'); + $this->assertRaw(t('Added text format %format.', array('%format' => $name))); + $this->assertText('hook_filter_format_insert invoked.'); $format_id = $edit['format']; @@ -64,8 +60,8 @@ function testFilterHooks() { $edit = array(); $edit['roles[' . DRUPAL_AUTHENTICATED_RID . ']'] = 1; $this->drupalPost('admin/config/content/formats/' . $format_id, $edit, t('Save configuration')); - $this->assertRaw(t('The text format %format has been updated.', array('%format' => $name)), 'Format successfully updated.'); - $this->assertText('hook_filter_format_update invoked.', 'hook_filter_format_update() was invoked.'); + $this->assertRaw(t('The text format %format has been updated.', array('%format' => $name))); + $this->assertText('hook_filter_format_update invoked.'); // Use the format created. $language_not_specified = LANGUAGE_NOT_SPECIFIED; @@ -76,11 +72,11 @@ function testFilterHooks() { "body[$language_not_specified][0][format]" => $format_id, ); $this->drupalPost("node/add/{$type->type}", $edit, t('Save')); - $this->assertText(t('@type @title has been created.', array('@type' => $type_name, '@title' => $title)), 'New node successfully created.'); + $this->assertText(t('@type @title has been created.', array('@type' => $type_name, '@title' => $title))); // Disable the text format. $this->drupalPost('admin/config/content/formats/' . $format_id . '/disable', array(), t('Disable')); - $this->assertRaw(t('Disabled text format %format.', array('%format' => $name)), 'Format successfully disabled.'); - $this->assertText('hook_filter_format_disable invoked.', 'hook_filter_format_disable() was invoked.'); + $this->assertRaw(t('Disabled text format %format.', array('%format' => $name))); + $this->assertText('hook_filter_format_disable invoked.'); } } diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterHtmlImageSecureTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterHtmlImageSecureTest.php index a7e38ac..8c95150 100644 --- a/core/modules/filter/lib/Drupal/filter/Tests/FilterHtmlImageSecureTest.php +++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterHtmlImageSecureTest.php @@ -33,7 +33,7 @@ function setUp() { parent::setUp(); // Setup Filtered HTML text format. - $filtered_html_format = array( + $filtered_html_format = entity_create('filter_format', array( 'format' => 'filtered_html', 'name' => 'Filtered HTML', 'filters' => array( @@ -50,9 +50,8 @@ function setUp() { 'status' => 1, ), ), - ); - $filtered_html_format = (object) $filtered_html_format; - filter_format_save($filtered_html_format); + )); + $filtered_html_format->save(); // Setup users. $this->checkPermissions(array(), TRUE); diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterSecurityTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterSecurityTest.php index 813d717..231b660 100644 --- a/core/modules/filter/lib/Drupal/filter/Tests/FilterSecurityTest.php +++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterSecurityTest.php @@ -36,7 +36,7 @@ function setUp() { $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page')); // Create Filtered HTML format. - $filtered_html_format = array( + $filtered_html_format = entity_create('filter_format', array( 'format' => 'filtered_html', 'name' => 'Filtered HTML', 'filters' => array( @@ -45,9 +45,8 @@ function setUp() { 'status' => 1, ), ) - ); - $filtered_html_format = (object) $filtered_html_format; - filter_format_save($filtered_html_format); + )); + $filtered_html_format->save(); $filtered_html_permission = filter_permission_name($filtered_html_format); user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array($filtered_html_permission)); diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterSettingsTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterSettingsTest.php index 0a6c00c..0bfcef3 100644 --- a/core/modules/filter/lib/Drupal/filter/Tests/FilterSettingsTest.php +++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterSettingsTest.php @@ -31,12 +31,12 @@ function testFilterDefaults() { $filters = array_fill_keys(array_keys($filter_info), array()); // Create text format using filter default settings. - $filter_defaults_format = (object) array( + $filter_defaults_format = entity_create('filter_format', array( 'format' => 'filter_defaults', 'name' => 'Filter defaults', 'filters' => $filters, - ); - filter_format_save($filter_defaults_format); + )); + $filter_defaults_format->save(); // Verify that default weights defined in hook_filter_info() were applied. $saved_settings = array(); @@ -51,7 +51,7 @@ function testFilterDefaults() { } // Re-save the text format. - filter_format_save($filter_defaults_format); + $filter_defaults_format->save(); // Reload it from scratch. filter_formats_reset(); $filter_defaults_format = filter_format_load($filter_defaults_format->format); diff --git a/core/modules/php/config/filter.format.php_code.yml b/core/modules/php/config/filter.format.php_code.yml new file mode 100644 index 0000000..cee6e9b --- /dev/null +++ b/core/modules/php/config/filter.format.php_code.yml @@ -0,0 +1,10 @@ +format: php_code +name: 'PHP code' +status: '1' +weight: '11' +cache: '0' +filters: + php_code: + module: php + status: '1' +langcode: und diff --git a/core/modules/php/php.install b/core/modules/php/php.install index 12944dd..a88fe6a 100644 --- a/core/modules/php/php.install +++ b/core/modules/php/php.install @@ -6,38 +6,6 @@ */ /** - * Implements hook_enable(). - */ -function php_enable() { - $format_exists = (bool) db_query_range('SELECT 1 FROM {filter_format} WHERE name = :name', 0, 1, array(':name' => 'PHP code'))->fetchField(); - // Add a PHP code text format, if it does not exist. Do this only for the - // first install (or if the format has been manually deleted) as there is no - // reliable method to identify the format in an uninstall hook or in - // subsequent clean installs. - if (!$format_exists) { - $php_format = array( - 'format' => 'php_code', - 'name' => 'PHP code', - // 'Plain text' format is installed with a weight of 10 by default. Use a - // higher weight here to ensure that this format will not be the default - // format for anyone. - 'weight' => 11, - 'filters' => array( - // Enable the PHP evaluator filter. - 'php_code' => array( - 'weight' => 0, - 'status' => 1, - ), - ), - ); - $php_format = (object) $php_format; - filter_format_save($php_format); - - drupal_set_message(t('A PHP code text format has been created.', array('@php-code' => url('admin/config/content/formats/' . $php_format->format)))); - } -} - -/** * Implements hook_disable(). */ function php_disable() { diff --git a/core/modules/search/lib/Drupal/search/Tests/SearchRankingTest.php b/core/modules/search/lib/Drupal/search/Tests/SearchRankingTest.php index a57e483..4987b56 100644 --- a/core/modules/search/lib/Drupal/search/Tests/SearchRankingTest.php +++ b/core/modules/search/lib/Drupal/search/Tests/SearchRankingTest.php @@ -106,12 +106,11 @@ function testRankings() { * Test rankings of HTML tags. */ function testHTMLRankings() { - $full_html_format = array( + $full_html_format = entity_create('filter_format', array( 'format' => 'full_html', 'name' => 'Full HTML', - ); - $full_html_format = (object) $full_html_format; - filter_format_save($full_html_format); + )); + $full_html_format->save(); // Login with sufficient privileges. $this->drupalLogin($this->drupalCreateUser(array('create page content'))); diff --git a/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php b/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php index 5813ffd..6bca9d6 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php @@ -74,8 +74,8 @@ function testEnableModulesLoad() { * Tests expected installation behavior of enableModules(). */ function testEnableModulesInstall() { - $module = 'filter'; - $table = 'filter'; + $module = 'node'; + $table = 'node'; // @todo Remove after configuration system conversion. $this->enableModules(array('system'), FALSE); diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php index 9efe0c3..b5989a6 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php @@ -29,12 +29,11 @@ public static function getInfo() { function setUp() { parent::setUp(); - $filtered_html_format = array( + $filtered_html_format = entity_create('filter_format', array( 'format' => 'filtered_html', 'name' => 'Filtered HTML', - ); - $filtered_html_format = (object) $filtered_html_format; - filter_format_save($filtered_html_format); + )); + $filtered_html_format->save(); $filtered_html_permission = filter_permission_name($filtered_html_format); user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array($filtered_html_permission)); diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php index 9c51a89..2a9f980 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php @@ -152,7 +152,8 @@ function testBreadCrumbs() { $this->assertBreadcrumb("admin/structure/types/manage/$type/fields/body/widget-type", $trail); // Verify Filter text format administration breadcrumbs. - $format = db_query_range("SELECT format, name FROM {filter_format}", 1, 1)->fetch(); + $filter_formats = filter_formats(); + $format = reset($filter_formats); $format_id = $format->format; $trail = $config + array( 'admin/config/content' => t('Content authoring'), diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FilterFormatUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FilterFormatUpgradePathTest.php new file mode 100644 index 0000000..1a42c7f --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FilterFormatUpgradePathTest.php @@ -0,0 +1,78 @@ + 'Filter Formats upgrade test', + 'description' => 'Upgrade tests with filter formats data.', + 'group' => 'Upgrade path', + ); + } + + public function setUp() { + $path = drupal_get_path('module', 'system'); + $this->databaseDumpFiles = array( + $path . '/tests/upgrade/drupal-7.bare.standard_all.database.php.gz', + $path . '/tests/upgrade/drupal-7.roles.database.php', + $path . '/tests/upgrade/drupal-7.filter_formats.database.php', + ); + parent::setUp(); + } + + /** + * Tests expected filter formats entities after a successful upgrade. + */ + public function testFilterFormatUpgrade() { + $this->assertTrue($this->performUpgrade(), 'The upgrade was completed successfully.'); + + // Checks that all the formats were upgraded + $one = filter_format_load('format_one'); + $this->assertTrue(!empty($one), 'Filter Format one was successfully upgraded'); + $two = filter_format_load('format_two'); + $this->assertTrue(!empty($two), 'Filter Format two was successfully upgraded'); + + // Filter format 'Three' is disabled, and filter_format_load should return + // FALSE. However the entity should be accessible using entity_load. + $three_disabled = filter_format_load('format_three'); + $three_entity = entity_load('filter_format', 'format_three'); + $this->assertTrue(empty($three_disabled) && !empty($three_entity), 'Filter Format three was successfully upgraded and it is disabled'); + + // Check the access to the text formats. + + // Check that the anonymous user role ID has been converted from "1" to + // "anonymous" and text formats permissions were updated. + $this->drupalGet('admin/people/permissions'); + $this->assertFieldChecked('edit-anonymous-use-text-format-format-one', 'Use text format format_one permission for "anonymous" is set correctly.'); + $this->assertNoFieldChecked('edit-anonymous-use-text-format-format-two', 'Use text format format_two permission for "anonymous" is set correctly.'); + + // Check that the anonymous user role ID has been converted from "2" to + // "authenticated" and text formats permissions were updated. + $this->assertNoFieldChecked('edit-authenticated-use-text-format-format-one', 'Use text format format_one permission for "authenticated" is set correctly.'); + $this->assertFieldChecked('edit-authenticated-use-text-format-format-two', 'Use text format format_two permission for "authenticated" is set correctly.'); + + // Check that the permission for "gärtner" still exists and text formats + // permissions were updated. + $this->assertFieldChecked('edit-4-use-text-format-format-one', 'Use text format format_one permission for role is set correctly.'); + $this->assertNoFieldChecked('edit-4-use-text-format-format-two', 'Use text format format_two permission for role is set correctly.'); + + // Check that role 5 cannot access to the defined text formats + $this->assertNoFieldChecked('edit-5-use-text-format-format-one', 'Use text format format_one permission for role is set correctly.'); + $this->assertNoFieldChecked('edit-5-use-text-format-format-two', 'Use text format format_two permission for role is set correctly.'); + } + +} diff --git a/core/modules/system/tests/upgrade/drupal-7.filter_formats.database.php b/core/modules/system/tests/upgrade/drupal-7.filter_formats.database.php new file mode 100644 index 0000000..402670c --- /dev/null +++ b/core/modules/system/tests/upgrade/drupal-7.filter_formats.database.php @@ -0,0 +1,174 @@ +fields(array( + 'format', + 'name', + 'cache', + 'status', + 'weight', +)) +// Adds some filters formats +->values(array( + 'format' => 'format_one', + 'name' => 'Format One', + 'cache' => '1', + 'weight' => '1', + 'status' => '1' +)) +->values(array( + 'format' => 'format_two', + 'name' => 'Format Two', + 'cache' => '1', + 'weight' => '2', + 'status' => '1' +)) +// Add a disabled filter format +->values(array( + 'format' => 'format_three', + 'name' => 'Format Three', + 'cache' => '1', + 'weight' => '3', + 'status' => '0' +)) +->execute(); + +// Adds filters to the crated filter formats +db_insert('filter')->fields(array( + 'format', + 'module', + 'name', + 'weight', + 'status', + 'settings', +)) +// Filters for: Format One +->values(array( + 'format' => 'format_one', + 'module' => 'filter', + 'name' => 'filter_autop', + 'weight' => '2', + 'status' => '1', + 'settings' => 'a:0:{}', +)) +->values(array( + 'format' => 'format_one', + 'module' => 'filter', + 'name' => 'filter_html', + 'weight' => '-10', + 'status' => '0', + 'settings' => 'a:3:{s:12:"allowed_html";s:74:"