Index: modules/block/block.module =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.module,v retrieving revision 1.411 diff -u -p -r1.411 block.module --- modules/block/block.module 7 Mar 2010 23:14:20 -0000 1.411 +++ modules/block/block.module 8 Mar 2010 01:11:22 -0000 @@ -428,7 +428,6 @@ function block_custom_block_form($edit = '#description' => t('The content of the block as shown to the user.'), '#required' => TRUE, '#weight' => -17, - '#access' => filter_access(filter_format_load($edit['format'])), ); return $form; Index: modules/field/modules/text/text.js =================================================================== RCS file: /cvs/drupal/drupal/modules/field/modules/text/text.js,v retrieving revision 1.2 diff -u -p -r1.2 text.js --- modules/field/modules/text/text.js 29 Nov 2009 20:45:17 -0000 1.2 +++ modules/field/modules/text/text.js 8 Mar 2010 02:11:40 -0000 @@ -11,8 +11,8 @@ Drupal.behaviors.textSummary = { var $widget = $(this).closest('div.field-type-text-with-summary'); var $summary = $widget.find('div.text-summary-wrapper'); var $summaryLabel = $summary.find('label'); - var $full = $widget.find('div.text-full-wrapper'); - var $fullLabel = $full.find('div.form-type-textarea label'); + var $full = $widget.find('.form-item:has(.text-full)'); + var $fullLabel = $full.find('label'); // Setup the edit/hide summary link. var $link = $('(' + Drupal.t('Hide summary') + ')').toggle( Index: modules/field/modules/text/text.module =================================================================== RCS file: /cvs/drupal/drupal/modules/field/modules/text/text.module,v retrieving revision 1.49 diff -u -p -r1.49 text.module --- modules/field/modules/text/text.module 7 Mar 2010 23:14:20 -0000 1.49 +++ modules/field/modules/text/text.module 8 Mar 2010 02:09:05 -0000 @@ -521,8 +521,7 @@ function text_field_widget_form(&$form, '#type' => 'textfield', '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL, '#size' => $instance['widget']['settings']['size'], - '#prefix' => '
', - '#suffix' => '
', + '#attributes' => array('class' => array('text-full')), ); break; @@ -549,8 +548,7 @@ function text_field_widget_form(&$form, '#type' => 'textarea', '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL, '#rows' => $instance['widget']['settings']['rows'], - '#prefix' => '
', - '#suffix' => '
', + '#attributes' => array('class' => array('text-full')), ); break; } Index: modules/filter/filter.module =================================================================== RCS file: /cvs/drupal/drupal/modules/filter/filter.module,v retrieving revision 1.321 diff -u -p -r1.321 filter.module --- modules/filter/filter.module 7 Mar 2010 23:14:20 -0000 1.321 +++ modules/filter/filter.module 8 Mar 2010 02:23:37 -0000 @@ -849,6 +849,36 @@ function filter_process_format($element) '#weight' => 0, ); + // Lastly, disallow editing of this field if the user is not allowed to use + // the stored text format. + if (!isset($formats[$element['#format']])) { + // Overload default values into #value to make them unalterable. + $element['value']['#value'] = $element['value']['#default_value']; + $element['format']['format']['#value'] = $element['format']['format']['#default_value']; + + // Prepend #pre_render callback to replace field value with user notice + // prior rendering. + if (!isset($element['value']['#pre_render'])) { + $element['value']['#pre_render'] = array(); + } + array_unshift($element['value']['#pre_render'], 'filter_form_access_denied'); + + // Cosmetical adjustments. + if (isset($element['value']['#rows'])) { + $element['value']['#rows'] = 3; + } + $element['value']['#disabled'] = TRUE; + $element['value']['#resizable'] = FALSE; + + // Hide the text format selector and any other child element (such as text + // field's summary). + foreach (element_children($element) as $key) { + if ($key != 'value') { + $element[$key]['#access'] = FALSE; + } + } + } + return $element; } @@ -884,6 +914,22 @@ function filter_form_after_build($elemen } /** + * #pre_render callback for #type 'text_format' to hide field value from prying eyes. + * + * To not break form processing and previews if a user does not have access to a + * stored text format, the expanded form elements in filter_process_format() are + * forced to take over the stored #default_values for 'value' and 'format'. + * However, to prevent the unfiltered, original #value from being displayed to + * the user, we replace it with a friendly notice here. + * + * @see filter_process_format() + */ +function filter_form_access_denied($element) { + $element['#value'] = t('This field has been disabled because you do not have sufficient permissions to edit it.'); + return $element; +} + +/** * Render a text format-enabled form element. * * @param $variables Index: modules/node/node.test =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.test,v retrieving revision 1.76 diff -u -p -r1.76 node.test --- modules/node/node.test 6 Mar 2010 06:39:00 -0000 1.76 +++ modules/node/node.test 8 Mar 2010 02:53:15 -0000 @@ -358,8 +358,14 @@ class PagePreviewTestCase extends Drupal function setUp() { parent::setUp(); - $web_user = $this->drupalCreateUser(array('edit own page content', 'create page content')); - $this->drupalLogin($web_user); + $this->full_html_format = db_query_range('SELECT * FROM {filter_format} WHERE name = :name', 0, 1, array(':name' => 'Full HTML'))->fetchObject(); + $this->admin_user = $this->drupalCreateUser(array( + 'edit any page content', + 'create page content', + filter_permission_name($this->full_html_format), + )); + $this->web_user = $this->drupalCreateUser(array('edit own page content', 'create page content')); + $this->drupalLogin($this->web_user); } /** @@ -415,6 +421,49 @@ class PagePreviewTestCase extends Drupal // Check that the log field has the correct value. $this->assertFieldByName('log', $edit['log'], t('Log field displayed.')); } + + /** + * Test editing a page using a disallowed text format. + * + * Verifies that a regular user is able to edit a page, but is not allowed to + * change the fields which use an inaccessible text format. + */ + function testPageEditLimitedPermission() { + $langcode = LANGUAGE_NONE; + $title_key = "title"; + $body_value_key = "body[$langcode][0][value]"; + $body_format_key = "body[$langcode][0][format]"; + + $moderator = $this->drupalCreateUser(array('edit any page content', 'create page content')); + + // Create node to edit. + $this->drupalLogin($this->admin_user); + $edit = array(); + $edit['title'] = $this->randomName(8); + $edit[$body_value_key] = $this->randomName(16); + $edit[$body_format_key] = $this->full_html_format->format; + $this->drupalPost('node/add/page', $edit, t('Save')); + $node = $this->drupalGetNodeByTitle($edit['title']); + + // Try to edit with normal user + $this->drupalLogin($moderator); + $this->drupalGet("node/$node->nid"); + $this->clickLink(t('Edit')); + + // Verify that body field is read-only and contains replacement value. + $this->assertFieldByXPath("//textarea[@name='$body_value_key' and @disabled='disabled']", t('This field has been disabled because you do not have sufficient permissions to edit it.'), t('Body field contains denied message')); + + // Verify that title can be changed, but preview displays original body. + $new_edit = array(); + $new_edit['title'] = $this->randomName(8); + $this->drupalPost(NULL, $new_edit, t('Preview')); + $this->assertText($edit[$body_value_key], t('Old body found in preview.')); + + // Save and verify that only the title was changed. + $this->drupalPost(NULL, $new_edit, t('Save')); + $this->assertText($new_edit['title'], t('New title found.')); + $this->assertText($edit[$body_value_key], t('Old body found.')); + } } class NodeCreationTestCase extends DrupalWebTestCase {