Index: misc/tabledrag.js
===================================================================
RCS file: /cvs/drupal/drupal/misc/tabledrag.js,v
retrieving revision 1.31
diff -u -p -r1.31 tabledrag.js
--- misc/tabledrag.js 20 Sep 2009 19:14:40 -0000 1.31
+++ misc/tabledrag.js 20 Oct 2009 19:06:50 -0000
@@ -56,8 +56,8 @@ Drupal.tableDrag = function (table, tabl
// this table. For efficiency, large sections of code can be skipped if we
// don't need to track horizontal movement and indentations.
this.indentEnabled = false;
- for (group in tableSettings) {
- for (n in tableSettings[group]) {
+ for (var group in tableSettings) {
+ for (var n in tableSettings[group]) {
if (tableSettings[group][n].relationship == 'parent') {
this.indentEnabled = true;
}
@@ -147,7 +147,7 @@ Drupal.tableDrag.prototype.hideColumns =
*/
Drupal.tableDrag.prototype.rowSettings = function (group, row) {
var field = $('.' + group, row);
- for (delta in this.tableSettings[group]) {
+ for (var delta in this.tableSettings[group]) {
var targetClass = this.tableSettings[group][delta].target;
if (field.is('.' + targetClass)) {
// Return a copy of the row settings.
@@ -442,7 +442,7 @@ Drupal.tableDrag.prototype.dropRow = fun
for (var group in self.tableSettings) {
var rowSettings = self.rowSettings(group, droppedRow);
if (rowSettings.relationship == 'group') {
- for (n in self.rowObject.children) {
+ for (var n in self.rowObject.children) {
self.updateField(self.rowObject.children[n], group);
}
}
@@ -535,7 +535,7 @@ Drupal.tableDrag.prototype.findDropTarge
if ((y > (rowY - rowHeight)) && (y < (rowY + rowHeight))) {
if (this.indentEnabled) {
// Check that this row is not a child of the row being dragged.
- for (n in this.rowObject.group) {
+ for (var n in this.rowObject.group) {
if (this.rowObject.group[n] == row) {
return null;
}
@@ -1035,7 +1035,7 @@ Drupal.tableDrag.prototype.row.prototype
* Remove indentation helper classes from the current row group.
*/
Drupal.tableDrag.prototype.row.prototype.removeIndentClasses = function () {
- for (n in this.children) {
+ for (var n in this.children) {
$('.indentation', this.children[n])
.removeClass('tree-child')
.removeClass('tree-child-first')
Index: modules/filter/filter.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.admin.inc,v
retrieving revision 1.49
diff -u -p -r1.49 filter.admin.inc
--- modules/filter/filter.admin.inc 13 Oct 2009 15:39:41 -0000 1.49
+++ modules/filter/filter.admin.inc 20 Oct 2009 20:40:27 -0000
@@ -109,6 +109,10 @@ function filter_admin_format_form($form,
$help = t('All roles for this text format must be enabled and cannot be changed.');
}
+ $form['#tree'] = TRUE;
+ $form['#attached']['js'][] = drupal_get_path('module', 'filter') . '/filter.admin.js';
+ $form['#attached']['css'][] = drupal_get_path('module', 'filter') . '/filter.css';
+
$form['name'] = array(
'#type' => 'textfield',
'#title' => t('Name'),
@@ -117,41 +121,71 @@ function filter_admin_format_form($form,
'#required' => TRUE,
);
- // Add a row of checkboxes for form group.
- $form['roles'] = array('#type' => 'fieldset',
+ // Add user role access selection.
+ $form['roles'] = array(
+ '#type' => 'checkboxes',
'#title' => t('Roles'),
'#description' => $is_fallback ? $help : t('Choose which roles may use this text format. Note that roles with the "administer filters" permission can always use all text formats.'),
- '#tree' => TRUE,
+ '#options' => user_roles(),
+ '#default_value' => array_keys(filter_get_roles_by_format($format)),
+ '#disabled' => $is_fallback,
);
- $checked = filter_get_roles_by_format($format);
- foreach (user_roles() as $rid => $name) {
- $form['roles'][$rid] = array('#type' => 'checkbox',
- '#title' => $name,
- '#default_value' => ($is_fallback || isset($checked[$rid])),
- );
- if ($is_fallback) {
- $form['roles'][$rid]['#disabled'] = TRUE;
- }
- }
- // Table with filters
+
+ // Build a form to change the settings for filters in a text format.
+ // The form is built by merging the results of 'settings callback' for each
+ // enabled filter in the given format.
$filter_info = filter_get_filters();
- $filters = filter_list_format($format->format, TRUE);
+ $filters = filter_list_format($format->format);
- $form['filters'] = array('#type' => 'fieldset',
- '#title' => t('Filters'),
- '#description' => t('Choose the filters that will be used in this text format.'),
- '#tree' => TRUE,
+ $form['filter_settings'] = array(
+ '#type' => 'vertical_tabs',
);
+
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]->settings = array();
+ $filters[$name]->weight = 0;
+ }
+ $form['filters'][$name]['#weight'] = $filters[$name]->weight;
+
$form['filters'][$name]['status'] = array(
'#type' => 'checkbox',
'#title' => $filter['title'],
'#default_value' => !empty($filters[$name]->status),
'#description' => $filter['description'],
);
+ // Tabledrag.
+ $form['filters'][$name]['filter'] = array(
+ '#markup' => $filter['title'],
+ );
+ $form['filters'][$name]['weight'] = array(
+ '#type' => 'weight',
+ '#delta' => 50,
+ '#default_value' => $filters[$name]->weight,
+ );
+ $form['filters'][$name]['settings'] = array();
+ if (isset($filter['settings callback']) && function_exists($filter['settings callback'])) {
+ $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);
+ if (!empty($settings_form)) {
+ $form['filters'][$name]['settings'] = array(
+ '#type' => 'fieldset',
+ '#title' => $filter['title'],
+ '#group' => 'filter_settings',
+ '#tree' => TRUE,
+ );
+ $form['filters'][$name]['settings'] += $settings_form;
+ }
+ }
}
+
if (!empty($format->format)) {
- $form['format'] = array('#type' => 'hidden', '#value' => $format->format);
+ $form['format'] = array('#type' => 'value', '#value' => $format->format);
// Composition tips (guidelines)
$tips = _filter_tips($format->format, FALSE);
@@ -172,11 +206,54 @@ function filter_admin_format_form($form,
}
/**
+ * Theme text format configuration form.
+ *
+ * @ingroup themeable
+ */
+function theme_filter_admin_format_form($variables) {
+ $form = $variables['form'];
+ $output = drupal_render($form['name']);
+ $output .= drupal_render($form['roles']);
+
+ // Filter status (checkboxes).
+ $output .= '' . t('Enabled filters') . '';
+ $checkboxes = '';
+ foreach (element_children($form['filters']) as $name) {
+ $checkboxes .= drupal_render($form['filters'][$name]['status']);
+ }
+ $output .= '
' . $checkboxes . '
';
+
+ // Filter order (tabledrag).
+ $output .= '' . t('Filter processing order') . '';
+ $rows = array();
+ foreach (element_children($form['filters'], TRUE) as $name) {
+ $form['filters'][$name]['weight']['#attributes']['class'][] = 'filter-order-weight';
+ $rows[] = array(
+ 'data' => array(
+ drupal_render($form['filters'][$name]['filter']),
+ drupal_render($form['filters'][$name]['weight']),
+ ),
+ 'class' => array('draggable'),
+ );
+ }
+ $output .= theme('table', array('rows' => $rows, 'attributes' => array('id' => 'filter-order')));
+ drupal_add_tabledrag('filter-order', 'order', 'sibling', 'filter-order-weight', NULL, NULL, TRUE);
+
+ // Filter settings.
+ $output .= '' . t('Filter settings') . '';
+ $output .= drupal_render($form['filter_settings']);
+ $output .= drupal_render_children($form);
+
+ return $output;
+}
+
+/**
* Validate text format form submissions.
*/
function filter_admin_format_form_validate($form, &$form_state) {
if (!isset($form_state['values']['format'])) {
$format_name = trim($form_state['values']['name']);
+ form_set_value($form['name'], $format_name, $form_state);
$result = db_query("SELECT format FROM {filter_format} WHERE name = :name", array(':name' => $format_name))->fetchField();
if ($result) {
form_set_error('name', t('Text format names must be unique. A format named %name already exists.', array('%name' => $format_name)));
@@ -188,10 +265,17 @@ function filter_admin_format_form_valida
* Process text format form submissions.
*/
function filter_admin_format_form_submit($form, &$form_state) {
+ // Remove unnecessary values.
+ form_state_values_clean($form_state);
+
+ // Save text format.
$format = (object) $form_state['values'];
- $format->format = isset($form_state['values']['format']) ? $form_state['values']['format'] : NULL;
+ if (!isset($form_state['values']['format'])) {
+ $format->format = NULL;
+ }
$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));
@@ -238,152 +322,3 @@ function filter_admin_delete_submit($for
$form_state['redirect'] = 'admin/config/content/formats';
}
-/**
- * Menu callback; display settings defined by a format's filters.
- */
-function filter_admin_configure_page($format) {
- drupal_set_title(t("Configure %format", array('%format' => $format->name)), PASS_THROUGH);
- return drupal_get_form('filter_admin_configure', $format);
-}
-
-/**
- * Build a form to change the settings for filters in a text format.
- *
- * The form is built by merging the results of 'settings callback' for each
- * enabled filter in the given format.
- *
- * @ingroup forms
- */
-function filter_admin_configure($form, &$form_state, $format) {
- $filters = filter_list_format($format->format);
- $filter_info = filter_get_filters();
-
- $form['#format'] = $format;
- foreach ($filters as $name => $filter) {
- if (isset($filter_info[$name]['settings callback']) && function_exists($filter_info[$name]['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_info[$name]['default settings']) ? $filter_info[$name]['default settings'] : array());
- $settings_form = $filter_info[$name]['settings callback']($form, $form_state, $filters[$name], $defaults, $format, $filters);
- if (isset($settings_form) && is_array($settings_form)) {
- $form['settings'][$name] = array(
- '#type' => 'fieldset',
- '#title' => check_plain($filter->title),
- );
- $form['settings'][$name] += $settings_form;
- }
- }
- }
-
- if (empty($form['settings'])) {
- $form['error'] = array('#markup' => t('No settings are available.'));
- return $form;
- }
- $form['settings']['#tree'] = TRUE;
- $form['submit'] = array('#type' => 'submit', '#value' => t('Save configuration'));
-
- return $form;
-}
-
-/**
- * Form submit handler for text format filter configuration form.
- *
- * @see filter_admin_configure()
- */
-function filter_admin_configure_submit($form, &$form_state) {
- $format = $form['#format'];
-
- foreach ($form_state['values']['settings'] as $name => $settings) {
- db_update('filter')
- ->fields(array(
- 'settings' => serialize($settings),
- ))
- ->condition('format', $format->format)
- ->condition('name', $name)
- ->execute();
- }
-
- // Clear the filter's cache when configuration settings are saved.
- cache_clear_all($format->format . ':', 'cache_filter', TRUE);
-
- drupal_set_message(t('The configuration options have been saved.'));
-}
-
-/**
- * Menu callback; display form for ordering filters for a format.
- */
-function filter_admin_order_page($format) {
- drupal_set_title(t("Rearrange %format", array('%format' => $format->name)), PASS_THROUGH);
- return drupal_get_form('filter_admin_order', $format);
-}
-
-/**
- * Build the form for ordering filters for a format.
- *
- * @ingroup forms
- * @see theme_filter_admin_order()
- * @see filter_admin_order_submit()
- */
-function filter_admin_order($form, &$form_state, $format = NULL) {
- // Get list (with forced refresh).
- $filters = filter_list_format($format->format);
-
- $form['weights'] = array('#tree' => TRUE);
- foreach ($filters as $id => $filter) {
- $form['names'][$id] = array('#markup' => $filter->title);
- $form['weights'][$id] = array('#type' => 'weight', '#default_value' => $filter->weight);
- }
- $form['format'] = array('#type' => 'hidden', '#value' => $format->format);
- $form['submit'] = array('#type' => 'submit', '#value' => t('Save configuration'));
-
- return $form;
-}
-
-/**
- * Theme filter order configuration form.
- *
- * @ingroup themeable
- */
-function theme_filter_admin_order($variables) {
- $form = $variables['form'];
-
- $header = array(t('Name'), t('Weight'));
- $rows = array();
- foreach (element_children($form['names']) as $id) {
- // Don't take form control structures.
- if (is_array($form['names'][$id])) {
- $form['weights'][$id]['#attributes']['class'] = array('filter-order-weight');
- $rows[] = array(
- 'data' => array(drupal_render($form['names'][$id]), drupal_render($form['weights'][$id])),
- 'class' => array('draggable'),
- );
- }
- }
-
- $output = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'filter-order')));
- $output .= drupal_render_children($form);
-
- drupal_add_tabledrag('filter-order', 'order', 'sibling', 'filter-order-weight', NULL, NULL, FALSE);
-
- return $output;
-}
-
-/**
- * Process filter order configuration form submission.
- */
-function filter_admin_order_submit($form, &$form_state) {
- foreach ($form_state['values']['weights'] as $name => $weight) {
- db_merge('filter')
- ->key(array(
- 'format' => $form_state['values']['format'],
- 'name' => $name,
- ))
- ->fields(array(
- 'weight' => $weight,
- ))
- ->execute();
- }
- drupal_set_message(t('The filter ordering has been saved.'));
-
- cache_clear_all($form_state['values']['format'] . ':', 'cache_filter', TRUE);
-}
Index: modules/filter/filter.admin.js
===================================================================
RCS file: modules/filter/filter.admin.js
diff -N modules/filter/filter.admin.js
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ modules/filter/filter.admin.js 10 Sep 2009 05:57:16 -0000
@@ -0,0 +1,76 @@
+// $Id$
+
+(function ($) {
+
+/**
+ * Displays the tab's content pane.
+ */
+Drupal.verticalTab.prototype.tabShow = function () {
+ this.item.show();
+ this.fieldset.removeClass('element-hidden');
+ this.focus();
+ this.updateSummary();
+};
+
+/**
+ * Displays the tab's content pane.
+ */
+Drupal.verticalTab.prototype.tabHide = function () {
+ this.item.hide();
+ this.fieldset.addClass('element-hidden');
+ var newtab = this.fieldset.siblings('fieldset.vertical-tabs-pane:not(.element-hidden):first')
+ .data('verticalTab')
+ .focus();
+};
+
+/**
+ * More intelligent table restriping.
+ */
+Drupal.tableDrag.prototype.restripeTable = function () {
+ // :even and :odd are reversed because jQuery counts from 0 and
+ // we count from 1, so we're out of sync.
+ // Match immediate children of the parent element to allow nesting.
+ $('> tbody > tr.draggable:not(:hidden), > tr.draggable:not(:hidden)', this.table)
+ .removeClass('odd even')
+ .filter(':odd').addClass('even').end()
+ .filter(':even').addClass('odd');
+};
+
+Drupal.behaviors.filterFieldsetSummaries = {
+ attach: function (context, settings) {
+ $('#filters-status-wrapper input.form-checkbox', context).once('filter-status', function () {
+ var $checkbox = $(this);
+ // Retrieve the tabledrag row belonging to this filter.
+ var $row = $('#' + $checkbox.attr('id').replace(/-status$/, '-weight'), context).closest('tr');
+ // Retrieve the settings tab belonging to this filter.
+ var tab = $('#' + $checkbox.attr('id').replace(/-status$/, '-settings'), context).data('verticalTab');
+
+ $checkbox.bind('click.filterUpdate', function () {
+ // Display filter settings.
+ if ($checkbox.is(':checked')) {
+ $row.show();
+ if (tab) {
+ tab.tabShow();
+ tab.fieldset.setSummary(function (tabContext) {
+ return Drupal.t('Enabled');
+ });
+ }
+ }
+ // Hide filter settings.
+ else {
+ $row.hide();
+ if (tab) {
+ tab.tabHide();
+ tab.fieldset.setSummary(function (tabContext) {
+ return Drupal.t('Disabled');
+ });
+ }
+ }
+ Drupal.tableDrag['filter-order'].restripeTable();
+ });
+ $checkbox.trigger('click.filterUpdate');
+ });
+ }
+};
+
+})(jQuery);
Index: modules/filter/filter.api.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.api.php,v
retrieving revision 1.15
diff -u -p -r1.15 filter.api.php
--- modules/filter/filter.api.php 20 Sep 2009 07:32:17 -0000 1.15
+++ modules/filter/filter.api.php 20 Oct 2009 20:46:07 -0000
@@ -92,12 +92,12 @@
*
* @code
* function mymodule_filter_settings($form, &$form_state, $filter, $defaults) {
- * $form['mymodule_url_length'] = array(
+ * $settings['mymodule_url_length'] = array(
* '#type' => 'textfield',
* '#title' => t('Maximum link text length'),
* '#default_value' => isset($filter->settings['mymodule_url_length']) ? $filter->settings['mymodule_url_length'] : $defaults['mymodule_url_length'],
* );
- * return $form;
+ * return $settings;
* }
* @endcode
*
Index: modules/filter/filter.css
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.css,v
retrieving revision 1.1
diff -u -p -r1.1 filter.css
--- modules/filter/filter.css 30 Mar 2009 03:15:40 -0000 1.1
+++ modules/filter/filter.css 10 Sep 2009 04:47:14 -0000
@@ -35,3 +35,11 @@
.text-format-wrapper .description {
margin-top: 0.5em;
}
+
+#filter-order tr .form-item {
+ padding: 0.5em 0 0 3em;
+ white-space: normal;
+}
+#filter-order tr .form-type-checkbox .description {
+ padding: 0 0 0 2.5em;
+}
Index: modules/filter/filter.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.module,v
retrieving revision 1.298
diff -u -p -r1.298 filter.module
--- modules/filter/filter.module 16 Oct 2009 19:06:23 -0000 1.298
+++ modules/filter/filter.module 20 Oct 2009 20:47:18 -0000
@@ -45,6 +45,10 @@ function filter_theme() {
'arguments' => array('form' => NULL),
'file' => 'filter.admin.inc',
),
+ 'filter_admin_format_form' => array(
+ 'arguments' => array('form' => NULL),
+ 'file' => 'filter.admin.inc',
+ ),
'filter_tips' => array(
'arguments' => array('tips' => NULL, 'long' => FALSE),
'file' => 'filter.pages.inc',
@@ -98,29 +102,6 @@ function filter_menu() {
'access arguments' => array('administer filters'),
'file' => 'filter.admin.inc',
);
- $items['admin/config/content/formats/%filter_format/edit'] = array(
- 'title' => 'Edit',
- 'type' => MENU_DEFAULT_LOCAL_TASK,
- 'weight' => 0,
- );
- $items['admin/config/content/formats/%filter_format/configure'] = array(
- 'title' => 'Configure',
- 'page callback' => 'filter_admin_configure_page',
- 'page arguments' => array(4),
- 'access arguments' => array('administer filters'),
- 'type' => MENU_LOCAL_TASK,
- 'weight' => 1,
- 'file' => 'filter.admin.inc',
- );
- $items['admin/config/content/formats/%filter_format/order'] = array(
- 'title' => 'Rearrange',
- 'page callback' => 'filter_admin_order_page',
- 'page arguments' => array(4),
- 'access arguments' => array('administer filters'),
- 'type' => MENU_LOCAL_TASK,
- 'weight' => 2,
- 'file' => 'filter.admin.inc',
- );
$items['admin/config/content/formats/%filter_format/delete'] = array(
'title' => 'Delete text format',
'page callback' => 'drupal_get_form',
@@ -191,9 +172,6 @@ function filter_format_save(&$format) {
$return = drupal_write_record('filter_format', $format, 'format');
}
- // Get the filters currently active in the format, to add new filters
- // to the bottom.
- $current = filter_list_format($format->format, TRUE);
$filter_info = filter_get_filters();
if (!isset($format->filters)) {
$format->filters = array();
@@ -201,7 +179,7 @@ function filter_format_save(&$format) {
foreach ($format->filters as $name => $filter) {
$fields = array();
// Add new filters to the bottom.
- $fields['weight'] = isset($current[$name]->weight) ? $current[$name]->weight : 10;
+ $fields['weight'] = isset($filter['weight']) ? $filter['weight'] : 10;
$fields['status'] = $filter['status'];
$fields['module'] = $filter_info[$name]['module'];
$format->filters[$name]['module'] = $filter_info[$name]['module'];
@@ -726,7 +704,7 @@ function _filter_tips($format_id, $long
$filters = filter_list_format($format->format);
$tips[$format->name] = array();
foreach ($filters as $name => $filter) {
- if (isset($filter_info[$name]['tips callback']) && function_exists($filter_info[$name]['tips callback'])) {
+ if ($filter->status && isset($filter_info[$name]['tips callback']) && function_exists($filter_info[$name]['tips callback'])) {
$tip = $filter_info[$name]['tips callback']($filter, $format, $long);
$tips[$format->name][$name] = array('tip' => $tip, 'id' => $name);
}
@@ -861,8 +839,8 @@ function filter_filter_info() {
/**
* Settings callback for the HTML filter.
*/
-function _filter_html_settings($form, &$form_state, $filter, $defaults) {
- $form['allowed_html'] = array(
+function _filter_html_settings($form, &$form_state, $filter, $format, $defaults) {
+ $settings['allowed_html'] = array(
'#type' => 'textfield',
'#title' => t('Allowed HTML tags'),
'#default_value' => isset($filter->settings['allowed_html']) ? $filter->settings['allowed_html'] : $defaults['allowed_html'],
@@ -870,19 +848,19 @@ function _filter_html_settings($form, &$
'#maxlength' => 1024,
'#description' => t('Specify a list of tags which should not be stripped. (Note that JavaScript event attributes are always stripped.)'),
);
- $form['filter_html_help'] = array(
+ $settings['filter_html_help'] = array(
'#type' => 'checkbox',
'#title' => t('Display HTML help'),
'#default_value' => isset($filter->settings['filter_html_help']) ? $filter->settings['filter_html_help'] : $defaults['filter_html_help'],
'#description' => t('If enabled, Drupal will display some basic HTML help in the long filter tips.'),
);
- $form['filter_html_nofollow'] = array(
+ $settings['filter_html_nofollow'] = array(
'#type' => 'checkbox',
'#title' => t('Spam link deterrent'),
'#default_value' => isset($filter->settings['filter_html_nofollow']) ? $filter->settings['filter_html_nofollow'] : $defaults['filter_html_nofollow'],
'#description' => t('If enabled, Drupal will add rel="nofollow" to all links, as a measure to reduce the effectiveness of spam links. Note: this will also prevent valid links from being followed by search engines, therefore it is likely most effective when enabled for anonymous users.'),
);
- return $form;
+ return $settings;
}
/**
@@ -1007,15 +985,15 @@ function _filter_html_tips($filter, $for
/**
* Settings callback for URL filter.
*/
-function _filter_url_settings($form, &$form_state, $filter, $defaults) {
- $form['filter_url_length'] = array(
+function _filter_url_settings($form, &$form_state, $filter, $format, $defaults) {
+ $settings['filter_url_length'] = array(
'#type' => 'textfield',
'#title' => t('Maximum link text length'),
'#default_value' => isset($filter->settings['filter_url_length']) ? $filter->settings['filter_url_length'] : $defaults['filter_url_length'],
'#maxlength' => 4,
'#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 $form;
+ return $settings;
}
/**