- Patch #11218 by David_Rothstein, sun, quicksketch, duncf, awood456, dropcube, mgifford | pwolanin, dww, RobRoy, Crell, webchick, beginner, ray007, bjaspan, chx, Gábor Hojtsy, Steven, Dries, lutegrass, sym, guardian, matt2000, geerlingguy, SeanBannister, matt westgate, com2, praseodym: allow default text formats per role, and integrate text format permissions.

merge-requests/26/head
Dries Buytaert 2009-09-20 07:32:19 +00:00
parent 3a2eff7145
commit 7cf7f99878
20 changed files with 712 additions and 287 deletions

View File

@ -43,6 +43,7 @@ Drupal 7.0, xxxx-xx-xx (development version)
* Redesigned the add content type screen. * Redesigned the add content type screen.
* Highlight duplicate URL aliases. * Highlight duplicate URL aliases.
* Renamed "input formats" to "text formats". * Renamed "input formats" to "text formats".
* Moved text format permissions to the main permissions page.
* Added configurable ability for users to cancel their own accounts. * Added configurable ability for users to cancel their own accounts.
* Added "vertical tabs", a reusable interface component that features automatic * Added "vertical tabs", a reusable interface component that features automatic
summaries and increases usability. summaries and increases usability.
@ -80,6 +81,7 @@ Drupal 7.0, xxxx-xx-xx (development version)
fallback to the system time zone and will have to be reconfigured by each user. fallback to the system time zone and will have to be reconfigured by each user.
- Filter system: - Filter system:
* Revamped the filter API and text format storage. * Revamped the filter API and text format storage.
* Added support for default text formats to be assigned on a per-role basis.
* Refactored the HTML corrector to take advantage of PHP 5 features. * Refactored the HTML corrector to take advantage of PHP 5 features.
- Removed ping module: - Removed ping module:
* Contributed modules with similar functionality are available. * Contributed modules with similar functionality are available.

View File

