diff --git a/modules/comment/comment.module b/modules/comment/comment.module index 1ffce389a523b056469b213fba1c832559edb5d2..03cbb546042d862d1756c90bf8553a58a8bfff3a 100644 --- a/modules/comment/comment.module +++ b/modules/comment/comment.module @@ -1633,7 +1633,7 @@ protected function buildQuery($ids, $conditions = array(), $revision_id = FALSE) $query->addField('n', 'type', 'node_type'); $query->innerJoin('users', 'u', 'base.uid = u.uid'); $query->addField('u', 'name', 'registered_name'); - $query->fields('u', array('uid', 'signature', 'picture')); + $query->fields('u', array('uid', 'signature', 'signature_format', 'picture')); return $query; } diff --git a/modules/comment/comment.pages.inc b/modules/comment/comment.pages.inc index 089825f56802bbec7158d675ce3d2003bb589196..8e39ea3879f9369218b91da92cdec2276e4fad6c 100644 --- a/modules/comment/comment.pages.inc +++ b/modules/comment/comment.pages.inc @@ -48,7 +48,7 @@ function comment_reply($node, $pid = NULL) { // $pid indicates that this is a reply to a comment. if ($pid) { // Load the comment whose cid = $pid - $comment = db_query('SELECT c.*, u.uid, u.name AS registered_name, u.signature, u.picture, u.data FROM {comment} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = :cid AND c.status = :status', array( + $comment = db_query('SELECT c.*, u.uid, u.name AS registered_name, u.signature, u.signature_format, u.picture, u.data FROM {comment} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = :cid AND c.status = :status', array( ':cid' => $pid, ':status' => COMMENT_PUBLISHED, ))->fetchObject(); diff --git a/modules/filter/filter.install b/modules/filter/filter.install index 6d67f70fd48ce1ff7fbc18343fef4b4fa069008a..ab3c3bdee079c10e9728ca1a5d3fe26ddfc39655 100644 --- a/modules/filter/filter.install +++ b/modules/filter/filter.install @@ -387,11 +387,11 @@ function filter_update_7005() { // Note that the update of the node body field is handled separately, in // node_update_7006(), as is the update of the comment body field, in // comment_update_7013(). - foreach (array('block_custom') as $table) { + foreach (array('block_custom' => 'format', 'users' => 'signature_format') as $table => $column) { if (db_table_exists($table)) { db_update($table) - ->fields(array('format' => $default_format)) - ->condition('format', 0) + ->fields(array($column => $default_format)) + ->condition($column, 0) ->execute(); } } diff --git a/modules/user/user.install b/modules/user/user.install index 6cc5d144d601d35e0359a8b61a61922811cd1592..0bff646bb1bd4b433bd918d045a0471a7b01c94b 100644 --- a/modules/user/user.install +++ b/modules/user/user.install @@ -160,6 +160,13 @@ function user_schema() { 'default' => '', 'description' => "User's signature.", ), + 'signature_format' => array( + 'type' => 'int', + 'size' => 'small', + 'not null' => TRUE, + 'default' => 0, + 'description' => 'The {filter_format}.format of the signature.', + ), 'created' => array( 'type' => 'int', 'not null' => TRUE, @@ -228,6 +235,9 @@ function user_schema() { 'name' => array('name'), ), 'primary key' => array('uid'), + 'foreign keys' => array( + 'signature_format' => array('filter_format' => 'format'), + ), ); $schema['users_roles'] = array( diff --git a/modules/user/user.module b/modules/user/user.module index 1420f83f015b85be8d7a3e250114e140a071f333..8c11e64d1435cee4c792b4b20c2d6bd76bbad0c5 100644 --- a/modules/user/user.module +++ b/modules/user/user.module @@ -1082,11 +1082,13 @@ function user_account_form(&$form, &$form_state) { '#weight' => 1, '#access' => (!$register && variable_get('user_signatures', 0)), ); + $form['signature_settings']['signature'] = array( - '#type' => 'textarea', + '#type' => 'text_format', '#title' => t('Signature'), '#default_value' => isset($account->signature) ? $account->signature : '', '#description' => t('Your signature will be publicly displayed at the end of your comments.'), + '#format' => isset($account->signature_format) ? $account->signature_format : NULL, ); // Picture/avatar. @@ -1179,6 +1181,11 @@ function user_account_form_validate($form, &$form_state) { // Make sure the signature isn't longer than the size of the database field. // Signatures are disabled by default, so make sure it exists first. if (isset($form_state['values']['signature'])) { + // Move text format for user signature into 'signature_format'. + $form_state['values']['signature_format'] = $form_state['values']['signature']['format']; + // Move text value for user signature into 'signature'. + $form_state['values']['signature'] = $form_state['values']['signature']['value']; + $user_schema = drupal_get_schema('users'); if (drupal_strlen($form_state['values']['signature']) > $user_schema['fields']['signature']['length']) { form_set_error('signature', t('The signature is too long: it must be %max characters or less.', array('%max' => $user_schema['fields']['signature']['length']))); @@ -3186,7 +3193,11 @@ function user_forms() { */ function user_comment_view($comment) { if (variable_get('user_signatures', 0) && !empty($comment->signature)) { - $comment->signature = check_markup($comment->signature, $comment->format, '', TRUE); + // @todo This alters and replaces the original object value, so a + // hypothetical process of loading, viewing, and saving will hijack the + // stored data. Consider renaming to $comment->signature_safe or similar + // here and elsewhere in Drupal 8. + $comment->signature = check_markup($comment->signature, $comment->signature_format, '', TRUE); } else { $comment->signature = ''; @@ -3561,6 +3572,16 @@ function user_modules_uninstalled($modules) { ->execute(); } +/** + * Implements hook_filter_format_delete(). + */ +function user_filter_format_delete($format, $fallback) { + db_update('users') + ->fields(array('signature_format' => $fallback->format)) + ->condition('signature_format', $format->format) + ->execute(); +} + /** * Helper function to rewrite the destination to avoid redirecting to login page after login. * diff --git a/modules/user/user.test b/modules/user/user.test index bf1bbbc812b99969eeaf1990c52f0e6f100859bd..392a2cb527e954752b5afd8c3f1ee1b3bc41a7a4 100644 --- a/modules/user/user.test +++ b/modules/user/user.test @@ -1435,6 +1435,90 @@ class UserEditTestCase extends DrupalWebTestCase { } /** + * Test case for user signatures. + */ +class UserSignatureTestCase extends DrupalWebTestCase { + public static function getInfo() { + return array( + 'name' => 'User signatures', + 'description' => 'Test user signatures.', + 'group' => 'User', + ); + } + + function setUp() { + parent::setUp('comment'); + + // Enable user signatures. + variable_set('user_signatures', 1); + + // Prefetch text formats. + $this->full_html_format = db_query_range('SELECT * FROM {filter_format} WHERE name = :name', 0, 1, array(':name' => 'Full HTML'))->fetchObject(); + $this->plain_text_format = db_query_range('SELECT * FROM {filter_format} WHERE name = :name', 0, 1, array(':name' => 'Plain text'))->fetchObject(); + + // Create regular and administrative users. + $this->web_user = $this->drupalCreateUser(array()); + $admin_permissions = array('administer comments'); + foreach (filter_formats() as $format) { + if ($permission = filter_permission_name($format)) { + $admin_permissions[] = $permission; + } + } + $this->admin_user = $this->drupalCreateUser($admin_permissions); + } + + /** + * Test that a user can change their signature format and that it is respected + * upon display. + */ + function testUserSignature() { + // Create a new node with comments on. + $node = $this->drupalCreateNode(array('comment' => COMMENT_NODE_OPEN)); + + // Verify that user signature field is not displayed on registration form. + $this->drupalGet('user/register'); + $this->assertNoText(t('Signature')); + + // Log in as a regular user and create a signature. + $this->drupalLogin($this->web_user); + $signature_text = "<h1>" . $this->randomName() . "</h1>"; + $edit = array( + 'signature[value]' => $signature_text, + 'signature[format]' => $this->plain_text_format->format, + ); + $this->drupalPost('user/' . $this->web_user->uid . '/edit', $edit, t('Save')); + + // Verify that values were stored. + $this->assertFieldByName('signature[value]', $edit['signature[value]'], 'Submitted signature text found.'); + $this->assertFieldByName('signature[format]', $edit['signature[format]'], 'Submitted signature format found.'); + + // Create a comment. + $langcode = LANGUAGE_NONE; + $edit = array(); + $edit['subject'] = $this->randomName(8); + $edit['comment_body[' . $langcode . '][0][value]'] = $this->randomName(16); + $this->drupalPost('comment/reply/' . $node->nid, $edit, t('Preview')); + $this->drupalPost(NULL, array(), t('Save')); + + // Get the comment ID. (This technique is the same one used in the Comment + // module's CommentHelperCase test case.) + preg_match('/#comment-([0-9]+)/', $this->getURL(), $match); + $comment_id = $match[1]; + + // Log in as an administrator and edit the comment to use Full HTML, so + // that the comment text itself is not filtered at all. + $this->drupalLogin($this->admin_user); + $edit['comment_body[' . $langcode . '][0][format]'] = $this->full_html_format->format; + $this->drupalPost('comment/' . $comment_id . '/edit', $edit, t('Save')); + + // Assert that the signature did not make it through unfiltered. + $this->drupalGet('node/' . $node->nid); + $this->assertNoRaw($signature_text, 'Unfiltered signature text not found.'); + $this->assertRaw(check_markup($signature_text, $this->plain_text_format->format), 'Filtered signature text found.'); + } +} + +/* * Test that a user, having editing their own account, can still log in. */ class UserEditedOwnAccountTestCase extends DrupalWebTestCase {