Index: includes/form.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/form.inc,v retrieving revision 1.324 diff -u -p -r1.324 form.inc --- includes/form.inc 14 Mar 2009 20:13:26 -0000 1.324 +++ includes/form.inc 26 Mar 2009 23:44:06 -0000 @@ -1927,7 +1927,22 @@ function form_process_text_format($eleme $element['#type'] = 'markup'; $element['#theme'] = NULL; $element['#theme_wrapper'] = NULL; - $element['format'] = filter_form($element['#text_format'], 1, $element_parents); + + if (filter_access($element['#text_format'])) { + $element['format'] = filter_form($element['#text_format'], 1, $element_parents); + } + else { + $element['value']['#access'] = FALSE; + $element['#markup'] = t('%title has been disabled because you do not have sufficient permissions to edit this field.', array('%title' => $element['#title'])); + $element['#markup'] .= check_markup($element['#default_value'], $element['#text_format'], '', FALSE); + + // Add fixed format. + $element['format'] = array( + '#type' => 'value', + '#value' => $element['#text_format'], + '#parents' => $element_parents, + ); + } // We need to clear the #text_format from the new child otherwise we // would get into an infinite loop. Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.1032 diff -u -p -r1.1032 node.module --- modules/node/node.module 20 Mar 2009 19:18:10 -0000 1.1032 +++ modules/node/node.module 26 Mar 2009 23:44:14 -0000 @@ -291,8 +291,17 @@ function node_mark($nid, $timestamp) { /** * See if the user used JS to submit a teaser. + * + * Disables teaser feature if body field is disabled. */ function node_teaser_js(&$form, &$form_state) { + + // Disable teaser fields when body is disabled + if (isset($form['body']['value']['#access']) && $form['body']['value']['#access'] == FALSE) { + unset($form['teaser_js']); + unset($form_state['values']['teaser_js']); + } + if (isset($form_state['input']['teaser_js'])) { // Glue the teaser to the body. if (trim($form_state['values']['teaser_js'])) { @@ -330,6 +339,12 @@ function node_teaser_js(&$form, &$form_s function node_teaser_include_verify(&$form, &$form_state) { $message = ''; + // Disable teaser fields when body is disabled, form state needs to be unset so that it is ignored + if (isset($form['body']['value']['#access']) && $form['body']['value']['#access'] == FALSE) { + unset($form['teaser_include']); + unset($form_state['values']['teaser_include']); + } + // $form_state['input'] is set only when the form is built for preview/submit. if (isset($form_state['input']['body']) && isset($form_state['values']['teaser_include']) && !$form_state['values']['teaser_include']) { // "teaser_include" checkbox is present and unchecked. @@ -2312,11 +2327,6 @@ function node_access($op, $node, $accoun if (empty($account)) { $account = $user; } - // If the node is in a restricted format, disallow editing. - if ($op == 'update' && !filter_access($node->format)) { - return FALSE; - } - if (user_access('bypass node access', $account)) { return TRUE; } Index: modules/node/node.test =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.test,v retrieving revision 1.17 diff -u -p -r1.17 node.test --- modules/node/node.test 8 Mar 2009 04:25:04 -0000 1.17 +++ modules/node/node.test 26 Mar 2009 23:44:18 -0000 @@ -363,6 +363,107 @@ class PageEditTestCase extends DrupalWeb $this->assertText($edit['title'], t('Title displayed.')); $this->assertText($edit['body'], t('Body displayed.')); } + /** + * Test edit page with special text format. + * + * Test if a normal user is able to edit the page but is not allowed to change + * the fields which use a text format he's not allowed to use. + */ + function testPageEditLimitedPermission() { + $admin_user = $this->drupalCreateUser(array('administer filters', 'edit any page content', 'create page content')); + $normal_user = $this->drupalCreateUser(array('edit any page content', 'create page content')); + + $this->drupalLogout(); + $this->drupalLogin($admin_user); + + list($filtered, $full) = $this->checkFilterFormats(); + + // Create node to edit. + $edit = array(); + $edit['title'] = $this->randomName(8); + $edit['body'] = $this->randomName(16); + $edit['body_format'] = $full; + $this->drupalPost('node/add/page', $edit, t('Save')); + + // Check that the node exists in the database. + $node = $this->drupalGetNodeByTitle($edit['title']); + $this->assertTrue($node, t('Node found in database.')); + + // Check that "edit" link points to correct page. + $this->clickLink(t('Edit')); + $edit_url = url("node/$node->nid/edit", array('absolute' => true)); + $actual_url = $this->getURL(); + $this->assertEqual($edit_url, $actual_url, t('On edit page.')); + + // Check that the title and body fields are displayed with the correct values. + $this->assertLink(t('Edit'), 0, t('Edit tab found.')); + $this->assertFieldByName('title', $edit['title'], t('Title field displayed.')); + $this->assertFieldByName('body', '' . $edit['body'], t('Body field displayed.')); + + // Edit the content of the node. + $edit = array(); + $edit['title'] = $this->randomName(8); + $edit['body'] = $this->randomName(16); + // Stay on the current page, without reloading. + $this->drupalPost(NULL, $edit, t('Save')); + + // Check that the title and body fields are displayed with the updated values. + $this->assertText($edit['title'], t('Title displayed.')); + $this->assertText($edit['body'], t('Body displayed.')); + + // Try to edit with normal user + $this->drupalLogout(); + $this->drupalLogin($normal_user); + + $this->drupalGet("node/$node->nid"); + + // Check that "edit" link points to correct page. + $this->clickLink(t('Edit')); + $edit_url = url("node/$node->nid/edit", array('absolute' => true)); + $actual_url = $this->getURL(); + $this->assertEqual($edit_url, $actual_url, t('On edit page.')); + + // Check if body field is read only + $this->assertText($edit['body'], t('Body is displayed as text')); + $this->assertRaw(t('%title has been disabled because you do not have sufficient permissions to edit this field.', array('%title' => t('Body'))), t('Description is available')); + + // Check if teaser is disabled + $this->assertNoFieldByXPath("//input[@class='teaser-button']", t('Join summary'), t('Join button is not available')); + $this->assertNoField('teaser_js', t('Teaser field is not available')); + $this->assertNoField('teaser_include', t('Teaser include checkbox is not available')); + + // Try to "force" the change + $new_edit = array(); + $new_edit['title'] = $this->randomName(8); + // Stay on the current page, without reloading. + $this->drupalPost(NULL, $new_edit, t('Save')); + + // Check that only the title is displayed with the updated values, the body should use the old values + $this->assertText($new_edit['title'], t('New title displayed.')); + $this->assertText($edit['body'], t('Old body displayed.')); + } + + /** + * Query the database to get the two basic formats. + * + * @return Array Array containing filtered and full filter ids. + */ + function checkFilterFormats() { + $result = db_query('SELECT format, name FROM {filter_format}'); + + $filtered = -1; + $full = -1; + while ($format = db_fetch_object($result)) { + if ($format->name == 'Filtered HTML') { + $filtered = $format->format; + } + elseif ($format->name == 'Full HTML') { + $full = $format->format; + } + } + + return array($filtered, $full); + } } class PagePreviewTestCase extends DrupalWebTestCase {