@ -1917,7 +1917,7 @@ function form_process_radios($element) {
* $form['body'] = array( * $form['body'] = array(
* '#type' => 'textarea', * '#type' => 'textarea',
* '#title' => t('Body'), * '#title' => t('Body'),
* '#text_format' => isset($node->format) ? $node->format : FILTER_FORMAT_DEFAULT, * '#text_format' => isset($node->format) ? $node->format : filter_default_format(),
* ); * );
* @endcode * @endcode
* *

View File

@ -156,7 +156,7 @@ function block_block_info() {
* Implement hook_block_configure(). * Implement hook_block_configure().
*/ */
function block_block_configure($delta = 0) { function block_block_configure($delta = 0) {
$custom_block = array('format' => FILTER_FORMAT_DEFAULT); $custom_block = array('format' => filter_default_format());
if ($delta) { if ($delta) {
$custom_block = block_custom_block_get($delta); $custom_block = block_custom_block_get($delta);
} }
@ -350,12 +350,12 @@ function block_custom_block_form($edit = array()) {
'#type' => 'textarea', '#type' => 'textarea',
'#title' => t('Block body'), '#title' => t('Block body'),
'#default_value' => $edit['body'], '#default_value' => $edit['body'],
'#text_format' => isset($edit['format']) ? $edit['format'] : FILTER_FORMAT_DEFAULT, '#text_format' => isset($edit['format']) ? $edit['format'] : filter_default_format(),
'#rows' => 15, '#rows' => 15,
'#description' => t('The content of the block as shown to the user.'), '#description' => t('The content of the block as shown to the user.'),
'#required' => TRUE, '#required' => TRUE,
'#weight' => -17, '#weight' => -17,
'#access' => filter_access($edit['format']), '#access' => filter_access(filter_format_load($edit['format'])),
); );
return $form; return $form;
@ -799,9 +799,9 @@ function block_user_role_delete($role) {
/** /**
* Implement hook_filter_format_delete(). * Implement hook_filter_format_delete().
*/ */
function block_filter_format_delete($format, $default) { function block_filter_format_delete($format, $fallback) {
db_update('block_custom') db_update('block_custom')
->fields(array('format' => $default->format)) ->fields(array('format' => $fallback->format))
->condition('format', $format->format) ->condition('format', $format->format)
->execute(); ->execute();
} }

View File

@ -1814,7 +1814,7 @@ function comment_form($form, &$form_state, $comment) {
'#title' => t('Comment'), '#title' => t('Comment'),
'#rows' => 15, '#rows' => 15,
'#default_value' => $default, '#default_value' => $default,
'#text_format' => isset($comment->format) ? $comment->format : FILTER_FORMAT_DEFAULT, '#text_format' => isset($comment->format) ? $comment->format : filter_default_format(),
'#required' => TRUE, '#required' => TRUE,
); );
@ -2418,9 +2418,9 @@ function comment_menu_alter(&$items) {
/** /**
* Implement hook_filter_format_delete(). * Implement hook_filter_format_delete().
*/ */
function comment_filter_format_delete($format, $default) { function comment_filter_format_delete($format, $fallback) {
db_update('comment') db_update('comment')
->fields(array('format' => $default->format)) ->fields(array('format' => $fallback->format))
->condition('format', $format->format) ->condition('format', $format->format)
->execute(); ->execute();
} }

View File

@ -541,7 +541,7 @@ function text_element_info() {
'#delta' => 0, '#delta' => 0,
'#process' => array('text_textarea_elements_process'), '#process' => array('text_textarea_elements_process'),
'#theme_wrappers' => array('text_textarea'), '#theme_wrappers' => array('text_textarea'),
'#filter_value' => FILTER_FORMAT_DEFAULT, '#filter_value' => filter_default_format(),
); );
$types['text_textarea_with_summary'] = array( $types['text_textarea_with_summary'] = array(
'#input' => TRUE, '#input' => TRUE,
@ -549,7 +549,7 @@ function text_element_info() {
'#delta' => 0, '#delta' => 0,
'#process' => array('text_textarea_with_summary_process'), '#process' => array('text_textarea_with_summary_process'),
'#theme_wrappers' => array('text_textarea'), '#theme_wrappers' => array('text_textarea'),
'#filter_value' => FILTER_FORMAT_DEFAULT, '#filter_value' => filter_default_format(),
); );
return $types; return $types;
} }
@ -651,7 +651,7 @@ function text_textfield_elements_process($element, $form_state, $form) {
if (!empty($instance['settings']['text_processing'])) { if (!empty($instance['settings']['text_processing'])) {
$filter_key = (count($element['#columns']) == 2) ? $element['#columns'][1] : 'format'; $filter_key = (count($element['#columns']) == 2) ? $element['#columns'][1] : 'format';
$format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT; $format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : filter_default_format();
$element[$field_key]['#text_format'] = $format; $element[$field_key]['#text_format'] = $format;
} }
@ -684,7 +684,7 @@ function text_textarea_elements_process($element, $form_state, $form) {
if (!empty($instance['settings']['text_processing'])) { if (!empty($instance['settings']['text_processing'])) {
$filter_key = (count($element['#columns']) == 2) ? $element['#columns'][1] : 'format'; $filter_key = (count($element['#columns']) == 2) ? $element['#columns'][1] : 'format';
$format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT; $format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : filter_default_format();
$element[$field_key]['#text_format'] = $format; $element[$field_key]['#text_format'] = $format;
} }
@ -739,7 +739,7 @@ function text_textarea_with_summary_process($element, $form_state, $form) {
if (!empty($instance['settings']['text_processing'])) { if (!empty($instance['settings']['text_processing'])) {
$filter_key = (count($element['#columns']) == 2) ? $element['#columns'][1] : 'format'; $filter_key = (count($element['#columns']) == 2) ? $element['#columns'][1] : 'format';
$format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT; $format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : filter_default_format();
$element[$field_key]['#text_format'] = $format; $element[$field_key]['#text_format'] = $format;
} }
@ -760,7 +760,7 @@ function text_field_widget_formatted_text_value($form, $edit = FALSE) {
// The format selector uses #access = FALSE if only one format is // The format selector uses #access = FALSE if only one format is
// available. In this case, we don't receive its value, and need to // available. In this case, we don't receive its value, and need to
// manually set it. // manually set it.
$edit['format'] = !empty($edit[$default_key]) ? $edit[$default_key] : filter_resolve_format(FILTER_FORMAT_DEFAULT); $edit['format'] = !empty($edit[$default_key]) ? $edit[$default_key] : filter_default_format();
unset($edit[$default_key]); unset($edit[$default_key]);
return $edit; return $edit;
} }

View File

@ -3,6 +3,8 @@
class TextFieldTestCase extends DrupalWebTestCase { class TextFieldTestCase extends DrupalWebTestCase {
protected $instance; protected $instance;
protected $admin_user;
protected $web_user;
public static function getInfo() { public static function getInfo() {
return array( return array(
@ -15,8 +17,9 @@ class TextFieldTestCase extends DrupalWebTestCase {
function setUp() { function setUp() {
parent::setUp('field_test'); parent::setUp('field_test');
$web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content')); $this->admin_user = $this->drupalCreateUser(array('administer filters'));
$this->drupalLogin($web_user); $this->web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content'));
$this->drupalLogin($this->web_user);
} }
// Test fields. // Test fields.
@ -147,15 +150,23 @@ class TextFieldTestCase extends DrupalWebTestCase {
field_create_instance($this->instance); field_create_instance($this->instance);
$langcode = FIELD_LANGUAGE_NONE; $langcode = FIELD_LANGUAGE_NONE;
// Display creation form. // Delete all text formats besides the plain text fallback format.
// By default, the user only has access to 'Filtered HTML', and no format $this->drupalLogin($this->admin_user);
// selector is displayed foreach (filter_formats() as $format) {
if ($format->format != filter_fallback_format()) {
$this->drupalPost('admin/config/content/formats/' . $format->format . '/delete', array(), t('Delete'));
}
}
$this->drupalLogin($this->web_user);
// Display the creation form. Since the user only has access to one format,
// no format selector will be displayed.
$this->drupalGet('test-entity/add/test-bundle'); $this->drupalGet('test-entity/add/test-bundle');
$this->assertFieldByName("{$this->field_name}[$langcode][0][value]", '', t('Widget is displayed')); $this->assertFieldByName("{$this->field_name}[$langcode][0][value]", '', t('Widget is displayed'));
$this->assertNoFieldByName("{$this->field_name}[$langcode][0][value_format]", '1', t('Format selector is not displayed')); $this->assertNoFieldByName("{$this->field_name}[$langcode][0][value_format]", '', t('Format selector is not displayed'));
// Submit with data that should be filtered. // Submit with data that should be filtered.
$value = $this->randomName() . '<br />' . $this->randomName(); $value = '<em>' . $this->randomName() . '</em>';
$edit = array( $edit = array(
"{$this->field_name}[$langcode][0][value]" => $value, "{$this->field_name}[$langcode][0][value]" => $value,
); );
@ -168,21 +179,31 @@ class TextFieldTestCase extends DrupalWebTestCase {
$entity = field_test_entity_load($id); $entity = field_test_entity_load($id);
$entity->content = field_attach_view($entity_type, $entity); $entity->content = field_attach_view($entity_type, $entity);
$this->content = drupal_render($entity->content); $this->content = drupal_render($entity->content);
$this->assertNoRaw($value, 'Filtered tags are not displayed'); $this->assertNoRaw($value, t('HTML tags are not displayed.'));
$this->assertRaw(str_replace('<br />', '', $value), t('Filtered value is displayed correctly')); $this->assertRaw(check_plain($value), t('Escaped HTML is displayed correctly.'));
// Allow the user to use the 'Full HTML' format. // Create a new text format that does not escape HTML, and grant the user
db_update('filter_format')->fields(array('roles' => ',2,'))->condition('format', 2)->execute(); // access to it.
$this->drupalLogin($this->admin_user);
$edit = array('name' => $this->randomName());
$this->drupalPost('admin/config/content/formats/add', $edit, t('Save configuration'));
filter_format_reset_cache();
$this->checkPermissions(array(), TRUE);
$format_id = db_query("SELECT format FROM {filter_format} WHERE name = :name", array(':name' => $edit['name']))->fetchField();
$permission = filter_permission_name(filter_format_load($format_id));
$rid = max(array_keys($this->web_user->roles));
user_role_set_permissions($rid, array($permission), TRUE);
$this->drupalLogin($this->web_user);
// Display edition form. // Display edition form.
// We should now have a 'text format' selector. // We should now have a 'text format' selector.
$this->drupalGet('test-entity/' . $id . '/edit'); $this->drupalGet('test-entity/' . $id . '/edit');
$this->assertFieldByName("{$this->field_name}[$langcode][0][value]", '', t('Widget is displayed')); $this->assertFieldByName("{$this->field_name}[$langcode][0][value]", '', t('Widget is displayed'));
$this->assertFieldByName("{$this->field_name}[$langcode][0][value_format]", '1', t('Format selector is displayed')); $this->assertFieldByName("{$this->field_name}[$langcode][0][value_format]", '', t('Format selector is displayed'));
// Edit and change the format to 'Full HTML'. // Edit and change the text format to the new one that was created.
$edit = array( $edit = array(
"{$this->field_name}[$langcode][0][value_format]" => 2, "{$this->field_name}[$langcode][0][value_format]" => $format_id,
); );
$this->drupalPost(NULL, $edit, t('Save')); $this->drupalPost(NULL, $edit, t('Save'));
$this->assertRaw(t('test_entity @id has been updated.', array('@id' => $id)), t('Entity was updated')); $this->assertRaw(t('test_entity @id has been updated.', array('@id' => $id)), t('Entity was updated'));

View File

@ -7,8 +7,7 @@
*/ */
/** /**
* Menu callback; Displays a list of all text formats and which * Menu callback; Displays a list of all text formats and allows them to be rearranged.
* one is the default.
* *
* @ingroup forms * @ingroup forms
* @see filter_admin_overview_submit() * @see filter_admin_overview_submit()
@ -16,37 +15,33 @@
function filter_admin_overview($form) { function filter_admin_overview($form) {
// Overview of all formats. // Overview of all formats.
$formats = filter_formats(); $formats = filter_formats();
$error = FALSE; $fallback_format = filter_fallback_format();
$form['#tree'] = TRUE; $form['#tree'] = TRUE;
foreach ($formats as $id => $format) { foreach ($formats as $id => $format) {
$roles = array(); // Check whether this is the fallback text format. This format is available
foreach (user_roles() as $rid => $name) { // to all roles and cannot be deleted via the admin interface.
// Prepare a roles array with roles that may access the filter. $form['formats'][$id]['#is_fallback'] = ($id == $fallback_format);
if (strpos($format->roles, ",$rid,") !== FALSE) { if ($form['formats'][$id]['#is_fallback']) {
$roles[] = $name; $form['formats'][$id]['name'] = array('#markup' => theme('placeholder', $format->name));
$roles_markup = theme('placeholder', t('All roles may use this format'));
} }
else {
$form['formats'][$id]['name'] = array('#markup' => check_plain($format->name));
$roles = filter_get_roles_by_format($format);
$roles_markup = $roles ? implode(', ', $roles) : t('No roles may use this format');
} }
$default = ($id == variable_get('filter_default_format', 1)); $form['formats'][$id]['roles'] = array('#markup' => $roles_markup);
$options[$id] = ''; $form['formats'][$id]['configure'] = array('#markup' => l(t('configure'), 'admin/config/content/formats/' . $id));
$form[$id]['name'] = array('#markup' => $format->name); $form['formats'][$id]['delete'] = array('#markup' => $form['formats'][$id]['#is_fallback'] ? '' : l(t('delete'), 'admin/config/content/formats/delete/' . $id));
$form[$id]['roles'] = array('#markup' => $default ? t('All roles may use the default format') : ($roles ? implode(', ', $roles) : t('No roles may use this format'))); $form['formats'][$id]['weight'] = array('#type' => 'weight', '#default_value' => $format->weight);
$form[$id]['configure'] = array('#markup' => l(t('configure'), 'admin/config/content/formats/' . $id));
$form[$id]['delete'] = array('#markup' => $default ? '' : l(t('delete'), 'admin/config/content/formats/delete/' . $id));
$form[$id]['weight'] = array('#type' => 'weight', '#default_value' => $format->weight);
} }
$form['default'] = array('#type' => 'radios', '#options' => $options, '#default_value' => variable_get('filter_default_format', 1));
$form['submit'] = array('#type' => 'submit', '#value' => t('Save changes')); $form['submit'] = array('#type' => 'submit', '#value' => t('Save changes'));
return $form; return $form;
} }
function filter_admin_overview_submit($form, &$form_state) { function filter_admin_overview_submit($form, &$form_state) {
// Process form submission to set the default format. foreach ($form_state['values']['formats'] as $id => $data) {
if (is_numeric($form_state['values']['default'])) {
drupal_set_message(t('Default format updated.'));
variable_set('filter_default_format', $form_state['values']['default']);
}
foreach ($form_state['values'] as $id => $data) {
if (is_array($data) && isset($data['weight'])) { if (is_array($data) && isset($data['weight'])) {
// Only update if this is a form element with weight. // Only update if this is a form element with weight.
db_update('filter_format') db_update('filter_format')
@ -55,35 +50,31 @@ function filter_admin_overview_submit($form, &$form_state) {
->execute(); ->execute();
} }
} }
filter_formats_reset();
drupal_set_message(t('The text format ordering has been saved.')); drupal_set_message(t('The text format ordering has been saved.'));
} }
/** /**
* Theme the admin overview form. * Theme the text format administration overview form.
* *
* @ingroup themeable * @ingroup themeable
*/ */
function theme_filter_admin_overview($form) { function theme_filter_admin_overview($form) {
$rows = array(); $rows = array();
foreach (element_children($form) as $id) { foreach (element_children($form['formats']) as $id) {
$element = $form[$id]; $form['formats'][$id]['weight']['#attributes']['class'] = array('text-format-order-weight');
if (isset($element['roles']) && is_array($element['roles'])) {
$element['weight']['#attributes']['class'] = array('text-format-order-weight');
$rows[] = array( $rows[] = array(
'data' => array( 'data' => array(
check_plain($element['name']['#markup']), drupal_render($form['formats'][$id]['name']),
drupal_render($element['roles']), drupal_render($form['formats'][$id]['roles']),
drupal_render($form['default'][$id]), drupal_render($form['formats'][$id]['weight']),
drupal_render($element['weight']), drupal_render($form['formats'][$id]['configure']),
drupal_render($element['configure']), drupal_render($form['formats'][$id]['delete']),
drupal_render($element['delete']),
), ),
'class' => array('draggable'), 'class' => array('draggable'),
); );
unset($form[$id]);
} }
} $header = array(t('Name'), t('Roles'), t('Weight'), array('data' => t('Operations'), 'colspan' => 2));
$header = array(t('Name'), t('Roles'), t('Default'), t('Weight'), array('data' => t('Operations'), 'colspan' => 2));
$output = theme('table', $header, $rows, array('id' => 'text-format-order')); $output = theme('table', $header, $rows, array('id' => 'text-format-order'));
$output .= drupal_render_children($form); $output .= drupal_render_children($form);
@ -98,7 +89,7 @@ function theme_filter_admin_overview($form) {
function filter_admin_format_page($format = NULL) { function filter_admin_format_page($format = NULL) {
if (!isset($format->name)) { if (!isset($format->name)) {
drupal_set_title(t('Add text format'), PASS_THROUGH); drupal_set_title(t('Add text format'), PASS_THROUGH);
$format = (object)array('name' => '', 'roles' => '', 'format' => FILTER_FORMAT_DEFAULT); $format = (object)array('name' => '', 'format' => 0);
} }
return drupal_get_form('filter_admin_format_form', $format); return drupal_get_form('filter_admin_format_form', $format);
} }
@ -111,10 +102,9 @@ function filter_admin_format_page($format = NULL) {
* @see filter_admin_format_form_submit() * @see filter_admin_format_form_submit()
*/ */
function filter_admin_format_form($form, &$form_state, $format) { function filter_admin_format_form($form, &$form_state, $format) {
$default = ($format->format == variable_get('filter_default_format', 1)); $is_fallback = ($format->format == filter_fallback_format());
if ($default) { if ($is_fallback) {
$help = t('All roles for the default format must be enabled and cannot be changed.'); $help = t('All roles for this text format must be enabled and cannot be changed.');
$form['default_format'] = array('#type' => 'hidden', '#value' => 1);
} }
$form['name'] = array( $form['name'] = array(
@ -128,17 +118,16 @@ function filter_admin_format_form($form, &$form_state, $format) {
// Add a row of checkboxes for form group. // Add a row of checkboxes for form group.
$form['roles'] = array('#type' => 'fieldset', $form['roles'] = array('#type' => 'fieldset',
'#title' => t('Roles'), '#title' => t('Roles'),
'#description' => $default ? $help : t('Choose which roles may use this text format. Note that roles with the "administer filters" permission can always use all text formats.'), '#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, '#tree' => TRUE,
); );
$checked = filter_get_roles_by_format($format);
foreach (user_roles() as $rid => $name) { foreach (user_roles() as $rid => $name) {
$checked = strpos($format->roles, ",$rid,") !== FALSE;
$form['roles'][$rid] = array('#type' => 'checkbox', $form['roles'][$rid] = array('#type' => 'checkbox',
'#title' => $name, '#title' => $name,
'#default_value' => ($default || $checked), '#default_value' => ($is_fallback || isset($checked[$rid])),
); );
if ($default) { if ($is_fallback) {
$form['roles'][$rid]['#disabled'] = TRUE; $form['roles'][$rid]['#disabled'] = TRUE;
} }
} }
@ -201,13 +190,19 @@ function filter_admin_format_form_submit($form, &$form_state) {
$format->format = isset($form_state['values']['format']) ? $form_state['values']['format'] : NULL; $format->format = isset($form_state['values']['format']) ? $form_state['values']['format'] : NULL;
$status = filter_format_save($format); $status = filter_format_save($format);
if ($permission = filter_permission_name($format)) {
foreach ($format->roles as $rid => $enabled) {
user_role_change_permissions($rid, array($permission => $enabled));
}
}
switch ($status) { switch ($status) {
case SAVED_NEW: case SAVED_NEW:
drupal_set_message(t('Added text format %format.', array('%format' => $format->name))); drupal_set_message(t('Added text format %format.', array('%format' => $format->name)));
break; break;
case SAVED_UPDATED: case SAVED_UPDATED:
drupal_set_message(t('The text format settings have been updated.')); drupal_set_message(t('The text format %format has been updated.', array('%format' => $format->name)));
break; break;
} }
} }
@ -219,27 +214,16 @@ function filter_admin_format_form_submit($form, &$form_state) {
* @see filter_admin_delete_submit() * @see filter_admin_delete_submit()
*/ */
function filter_admin_delete($form, &$form_state, $format) { function filter_admin_delete($form, &$form_state, $format) {
if ($format) {
if ($format->format != variable_get('filter_default_format', 1)) {
$form['#format'] = $format; $form['#format'] = $format;
return confirm_form($form, return confirm_form($form,
t('Are you sure you want to delete the text format %format?', array('%format' => $format->name)), t('Are you sure you want to delete the text format %format?', array('%format' => $format->name)),
'admin/config/content/formats', 'admin/config/content/formats',
t('If you have any content left in this text format, it will be switched to the default text format. This action cannot be undone.'), t('If you have any content left in this text format, it will be switched to the %fallback text format. This action cannot be undone.', array('%fallback' => filter_fallback_format_title())),
t('Delete'), t('Delete'),
t('Cancel') t('Cancel')
); );
} }
else {
drupal_set_message(t('The default format cannot be deleted.'));
drupal_goto('admin/config/content/formats');
}
}
else {
drupal_not_found();
}
}
/** /**
* Process filter delete form submission. * Process filter delete form submission.

View File

@ -236,20 +236,21 @@ function hook_filter_format_update($format) {
* *
* It is recommended for modules to implement this hook, when they store * It is recommended for modules to implement this hook, when they store
* references to text formats to replace existing references to the deleted * references to text formats to replace existing references to the deleted
* text format with the default format. * text format with the fallback format.
* *
* @param $format * @param $format
* The format object of the format being deleted. * The format object of the format being deleted.
* @param $default * @param $fallback
* The format object of the site's default format. * The format object of the site's fallback format, which is always available
* to all users.
* *
* @see hook_filter_format_update(). * @see hook_filter_format_update().
* @see hook_filter_format_delete(). * @see hook_filter_format_delete().
*/ */
function hook_filter_format_delete($format, $default) { function hook_filter_format_delete($format, $fallback) {
// Replace the deleted format with the default format. // Replace the deleted format with the fallback format.
db_update('my_module_table') db_update('my_module_table')
->fields(array('format' => $default->format)) ->fields(array('format' => $fallback->format))
->condition('format', $format->format) ->condition('format', $format->format)
->execute(); ->execute();
} }

View File

@ -77,13 +77,6 @@ function filter_schema() {
'default' => '', 'default' => '',
'description' => 'Name of the text format (Filtered HTML).', 'description' => 'Name of the text format (Filtered HTML).',
), ),
'roles' => array(
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
'description' => 'A comma-separated string of roles; references {role}.rid.', // This is bad since you can't use joins, nor index.
),
'cache' => array( 'cache' => array(
'type' => 'int', 'type' => 'int',
'not null' => TRUE, 'not null' => TRUE,
@ -111,6 +104,11 @@ function filter_schema() {
return $schema; return $schema;
} }
/**
* @defgroup updates-6.x-to-7.x Filter updates from 6.x to 7.x
* @{
*/
/** /**
* Add a weight column to the filter formats table. * Add a weight column to the filter formats table.
*/ */
@ -260,3 +258,88 @@ function filter_update_7004() {
return $ret; return $ret;
} }
/**
* Integrate text formats with the user permissions system.
*
* This function converts text format role assignments to use the new text
* format permissions introduced in Drupal 7, creates a fallback (plain text)
* format that is available to all users, and explicitly sets the text format
* in cases that used to rely on a single site-wide default.
*/
function filter_update_7005() {
$ret = array();
// Move role data from the filter system to the user permission system.
$all_roles = array_keys(user_roles());
$default_format = variable_get('filter_default_format', 1);
$result = db_query("SELECT * FROM {filter_format}");
foreach ($result as $format) {
// We need to assign the default format to all roles (regardless of what
// was stored in the database) to preserve the behavior of the site at the
// moment of the upgrade.
$format_roles = ($format->format == $default_format ? $all_roles : explode(',', $format->roles));
foreach ($format_roles as $format_role) {
if (in_array($format_role, $all_roles)) {
user_role_grant_permissions($format_role, array(filter_permission_name($format)));
}
}
}
// Drop the roles field from the {filter_format} table.
db_drop_field($ret, 'filter_format', 'roles');
// Add a fallback text format which outputs plain text and appears last on
// the list for all users. Generate a unique name for it, starting with
// "Plain text".
$start_name = 'Plain text';
$format_name = $start_name;
while ($format = db_query('SELECT format FROM {filter_format} WHERE name = :name', array(':name' => $format_name))->fetchField()) {
$id = empty($id) ? 1 : $id + 1;
$format_name = $start_name . ' ' . $id;
}
$fallback_format = new stdClass();
$fallback_format->name = $format_name;
$fallback_format->cache = 1;
$fallback_format->weight = 1;
// This format should output plain text, so we escape all HTML and apply the
// line break filter only.
$fallback_format->filters = array(
'filter_html_escape' => array('status' => 1),
'filter_autop' => array('status' => 1),
);
filter_format_save($fallback_format);
variable_set('filter_fallback_format', $fallback_format->format);
drupal_set_message('A new <em>Plain text</em> format has been created which will be available to all users. You can configure this text format on the <a href="' . url('admin/config/content/formats/' . $fallback_format->format) . '">text format configuration page</a>.');
// Move the former site-wide default text format to the top of the list, so
// that it continues to be the default text format for all users.
db_update('filter_format')
->fields(array('weight' => -1))
->condition('format', $default_format)
->execute();
// It was previously possible for a value of "0" to be stored in database
// tables to indicate that a particular piece of text should be filtered
// using the default text format. Therefore, we have to convert all such
// instances (in Drupal core) to explicitly use the appropriate format.
// Note that the update of the node body field is handled separately, in
// node_update_7006().
foreach (array('block_custom', 'comment') as $table) {
if (db_table_exists($table)) {
db_update($table)
->fields(array('format' => $default_format))
->condition('format', 0)
->execute();
}
}
// We do not delete the 'filter_default_format' variable, since other modules
// may need it in their update functions.
// @todo This variable can be deleted in Drupal 8.
return $ret;
}
/**
* @} End of "defgroup updates-6.x-to-7.x"
* The next series of updates should start at 8000.
*/

View File

@ -6,14 +6,6 @@
* Framework for handling filtering of content. * Framework for handling filtering of content.
*/ */
/**
* Special format ID which means "use the default format".
*
* This value can be passed to the filter APIs as a format ID: this is
* equivalent to not passing an explicit format at all.
*/
define('FILTER_FORMAT_DEFAULT', 0);
/** /**
* Implement hook_help(). * Implement hook_help().
*/ */
@ -22,12 +14,12 @@ function filter_help($path, $arg) {
case 'admin/help#filter': case 'admin/help#filter':
$output = '<p>' . t("The filter module allows administrators to configure text formats for use on your site. A text format defines the HTML tags, codes, and other input allowed in both content and comments, and is a key feature in guarding against potentially damaging input from malicious users. Two formats included by default are <em>Filtered HTML</em> (which allows only an administrator-approved subset of HTML tags) and <em>Full HTML</em> (which allows the full set of HTML tags). Additional formats may be created by an administrator.") . '</p>'; $output = '<p>' . t("The filter module allows administrators to configure text formats for use on your site. A text format defines the HTML tags, codes, and other input allowed in both content and comments, and is a key feature in guarding against potentially damaging input from malicious users. Two formats included by default are <em>Filtered HTML</em> (which allows only an administrator-approved subset of HTML tags) and <em>Full HTML</em> (which allows the full set of HTML tags). Additional formats may be created by an administrator.") . '</p>';
$output .= '<p>' . t('Each text format uses filters to manipulate text, and most formats apply several different filters to text in a specific order. Each filter is designed for a specific purpose, and generally either adds, removes or transforms elements within user-entered text before it is displayed. A filter does not change the actual content of a post, but instead, modifies it temporarily before it is displayed. A filter may remove unapproved HTML tags, for instance, while another automatically adds HTML to make links referenced in text clickable.') . '</p>'; $output .= '<p>' . t('Each text format uses filters to manipulate text, and most formats apply several different filters to text in a specific order. Each filter is designed for a specific purpose, and generally either adds, removes or transforms elements within user-entered text before it is displayed. A filter does not change the actual content of a post, but instead, modifies it temporarily before it is displayed. A filter may remove unapproved HTML tags, for instance, while another automatically adds HTML to make links referenced in text clickable.') . '</p>';
$output .= '<p>' . t('Users with access to more than one text format can use the <em>Text format</em> fieldset to choose between available text formats when creating or editing multi-line content. Administrators determine the text formats available to each user role, select a default text format, and control the order of formats listed in the <em>Text format</em> fieldset.') . '</p>'; $output .= '<p>' . t('Users with access to more than one text format can use the <em>Text format</em> fieldset to choose between available text formats when creating or editing multi-line content. Administrators determine the text formats available to each user role and control the order of formats listed in the <em>Text format</em> fieldset.') . '</p>';
$output .= '<p>' . t('For more information, see the online handbook entry for <a href="@filter">Filter module</a>.', array('@filter' => 'http://drupal.org/handbook/modules/filter/')) . '</p>'; $output .= '<p>' . t('For more information, see the online handbook entry for <a href="@filter">Filter module</a>.', array('@filter' => 'http://drupal.org/handbook/modules/filter/')) . '</p>';
return $output; return $output;
case 'admin/config/content/formats': case 'admin/config/content/formats':
$output = '<p>' . t('Use the list below to review the text formats available to each user role, to select a default text format, and to control the order of formats listed in the <em>Text format</em> fieldset. (The <em>Text format</em> fieldset is displayed below textareas when users with access to more than one text format create multi-line content.) The text format selected as <em>Default</em> is available to all users and, unless another format is selected, is applied to all content. All text formats are available to users in roles with the "administer filters" permission.') . '</p>'; $output = '<p>' . t('Use the list below to review the text formats available to each user role and to control the order of formats listed in the <em>Text format</em> fieldset. (The <em>Text format</em> fieldset is displayed below textareas when users with access to more than one text format create multi-line content.) All text formats are available to users in roles with the "administer filters" permission, and the special %fallback format is available to all users. You can configure access to other text formats on the <a href="@url">permissions page</a>.', array('%fallback' => filter_fallback_format_title(), '@url' => url('admin/config/people/permissions', array('fragment' => 'module-filter')))) . '</p>';
$output .= '<p>' . t('Since text formats, if available, are presented in the same order as the list below, it may be helpful to arrange the formats in descending order of your preference for their use. Remember that your changes will not be saved until you click the <em>Save changes</em> button at the bottom of the page.') . '</p>'; $output .= '<p>' . t('Since text formats, if available, are presented in the same order as the list below, and the default format for each user is the first one on the list for which that user has access, it may be helpful to arrange the formats in descending order of your preference for their use. Remember that your changes will not be saved until you click the <em>Save changes</em> button at the bottom of the page.') . '</p>';
return $output; return $output;
case 'admin/config/content/formats/%': case 'admin/config/content/formats/%':
return '<p>' . t('Every <em>filter</em> performs one particular change on the user input, for example stripping out malicious HTML or making URLs clickable. Choose which filters you want to apply to text in this format. If you notice some filters are causing conflicts in the output, you can <a href="@rearrange">rearrange them</a>.', array('@rearrange' => url('admin/config/content/formats/' . $arg[4] . '/order'))) . '</p>'; return '<p>' . t('Every <em>filter</em> performs one particular change on the user input, for example stripping out malicious HTML or making URLs clickable. Choose which filters you want to apply to text in this format. If you notice some filters are causing conflicts in the output, you can <a href="@rearrange">rearrange them</a>.', array('@rearrange' => url('admin/config/content/formats/' . $arg[4] . '/order'))) . '</p>';
@ -133,13 +125,28 @@ function filter_menu() {
'title' => 'Delete text format', 'title' => 'Delete text format',
'page callback' => 'drupal_get_form', 'page callback' => 'drupal_get_form',
'page arguments' => array('filter_admin_delete', 4), 'page arguments' => array('filter_admin_delete', 4),
'access arguments' => array('administer filters'), 'access callback' => '_filter_delete_format_access',
'access arguments' => array(4),
'type' => MENU_CALLBACK, 'type' => MENU_CALLBACK,
'file' => 'filter.admin.inc', 'file' => 'filter.admin.inc',
); );
return $items; return $items;
} }
/**
* Access callback for deleting text formats.
*
* @param $format
* A text format object.
* @return
* TRUE if the text format can be deleted by the current user, FALSE
* otherwise.
*/
function _filter_delete_format_access($format) {
// The fallback format can never be deleted.
return user_access('administer filters') && ($format->format != filter_fallback_format());
}
/** /**
* Load a text format object from the database. * Load a text format object from the database.
* *
@ -150,7 +157,8 @@ function filter_menu() {
* A fully-populated text format object. * A fully-populated text format object.
*/ */
function filter_format_load($format) { function filter_format_load($format) {
return filter_formats($format); $formats = filter_formats();
return isset($formats[$format]) ? $formats[$format] : FALSE;
} }
/** /**
@ -160,17 +168,6 @@ function filter_format_load($format) {
* A format object. * A format object.
*/ */
function filter_format_save($format) { function filter_format_save($format) {
// We store the roles as a string for ease of use.
// We should always set all roles to TRUE when saving the default format.
// We use leading and trailing comma's to allow easy substring matching.
$roles = array_filter($format->roles);
if (!empty($format->format) && $format->format == variable_get('filter_default_format', 1)) {
$roles = ',' . implode(',', array_keys(user_roles())) . ',';
}
else {
$roles = ',' . implode(',', array_keys($roles)) . ',';
}
$format->roles = $roles;
$format->name = trim($format->name); $format->name = trim($format->name);
// Add a new text format. // Add a new text format.
@ -208,11 +205,17 @@ function filter_format_save($format) {
} }
else { else {
module_invoke_all('filter_format_update', $format); 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 call to drupal_write_record() above would not return an indication
// that anything had changed.
$return = SAVED_UPDATED;
// Clear the filter cache whenever a text format is updated.
cache_clear_all($format->format . ':', 'cache_filter', TRUE);
} }
// Clear the filter cache whenever a text format is saved. filter_formats_reset();
drupal_static_reset('filter_list_format');
cache_clear_all($format->format . ':', 'cache_filter', TRUE);
return $return; return $return;
} }
@ -232,9 +235,10 @@ function filter_format_delete($format) {
->execute(); ->execute();
// Allow modules to react on text format deletion. // Allow modules to react on text format deletion.
$default = filter_format_load(variable_get('filter_default_format', 1)); $fallback = filter_format_load(filter_fallback_format());
module_invoke_all('filter_format_delete', $format, $default); module_invoke_all('filter_format_delete', $format, $fallback);
filter_formats_reset();
cache_clear_all($format->format . ':', 'cache_filter', TRUE); cache_clear_all($format->format . ':', 'cache_filter', TRUE);
} }
@ -249,12 +253,42 @@ function filter_admin_format_title($format) {
* Implement hook_permission(). * Implement hook_permission().
*/ */
function filter_permission() { function filter_permission() {
return array( $perms['administer filters'] = array(
'administer filters' => array(
'title' => t('Administer filters'), 'title' => t('Administer filters'),
'description' => t('Manage text formats and filters, and select which roles may use them. %warning', array('%warning' => t('Warning: Give to trusted roles only; this permission has security implications.'))), 'description' => t('Manage text formats and filters, and use any of them, without restriction, when entering or editing content. %warning', array('%warning' => t('Warning: Give to trusted roles only; this permission has security implications.'))),
),
); );
// Generate permissions for each text format. Warn the administrator that any
// of them are potentially unsafe.
foreach (filter_formats() as $format) {
$permission = filter_permission_name($format);
if (!empty($permission)) {
// Only link to the text format configuration page if the user who is
// viewing this will have access to that page.
$format_name_replacement = user_access('administer filters') ? l($format->name, 'admin/config/content/formats/' . $format->format) : theme('placeholder', $format->name);
$perms[$permission] = array(
'title' => t("Use the %text_format text format", array('%text_format' => $format->name)),
'description' => t('Use !text_format in forms when entering or editing content. %warning', array('!text_format' => $format_name_replacement, '%warning' => t('Warning: This permission may have security implications depending on how the text format is configured.'))),
);
}
}
return $perms;
}
/**
* Returns the machine-readable permission name for a provided text format.
*
* @param $format
* An object representing a text format.
* @return
* The machine-readable permission name, or FALSE if the provided text format
* is malformed or is the fallback format (which is available to all users).
*/
function filter_permission_name($format) {
if (isset($format->format) && $format->format != filter_fallback_format()) {
return 'use text format ' . $format->format;
}
return FALSE;
} }
/** /**
@ -389,55 +423,139 @@ function _filter_html_escape_tips($filter, $format, $long = FALSE) {
*/ */
/** /**
* Retrieve a list of text formats. * Retrieve a list of text formats, ordered by weight.
* *
* @param $format
* (optional) The text format to retrieve; if omitted or NULL, retrieve an
* array of accessible text formats.
* @param $account * @param $account
* (optional) The user account to retrieve accessible text formats for; if * (optional) If provided, only those formats that are allowed for this user
* omitted, the currently logged-in user is used. * account will be returned. All formats will be returned otherwise.
*
* @return * @return
* Either one text format object or a list of text format objects, depending * An array of text format objects, keyed by the format ID and ordered by
* on the $format parameter. FALSE if the user does not have access to the * weight.
* given text $format. *
* @see filter_formats_reset()
*/ */
function filter_formats($format = NULL, $account = NULL) { function filter_formats($account = NULL) {
global $user;
$formats = &drupal_static(__FUNCTION__, array()); $formats = &drupal_static(__FUNCTION__, array());
// Statically cache all existing formats upfront.
if (!isset($formats['all'])) {
$formats['all'] = db_query('SELECT * FROM {filter_format} ORDER BY weight')->fetchAllAssoc('format');
}
// Build a list of user-specific formats.
if (isset($account) && !isset($formats['user'][$account->uid])) {
$formats['user'][$account->uid] = array();
foreach ($formats['all'] as $format) {
if (filter_access($format, $account)) {
$formats['user'][$account->uid][$format->format] = $format;
}
}
}
return isset($account) ? $formats['user'][$account->uid] : $formats['all'];
}
/**
* Resets the static cache of all text formats.
*
* @see filter_formats()
*/
function filter_formats_reset() {
drupal_static_reset('filter_list_format');
drupal_static_reset('filter_formats');
}
/**
* Retrieves a list of roles that are allowed to use a given text format.
*
* @param $format
* An object representing the text format.
* @return
* An array of role names, keyed by role ID.
*/
function filter_get_roles_by_format($format) {
// Handle the fallback format upfront (all roles have access to this format).
if ($format->format == filter_fallback_format()) {
return user_roles();
}
// Do not list any roles if the permission does not exist.
$permission = filter_permission_name($format);
return !empty($permission) ? user_roles(FALSE, $permission) : array();
}
/**
* Retrieves a list of text formats that are allowed for a given role.
*
* @param $rid
* The user role ID to retrieve text formats for.
* @return
* An array of text format objects that are allowed for the role, keyed by
* the text format ID and ordered by weight.
*/
function filter_get_formats_by_role($rid) {
$formats = array();
foreach (filter_formats() as $format) {
$roles = filter_get_roles_by_format($format);
if (isset($roles[$rid])) {
$formats[$format->format] = $format;
}
}
return $formats;
}
/**
* Returns the ID of the default text format for a particular user.
*
* The default text format is the first available format that the user is
* allowed to access, when the formats are ordered by weight. It should
* generally be used as a default choice when presenting the user with a list
* of possible text formats (for example, in a node creation form).
*
* Conversely, when existing content that does not have an assigned text format
* needs to be filtered for display, the default text format is the wrong
* choice, because it is not guaranteed to be consistent from user to user, and
* some trusted users may have an unsafe text format set by default, which
* should not be used on text of unknown origin. Instead, the fallback format
* returned by filter_fallback_format() should be used, since that is intended
* to be a safe, consistent format that is always available to all users.
*
* @param $account
* (optional) The user account to check. Defaults to the currently logged-in
* user.
* @return
* The ID of the user's default text format.
*
* @see filter_fallback_format()
*/
function filter_default_format($account = NULL) {
global $user;
if (!isset($account)) { if (!isset($account)) {
$account = $user; $account = $user;
} }
// Get a list of formats for this user, ordered by weight. The first one
// Administrators can always use all text formats. // available is the user's default format.
$all = user_access('administer filters', $account); $format = array_shift(filter_formats($account));
return $format->format;
if (!isset($formats[$account->uid])) {
$query = db_select('filter_format', 'f');
$query->addField('f', 'format', 'format');
$query->addField('f', 'name', 'name');
$query->addField('f', 'roles', 'roles');
$query->addField('f', 'cache', 'cache');
$query->addField('f', 'weight', 'weight');
$query->orderBy('weight');
// Build query for selecting the format(s) based on the user's roles.
if (!$all) {
$or = db_or()->condition('format', variable_get('filter_default_format', 1));
foreach ($user->roles as $rid => $role) {
$or->condition('roles', '%' . (int)$rid . '%', 'LIKE');
}
$query->condition($or);
} }
$formats[$account->uid] = $query->execute()->fetchAllAssoc('format'); /**
* Returns the ID of the fallback text format that all users have access to.
*/
function filter_fallback_format() {
// This variable is automatically set in the database for all installations
// of Drupal. In the event that it gets deleted somehow, there is no safe
// default to return, since we do not want to risk making an existing (and
// potentially unsafe) text format on the site automatically available to all
// users. Returning NULL at least guarantees that this cannot happen.
return variable_get('filter_fallback_format');
} }
if (isset($format)) {
return isset($formats[$account->uid][$format]) ? $formats[$account->uid][$format] : FALSE; /**
} * Returns the title of the fallback text format.
return $formats[$account->uid]; */
function filter_fallback_format_title() {
$fallback_format = filter_format_load(filter_fallback_format());
return filter_admin_format_title($fallback_format);
} }
/** /**
@ -469,18 +587,11 @@ function _filter_list_cmp($a, $b) {
return strcmp($a['title'], $b['title']); return strcmp($a['title'], $b['title']);
} }
/**
* Resolve a format id, including the default format.
*/
function filter_resolve_format($format) {
return $format == FILTER_FORMAT_DEFAULT ? variable_get('filter_default_format', 1) : $format;
}
/** /**
* Check if text in a certain text format is allowed to be cached. * Check if text in a certain text format is allowed to be cached.
*/ */
function filter_format_allowcache($format) { function filter_format_allowcache($format) {
static $cache = array(); static $cache = array();
$format = filter_resolve_format($format);
if (!isset($cache[$format])) { if (!isset($cache[$format])) {
$cache[$format] = db_query('SELECT cache FROM {filter_format} WHERE format = :format', array(':format' => $format))->fetchField(); $cache[$format] = db_query('SELECT cache FROM {filter_format} WHERE format = :format', array(':format' => $format))->fetchField();
} }
@ -557,8 +668,8 @@ function filter_list_format($format, $include_disabled = FALSE) {
* @param $text * @param $text
* The text to be filtered. * The text to be filtered.
* @param $format * @param $format
* The format of the text to be filtered. Specify FILTER_FORMAT_DEFAULT for * The format of the text to be filtered. If no format is assigned, the
* the default format. * fallback format will be used.
* @param $langcode * @param $langcode
* Optional: the language code of the text to be filtered, e.g. 'en' for * Optional: the language code of the text to be filtered, e.g. 'en' for
* English. This allows filters to be language aware so language specific * English. This allows filters to be language aware so language specific
@ -568,8 +679,10 @@ function filter_list_format($format, $include_disabled = FALSE) {
* The caller may set this to FALSE when the output is already cached * The caller may set this to FALSE when the output is already cached
* elsewhere to avoid duplicate cache lookups and storage. * elsewhere to avoid duplicate cache lookups and storage.
*/ */
function check_markup($text, $format = FILTER_FORMAT_DEFAULT, $langcode = '', $cache = TRUE) { function check_markup($text, $format = NULL, $langcode = '', $cache = TRUE) {
$format = filter_resolve_format($format); if (empty($format)) {
$format = filter_fallback_format();
}
// Check for a cached version of this piece of text. // Check for a cached version of this piece of text.
$cache_id = $format . ':' . $langcode . ':' . md5($text); $cache_id = $format . ':' . $langcode . ':' . md5($text);
@ -620,9 +733,16 @@ function check_markup($text, $format = FILTER_FORMAT_DEFAULT, $langcode = '', $c
* @return * @return
* HTML for the form element. * HTML for the form element.
*/ */
function filter_form($selected_format = FILTER_FORMAT_DEFAULT, $weight = NULL, $parents = array('format')) { function filter_form($selected_format = NULL, $weight = NULL, $parents = array('format')) {
$selected_format = filter_resolve_format($selected_format); global $user;
$formats = filter_formats();
// Use the default format for this user if none was selected.
if (empty($selected_format)) {
$selected_format = filter_default_format($user);
}
// Get a list of formats that the current user has access to.
$formats = filter_formats($user);
drupal_add_js('misc/form.js'); drupal_add_js('misc/form.js');
drupal_add_css(drupal_get_path('module', 'filter') . '/filter.css'); drupal_add_css(drupal_get_path('module', 'filter') . '/filter.css');
@ -665,28 +785,31 @@ function filter_form($selected_format = FILTER_FORMAT_DEFAULT, $weight = NULL, $
} }
/** /**
* Returns whether a user is allowed to access a given text format. * Checks if a user has access to a particular text format.
* *
* @param $format * @param $format
* The format of a text to be filtered. Specify FILTER_FORMAT_DEFAULT for * An object representing the text format.
* the site's default text format.
* @param $account * @param $account
* (optional) The user account to check access for; if omitted, the currently * (optional) The user account to check access for; if omitted, the currently
* logged-in user is used. * logged-in user is used.
* *
* @return * @return
* Boolean TRUE if the user is allowed to access the given format. * Boolean TRUE if the user is allowed to access the given format.
*
* @see filter_formats()
*/ */
function filter_access($format, $account = NULL) { function filter_access($format, $account = NULL) {
$format = filter_resolve_format($format); global $user;
if (user_access('administer filters', $account) || ($format == variable_get('filter_default_format', 1))) { if (!isset($account)) {
$account = $user;
}
// Handle special cases up front. All users have access to the fallback
// format, and administrators have access to all formats.
if (user_access('administer filters', $account) || $format->format == filter_fallback_format()) {
return TRUE; return TRUE;
} }
else { // Check the permission if one exists; otherwise, we have a non-existent
return (bool) filter_formats($format, $account); // format so we return FALSE.
} $permission = filter_permission_name($format);
return !empty($permission) && user_access($permission, $account);
} }
/** /**
@ -698,7 +821,9 @@ function filter_access($format, $account = NULL) {
* Helper function for fetching filter tips. * Helper function for fetching filter tips.
*/ */
function _filter_tips($format, $long = FALSE) { function _filter_tips($format, $long = FALSE) {
$formats = filter_formats(); global $user;
$formats = filter_formats($user);
$filter_info = filter_get_filters(); $filter_info = filter_get_filters();
$tips = array(); $tips = array();
@ -1034,15 +1159,3 @@ function _filter_html_escape($text) {
/** /**
* @} End of "Standard filters". * @} End of "Standard filters".
*/ */
/**
* Implement hook_user_role_delete().
*
* Remove deleted role from formats that use it.
*/
function filter_user_role_delete($role) {
db_update('filter_format')
->expression('roles', 'REPLACE(roles, :rid, :replacement)', array(':rid' => ',' . $role->rid, ':replacement' => ''))
->condition('roles', '%,' . $role->rid . '%', 'LIKE')
->execute();
}

View File

@ -21,22 +21,21 @@ class FilterAdminTestCase extends DrupalWebTestCase {
// Create users. // Create users.
$admin_user = $this->drupalCreateUser(array('administer filters')); $admin_user = $this->drupalCreateUser(array('administer filters'));
$web_user = $this->drupalCreateUser(array('create page content')); $web_user = $this->drupalCreateUser(array('create page content', 'edit own page content'));
$this->drupalLogin($admin_user); $this->drupalLogin($admin_user);
list($filtered, $full) = $this->checkFilterFormats(); list($filtered, $full, $plain) = $this->checkFilterFormats();
// Check that the fallback format exists and cannot be deleted.
$this->assertTrue(!empty($plain) && $plain == filter_fallback_format(), t('The fallback format is set to plain text.'));
$this->drupalGet('admin/config/content/formats');
$this->assertNoRaw('admin/config/content/formats/' . $plain . '/delete', t('Delete link for the fallback format not found.'));
$this->drupalGet('admin/config/content/formats/' . $plain . '/delete');
$this->assertResponse(403, t('The fallback format cannot be deleted.'));
// Verify access permissions to Full HTML format. // Verify access permissions to Full HTML format.
$this->assertTrue(filter_access($full, $admin_user), t('Admin user may use Full HTML.')); $this->assertTrue(filter_access(filter_format_load($full), $admin_user), t('Admin user may use Full HTML.'));
$this->assertFalse(filter_access($full, $web_user), t('Web user may not use Full HTML.')); $this->assertFalse(filter_access(filter_format_load($full), $web_user), t('Web user may not use Full HTML.'));
// Change default filter.
$edit = array();
$edit['default'] = $full;
$this->drupalPost('admin/config/content/formats', $edit, t('Save changes'));
$this->assertText(t('Default format updated.'), t('Default filter updated successfully.'));
$this->assertNoRaw('admin/config/content/formats/' . $full . '/delete', t('Delete link not found.'));
// Add an additional tag. // Add an additional tag.
$edit = array(); $edit = array();
@ -87,20 +86,13 @@ class FilterAdminTestCase extends DrupalWebTestCase {
$this->assertRaw(t('Deleted text format %format.', array('%format' => $edit['name'])), t('Format successfully deleted.')); $this->assertRaw(t('Deleted text format %format.', array('%format' => $edit['name'])), t('Format successfully deleted.'));
} }
// Change default filter back.
$edit = array();
$edit['default'] = $filtered;
$this->drupalPost('admin/config/content/formats', $edit, t('Save changes'));
$this->assertText(t('Default format updated.'), t('Default filter updated successfully.'));
$this->assertNoRaw('admin/config/content/formats/' . $filtered . '/delete', t('Delete link not found.'));
// Allow authenticated users on full HTML. // Allow authenticated users on full HTML.
$format = filter_format_load($full);
$edit = array(); $edit = array();
$edit['roles[1]'] = 0; $edit['roles[1]'] = 0;
$edit['roles[2]'] = 1; $edit['roles[2]'] = 1;
$this->drupalPost('admin/config/content/formats/' . $full, $edit, t('Save configuration')); $this->drupalPost('admin/config/content/formats/' . $full, $edit, t('Save configuration'));
$this->assertText(t('The text format settings have been updated.'), t('Full HTML format successfully updated.')); $this->assertRaw(t('The text format %format has been updated.', array('%format' => $format->name)), t('Full HTML format successfully updated.'));
// Switch user. // Switch user.
$this->drupalLogout(); $this->drupalLogout();
@ -110,13 +102,14 @@ class FilterAdminTestCase extends DrupalWebTestCase {
$this->assertRaw('<option value="' . $full . '">Full HTML</option>', t('Full HTML filter accessible.')); $this->assertRaw('<option value="' . $full . '">Full HTML</option>', t('Full HTML filter accessible.'));
// Use filtered HTML and see if it removes tags that are not allowed. // Use filtered HTML and see if it removes tags that are not allowed.
$body = $this->randomName(); $body = '<em>' . $this->randomName() . '</em>';
$extra_text = 'text'; $extra_text = 'text';
$text = $body . '<random>' . $extra_text . '</random>';
$edit = array(); $edit = array();
$edit['title'] = $this->randomName(); $edit['title'] = $this->randomName();
$langcode = FIELD_LANGUAGE_NONE; $langcode = FIELD_LANGUAGE_NONE;
$edit["body[$langcode][0][value]"] = $body . '<random>' . $extra_text . '</random>'; $edit["body[$langcode][0][value]"] = $text;
$edit["body[$langcode][0][value_format]"] = $filtered; $edit["body[$langcode][0][value_format]"] = $filtered;
$this->drupalPost('node/add/page', $edit, t('Save')); $this->drupalPost('node/add/page', $edit, t('Save'));
$this->assertRaw(t('Page %title has been created.', array('%title' => $edit['title'])), t('Filtered node created.')); $this->assertRaw(t('Page %title has been created.', array('%title' => $edit['title'])), t('Filtered node created.'));
@ -125,7 +118,14 @@ class FilterAdminTestCase extends DrupalWebTestCase {
$this->assertTrue($node, t('Node found in database.')); $this->assertTrue($node, t('Node found in database.'));
$this->drupalGet('node/' . $node->nid); $this->drupalGet('node/' . $node->nid);
$this->assertText($body . $extra_text, t('Filter removed invalid tag.')); $this->assertRaw($body . $extra_text, t('Filter removed invalid tag.'));
// Use plain text and see if it escapes all tags, whether allowed or not.
$edit = array();
$edit["body[$langcode][0][value_format]"] = $plain;
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
$this->drupalGet('node/' . $node->nid);
$this->assertText(check_plain($text), t('The "Plain text" text format escapes all HTML tags.'));
// Switch user. // Switch user.
$this->drupalLogout(); $this->drupalLogout();
@ -142,7 +142,7 @@ class FilterAdminTestCase extends DrupalWebTestCase {
$edit = array(); $edit = array();
$edit['roles[2]'] = FALSE; $edit['roles[2]'] = FALSE;
$this->drupalPost('admin/config/content/formats/' . $full, $edit, t('Save configuration')); $this->drupalPost('admin/config/content/formats/' . $full, $edit, t('Save configuration'));
$this->assertText(t('The text format settings have been updated.'), t('Full HTML format successfully reverted.')); $this->assertRaw(t('The text format %format has been updated.', array('%format' => $format->name)), t('Full HTML format successfully reverted.'));
// Filter order. // Filter order.
$edit = array(); $edit = array();
@ -153,16 +153,17 @@ class FilterAdminTestCase extends DrupalWebTestCase {
} }
/** /**
* Query the database to get the two basic formats. * Query the database to get the three basic formats.
* *
* @return * @return
* An array containing filtered and full filter ids. * An array containing filtered, full, and plain text format ids.
*/ */
function checkFilterFormats() { function checkFilterFormats() {
$result = db_query('SELECT format, name FROM {filter_format}'); $result = db_query('SELECT format, name FROM {filter_format}');
$filtered = -1; $filtered = -1;
$full = -1; $full = -1;
$plain = -1;
foreach ($result as $format) { foreach ($result as $format) {
if ($format->name == 'Filtered HTML') { if ($format->name == 'Filtered HTML') {
$filtered = $format->format; $filtered = $format->format;
@ -170,9 +171,12 @@ class FilterAdminTestCase extends DrupalWebTestCase {
elseif ($format->name == 'Full HTML') { elseif ($format->name == 'Full HTML') {
$full = $format->format; $full = $format->format;
} }
elseif ($format->name == 'Plain text') {
$plain = $format->format;
}
} }
return array($filtered, $full); return array($filtered, $full, $plain);
} }
/** /**
@ -188,6 +192,184 @@ class FilterAdminTestCase extends DrupalWebTestCase {
} }
} }
class FilterAccessTestCase extends DrupalWebTestCase {
protected $admin_user;
protected $web_user;
protected $allowed_format;
protected $disallowed_format;
public static function getInfo() {
return array(
'name' => 'Filter access functionality',
'description' => 'Test the filter access system.',
'group' => 'Filter',
);
}
function setUp() {
parent::setUp();
// Create two text formats and grant a regular user access to one of them.
$this->admin_user = $this->drupalCreateUser(array('administer filters'));
$this->drupalLogin($this->admin_user);
$formats = array();
for ($i = 0; $i < 2; $i++) {
$edit = array('name' => $this->randomName());
$this->drupalPost('admin/config/content/formats/add', $edit, t('Save configuration'));
$this->resetFilterCaches();
$format_id = db_query("SELECT format FROM {filter_format} WHERE name = :name", array(':name' => $edit['name']))->fetchField();
$formats[] = filter_format_load($format_id);
}
list($this->allowed_format, $this->disallowed_format) = $formats;
$this->web_user = $this->drupalCreateUser(array('create page content', filter_permission_name($this->allowed_format)));
}
function testFormatPermissions() {
// Make sure that a regular user only has access to the text format they
// were granted access to, as well to the fallback format.
$this->assertTrue(filter_access($this->allowed_format, $this->web_user), t('A regular user has access to a text format they were granted access to.'));
$this->assertFalse(filter_access($this->disallowed_format, $this->web_user), t('A regular user does not have access to a text format they were not granted access to.'));
$this->assertTrue(filter_access(filter_format_load(filter_fallback_format()), $this->web_user), t('A regular user has access to the fallback format.'));
// Perform similar checks as above, but now against the entire list of
// available formats for this user.
$this->assertTrue(in_array($this->allowed_format->format, array_keys(filter_formats($this->web_user))), t('The allowed format appears in the list of available formats for a regular user.'));
$this->assertFalse(in_array($this->disallowed_format->format, array_keys(filter_formats($this->web_user))), t('The disallowed format does not appear in the list of available formats for a regular user.'));
$this->assertTrue(in_array(filter_fallback_format(), array_keys(filter_formats($this->web_user))), t('The fallback format appears in the list of available formats for a regular user.'));
// Make sure that a regular user only has permission to use the format
// they were granted access to.
$this->assertTrue(user_access(filter_permission_name($this->allowed_format), $this->web_user), t('A regular user has permission to use the allowed text format.'));
$this->assertFalse(user_access(filter_permission_name($this->disallowed_format), $this->web_user), t('A regular user does not have permission to use the disallowed text format.'));
// Make sure that the allowed format appears on the node form and that
// the disallowed format does not.
$this->drupalLogin($this->web_user);
$this->drupalGet('node/add/page');
$this->assertRaw($this->formatSelectorHTML($this->allowed_format), t('The allowed text format appears as an option when adding a new node.'));
$this->assertNoRaw($this->formatSelectorHTML($this->disallowed_format), t('The disallowed text format does not appear as an option when adding a new node.'));
$this->assertRaw($this->formatSelectorHTML(filter_format_load(filter_fallback_format())), t('The fallback format appears as an option when adding a new node.'));
}
function testFormatRoles() {
// Get the role ID assigned to the regular user; it must be the maximum.
$rid = max(array_keys($this->web_user->roles));
// Check that this role appears in the list of roles that have access to an
// allowed text format, but does not appear in the list of roles that have
// access to a disallowed text format.
$this->assertTrue(in_array($rid, array_keys(filter_get_roles_by_format($this->allowed_format))), t('A role which has access to a text format appears in the list of roles that have access to that format.'));
$this->assertFalse(in_array($rid, array_keys(filter_get_roles_by_format($this->disallowed_format))), t('A role which does not have access to a text format does not appear in the list of roles that have access to that format.'));
// Check that the correct text format appears in the list of formats
// available to that role.
$this->assertTrue(in_array($this->allowed_format->format, array_keys(filter_get_formats_by_role($rid))), t('A text format which a role has access to appears in the list of formats available to that role.'));
$this->assertFalse(in_array($this->disallowed_format->format, array_keys(filter_get_formats_by_role($rid))), t('A text format which a role does not have access to does not appear in the list of formats available to that role.'));
// Check that the fallback format is always allowed.
$this->assertEqual(filter_get_roles_by_format(filter_format_load(filter_fallback_format())), user_roles(), t('All roles have access to the fallback format.'));
$this->assertTrue(in_array(filter_fallback_format(), array_keys(filter_get_formats_by_role($rid))), t('The fallback format appears in the list of allowed formats for any role.'));
}
/**
* Returns the expected HTML for a particular text format selector.
*
* @param $format
* An object representing the text format for which to return HTML.
* @return
* The expected HTML for that text format's selector.
*/
function formatSelectorHTML($format) {
return '<option value="' . $format->format . '">' . $format->name . '</option>';
}
/**
* Rebuild text format and permission caches in the thread running the tests.
*/
protected function resetFilterCaches() {
filter_formats_reset();
$this->checkPermissions(array(), TRUE);
}
}
class FilterDefaultFormatTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'Default text format functionality',
'description' => 'Test the default text formats for different users.',
'group' => 'Filter',
);
}
function testDefaultTextFormats() {
// Create two text formats, and two users. The first user has access to
// both formats, but the second user only has access to the second one.
$admin_user = $this->drupalCreateUser(array('administer filters'));
$this->drupalLogin($admin_user);
$formats = array();
for ($i = 0; $i < 2; $i++) {
$edit = array('name' => $this->randomName());
$this->drupalPost('admin/config/content/formats/add', $edit, t('Save configuration'));
$this->resetFilterCaches();
$format_id = db_query("SELECT format FROM {filter_format} WHERE name = :name", array(':name' => $edit['name']))->fetchField();
$formats[] = filter_format_load($format_id);
}
list($first_format, $second_format) = $formats;
$first_user = $this->drupalCreateUser(array(filter_permission_name($first_format), filter_permission_name($second_format)));
$second_user = $this->drupalCreateUser(array(filter_permission_name($second_format)));
// 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();
$edit = array();
$edit['formats[' . $first_format->format . '][weight]'] = $minimum_weight - 2;
$edit['formats[' . $second_format->format . '][weight]'] = $minimum_weight - 1;
$this->drupalPost('admin/config/content/formats', $edit, t('Save changes'));
$this->resetFilterCaches();
// Check that each user's default format is the lowest weighted format that
// the user has access to.
$this->assertEqual(filter_default_format($first_user), $first_format->format, t("The first user's default format is the lowest weighted format that the user has access to."));
$this->assertEqual(filter_default_format($second_user), $second_format->format, t("The second user's default format is the lowest weighted format that the user has access to, and is different than the first user's."));
// Reorder the two formats, and check that both users now have the same
// default.
$edit = array();
$edit['formats[' . $second_format->format . '][weight]'] = $minimum_weight - 3;
$this->drupalPost('admin/config/content/formats', $edit, t('Save changes'));
$this->resetFilterCaches();
$this->assertEqual(filter_default_format($first_user), filter_default_format($second_user), t('After the formats are reordered, both users have the same default format.'));
}
/**
* Rebuild text format and permission caches in the thread running the tests.
*/
protected function resetFilterCaches() {
filter_formats_reset();
$this->checkPermissions(array(), TRUE);
}
}
class FilterNoFormatTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'Unassigned text format functionality',
'description' => 'Test the behavior of check_markup() when it is called without a text format.',
'group' => 'Filter',
);
}
function testCheckMarkupNoFormat() {
// Create some text. Include some HTML and line breaks, so we get a good
// test of the filtering that is applied to it.
$text = "<strong>" . $this->randomName(32) . "</strong>\n\n<div>" . $this->randomName(32) . "</div>";
// Make sure that when this text is run through check_markup() with no text
// format, it is filtered as though it is in the fallback format.
$this->assertEqual(check_markup($text), check_markup($text, filter_fallback_format()), t('Text with no format is filtered the same as text in the fallback format.'));
}
}
/** /**
* Unit tests for core filters. * Unit tests for core filters.
*/ */
@ -805,7 +987,7 @@ class FilterHooksTestCase extends DrupalWebTestCase {
$edit = array(); $edit = array();
$edit['roles[2]'] = 1; $edit['roles[2]'] = 1;
$this->drupalPost('admin/config/content/formats/' . $format, $edit, t('Save configuration')); $this->drupalPost('admin/config/content/formats/' . $format, $edit, t('Save configuration'));
$this->assertRaw(t('The text format settings have been updated.'), t('Full HTML format successfully updated.')); $this->assertRaw(t('The text format %format has been updated.', array('%format' => $name)), t('Format successfully updated.'));
$this->assertText('hook_filter_format_update invoked.', t('hook_filter_format_update() was invoked.')); $this->assertText('hook_filter_format_update invoked.', t('hook_filter_format_update() was invoked.'));
// Add a new custom block. // Add a new custom block.
@ -827,14 +1009,13 @@ class FilterHooksTestCase extends DrupalWebTestCase {
$this->assertRaw(t('Deleted text format %format.', array('%format' => $name)), t('Format successfully deleted.')); $this->assertRaw(t('Deleted text format %format.', array('%format' => $name)), t('Format successfully deleted.'));
$this->assertText('hook_filter_format_delete invoked.', t('hook_filter_format_delete() was invoked.')); $this->assertText('hook_filter_format_delete invoked.', t('hook_filter_format_delete() was invoked.'));
// Verify that the deleted format was replaced with the default format. // Verify that the deleted format was replaced with the fallback format.
$current_format = db_select('block_custom', 'b') $current_format = db_select('block_custom', 'b')
->fields('b', array('format')) ->fields('b', array('format'))
->condition('bid', $bid) ->condition('bid', $bid)
->execute() ->execute()
->fetchField(); ->fetchField();
$default = variable_get('filter_default_format', 1); $this->assertEqual($current_format, filter_fallback_format(), t('Deleted text format replaced with the fallback format.'));
$this->assertEqual($current_format, $default, t('Deleted text format replaced with the default format.'));
} }
} }

View File

@ -506,7 +506,11 @@ function node_update_7006(&$context) {
$revision->body = substr($revision->body, strlen($break)); $revision->body = substr($revision->body, strlen($break));
} }
$node->body[FIELD_LANGUAGE_NONE][0]['value'] = $revision->body; $node->body[FIELD_LANGUAGE_NONE][0]['value'] = $revision->body;
$node->body[FIELD_LANGUAGE_NONE][0]['format'] = $revision->format; // Explicitly store the current default text format if the revision
// did not have its own text format. Similar conversions for other
// core modules are performed in filter_update_7005(), but we do this
// one here since we are already migrating the data.
$node->body[FIELD_LANGUAGE_NONE][0]['format'] = !empty($revision->format) ? $revision->format : variable_get('filter_default_format', 1);
// This is a core update and no contrib modules are enabled yet, so // This is a core update and no contrib modules are enabled yet, so
// we can assume default field storage for a faster update. // we can assume default field storage for a faster update.
field_sql_storage_field_storage_write('node', $node, FIELD_STORAGE_INSERT, array()); field_sql_storage_field_storage_write('node', $node, FIELD_STORAGE_INSERT, array());

View File

@ -19,7 +19,6 @@ function php_install() {
$format = db_insert('filter_format') $format = db_insert('filter_format')
->fields(array( ->fields(array(
'name' => 'PHP code', 'name' => 'PHP code',
'roles' => '',
'cache' => 0, 'cache' => 0,
)) ))
->execute(); ->execute();

View File

@ -5,6 +5,8 @@
* Base PHP test case class. * Base PHP test case class.
*/ */
class PHPTestCase extends DrupalWebTestCase { class PHPTestCase extends DrupalWebTestCase {
protected $php_code_format;
function setUp() { function setUp() {
parent::setUp('php'); parent::setUp('php');
@ -12,9 +14,14 @@ class PHPTestCase extends DrupalWebTestCase {
$admin_user = $this->drupalCreateUser(array('administer filters')); $admin_user = $this->drupalCreateUser(array('administer filters'));
$this->drupalLogin($admin_user); $this->drupalLogin($admin_user);
// Confirm that the PHP filter is #3. // Confirm that the PHP code text format was inserted as the newest format
$this->drupalGet('admin/config/content/formats/3'); // on the site.
$this->assertText('PHP code', t('On PHP code filter page.')); $newest_format_id = db_query("SELECT MAX(format) FROM {filter_format}")->fetchField();
$newest_format = filter_format_load($newest_format_id);
$this->assertEqual($newest_format->name, 'PHP code', t('PHP code text format was created.'));
// Store the format ID of the PHP code text format for later use.
$this->php_code_format = $newest_format_id;
} }
/** /**
@ -43,15 +50,12 @@ class PHPFilterTestCase extends PHPTestCase {
* Make sure that the PHP filter evaluates PHP code when used. * Make sure that the PHP filter evaluates PHP code when used.
*/ */
function testPHPFilter() { function testPHPFilter() {
// Setup PHP filter. // Log in as a user with permission to use the PHP code text format.
$edit = array(); $php_code_permission = filter_permission_name(filter_format_load($this->php_code_format));
$edit['roles[2]'] = TRUE; // Set authenticated users to have permission to use filter. $web_user = $this->drupalCreateUser(array('access content', 'create page content', 'edit own page content', $php_code_permission));
$this->drupalPost(NULL, $edit, 'Save configuration');
$this->assertText(t('The text format settings have been updated.'), t('PHP format available to authenticated users.'));
// Create node with PHP filter enabled.
$web_user = $this->drupalCreateUser(array('access content', 'create page content', 'edit own page content'));
$this->drupalLogin($web_user); $this->drupalLogin($web_user);
// Create a node with PHP code in it.
$node = $this->createNodeWithCode(); $node = $this->createNodeWithCode();
// Make sure that the PHP code shows up as text. // Make sure that the PHP code shows up as text.
@ -61,7 +65,7 @@ class PHPFilterTestCase extends PHPTestCase {
// Change filter to PHP filter and see that PHP code is evaluated. // Change filter to PHP filter and see that PHP code is evaluated.
$edit = array(); $edit = array();
$langcode = FIELD_LANGUAGE_NONE; $langcode = FIELD_LANGUAGE_NONE;
$edit["body[$langcode][0][value_format]"] = 3; $edit["body[$langcode][0][value_format]"] = $this->php_code_format;
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save')); $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
$this->assertRaw(t('Page %title has been updated.', array('%title' => $node->title)), t('PHP code filter turned on.')); $this->assertRaw(t('Page %title has been updated.', array('%title' => $node->title)), t('PHP code filter turned on.'));
@ -98,6 +102,6 @@ class PHPAccessTestCase extends PHPTestCase {
// Make sure that user doesn't have access to filter. // Make sure that user doesn't have access to filter.
$this->drupalGet('node/' . $node->nid . '/edit'); $this->drupalGet('node/' . $node->nid . '/edit');
$this->assertNoFieldByName('body_format', '3', t('Format not available.')); $this->assertNoRaw('<option value="' . $this->php_code_format . '">', t('PHP code format not available.'));
} }
} }

View File

@ -292,7 +292,7 @@ function profile_view_field($account, $field) {
if (isset($account->{$field->name}) && $value = $account->{$field->name}) { if (isset($account->{$field->name}) && $value = $account->{$field->name}) {
switch ($field->type) { switch ($field->type) {
case 'textarea': case 'textarea':
return check_markup($value); return check_markup($value, filter_default_format($account));
case 'textfield': case 'textfield':
case 'selection': case 'selection':
return $browse ? l($value, 'profile/' . $field->name . '/' . $value) : check_plain($value); return $browse ? l($value, 'profile/' . $field->name . '/' . $value) : check_plain($value);

View File

@ -728,7 +728,7 @@ class DrupalWebTestCase extends DrupalTestCase {
// Merge body field value and format separately. // Merge body field value and format separately.
$body = array( $body = array(
'value' => $this->randomName(32), 'value' => $this->randomName(32),
'format' => FILTER_FORMAT_DEFAULT 'format' => filter_default_format(),
); );
$settings['body'][FIELD_LANGUAGE_NONE][0] += $body; $settings['body'][FIELD_LANGUAGE_NONE][0] += $body;

View File

@ -374,7 +374,17 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase {
// Create a node, using the PHP filter that tests drupal_add_css(). // Create a node, using the PHP filter that tests drupal_add_css().
$settings = array( $settings = array(
'type' => 'page', 'type' => 'page',
'body' => array(FIELD_LANGUAGE_NONE => array(array('value' => t('This tests the inline CSS!') . "<?php drupal_add_css('$css', 'inline'); ?>", 'format' => 3))), // PHP filter. 'body' => array(
FIELD_LANGUAGE_NONE => array(
array(
'value' => t('This tests the inline CSS!') . "<?php drupal_add_css('$css', 'inline'); ?>",
// The "PHP code" format is always the most recent one added, since
// the PHP module was enabled in the setUp() method of the current
// test.
'format' => db_query("SELECT MAX(format) FROM {filter_format}")->fetchField(),
),
),
),
'promote' => 1, 'promote' => 1,
); );
$node = $this->drupalCreateNode($settings); $node = $this->drupalCreateNode($settings);

View File

@ -409,7 +409,6 @@ function system_install() {
->execute(); ->execute();
} }
variable_set('theme_default', 'garland'); variable_set('theme_default', 'garland');
db_update('system') db_update('system')
@ -433,15 +432,22 @@ function system_install() {
$filtered_html_format = db_insert('filter_format') $filtered_html_format = db_insert('filter_format')
->fields(array( ->fields(array(
'name' => 'Filtered HTML', 'name' => 'Filtered HTML',
'roles' => ',' . DRUPAL_ANONYMOUS_RID . ',' . DRUPAL_AUTHENTICATED_RID . ',',
'cache' => 1, 'cache' => 1,
'weight' => 0,
)) ))
->execute(); ->execute();
$full_html_format = db_insert('filter_format') $full_html_format = db_insert('filter_format')
->fields(array( ->fields(array(
'name' => 'Full HTML', 'name' => 'Full HTML',
'roles' => '',
'cache' => 1, 'cache' => 1,
'weight' => 0,
))
->execute();
$plain_text_format = db_insert('filter_format')
->fields(array(
'name' => 'Plain text',
'cache' => 1,
'weight' => 1,
)) ))
->execute(); ->execute();
@ -507,10 +513,27 @@ function system_install() {
'weight' => 10, 'weight' => 10,
'status' => 1, 'status' => 1,
)) ))
// Plain text:
// Escape all HTML.
->values(array(
'format' => $plain_text_format,
'module' => 'filter',
'name' => 'filter_html_escape',
'weight' => 0,
'status' => 1,
))
// Line break filter.
->values(array(
'format' => $plain_text_format,
'module' => 'filter',
'name' => 'filter_autop',
'weight' => 1,
'status' => 1,
))
->execute(); ->execute();
// Set the default input format to Filtered HTML. // Set the fallback format to plain text.
variable_set('filter_default_format', $filtered_html_format); variable_set('filter_fallback_format', $plain_text_format);
$cron_key = md5(mt_rand()); $cron_key = md5(mt_rand());
@ -2073,8 +2096,9 @@ function system_update_7021() {
$ret[] = update_sql("UPDATE {block} SET region = 'sidebar_second' WHERE region = 'right'"); $ret[] = update_sql("UPDATE {block} SET region = 'sidebar_second' WHERE region = 'right'");
// Migrate contact form information. // Migrate contact form information.
$default_format = variable_get('filter_default_format', 1);
if ($contact_help = variable_get('contact_form_information', '')) { if ($contact_help = variable_get('contact_form_information', '')) {
$bid = db_insert('box')->fields(array('body' => $contact_help, 'info' => 'Contact page help', 'format' => FILTER_FORMAT_DEFAULT))->execute(); $bid = db_insert('box')->fields(array('body' => $contact_help, 'info' => 'Contact page help', 'format' => $default_format))->execute();
foreach ($themes_with_blocks as $theme) { foreach ($themes_with_blocks as $theme) {
// Add contact help block for themes, which had blocks. // Add contact help block for themes, which had blocks.
$ret[] = update_sql("INSERT INTO {block} (module, delta, theme, status, weight, region, visibility, pages, cache) VALUES ('block', '" . $bid . "', '" . $theme . "', 1, 5, 'help', 1, 'contact', -1)"); $ret[] = update_sql("INSERT INTO {block} (module, delta, theme, status, weight, region, visibility, pages, cache) VALUES ('block', '" . $bid . "', '" . $theme . "', 1, 5, 'help', 1, 'contact', -1)");
@ -2084,7 +2108,7 @@ function system_update_7021() {
// Migrate user help setting. // Migrate user help setting.
if ($user_help = variable_get('user_registration_help', '')) { if ($user_help = variable_get('user_registration_help', '')) {
$bid = db_insert('box')->fields(array('body' => $user_help, 'info' => 'User registration guidelines', 'format' => FILTER_FORMAT_DEFAULT))->execute(); $bid = db_insert('box')->fields(array('body' => $user_help, 'info' => 'User registration guidelines', 'format' => $default_format))->execute();
foreach ($themes_with_blocks as $theme) { foreach ($themes_with_blocks as $theme) {
// Add user registration help block for themes, which had blocks. // Add user registration help block for themes, which had blocks.
$ret[] = update_sql("INSERT INTO {block} (module, delta, theme, status, weight, region, visibility, pages, cache) VALUES ('block', '" . $bid . "', '" . $theme . "', 1, 5, 'help', 1, 'user/register', -1)"); $ret[] = update_sql("INSERT INTO {block} (module, delta, theme, status, weight, region, visibility, pages, cache) VALUES ('block', '" . $bid . "', '" . $theme . "', 1, 5, 'help', 1, 'user/register', -1)");
@ -2094,7 +2118,7 @@ function system_update_7021() {
// Migrate site mission setting. // Migrate site mission setting.
if ($mission = variable_get('site_mission')) { if ($mission = variable_get('site_mission')) {
$bid = db_insert('box')->fields(array('body' => $mission, 'info' => 'Site mission', 'format' => FILTER_FORMAT_DEFAULT))->execute(); $bid = db_insert('box')->fields(array('body' => $mission, 'info' => 'Site mission', 'format' => $default_format))->execute();
foreach ($themes_with_blocks as $theme) { foreach ($themes_with_blocks as $theme) {
// Add mission block for themes, which had blocks. // Add mission block for themes, which had blocks.
$ret[] = update_sql("INSERT INTO {block} (module, delta, theme, status, weight, region, visibility, pages, cache) VALUES ('block', '" . $bid . "', '" . $theme . "', 1, 0, 'highlight', 1, '<front>', -1)"); $ret[] = update_sql("INSERT INTO {block} (module, delta, theme, status, weight, region, visibility, pages, cache) VALUES ('block', '" . $bid . "', '" . $theme . "', 1, 0, 'highlight', 1, '<front>', -1)");
@ -2106,7 +2130,7 @@ function system_update_7021() {
// Migrate site footer message to a custom block. // Migrate site footer message to a custom block.
if ($footer_message = variable_get('site_footer', '')) { if ($footer_message = variable_get('site_footer', '')) {
$bid = db_insert('box')->fields(array('body' => $footer_message, 'info' => 'Footer message', 'format' => FILTER_FORMAT_DEFAULT))->execute(); $bid = db_insert('box')->fields(array('body' => $footer_message, 'info' => 'Footer message', 'format' => $default_format))->execute();
foreach ($themes_with_blocks as $theme) { foreach ($themes_with_blocks as $theme) {
// Add site footer block for themes, which had blocks. // Add site footer block for themes, which had blocks.
// Set low weight, so the block comes early (it used to be // Set low weight, so the block comes early (it used to be

View File

@ -184,9 +184,8 @@ function default_install() {
db_insert('taxonomy_vocabulary_node_type')->fields(array('vid' => $vid, 'type' => 'article'))->execute(); db_insert('taxonomy_vocabulary_node_type')->fields(array('vid' => $vid, 'type' => 'article'))->execute();
// Enable default permissions for system roles. // Enable default permissions for system roles.
user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('access content')); user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('access content', 'use text format 1'));
user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID, array('access content', 'access comments', 'post comments', 'post comments without approval')); user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID, array('access content', 'access comments', 'post comments', 'post comments without approval', 'use text format 1'));
// Create a default role for site administrators, with all available permissions assigned. // Create a default role for site administrators, with all available permissions assigned.
$admin_role = new stdClass(); $admin_role = new stdClass();

View File

@ -68,8 +68,8 @@ function expert_install() {
$query->execute(); $query->execute();
// Enable default permissions for system roles. // Enable default permissions for system roles.
user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('access content')); user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('access content', 'use text format 1'));
user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID, array('access content', 'access comments', 'post comments', 'post comments without approval')); user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID, array('access content', 'access comments', 'post comments', 'post comments without approval', 'use text format 1'));
} }