diff --git a/core/modules/filter/filter.admin.inc b/core/modules/filter/filter.admin.inc index aa5bf4a..49cbe53 100644 --- a/core/modules/filter/filter.admin.inc +++ b/core/modules/filter/filter.admin.inc @@ -213,13 +213,7 @@ function filter_admin_format_form($form, &$form_state, $format) { foreach ($filter_info as $name => $filter) { // Create an empty filter object for new/unconfigured filters. if (!isset($filters[$name])) { - $filters[$name] = new stdClass(); - $filters[$name]->format = $format->format; - $filters[$name]->module = $filter['module']; - $filters[$name]->name = $name; - $filters[$name]->status = 0; - $filters[$name]->weight = $filter['weight']; - $filters[$name]->settings = array(); + $filters[$name] = $format->filterPlugins[$name]; } } $form['#filters'] = $filters; @@ -231,14 +225,14 @@ function filter_admin_format_form($form, &$form_state, $format) { '#prefix' => '
-
-
- ',
- 'filter_html_help' => 1,
- 'filter_html_nofollow' => 0,
- ),
- 'tips callback' => '_filter_html_tips',
- );
- $filters['filter_autop'] = array(
- 'title' => t('Convert line breaks'),
- 'description' => t('Converts line breaks into HTML (i.e. <br> and <p>) tags.'),
- 'process callback' => '_filter_autop',
- 'tips callback' => '_filter_autop_tips',
- );
- return $filters;
-}
-
-/**
* Perform alterations on filter definitions.
*
* @param $info
- * Array of information on filters exposed by hook_filter_info()
- * implementations.
+ * Array of information on filters exposed by filter plugins.
*/
function hook_filter_info_alter(&$info) {
- // Replace the PHP evaluator process callback with an improved
- // PHP evaluator provided by a module.
- $info['php_code']['process callback'] = 'my_module_php_evaluator';
-
// Alter the default settings of the URL filter provided by core.
- $info['filter_url']['default settings'] = array(
+ $info['filter_url']['default_settings'] = array(
'filter_url_length' => 100,
);
}
/**
- * @} End of "addtogroup hooks".
- */
-
-/**
- * Settings callback for hook_filter_info().
- *
- * Note: This is not really a hook. The function name is manually specified via
- * 'settings callback' in hook_filter_info(), with this recommended callback
- * name pattern. It is called from filter_admin_format_form().
- *
- * This callback function is used to provide a settings form for filter
- * settings, for filters that need settings on a per-text-format basis. This
- * function should return the form elements for the settings; the filter
- * module will take care of saving the settings in the database.
- *
- * If the filter's behavior depends on an extensive list and/or external data
- * (e.g. a list of smileys, a list of glossary terms), then the filter module
- * can choose to provide a separate, global configuration page rather than
- * per-text-format settings. In that case, the settings callback function
- * should provide a link to the separate settings page.
- *
- * @param $form
- * The prepopulated form array of the filter administration form.
- * @param $form_state
- * The state of the (entire) configuration form.
- * @param $filter
- * The filter object containing the current settings for the given format,
- * in $filter->settings.
- * @param $format
- * The format object being configured.
- * @param $defaults
- * The default settings for the filter, as defined in 'default settings' in
- * hook_filter_info(). These should be combined with $filter->settings to
- * define the form element defaults.
- * @param $filters
- * The complete list of filter objects that are enabled for the given format.
- *
- * @return
- * An array of form elements defining settings for the filter. Array keys
- * should match the array keys in $filter->settings and $defaults.
- */
-function hook_filter_FILTER_settings($form, &$form_state, $filter, $format, $defaults, $filters) {
- $filter->settings += $defaults;
-
- $elements = array();
- $elements['nofollow'] = array(
- '#type' => 'checkbox',
- '#title' => t('Add rel="nofollow" to all links'),
- '#default_value' => $filter->settings['nofollow'],
- );
- return $elements;
-}
-
-/**
- * Prepare callback for hook_filter_info().
- *
- * Note: This is not really a hook. The function name is manually specified via
- * 'prepare callback' in hook_filter_info(), with this recommended callback
- * name pattern. It is called from check_markup().
- *
- * See hook_filter_info() for a description of the filtering process. Filters
- * should not use the 'prepare callback' step for anything other than escaping,
- * because that would short-circuit the control the user has over the order in
- * which filters are applied.
- *
- * @param $text
- * The text string to be filtered.
- * @param $filter
- * The filter object containing settings for the given format.
- * @param $format
- * The text format object assigned to the text to be filtered.
- * @param $langcode
- * The language code of the text to be filtered.
- * @param $cache
- * A Boolean indicating whether the filtered text is going to be cached in
- * {cache_filter}.
- * @param $cache_id
- * The ID of the filtered text in {cache_filter}, if $cache is TRUE.
- *
- * @return
- * The prepared, escaped text.
- */
-function hook_filter_FILTER_prepare($text, $filter, $format, $langcode, $cache, $cache_id) {
- // Escape
and
tags.
- $text = preg_replace('|(.+?)
|se', "[codefilter_code]$1[/codefilter_code]", $text);
- return $text;
-}
-
-/**
- * Process callback for hook_filter_info().
- *
- * Note: This is not really a hook. The function name is manually specified via
- * 'process callback' in hook_filter_info(), with this recommended callback
- * name pattern. It is called from check_markup().
- *
- * See hook_filter_info() for a description of the filtering process. This step
- * is where the filter actually transforms the text.
- *
- * @param $text
- * The text string to be filtered.
- * @param $filter
- * The filter object containing settings for the given format.
- * @param $format
- * The text format object assigned to the text to be filtered.
- * @param $langcode
- * The language code of the text to be filtered.
- * @param $cache
- * A Boolean indicating whether the filtered text is going to be cached in
- * {cache_filter}.
- * @param $cache_id
- * The ID of the filtered text in {cache_filter}, if $cache is TRUE.
- *
- * @return
- * The filtered text.
- */
-function hook_filter_FILTER_process($text, $filter, $format, $langcode, $cache, $cache_id) {
- $text = preg_replace('|\[codefilter_code\](.+?)\[/codefilter_code\]|se', "$1
", $text);
-
- return $text;
-}
-
-/**
- * Tips callback for hook_filter_info().
- *
- * Note: This is not really a hook. The function name is manually specified via
- * 'tips callback' in hook_filter_info(), with this recommended callback
- * name pattern. It is called from _filter_tips().
- *
- * A filter's tips should be informative and to the point. Short tips are
- * preferably one-liners.
- *
- * @param $filter
- * An object representing the filter.
- * @param $format
- * An object representing the text format the filter is contained in.
- * @param $long
- * Whether this callback should return a short tip to display in a form
- * (FALSE), or whether a more elaborate filter tips should be returned for
- * theme_filter_tips() (TRUE).
- *
- * @return
- * Translated text to display as a tip.
- */
-function hook_filter_FILTER_tips($filter, $format, $long) {
- if ($long) {
- return t('Lines and paragraphs are automatically recognized. The <br /> line break, <p> paragraph and </p> close paragraph tags are inserted automatically. If paragraphs are not recognized simply add a couple blank lines.');
- }
- else {
- return t('Lines and paragraphs break automatically.');
- }
-}
-
-/**
- * @addtogroup hooks
- * @{
- */
-
-/**
* Perform actions when a new text format has been created.
*
* @param $format
diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module
index 9af423f..e2593b5 100644
--- a/core/modules/filter/filter.module
+++ b/core/modules/filter/filter.module
@@ -526,19 +526,11 @@ function filter_get_filter_types_by_format($format_id) {
$filter_types = array();
$filters = filter_list_format($format_id);
-
- // Ignore filters that are disabled.
- $filters = array_filter($filters, function($filter) {
- return $filter->status;
- });
-
- $filters_info = filter_get_filters();
- foreach ($filters as $filter) {
- if (!isset($filters_info[$filter->name]['type'])) {
- throw new Exception(t('Filter %filter has no type specified.', array ('%filter' => $filter->name)));
+ foreach ($filters as $filter_id => $filter) {
+ // Ignore filters that are disabled.
+ if ($filter->status) {
+ $filter_types[] = $filter->type;
}
-
- $filter_types[] = $filters_info[$filter->name]['type'];
}
return array_unique($filter_types);
@@ -598,56 +590,29 @@ function filter_get_filters() {
$filters = &drupal_static(__FUNCTION__, array());
if (empty($filters)) {
- foreach (module_implements('filter_info') as $module) {
- $info = module_invoke($module, 'filter_info');
- if (isset($info) && is_array($info)) {
- // Assign the name of the module implementing the filters and ensure
- // default values.
- foreach (array_keys($info) as $name) {
- $info[$name]['module'] = $module;
- $info[$name] += array(
- 'description' => '',
- 'weight' => 0,
- );
- }
- $filters = array_merge($filters, $info);
- }
- }
- // Allow modules to alter filter definitions.
- drupal_alter('filter_info', $filters);
-
- uasort($filters, '_filter_list_cmp');
+ $filters = drupal_container()->get('plugin.manager.filter')->getDefinitions();
}
return $filters;
}
/**
- * Sorts an array of filters by filter name.
- *
- * Callback for uasort() within filter_get_filters().
- */
-function _filter_list_cmp($a, $b) {
- return strcmp($a['title'], $b['title']);
-}
-
-/**
* Sorts an array of filters by filter status, weight, module, name.
*
* @see filter_list_format()
* @see Drupal\filter\Plugin\Core\Entity\FilterFormat::save()
*/
function _filter_format_filter_cmp($a, $b) {
- if ($a['status'] != $b['status']) {
- return !empty($a['status']) ? -1 : 1;
+ 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->weight != $b->weight) {
+ return ($a->weight < $b->weight) ? -1 : 1;
}
- elseif ($a['module'] != $b['module']) {
- return strcmp($a['module'], $b['module']);
+ elseif ($a->module != $b->module) {
+ return strcmp($a->module, $b->module);
}
- return strcmp($a['name'], $b['name']);
+ return strcmp($a->name, $b->name);
}
/**
@@ -687,10 +652,8 @@ function _filter_format_is_cacheable($format) {
if (empty($format->filters)) {
return TRUE;
}
- $filter_info = filter_get_filters();
- foreach ($format->filters as $name => $filter) {
- // By default, 'cache' is TRUE for all filters unless specified otherwise.
- if (!empty($filter['status']) && isset($filter_info[$name]['cache']) && !$filter_info[$name]['cache']) {
+ foreach ($format->filterPlugins as $name => $filter) {
+ if ($filter->status && !$filter->cache) {
return FALSE;
}
}
@@ -714,7 +677,6 @@ function _filter_format_is_cacheable($format) {
*/
function filter_list_format($format_id) {
$filters = &drupal_static(__FUNCTION__, array());
- $filter_info = filter_get_filters();
if (!isset($filters['all'])) {
if ($cache = cache()->get('filter_list_format')) {
@@ -723,40 +685,17 @@ function filter_list_format($format_id) {
else {
$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;
+ foreach ($filter_format->filterPlugins as $filter_name => $filter) {
+ $filters['all'][$filter_format->format][$filter_name] = $filter_format->filterPlugins[$filter_name];
}
@uasort($filters['all'][$filter_format->format], '_filter_format_filter_cmp');
- foreach ($filters['all'][$filter_format->format] as $filter_name => $filter) {
- // Before Conversion to CMI, filter were objects, now they are arrays.
- // Convert filters back to objects to reduce the impact of changes.
- // @todo Follow-up: filters should be arrays instead of objects.
- $filters['all'][$filter_format->format][$filter_name] = (object)$filter;
- }
}
cache()->set('filter_list_format', $filters['all']);
}
}
- if (!isset($filters[$format_id])) {
- $format_filters = array();
- $filter_map = isset($filters['all'][$format_id]) ? $filters['all'][$format_id] : array();
- foreach ($filter_map as $name => $filter) {
- if (isset($filter_info[$name])) {
- $filter->title = $filter_info[$name]['title'];
-
- $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'];
- }
-
- $format_filters[$name] = $filter;
- }
- }
- $filters[$format_id] = $format_filters;
+ if (!isset($filters[$format_id]) && isset($filters['all'][$format_id])) {
+ $filters[$format_id] = $filters['all'][$format_id];
}
return isset($filters[$format_id]) ? $filters[$format_id] : array();
@@ -831,29 +770,26 @@ function check_markup($text, $format_id = NULL, $langcode = '', $cache = FALSE,
// Get a complete list of filters, ordered properly.
$filters = filter_list_format($format->format);
- $filter_info = filter_get_filters();
// Give filters the chance to escape HTML-like data such as code or formulas.
foreach ($filters as $name => $filter) {
// If necessary, skip filters of a certain type.
- if (in_array($filter_info[$name]['type'], $filter_types_to_skip)) {
+ if (in_array($filter->type, $filter_types_to_skip)) {
continue;
}
- if ($filter->status && isset($filter_info[$name]['prepare callback'])) {
- $function = $filter_info[$name]['prepare callback'];
- $text = $function($text, $filter, $format, $langcode, $cache, $cache_id);
+ if ($filter->status) {
+ $text = $filter->prepare($text, $filter, $format, $langcode, $cache, $cache_id);
}
}
// Perform filtering.
foreach ($filters as $name => $filter) {
// If necessary, skip filters of a certain type.
- if (in_array($filter_info[$name]['type'], $filter_types_to_skip)) {
+ if (in_array($filter->type, $filter_types_to_skip)) {
continue;
}
- if ($filter->status && isset($filter_info[$name]['process callback'])) {
- $function = $filter_info[$name]['process callback'];
- $text = $function($text, $filter, $format, $langcode, $cache, $cache_id);
+ if ($filter->status) {
+ $text = $filter->process($text, $filter, $format, $langcode, $cache, $cache_id);
}
}
@@ -1112,7 +1048,6 @@ function _filter_tips($format_id, $long = FALSE) {
global $user;
$formats = filter_formats($user);
- $filter_info = filter_get_filters();
$tips = array();
@@ -1123,10 +1058,9 @@ function _filter_tips($format_id, $long = FALSE) {
foreach ($formats as $format) {
$filters = filter_list_format($format->format);
- $tips[$format->name] = array();
foreach ($filters as $name => $filter) {
- if ($filter->status && isset($filter_info[$name]['tips callback'])) {
- $tip = $filter_info[$name]['tips callback']($filter, $format, $long);
+ if ($filter->status) {
+ $tip = $filter->tips($filter, $format, $long);
if (isset($tip)) {
$tips[$format->name][$name] = array('tip' => $tip, 'id' => $name);
}
@@ -1268,93 +1202,6 @@ function theme_filter_guidelines($variables) {
*/
/**
- * Implements hook_filter_info().
- */
-function filter_filter_info() {
- $filters['filter_html'] = array(
- 'title' => t('Limit allowed HTML tags'),
- 'type' => FILTER_TYPE_HTML_RESTRICTOR,
- 'process callback' => '_filter_html',
- 'settings callback' => '_filter_html_settings',
- 'default settings' => array(
- 'allowed_html' => ' -
-
-
',
- 'filter_html_help' => 1,
- 'filter_html_nofollow' => 0,
- ),
- 'tips callback' => '_filter_html_tips',
- 'weight' => -10,
- );
- $filters['filter_autop'] = array(
- 'title' => t('Convert line breaks into HTML (i.e. <br>
and <p>
)'),
- 'type' => FILTER_TYPE_MARKUP_LANGUAGE,
- 'process callback' => '_filter_autop',
- 'tips callback' => '_filter_autop_tips',
- );
- $filters['filter_url'] = array(
- 'title' => t('Convert URLs into links'),
- 'type' => FILTER_TYPE_MARKUP_LANGUAGE,
- 'process callback' => '_filter_url',
- 'settings callback' => '_filter_url_settings',
- 'default settings' => array(
- 'filter_url_length' => 72,
- ),
- 'tips callback' => '_filter_url_tips',
- );
- $filters['filter_html_image_secure'] = array(
- 'title' => t('Restrict images to this site'),
- 'type' => FILTER_TYPE_HTML_RESTRICTOR,
- 'description' => t('Disallows usage of <img> tag sources that are not hosted on this site by replacing them with a placeholder image.'),
- 'process callback' => '_filter_html_image_secure_process',
- 'tips callback' => '_filter_html_image_secure_tips',
- // Supposed to run after other filters and before HTML corrector by default.
- 'weight' => 9,
- );
- $filters['filter_htmlcorrector'] = array(
- 'title' => t('Correct faulty and chopped off HTML'),
- 'type' => FILTER_TYPE_HTML_RESTRICTOR,
- 'process callback' => '_filter_htmlcorrector',
- 'weight' => 10,
- );
- $filters['filter_html_escape'] = array(
- 'title' => t('Display any HTML as plain text'),
- 'type' => FILTER_TYPE_HTML_RESTRICTOR,
- 'process callback' => '_filter_html_escape',
- 'tips callback' => '_filter_html_escape_tips',
- 'weight' => -10,
- );
- return $filters;
-}
-
-/**
- * Filter settings callback for the HTML content filter.
- *
- * See hook_filter_FILTER_settings() for documentation of parameters and return
- * value.
- */
-function _filter_html_settings($form, &$form_state, $filter, $format, $defaults) {
- $filter->settings += $defaults;
-
- $settings['allowed_html'] = array(
- '#type' => 'textfield',
- '#title' => t('Allowed HTML tags'),
- '#default_value' => $filter->settings['allowed_html'],
- '#maxlength' => 1024,
- '#description' => t('A list of HTML tags that can be used. JavaScript event attributes, JavaScript URLs, and CSS are always stripped.'),
- );
- $settings['filter_html_help'] = array(
- '#type' => 'checkbox',
- '#title' => t('Display basic HTML help in long filter tips'),
- '#default_value' => $filter->settings['filter_html_help'],
- );
- $settings['filter_html_nofollow'] = array(
- '#type' => 'checkbox',
- '#title' => t('Add rel="nofollow" to all links'),
- '#default_value' => $filter->settings['filter_html_nofollow'],
- );
- return $settings;
-}
-
-/**
* Provides filtering of input into accepted HTML.
*/
function _filter_html($text, $filter) {
@@ -1374,125 +1221,6 @@ function _filter_html($text, $filter) {
}
/**
- * Filter tips callback: Provides help for the HTML filter.
- *
- * @see filter_filter_info()
- */
-function _filter_html_tips($filter, $format, $long = FALSE) {
- global $base_url;
-
- if (!($allowed_html = $filter->settings['allowed_html'])) {
- return;
- }
- $output = t('Allowed HTML tags: @tags', array('@tags' => $allowed_html));
- if (!$long) {
- return $output;
- }
-
- $output = '
' . $output . '
';
- if (!$filter->settings['filter_html_help']) {
- return $output;
- }
-
- $output .= '' . t('This site allows HTML content. While learning all of HTML may feel intimidating, learning how to use a very small number of the most basic HTML "tags" is very easy. This table provides examples for each tag that is enabled on this site.') . '
';
- $output .= '' . t('For more information see W3C\'s HTML Specifications or use your favorite search engine to find other sites that explain HTML.', array('@html-specifications' => 'http://www.w3.org/TR/html/')) . '
';
- $tips = array(
- 'a' => array(t('Anchors are used to make links to other pages.'), '' . check_plain(config('system.site')->get('name')) . ''),
- 'br' => array(t('By default line break tags are automatically added, so use this tag to add additional ones. Use of this tag is different because it is not used with an open/close pair like all the others. Use the extra " /" inside the tag to maintain XHTML 1.0 compatibility'), t('Text with
line break')),
- 'p' => array(t('By default paragraph tags are automatically added, so use this tag to add additional ones.'), '' . t('Paragraph one.') . '
' . t('Paragraph two.') . '
'),
- 'strong' => array(t('Strong', array(), array('context' => 'Font weight')), '' . t('Strong', array(), array('context' => 'Font weight')) . ''),
- 'em' => array(t('Emphasized'), '' . t('Emphasized') . ''),
- 'cite' => array(t('Cited'), '' . t('Cited') . ''),
- 'code' => array(t('Coded text used to show programming source code'), '' . t('Coded') . '
'),
- 'b' => array(t('Bolded'), '' . t('Bolded') . ''),
- 'u' => array(t('Underlined'), '' . t('Underlined') . ''),
- 'i' => array(t('Italicized'), '' . t('Italicized') . ''),
- 'sup' => array(t('Superscripted'), t('Superscripted')),
- 'sub' => array(t('Subscripted'), t('Subscripted')),
- 'pre' => array(t('Preformatted'), '' . t('Preformatted') . '
'),
- 'abbr' => array(t('Abbreviation'), t('Abbrev.')),
- 'acronym' => array(t('Acronym'), t('TLA')),
- 'blockquote' => array(t('Block quoted'), '' . t('Block quoted') . '
'),
- 'q' => array(t('Quoted inline'), '' . t('Quoted inline') . '
'),
- // Assumes and describes tr, td, th.
- 'table' => array(t('Table'), ' ' . t('Table header') . ' ' . t('Table cell') . '
'),
- 'tr' => NULL, 'td' => NULL, 'th' => NULL,
- 'del' => array(t('Deleted'), '' . t('Deleted') . ''),
- 'ins' => array(t('Inserted'), '' . t('Inserted') . ''),
- // Assumes and describes li.
- 'ol' => array(t('Ordered list - use the <li> to begin each list item'), ' - ' . t('First item') . '
- ' . t('Second item') . '
'),
- 'ul' => array(t('Unordered list - use the <li> to begin each list item'), ' - ' . t('First item') . '
- ' . t('Second item') . '
'),
- 'li' => NULL,
- // Assumes and describes dt and dd.
- 'dl' => array(t('Definition lists are similar to other HTML lists. <dl> begins the definition list, <dt> begins the definition term and <dd> begins the definition description.'), ' - ' . t('First term') . '
- ' . t('First definition') . '
- ' . t('Second term') . '
- ' . t('Second definition') . '
'),
- 'dt' => NULL, 'dd' => NULL,
- 'h1' => array(t('Heading'), '' . t('Title') . '
'),
- 'h2' => array(t('Heading'), '' . t('Subtitle') . '
'),
- 'h3' => array(t('Heading'), '' . t('Subtitle three') . '
'),
- 'h4' => array(t('Heading'), '' . t('Subtitle four') . '
'),
- 'h5' => array(t('Heading'), '' . t('Subtitle five') . '
'),
- 'h6' => array(t('Heading'), '' . t('Subtitle six') . '
')
- );
- $header = array(t('Tag Description'), t('You Type'), t('You Get'));
- preg_match_all('/<([a-z0-9]+)[^a-z0-9]/i', $allowed_html, $out);
- foreach ($out[1] as $tag) {
- if (!empty($tips[$tag])) {
- $rows[] = array(
- array('data' => $tips[$tag][0], 'class' => array('description')),
- array('data' => '' . check_plain($tips[$tag][1]) . '
', 'class' => array('type')),
- array('data' => $tips[$tag][1], 'class' => array('get'))
- );
- }
- else {
- $rows[] = array(
- array('data' => t('No help provided for tag %tag.', array('%tag' => $tag)), 'class' => array('description'), 'colspan' => 3),
- );
- }
- }
- $output .= theme('table', array('header' => $header, 'rows' => $rows));
-
- $output .= '' . t('Most unusual characters can be directly entered without any problems.') . '
';
- $output .= '' . t('If you do encounter problems, try using HTML character entities. A common example looks like & for an ampersand & character. For a full list of entities see HTML\'s entities page. Some of the available characters include:', array('@html-entities' => 'http://www.w3.org/TR/html4/sgml/entities.html')) . '
';
-
- $entities = array(
- array(t('Ampersand'), '&'),
- array(t('Greater than'), '>'),
- array(t('Less than'), '<'),
- array(t('Quotation mark'), '"'),
- );
- $header = array(t('Character Description'), t('You Type'), t('You Get'));
- unset($rows);
- foreach ($entities as $entity) {
- $rows[] = array(
- array('data' => $entity[0], 'class' => array('description')),
- array('data' => '' . check_plain($entity[1]) . '
', 'class' => array('type')),
- array('data' => $entity[1], 'class' => array('get'))
- );
- }
- $output .= theme('table', array('header' => $header, 'rows' => $rows));
- return $output;
-}
-
-/**
- * Filter URL settings callback: Provides settings for the URL filter.
- *
- * @see filter_filter_info()
- */
-function _filter_url_settings($form, &$form_state, $filter, $format, $defaults) {
- $filter->settings += $defaults;
-
- $settings['filter_url_length'] = array(
- '#type' => 'number',
- '#title' => t('Maximum link text length'),
- '#default_value' => $filter->settings['filter_url_length'],
- '#min' => 1,
- '#field_suffix' => t('characters'),
- '#description' => t('URLs longer than this number of characters will be truncated to prevent long strings that break formatting. The link itself will be retained; just the text portion of the link will be truncated.'),
- );
- return $settings;
-}
-
-/**
* Converts text into hyperlinks automatically.
*
* This filter identifies and makes clickable three types of "links".
@@ -1718,15 +1446,6 @@ function _filter_url_trim($text, $length = NULL) {
}
/**
- * Filter tips callback: Provides help for the URL filter.
- *
- * @see filter_filter_info()
- */
-function _filter_url_tips($filter, $format, $long = FALSE) {
- return t('Web page addresses and e-mail addresses turn into links automatically.');
-}
-
-/**
* Scans the input and makes sure that HTML tags are properly closed.
*/
function _filter_htmlcorrector($text) {
@@ -1801,20 +1520,6 @@ function _filter_autop($text) {
}
/**
- * Filter tips callback: Provides help for the auto-paragraph filter.
- *
- * @see filter_filter_info()
- */
-function _filter_autop_tips($filter, $format, $long = FALSE) {
- if ($long) {
- return t('Lines and paragraphs are automatically recognized. The <br /> line break, <p> paragraph and </p> close paragraph tags are inserted automatically. If paragraphs are not recognized simply add a couple blank lines.');
- }
- else {
- return t('Lines and paragraphs break automatically.');
- }
-}
-
-/**
* Escapes all HTML tags, so they will be visible instead of being effective.
*/
function _filter_html_escape($text) {
@@ -1822,15 +1527,6 @@ function _filter_html_escape($text) {
}
/**
- * Filter tips callback: Provides help for the HTML escaping filter.
- *
- * @see filter_filter_info()
- */
-function _filter_html_escape_tips($filter, $format, $long = FALSE) {
- return t('No HTML tags allowed.');
-}
-
-/**
* Process callback for local image filter.
*/
function _filter_html_image_secure_process($text) {
@@ -1896,13 +1592,6 @@ function theme_filter_html_image_secure_image(&$variables) {
}
/**
- * Filter tips callback for secure HTML image filter.
- */
-function _filter_html_image_secure_tips($filter, $format, $long = FALSE) {
- return t('Only images hosted on this site may be used in <img> tags.');
-}
-
-/**
* @} End of "defgroup standard_filters".
*/
diff --git a/core/modules/filter/lib/Drupal/filter/FilterBundle.php b/core/modules/filter/lib/Drupal/filter/FilterBundle.php
new file mode 100644
index 0000000..a882ad4
--- /dev/null
+++ b/core/modules/filter/lib/Drupal/filter/FilterBundle.php
@@ -0,0 +1,25 @@
+register('plugin.manager.filter', 'Drupal\filter\FilterManager');
+ }
+
+}
diff --git a/core/modules/filter/lib/Drupal/filter/FilterManager.php b/core/modules/filter/lib/Drupal/filter/FilterManager.php
new file mode 100644
index 0000000..24d9cb1
--- /dev/null
+++ b/core/modules/filter/lib/Drupal/filter/FilterManager.php
@@ -0,0 +1,127 @@
+ FALSE while developing, but be sure to remove that
+ * setting if it's not needed, when you are no longer in development mode.
+ *
+ * @return
+ * An associative array of filters, whose keys are internal filter names,
+ * which should be unique and therefore prefixed with the name of the module.
+ * Each value is an associative array describing the filter, with the
+ * following elements (all are optional except as noted):
+ * - title: (required) An administrative summary of what the filter does.
+ * - description: Additional administrative information about the filter's
+ * behavior, if needed for clarification.
+ * - default settings: An associative array containing default settings for
+ * the filter, to be applied when the filter has not been configured yet.
+ * - prepare callback: The name of a function that escapes the content before
+ * the actual filtering happens. See hook_filter_FILTER_prepare() for
+ * details.
+ * - cache (default TRUE): Specifies whether the filtered text can be cached.
+ * Note that setting this to FALSE makes the entire text format not
+ * cacheable, which may have an impact on the site's overall performance.
+ * See filter_format_allowcache() for details.
+ * - weight: A default weight for the filter in new text formats.
+ *
+ * @see filter_example.module
+ * @see hook_filter_info_alter()
+ */
+class FilterManager extends PluginManagerBase {
+
+ /**
+ * Constructs a FilterManager object.
+ */
+ public function __construct() {
+ $this->discovery = new AnnotatedClassDiscovery('filter', 'filter');
+ $this->discovery = new AlterDecorator($this->discovery, 'filter_info');
+ $this->discovery = new ProcessDecorator($this->discovery, array($this, 'processDefinition'));
+
+ $this->factory = new DefaultFactory($this->discovery);
+
+ $this->defaults += array(
+ 'description' => '',
+ 'default_settings' => array(),
+ 'weight' => 0,
+ 'status' => FALSE,
+ 'cache' => TRUE,
+ 'settings' => array(),
+ );
+ }
+
+ /**
+ * Overrides \Drupal\Component\Plugin\PluginManagerBase::getDefinitions().
+ */
+ public function getDefinitions() {
+ $definitions = parent::getDefinitions();
+ uasort($definitions, function($a, $b) {
+ return strcmp($a['title'], $b['title']);
+ });
+ return $definitions;
+ }
+
+ /**
+ * Overrides \Drupal\Component\Plugin\PluginManagerBase::processDefinition().
+ */
+ public function processDefinition(&$definition, $plugin_id) {
+ parent::processDefinition($definition, $plugin_id);
+
+ // @todo Remove this check once http://drupal.org/node/1780396 is resolved.
+ if (!module_exists($definition['module'])) {
+ $definition = NULL;
+ return;
+ }
+
+ if (!isset($definition['type'])) {
+ throw new \Exception(t('Filter %filter has no type specified.', array ('%filter' => $definition['title'])));
+ }
+ }
+
+}
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 d917142..7905105 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
@@ -10,6 +10,7 @@
use Drupal\Core\Config\Entity\ConfigEntityBase;
use Drupal\Core\Annotation\Plugin;
use Drupal\Core\Annotation\Translation;
+use Drupal\filter\Plugin\FilterBag;
/**
* Defines the Filter Format entity.
@@ -84,6 +85,14 @@ class FilterFormat extends ConfigEntityBase {
*/
public $filters = array();
+ public $filterPlugins = array();
+
+ public function __construct(array $values, $entity_type) {
+ parent::__construct($values, $entity_type);
+
+ $this->filterPlugins = new FilterBag($this, drupal_container()->get('plugin.manager.filter'));
+ }
+
/**
* Implements Drupal\Core\Entity\EntityInterface::id().
*/
@@ -108,7 +117,12 @@ public function save() {
if (!isset($this->filters)) {
$this->filters = array();
}
+
+ // Clear out any instances to ensure they are rebuilt.
+ $this->filterPlugins->clear();
+
$filter_info = filter_get_filters();
+ $this->filters = array_intersect_key($this->filters, $filter_info);
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
@@ -121,13 +135,11 @@ public function save() {
// If settings were passed, only ensure default settings.
if (isset($this->filters[$name]['settings'])) {
- if (isset($filter['default settings'])) {
- $this->filters[$name]['settings'] = array_merge($filter['default settings'], $this->filters[$name]['settings']);
- }
+ $this->filters[$name]['settings'] = array_merge($filter['default_settings'], $this->filters[$name]['settings']);
}
// Otherwise, use default settings or fall back to an empty array.
else {
- $this->filters[$name]['settings'] = isset($filter['default settings']) ? $filter['default settings'] : array();
+ $this->filters[$name]['settings'] = $filter['default_settings'];
}
// Sort filters properties by key, to minimize diff issues.
@@ -157,4 +169,14 @@ public function save() {
return $return;
}
+
+ /**
+ * Overrides \Drupal\Core\Config\Entity\ConfigEntityBase::getExportProperties();
+ */
+ public function getExportProperties() {
+ $properties = parent::getExportProperties();
+ unset($properties['filterPlugins']);
+ return $properties;
+ }
+
}
diff --git a/core/modules/filter/lib/Drupal/filter/Plugin/FilterBag.php b/core/modules/filter/lib/Drupal/filter/Plugin/FilterBag.php
new file mode 100644
index 0000000..4fd4da2
--- /dev/null
+++ b/core/modules/filter/lib/Drupal/filter/Plugin/FilterBag.php
@@ -0,0 +1,67 @@
+format = $format;
+ $this->manager = $manager;
+ $this->instanceIDs = drupal_map_assoc(array_keys(array_filter($manager->getDefinitions(), function ($filter) {
+ return isset($filter['module']) && module_exists($filter['module']);
+ })));
+ }
+
+ /**
+ * Overrides \Drupal\Component\Plugin\PluginBag::initializePlugin().
+ */
+ protected function initializePlugin($instance_id) {
+ // If the display was initialized before, just return.
+ if (isset($this->pluginInstances[$instance_id])) {
+ return;
+ }
+
+ if (isset($this->instanceIDs[$instance_id])) {
+ $filter = array();
+ if (isset($this->format->filters[$instance_id])) {
+ $filter = $this->format->filters[$instance_id];
+ }
+ $this->pluginInstances[$instance_id] = $this->manager->createInstance($instance_id, $filter);
+ }
+ }
+
+}
diff --git a/core/modules/filter/lib/Drupal/filter/Plugin/filter/filter/FilterAutoP.php b/core/modules/filter/lib/Drupal/filter/Plugin/filter/filter/FilterAutoP.php
new file mode 100644
index 0000000..81c6276
--- /dev/null
+++ b/core/modules/filter/lib/Drupal/filter/Plugin/filter/filter/FilterAutoP.php
@@ -0,0 +1,46 @@
+<br>
and <p>
)"),
+ * type = FILTER_TYPE_MARKUP_LANGUAGE
+ * )
+ */
+class FilterAutoP extends FilterBase {
+
+ /**
+ * Overrides \Drupal\filter\Plugin\filter\filter\Plugin\filter\filter\FilterBase::tips().
+ */
+ public function tips($filter, FilterFormat $format, $long = FALSE) {
+ if ($long) {
+ return t('Lines and paragraphs are automatically recognized. The <br /> line break, <p> paragraph and </p> close paragraph tags are inserted automatically. If paragraphs are not recognized simply add a couple blank lines.');
+ }
+ else {
+ return t('Lines and paragraphs break automatically.');
+ }
+ }
+
+ /**
+ * Implements \Drupal\filter\Plugin\filter\filter\Plugin\filter\filter\FilterInterface::process().
+ */
+ public function process($text, $filter, FilterFormat $format, $langcode, $cache, $cache_id) {
+ return _filter_autop($text);
+ }
+
+}
diff --git a/core/modules/filter/lib/Drupal/filter/Plugin/filter/filter/FilterBase.php b/core/modules/filter/lib/Drupal/filter/Plugin/filter/filter/FilterBase.php
new file mode 100644
index 0000000..32ea774
--- /dev/null
+++ b/core/modules/filter/lib/Drupal/filter/Plugin/filter/filter/FilterBase.php
@@ -0,0 +1,76 @@
+definition = $configuration + $this->getDefinition();
+ $this->settings += $this->default_settings;
+ }
+
+ /**
+ * @todo.
+ */
+ public function __get($key) {
+ if (isset($this->definition[$key])) {
+ return $this->definition[$key];
+ }
+ }
+
+ public function __isset($key) {
+ return isset($this->definition[$key]);
+ }
+
+ /**
+ * @todo.
+ */
+ public function __set($key, $value) {
+ $this->definition[$key] = $value;
+ }
+
+ /**
+ * Implements \Drupal\filter\Plugin\filter\filter\Plugin\filter\filter\FilterInterface::tips().
+ */
+ public function tips($filter, FilterFormat $format, $long = FALSE) {
+ }
+
+ /**
+ * Implements \Drupal\filter\Plugin\filter\filter\Plugin\filter\filter\FilterInterface::settings().
+ */
+ public function settings(array $form, array &$form_state, FilterFormat $format) {
+ return array();
+ }
+
+ /**
+ * Implements \Drupal\filter\Plugin\filter\filter\Plugin\filter\filter\FilterInterface::prepare().
+ */
+ public function prepare($text, $filter, FilterFormat $format, $langcode, $cache, $cache_id) {
+ return $text;
+ }
+
+}
diff --git a/core/modules/filter/lib/Drupal/filter/Plugin/filter/filter/FilterHtml.php b/core/modules/filter/lib/Drupal/filter/Plugin/filter/filter/FilterHtml.php
new file mode 100644
index 0000000..0369893
--- /dev/null
+++ b/core/modules/filter/lib/Drupal/filter/Plugin/filter/filter/FilterHtml.php
@@ -0,0 +1,162 @@
+ -
-
-
",
+ * "filter_html_help" = 1,
+ * "filter_html_nofollow" = 0
+ * },
+ * weight = -10
+ * )
+ */
+class FilterHtml extends FilterBase {
+
+ /**
+ * Overrides \Drupal\filter\Plugin\filter\filter\Plugin\filter\filter\FilterBase::tips().
+ */
+ public function tips($filter, FilterFormat $format, $long = FALSE) {
+ global $base_url;
+
+ if (!($allowed_html = $filter->settings['allowed_html'])) {
+ return;
+ }
+ $output = t('Allowed HTML tags: @tags', array('@tags' => $allowed_html));
+ if (!$long) {
+ return $output;
+ }
+
+ $output = '
' . $output . '
';
+ if (!$filter->settings['filter_html_help']) {
+ return $output;
+ }
+
+ $output .= '' . t('This site allows HTML content. While learning all of HTML may feel intimidating, learning how to use a very small number of the most basic HTML "tags" is very easy. This table provides examples for each tag that is enabled on this site.') . '
';
+ $output .= '' . t('For more information see W3C\'s HTML Specifications or use your favorite search engine to find other sites that explain HTML.', array('@html-specifications' => 'http://www.w3.org/TR/html/')) . '
';
+ $tips = array(
+ 'a' => array(t('Anchors are used to make links to other pages.'), '' . check_plain(config('system.site')->get('name')) . ''),
+ 'br' => array(t('By default line break tags are automatically added, so use this tag to add additional ones. Use of this tag is different because it is not used with an open/close pair like all the others. Use the extra " /" inside the tag to maintain XHTML 1.0 compatibility'), t('Text with
line break')),
+ 'p' => array(t('By default paragraph tags are automatically added, so use this tag to add additional ones.'), '' . t('Paragraph one.') . '
' . t('Paragraph two.') . '
'),
+ 'strong' => array(t('Strong', array(), array('context' => 'Font weight')), '' . t('Strong', array(), array('context' => 'Font weight')) . ''),
+ 'em' => array(t('Emphasized'), '' . t('Emphasized') . ''),
+ 'cite' => array(t('Cited'), '' . t('Cited') . ''),
+ 'code' => array(t('Coded text used to show programming source code'), '' . t('Coded') . '
'),
+ 'b' => array(t('Bolded'), '' . t('Bolded') . ''),
+ 'u' => array(t('Underlined'), '' . t('Underlined') . ''),
+ 'i' => array(t('Italicized'), '' . t('Italicized') . ''),
+ 'sup' => array(t('Superscripted'), t('Superscripted')),
+ 'sub' => array(t('Subscripted'), t('Subscripted')),
+ 'pre' => array(t('Preformatted'), '' . t('Preformatted') . '
'),
+ 'abbr' => array(t('Abbreviation'), t('Abbrev.')),
+ 'acronym' => array(t('Acronym'), t('TLA')),
+ 'blockquote' => array(t('Block quoted'), '' . t('Block quoted') . '
'),
+ 'q' => array(t('Quoted inline'), '' . t('Quoted inline') . '
'),
+ // Assumes and describes tr, td, th.
+ 'table' => array(t('Table'), ' ' . t('Table header') . ' ' . t('Table cell') . '
'),
+ 'tr' => NULL, 'td' => NULL, 'th' => NULL,
+ 'del' => array(t('Deleted'), '' . t('Deleted') . ''),
+ 'ins' => array(t('Inserted'), '' . t('Inserted') . ''),
+ // Assumes and describes li.
+ 'ol' => array(t('Ordered list - use the <li> to begin each list item'), ' - ' . t('First item') . '
- ' . t('Second item') . '
'),
+ 'ul' => array(t('Unordered list - use the <li> to begin each list item'), ' - ' . t('First item') . '
- ' . t('Second item') . '
'),
+ 'li' => NULL,
+ // Assumes and describes dt and dd.
+ 'dl' => array(t('Definition lists are similar to other HTML lists. <dl> begins the definition list, <dt> begins the definition term and <dd> begins the definition description.'), ' - ' . t('First term') . '
- ' . t('First definition') . '
- ' . t('Second term') . '
- ' . t('Second definition') . '
'),
+ 'dt' => NULL, 'dd' => NULL,
+ 'h1' => array(t('Heading'), '' . t('Title') . '
'),
+ 'h2' => array(t('Heading'), '' . t('Subtitle') . '
'),
+ 'h3' => array(t('Heading'), '' . t('Subtitle three') . '
'),
+ 'h4' => array(t('Heading'), '' . t('Subtitle four') . '
'),
+ 'h5' => array(t('Heading'), '' . t('Subtitle five') . '
'),
+ 'h6' => array(t('Heading'), '' . t('Subtitle six') . '
')
+ );
+ $header = array(t('Tag Description'), t('You Type'), t('You Get'));
+ preg_match_all('/<([a-z0-9]+)[^a-z0-9]/i', $allowed_html, $out);
+ foreach ($out[1] as $tag) {
+ if (!empty($tips[$tag])) {
+ $rows[] = array(
+ array('data' => $tips[$tag][0], 'class' => array('description')),
+ array('data' => '' . check_plain($tips[$tag][1]) . '
', 'class' => array('type')),
+ array('data' => $tips[$tag][1], 'class' => array('get'))
+ );
+ }
+ else {
+ $rows[] = array(
+ array('data' => t('No help provided for tag %tag.', array('%tag' => $tag)), 'class' => array('description'), 'colspan' => 3),
+ );
+ }
+ }
+ $output .= theme('table', array('header' => $header, 'rows' => $rows));
+
+ $output .= '' . t('Most unusual characters can be directly entered without any problems.') . '
';
+ $output .= '' . t('If you do encounter problems, try using HTML character entities. A common example looks like & for an ampersand & character. For a full list of entities see HTML\'s entities page. Some of the available characters include:', array('@html-entities' => 'http://www.w3.org/TR/html4/sgml/entities.html')) . '
';
+
+ $entities = array(
+ array(t('Ampersand'), '&'),
+ array(t('Greater than'), '>'),
+ array(t('Less than'), '<'),
+ array(t('Quotation mark'), '"'),
+ );
+ $header = array(t('Character Description'), t('You Type'), t('You Get'));
+ unset($rows);
+ foreach ($entities as $entity) {
+ $rows[] = array(
+ array('data' => $entity[0], 'class' => array('description')),
+ array('data' => '' . check_plain($entity[1]) . '
', 'class' => array('type')),
+ array('data' => $entity[1], 'class' => array('get'))
+ );
+ }
+ $output .= theme('table', array('header' => $header, 'rows' => $rows));
+ return $output;
+ }
+
+ /**
+ * Overrides \Drupal\filter\Plugin\filter\filter\Plugin\filter\filter\FilterBase::settings().
+ */
+ public function settings(array $form, array &$form_state, FilterFormat $format) {
+ $settings['allowed_html'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Allowed HTML tags'),
+ '#default_value' => $this->settings['allowed_html'],
+ '#maxlength' => 1024,
+ '#description' => t('A list of HTML tags that can be used. JavaScript event attributes, JavaScript URLs, and CSS are always stripped.'),
+ );
+ $settings['filter_html_help'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Display basic HTML help in long filter tips'),
+ '#default_value' => $this->settings['filter_html_help'],
+ );
+ $settings['filter_html_nofollow'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Add rel="nofollow" to all links'),
+ '#default_value' => $this->settings['filter_html_nofollow'],
+ );
+ return $settings;
+ }
+
+ /**
+ * Implements \Drupal\filter\Plugin\filter\filter\Plugin\filter\filter\FilterInterface::process().
+ */
+ public function process($text, $filter, FilterFormat $format, $langcode, $cache, $cache_id) {
+ return _filter_html($text, $filter);
+ }
+
+}
diff --git a/core/modules/filter/lib/Drupal/filter/Plugin/filter/filter/FilterHtmlCorrector.php b/core/modules/filter/lib/Drupal/filter/Plugin/filter/filter/FilterHtmlCorrector.php
new file mode 100644
index 0000000..0dd9688
--- /dev/null
+++ b/core/modules/filter/lib/Drupal/filter/Plugin/filter/filter/FilterHtmlCorrector.php
@@ -0,0 +1,35 @@
+settings and $defaults.
+ */
+ public function settings(array $form, array &$form_state, FilterFormat $format);
+
+ /**
+ * Prepares the text for processing.
+ *
+ * Filters should not use the prepare method for anything other than escaping,
+ * because that would short-circuit the control the user has over the order in
+ * which filters are applied.
+ *
+ * @param string $text
+ * The text string to be filtered.
+ * @param \stdClass $filter
+ * The filter object containing settings for the given format.
+ * @param \Drupal\filter\Plugin\Core\Entity\FilterFormat $format
+ * The text format object assigned to the text to be filtered.
+ * @param string $langcode
+ * The language code of the text to be filtered.
+ * @param bool $cache
+ * A Boolean indicating whether the filtered text is going to be cached in
+ * {cache_filter}.
+ * @param string $cache_id
+ * The ID of the filtered text in {cache_filter}, if $cache is TRUE.
+ *
+ * @return string
+ * The prepared, escaped text.
+ */
+ public function prepare($text, $filter, FilterFormat $format, $langcode, $cache, $cache_id);
+
+ /**
+ * Performs the filter processing.
+ *
+ * @param string $text
+ * The text string to be filtered.
+ * @param \stdClass $filter
+ * The filter object containing settings for the given format.
+ * @param \Drupal\filter\Plugin\Core\Entity\FilterFormat $format
+ * The text format object assigned to the text to be filtered.
+ * @param string $langcode
+ * The language code of the text to be filtered.
+ * @param bool $cache
+ * A Boolean indicating whether the filtered text is going to be cached in
+ * {cache_filter}.
+ * @param string $cache_id
+ * The ID of the filtered text in {cache_filter}, if $cache is TRUE.
+ *
+ * @return string
+ * The filtered text.
+ */
+ public function process($text, $filter, FilterFormat $format, $langcode, $cache, $cache_id);
+
+}
diff --git a/core/modules/filter/lib/Drupal/filter/Plugin/filter/filter/FilterUrl.php b/core/modules/filter/lib/Drupal/filter/Plugin/filter/filter/FilterUrl.php
new file mode 100644
index 0000000..89304fd
--- /dev/null
+++ b/core/modules/filter/lib/Drupal/filter/Plugin/filter/filter/FilterUrl.php
@@ -0,0 +1,59 @@
+ 'number',
+ '#title' => t('Maximum link text length'),
+ '#default_value' => $this->settings['filter_url_length'],
+ '#min' => 1,
+ '#field_suffix' => t('characters'),
+ '#description' => t('URLs longer than this number of characters will be truncated to prevent long strings that break formatting. The link itself will be retained; just the text portion of the link will be truncated.'),
+ );
+ return $settings;
+ }
+
+ /**
+ * Implements \Drupal\filter\Plugin\filter\filter\Plugin\filter\filter\FilterInterface::process().
+ */
+ public function process($text, $filter, FilterFormat $format, $langcode, $cache, $cache_id) {
+ return _filter_url($text, $filter);
+ }
+
+}
diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterCrudTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterCrudTest.php
index 2fa330b..6e3409c 100644
--- a/core/modules/filter/lib/Drupal/filter/Tests/FilterCrudTest.php
+++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterCrudTest.php
@@ -93,13 +93,12 @@ function verifyTextFormat($format) {
$this->assertEqual($filter_format->weight, $format->weight, format_string('filter_format_load: Proper weight for text format %format.', $t_args));
// Verify the 'cache' text format property according to enabled filters.
- $filter_info = filter_get_filters();
$filters = filter_list_format($filter_format->format);
$cacheable = TRUE;
foreach ($filters as $name => $filter) {
// If this filter is not cacheable, update $cacheable accordingly, so we
// can verify $format->cache after iterating over all filters.
- if ($filter->status && isset($filter_info[$name]['cache']) && !$filter_info[$name]['cache']) {
+ if ($filter->status && !$filter->cache) {
$cacheable = FALSE;
break;
}
diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterSettingsTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterSettingsTest.php
index 1aa7909..d705955 100644
--- a/core/modules/filter/lib/Drupal/filter/Tests/FilterSettingsTest.php
+++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterSettingsTest.php
@@ -27,7 +27,7 @@ public static function getInfo() {
* Tests explicit and implicit default settings for filters.
*/
function testFilterDefaults() {
- $filter_info = filter_filter_info();
+ $filter_info = filter_get_filters();
$filters = array_fill_keys(array_keys($filter_info), array());
// Create text format using filter default settings.
diff --git a/core/modules/php/lib/Drupal/php/Plugin/filter/filter/Php.php b/core/modules/php/lib/Drupal/php/Plugin/filter/filter/Php.php
new file mode 100644
index 0000000..31e4bf6
--- /dev/null
+++ b/core/modules/php/lib/Drupal/php/Plugin/filter/filter/Php.php
@@ -0,0 +1,77 @@
+' . t('Using custom PHP code') . '';
+ $output .= '' . t('Custom PHP code may be embedded in some types of site content, including posts and blocks. While embedding PHP code inside a post or block is a powerful and flexible feature when used by a trusted user with PHP experience, it is a significant and dangerous security risk when used improperly. Even a small mistake when posting PHP code may accidentally compromise your site.') . '
';
+ $output .= '' . t('If you are unfamiliar with PHP, SQL, or Drupal, avoid using custom PHP code within posts. Experimenting with PHP may corrupt your database, render your site inoperable, or significantly compromise security.') . '
';
+ $output .= '' . t('Notes:') . '
';
+ $output .= '- ' . t('Remember to double-check each line for syntax and logic errors before saving.') . '
';
+ $output .= '- ' . t('Statements must be correctly terminated with semicolons.') . '
';
+ $output .= '- ' . t('Global variables used within your PHP code retain their values after your script executes.') . '
';
+ $output .= '- ' . t('
register_globals
is turned off. If you need to use forms, understand and use the functions in the Drupal Form API.', array('@formapi' => url('http://api.drupal.org/api/group/form_api/8'))) . ' ';
+ $output .= '- ' . t('Use a
print
or return
statement in your code to output content.') . ' ';
+ $output .= '- ' . t('Develop and test your PHP code using a separate test script and sample database before deploying on a production site.') . '
';
+ $output .= '- ' . t('Consider including your custom PHP code within a site-specific module or
template.php
file rather than embedding it directly into a post or block.') . ' ';
+ $output .= '- ' . t('Be aware that the ability to embed PHP code within content is provided by the PHP Filter module. If this module is disabled or deleted, then blocks and posts with embedded PHP may display, rather than execute, the PHP code.') . '
';
+ $output .= '' . t('A basic example: Creating a "Welcome" block that greets visitors with a simple message.') . '
';
+ $output .= '- ' . t('
Add a custom block to your site, named "Welcome" . With its text format set to "PHP code" (or another format supporting PHP input), add the following in the Block body:
+
+ print t(\'Welcome visitor! Thank you for visiting.\');
+
') . ' ';
+ $output .= '- ' . t('
To display the name of a registered user, use this instead:
+
+ global $user;
+ if ($user->uid) {
+ print t(\'Welcome @name! Thank you for visiting.\', array(\'@name\' => user_format_name($user)));
+ }
+ else {
+ print t(\'Welcome visitor! Thank you for visiting.\');
+ }
+
') . '
';
+ $output .= '' . t('Drupal.org offers some example PHP snippets, or you can create your own with some PHP experience and knowledge of the Drupal system.', array('@drupal' => url('http://drupal.org'), '@php-snippets' => url('http://drupal.org/documentation/customization/php-snippets'))) . '
';
+ return $output;
+ }
+ else {
+ return t('You may post PHP code. You should include <?php ?> tags.');
+ }
+ }
+
+ /**
+ * Implements \Drupal\filter\Plugin\filter\filter\Plugin\filter\filter\FilterInterface::process().
+ */
+ public function process($text, $filter, FilterFormat $format, $langcode, $cache, $cache_id) {
+ return php_eval($text);
+ }
+
+}
diff --git a/core/modules/php/php.module b/core/modules/php/php.module
index 8e885e4..2932bfa 100644
--- a/core/modules/php/php.module
+++ b/core/modules/php/php.module
@@ -86,63 +86,3 @@ function php_eval($code) {
return $output;
}
-
-/**
- * Implements hook_filter_FILTER_tips().
- *
- * @see php_filter_info()
- */
-function _php_filter_tips($filter, $format, $long = FALSE) {
- global $base_url;
- if ($long) {
- $output = '' . t('Using custom PHP code') . '
';
- $output .= '' . t('Custom PHP code may be embedded in some types of site content, including posts and blocks. While embedding PHP code inside a post or block is a powerful and flexible feature when used by a trusted user with PHP experience, it is a significant and dangerous security risk when used improperly. Even a small mistake when posting PHP code may accidentally compromise your site.') . '
';
- $output .= '' . t('If you are unfamiliar with PHP, SQL, or Drupal, avoid using custom PHP code within posts. Experimenting with PHP may corrupt your database, render your site inoperable, or significantly compromise security.') . '
';
- $output .= '' . t('Notes:') . '
';
- $output .= '- ' . t('Remember to double-check each line for syntax and logic errors before saving.') . '
';
- $output .= '- ' . t('Statements must be correctly terminated with semicolons.') . '
';
- $output .= '- ' . t('Global variables used within your PHP code retain their values after your script executes.') . '
';
- $output .= '- ' . t('
register_globals
is turned off. If you need to use forms, understand and use the functions in the Drupal Form API.', array('@formapi' => url('http://api.drupal.org/api/group/form_api/8'))) . ' ';
- $output .= '- ' . t('Use a
print
or return
statement in your code to output content.') . ' ';
- $output .= '- ' . t('Develop and test your PHP code using a separate test script and sample database before deploying on a production site.') . '
';
- $output .= '- ' . t('Consider including your custom PHP code within a site-specific module or
template.php
file rather than embedding it directly into a post or block.') . ' ';
- $output .= '- ' . t('Be aware that the ability to embed PHP code within content is provided by the PHP Filter module. If this module is disabled or deleted, then blocks and posts with embedded PHP may display, rather than execute, the PHP code.') . '
';
- $output .= '' . t('A basic example: Creating a "Welcome" block that greets visitors with a simple message.') . '
';
- $output .= '- ' . t('
Add a custom block to your site, named "Welcome" . With its text format set to "PHP code" (or another format supporting PHP input), add the following in the Block body:
-
-print t(\'Welcome visitor! Thank you for visiting.\');
-
') . ' ';
- $output .= '- ' . t('
To display the name of a registered user, use this instead:
-
-global $user;
-if ($user->uid) {
- print t(\'Welcome @name! Thank you for visiting.\', array(\'@name\' => user_format_name($user)));
-}
-else {
- print t(\'Welcome visitor! Thank you for visiting.\');
-}
-
') . '
';
- $output .= '' . t('Drupal.org offers some example PHP snippets, or you can create your own with some PHP experience and knowledge of the Drupal system.', array('@drupal' => url('http://drupal.org'), '@php-snippets' => url('http://drupal.org/documentation/customization/php-snippets'))) . '
';
- return $output;
- }
- else {
- return t('You may post PHP code. You should include <?php ?> tags.');
- }
-}
-
-/**
- * Implements hook_filter_info().
- *
- * Provide PHP code filter. Use with care.
- */
-function php_filter_info() {
- $filters['php_code'] = array(
- 'title' => t('PHP evaluator'),
- 'type' => FILTER_TYPE_MARKUP_LANGUAGE,
- 'description' => t('Executes a piece of PHP code. The usage of this filter should be restricted to administrators only!'),
- 'process callback' => 'php_eval',
- 'tips callback' => '_php_filter_tips',
- 'cache' => FALSE,
- );
- return $filters;
-}
diff --git a/core/modules/system/tests/modules/filter_test/filter_test.module b/core/modules/system/tests/modules/filter_test/filter_test.module
index a61941a..e3983b4 100644
--- a/core/modules/system/tests/modules/filter_test/filter_test.module
+++ b/core/modules/system/tests/modules/filter_test/filter_test.module
@@ -25,40 +25,3 @@ function filter_test_filter_format_update($format) {
function filter_test_filter_format_disable($format) {
drupal_set_message('hook_filter_format_disable invoked.');
}
-
-/**
- * Implements hook_filter_info().
- */
-function filter_test_filter_info() {
- $filters['filter_test_uncacheable'] = array(
- 'title' => 'Uncacheable filter',
- 'type' => FILTER_TYPE_TRANSFORM_IRREVERSIBLE,
- 'description' => 'Does nothing, but makes a text format uncacheable.',
- 'cache' => FALSE,
- );
- $filters['filter_test_replace'] = array(
- 'title' => 'Testing filter',
- 'type' => FILTER_TYPE_TRANSFORM_IRREVERSIBLE,
- 'description' => 'Replaces all content with filter and text format information.',
- 'process callback' => 'filter_test_replace',
- );
- return $filters;
-}
-
-/**
- * Process handler for filter_test_replace filter.
- *
- * Replaces all text with filter and text format information.
- */
-function filter_test_replace($text, $filter, $format, $langcode, $cache, $cache_id) {
- $text = array();
- $text[] = 'Filter: ' . $filter->title . ' (' . $filter->name . ')';
- $text[] = 'Format: ' . $format->name . ' (' . $format->format . ')';
- $text[] = 'Language: ' . $langcode;
- $text[] = 'Cache: ' . ($cache ? 'Enabled' : 'Disabled');
- if ($cache_id) {
- $text[] = 'Cache ID: ' . $cache_id;
- }
- return implode("
\n", $text);
-}
-
diff --git a/core/modules/system/tests/modules/filter_test/lib/Drupal/filter_test/Plugin/filter/filter/FilterTestReplace.php b/core/modules/system/tests/modules/filter_test/lib/Drupal/filter_test/Plugin/filter/filter/FilterTestReplace.php
new file mode 100644
index 0000000..7f9e2c0
--- /dev/null
+++ b/core/modules/system/tests/modules/filter_test/lib/Drupal/filter_test/Plugin/filter/filter/FilterTestReplace.php
@@ -0,0 +1,43 @@
+title . ' (' . $filter->name . ')';
+ $text[] = 'Format: ' . $format->name . ' (' . $format->format . ')';
+ $text[] = 'Language: ' . $langcode;
+ $text[] = 'Cache: ' . ($cache ? 'Enabled' : 'Disabled');
+ if ($cache_id) {
+ $text[] = 'Cache ID: ' . $cache_id;
+ }
+ return implode("
\n", $text);
+ }
+
+}
diff --git a/core/modules/system/tests/modules/filter_test/lib/Drupal/filter_test/Plugin/filter/filter/FilterTestUncacheable.php b/core/modules/system/tests/modules/filter_test/lib/Drupal/filter_test/Plugin/filter/filter/FilterTestUncacheable.php
new file mode 100644
index 0000000..929b6a1
--- /dev/null
+++ b/core/modules/system/tests/modules/filter_test/lib/Drupal/filter_test/Plugin/filter/filter/FilterTestUncacheable.php
@@ -0,0 +1,36 @@
+