diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index 3c92450..8ece425 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -1383,13 +1383,6 @@ function template_preprocess_comment(&$variables) { $variables['user_picture'] = array(); } - if (\Drupal::config('user.settings')->get('signatures') && $account->getSignature()) { - $variables['signature'] = check_markup($account->getSignature(), $account->getSignatureFormat(), '', TRUE) ; - } - else { - $variables['signature'] = ''; - } - $uri = $comment->uri(); $permalink_uri = $comment->permalink(); $uri['options'] += array('attributes' => array('class' => 'permalink', 'rel' => 'bookmark')); diff --git a/core/modules/comment/templates/comment.html.twig b/core/modules/comment/templates/comment.html.twig index 570448f..8e4793d 100644 --- a/core/modules/comment/templates/comment.html.twig +++ b/core/modules/comment/templates/comment.html.twig @@ -97,6 +97,7 @@ {{ content }} {% if signature %} + {# @todo #}
{{ signature }}
diff --git a/core/modules/user/config/schema/user.schema.yml b/core/modules/user/config/schema/user.schema.yml index 05155ff..e82682c 100644 --- a/core/modules/user/config/schema/user.schema.yml +++ b/core/modules/user/config/schema/user.schema.yml @@ -44,9 +44,6 @@ user.settings: register: type: string label: 'Who can register accounts?' - signatures: - type: boolean - label: 'Enable signatures.' cancel_method: type: string label: 'When cancelling a user account' diff --git a/core/modules/user/config/user.settings.yml b/core/modules/user/config/user.settings.yml index fbb0d98..dde445f 100644 --- a/core/modules/user/config/user.settings.yml +++ b/core/modules/user/config/user.settings.yml @@ -11,7 +11,6 @@ notify: register_no_approval_required: true register_pending_approval: true register: visitors -signatures: false cancel_method: user_cancel_block password_reset_timeout: 86400 password_strength: true diff --git a/core/modules/user/lib/Drupal/user/AccountFormController.php b/core/modules/user/lib/Drupal/user/AccountFormController.php index de2c14c..00a2bbc 100644 --- a/core/modules/user/lib/Drupal/user/AccountFormController.php +++ b/core/modules/user/lib/Drupal/user/AccountFormController.php @@ -194,22 +194,6 @@ public function form(array $form, array &$form_state) { '#access' => $register && $admin, ); - // Signature. - $form['signature_settings'] = array( - '#type' => 'details', - '#title' => $this->t('Signature settings'), - '#weight' => 1, - '#access' => (!$register && $config->get('signatures')), - ); - - $form['signature_settings']['signature'] = array( - '#type' => 'text_format', - '#title' => $this->t('Signature'), - '#default_value' => $account->getSignature(), - '#description' => $this->t('Your signature will be publicly displayed at the end of your comments.'), - '#format' => $account->getSignatureFormat(), - ); - $user_preferred_langcode = $register ? $language_interface->id : $account->getPreferredLangcode(); $user_preferred_admin_langcode = $register ? $language_interface->id : $account->getPreferredAdminLangcode(); @@ -336,20 +320,6 @@ public function validate(array $form, array &$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__value']['length']) { - $this->setFormError('signature', $form_state, $this->t('The signature is too long: it must be %max characters or less.', array('%max' => $user_schema['fields']['signature__value']['length']))); - } - } } } diff --git a/core/modules/user/lib/Drupal/user/AccountSettingsForm.php b/core/modules/user/lib/Drupal/user/AccountSettingsForm.php index ace1834..3fd1686 100644 --- a/core/modules/user/lib/Drupal/user/AccountSettingsForm.php +++ b/core/modules/user/lib/Drupal/user/AccountSettingsForm.php @@ -155,11 +155,6 @@ public function buildForm(array $form, array &$form_state) { '#type' => 'details', '#title' => $this->t('Personalization'), ); - $form['personalization']['user_signatures'] = array( - '#type' => 'checkbox', - '#title' => $this->t('Enable signatures.'), - '#default_value' => $config->get('signatures'), - ); // Default notifications address. $form['mail_notification_address'] = array( @@ -416,7 +411,6 @@ public function submitForm(array &$form, array &$form_state) { ->set('register', $form_state['values']['user_register']) ->set('password_strength', $form_state['values']['user_password_strength']) ->set('verify_mail', $form_state['values']['user_email_verification']) - ->set('signatures', $form_state['values']['user_signatures']) ->set('cancel_method', $form_state['values']['user_cancel_method']) ->set('notify.status_activated', $form_state['values']['user_mail_status_activated_notify']) ->set('notify.status_blocked', $form_state['values']['user_mail_status_blocked_notify']) diff --git a/core/modules/user/lib/Drupal/user/Entity/User.php b/core/modules/user/lib/Drupal/user/Entity/User.php index 3c481d3..9f84373 100644 --- a/core/modules/user/lib/Drupal/user/Entity/User.php +++ b/core/modules/user/lib/Drupal/user/Entity/User.php @@ -276,20 +276,6 @@ public function getDefaultTheme() { /** * {@inheritdoc} */ - public function getSignature() { - return $this->get('signature')->value; - } - - /** - * {@inheritdoc} - */ - public function getSignatureFormat() { - return $this->get('signature')->format; - } - - /** - * {@inheritdoc} - */ public function getCreatedTime() { return $this->get('created')->value; } @@ -473,11 +459,6 @@ public static function baseFieldDefinitions($entity_type) { ->setSetting('default_value', '') ->setPropertyConstraints('value', array('UserMailUnique' => array())); - $fields['signature'] = FieldDefinition::create('text') - ->setLabel(t('Signature')) - ->setDescription(t('The signature of this user.')) - ->setSetting('max_length', 255); - $fields['theme'] = FieldDefinition::create('string') ->setLabel(t('Theme')) ->setDescription(t('The default theme of this user.')) diff --git a/core/modules/user/lib/Drupal/user/UserInterface.php b/core/modules/user/lib/Drupal/user/UserInterface.php index 2196378..f07a6f7 100644 --- a/core/modules/user/lib/Drupal/user/UserInterface.php +++ b/core/modules/user/lib/Drupal/user/UserInterface.php @@ -92,22 +92,6 @@ public function setEmail($mail); public function getDefaultTheme(); /** - * Returns the user signature. - * - * @return string - * The signature text. - */ - public function getSignature(); - - /** - * Returns the signature format. - * - * @return string - * Name of the filter format. - */ - public function getSignatureFormat(); - - /** * Returns the creation time of the user as a UNIX timestamp. * * @return int diff --git a/core/modules/user/user.info.yml b/core/modules/user/user.info.yml index 88171ad..45a421a 100644 --- a/core/modules/user/user.info.yml +++ b/core/modules/user/user.info.yml @@ -5,6 +5,4 @@ package: Core version: VERSION core: 8.x required: true -dependencies: - - text configure: user.admin_index diff --git a/core/modules/user/user.install b/core/modules/user/user.install index 6390631..c636761 100644 --- a/core/modules/user/user.install +++ b/core/modules/user/user.install @@ -65,18 +65,6 @@ function user_schema() { 'default' => '', 'description' => "User's default theme.", ), - 'signature__value' => array( - 'type' => 'varchar', - 'length' => 255, - 'not null' => FALSE, - 'description' => "User's signature.", - ), - 'signature__format' => array( - 'type' => 'varchar', - 'length' => 255, - 'not null' => FALSE, - 'description' => 'The filter format ID of the signature.', - ), 'created' => array( 'type' => 'int', 'not null' => TRUE, @@ -391,7 +379,6 @@ function user_update_8004() { 'anonymous' => 'anonymous', 'user_admin_role' => 'admin_role', 'user_register' => 'register', - 'user_signatures' => 'signatures', 'user_cancel_method' => 'cancel_method', 'user_mail_status_activated_notify' => 'notify.status_activated', 'user_mail_status_blocked_notify' => 'notify.status_blocked', @@ -1065,24 +1052,22 @@ function user_update_8021() { } /** - * Rename the 'signature' and 'signature_format' columns for users. + * Enable user_signature module and migrate data. */ function user_update_8022() { - $signature = array( - 'type' => 'varchar', - 'length' => 255, - 'not null' => FALSE, - 'description' => "User's signature.", - ); - db_change_field('users', 'signature', 'signature__value', $signature); - - $format = array( - 'type' => 'varchar', - 'length' => 255, - 'not null' => FALSE, - 'description' => 'The filter format ID of the signature.', - ); - db_change_field('users', 'signature_format', 'signature__format', $format); + if (update_variable_get('user_signatures', FALSE)) { + \Drupal::moduleHandler()->install(array('user_signature')); + + $select = db_select('users') + ->fields(array('uid', 'signature', 'signature_format')); + db_insert('user_signature') + ->fields(array('uid', 'signature__value', 'signature__format')) + ->from($select) + ->execute(); + } + db_drop_field('users', 'signature'); + db_drop_field('users', 'signature_format'); + update_variable_del('user_signatures'); } /** diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 6744e9e..d1b8531 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -61,7 +61,7 @@ function user_help($path, $arg) { $output .= '
' . t('User roles and permissions') . '
'; $output .= '
' . t('Roles are used to group and classify users; each user can be assigned one or more roles. By default there are two roles: anonymous user (users that are not logged in) and authenticated user (users that are registered and logged in). Depending on choices you made when you installed Drupal, the installation process may have defined more roles, and you can create additional custom roles on the Roles page. After creating roles, you can set permissions for each role on the Permissions page. Granting a permission allows users who have been assigned a particular role to perform an action on the site, such as viewing a particular type of content, editing or creating content, administering settings for a particular module, or using a particular function of the site (such as search).', array('@permissions_user' => url('admin/people/permissions'), '@roles' => url('admin/people/roles'))) . '
'; $output .= '
' . t('Account settings') . '
'; - $output .= '
' . t('The Account settings page allows you to manage settings for the displayed name of the anonymous user role, personal contact forms, user registration, and account cancellation. On this page you can also manage settings for account personalization (including signatures), and adapt the text for the e-mail messages that are sent automatically during the user registration process.', array('@accounts' => url('admin/config/people/accounts'))) . '
'; + $output .= '
' . t('The Account settings page allows you to manage settings for the displayed name of the anonymous user role, personal contact forms, user registration, and account cancellation. On this page you can also manage settings for account personalization and adapt the text for the e-mail messages that are sent automatically during the user registration process.', array('@accounts' => url('admin/config/people/accounts'))) . '
'; $output .= ''; return $output; case 'admin/people/create': @@ -102,9 +102,6 @@ function user_theme() { 'variables' => array('permission_item' => NULL, 'hide' => NULL), 'file' => 'user.admin.inc', ), - 'user_signature' => array( - 'variables' => array('signature' => NULL), - ), 'username' => array( 'variables' => array('account' => NULL, 'attributes' => array()), ), @@ -1615,29 +1612,6 @@ function user_role_revoke_permissions($rid, array $permissions = array()) { } /** - * Returns HTML for a user signature. - * - * @param $variables - * An associative array containing: - * - signature: The user's signature. - * - * @ingroup themeable - */ -function theme_user_signature($variables) { - $signature = $variables['signature']; - $output = ''; - - if ($signature) { - $output .= '
'; - $output .= '
'; - $output .= $signature; - $output .= '
'; - } - - return $output; -} - -/** * Conditionally create and send a notification email when a certain * operation happens on the given user account. * diff --git a/core/modules/user/user.views.inc b/core/modules/user/user.views.inc index 519b946..516083a 100644 --- a/core/modules/user/user.views.inc +++ b/core/modules/user/user.views.inc @@ -267,19 +267,6 @@ function user_views_data() { ), ); - $data['users']['signature__value'] = array( - 'title' => t('Signature'), - 'help' => t("The user's signature."), - 'field' => array( - 'id' => 'markup', - 'format' => array('field' => 'signature__format'), - 'click sortable' => FALSE, - ), - 'filter' => array( - 'id' => 'string', - ), - ); - if (\Drupal::moduleHandler()->moduleExists('content_translation')) { $data['users']['translation_link'] = array( 'title' => t('Translation link'), diff --git a/core/modules/user_signature/user_signature.info.yml b/core/modules/user_signature/user_signature.info.yml new file mode 100644 index 0000000..4ad89b6 --- /dev/null +++ b/core/modules/user_signature/user_signature.info.yml @@ -0,0 +1,10 @@ +name: User signature +type: module +description: 'Enables user signatures.' +package: Core +version: VERSION +core: 8.x +dependencies: + - filter + - text +# configure: user.admin_index diff --git a/core/modules/user_signature/user_signature.install b/core/modules/user_signature/user_signature.install new file mode 100644 index 0000000..941f5fb --- /dev/null +++ b/core/modules/user_signature/user_signature.install @@ -0,0 +1,45 @@ + 'Stores user signatures.', + 'fields' => array( + 'uid' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'description' => 'Primary Key: {users}.uid of the user.', + ), + 'signature__value' => array( + 'type' => 'varchar', + 'length' => 255, + 'not null' => FALSE, + 'description' => "User's signature.", + ), + 'signature__format' => array( + 'type' => 'varchar', + 'length' => 255, + 'not null' => FALSE, + 'description' => 'The filter format ID of the signature.', + ), + ), + 'primary key' => array('uid'), + ); + return $schema; +} + +/** + * Implements hook_uninstall(). + */ +function user_signature_uninstall() { +} + diff --git a/core/modules/user_signature/user_signature.module b/core/modules/user_signature/user_signature.module new file mode 100644 index 0000000..7142c62 --- /dev/null +++ b/core/modules/user_signature/user_signature.module @@ -0,0 +1,253 @@ +' . t('About') . ''; + $output .= '

' . t('The User signature module allows users to set up custom user-specific signatures that are diplayed below posts. For more information, see the online handbook entry for User signature module.', array( + '@user-signature' => 'http://drupal.org/documentation/modules/user_signature', + )) . '

'; + $output .= '

' . t('Uses') . '

'; + $output .= '
'; + $output .= '
' . t('Account settings') . '
'; + $output .= '
' . t('The Account settings page allows you to manage settings for the displayed name of the anonymous user role, personal contact forms, user registration, and account cancellation. On this page you can also manage settings for account personalization and adapt the text for the e-mail messages that are sent automatically during the user registration process.', array('@accounts' => url('admin/config/people/accounts'))) . '
'; + $output .= '
'; + return $output; + } +} + +/** + * Implements hook_theme(). + */ +function user_signature_theme() { + return array( + 'user_signature' => array( + 'variables' => array('signature' => NULL), + ), + ); +} + +/** + * Implements hook_form_FORMID_alter(). + */ +function user_signature_form_user_admin_settings_alter(&$form, &$form_state) { + // @todo Convert into checkboxes to enable per-entity-type support? + $form['personalization']['user_signature'] = array( + '#type' => 'checkbox', + '#title' => t('Enable user signatures'), + '#default_value' => TRUE, + ); +} + +/** + * Implements hook_form_FORMID_alter(). + */ +function user_signature_form_user_form_alter(&$form, &$form_state) { + $account = $form_state['controller']->getEntity(); + if ($account->isAnonymous()) { + return; + } + // @todo There does not appear to be a way to cleanly load the field item + // values of attached third-party fields within the Entity API or + // Entity Field API scope? -- hook_entity_load() is too gross (performance), + // and no lazy-loading in FieldItemBase? + $signature = db_query('SELECT signature__value AS value, signature__format AS format FROM {user_signature} WHERE uid = :uid', array(':uid' => $account->id()))->fetchAssoc(); + if ($signature) { + $account->set('user_signature', $signature); + } + + $form['user_signature'] = array( + '#type' => 'details', + '#title' => t('Signature settings'), + '#weight' => 1, + ); + $form['user_signature']['user_signature'] = array( + '#type' => 'text_format', + '#title' => t('Signature'), + '#default_value' => $account->get('user_signature')->value, + '#format' => $account->get('user_signature')->format, + // @todo Wasn't #maxlength support for #type 'textarea' committed already? + '#maxlength' => $account->get('user_signature')->getFieldDefinition()->getSetting('max_length'), + '#element_validate' => array('user_signature_element_validate_signature'), + '#description' => t('Your signature will be publicly displayed at the end of your posts.'), + ); + $form['actions']['submit']['#submit'][] = 'user_signature_user_form_submit'; +} + +/** + * #element_validate handler for the 'user_signature' form element. + * + * @todo Why is the TextFieldItem 'max_length' constraint not automatically + * enforced? + */ +function user_signature_element_validate_signature($element, &$form_state) { + // @todo #type 'text_format' self-expands itself into multiple elements + // without resetting #element_validate on the injected wrapper element. + if ($element['#type'] != $element['#base_type']) { + return; + } + if (drupal_strlen($element['#value']) > $element['#maxlength']) { + form_error($element, $form_state, t('The signature is too long: it must be %max characters or less.', array( + '%max' => $element['#maxlength'], + ))); + } +} + +/** + * Form submission handler for user form to save the user signature. + * + * @todo Move CRUD logic into new user_signature FieldItem extends TextFieldItem? + */ +function user_signature_user_form_submit($form, &$form_state) { + $account = $form_state['controller']->getEntity(); + if ($account->id() && isset($form_state['values']['user_signature'])) { + if (!$account->get('user_signature')->isEmpty()) { + db_merge('user_signature') + ->key(array('uid' => $account->id())) + ->fields(array( + 'signature__value' => $account->get('user_signature')->value, + 'signature__format' => $account->get('user_signature')->format, + )) + ->execute(); + } + else { + db_delete('user_signature') + ->condition('uid', $account->id()) + ->execute(); + } + } +} + +/** + * Implements hook_entity_field_info(). + */ +function user_signature_entity_field_info($entity_type) { + // Make sure the signature isn't longer than the size of the database field. + $schema = drupal_get_schema('user_signature'); + $maxlength = $schema['fields']['signature__value']['length']; + + $info['definitions']['user_signature'] = FieldDefinition::create('text') + ->setLabel(t('User signature')) + ->setDescription(t('The user signature of the author.')) + ->setSetting('max_length', $maxlength); + + if ($entity_type != 'user') { + $info['definitions']['user_signature']->setReadOnly(TRUE); + } + return $info; +} + +/** + * Implements hook_field_extra_fields(). + */ +function user_signature_field_extra_fields() { + $fields['user']['user']['form']['user_signature'] = array( + 'label' => t('Signature settings'), + 'description' => t('User signature module form element.'), + 'weight' => 1, + ); + + $display_field = array( + 'label' => t('User signature'), + 'description' => t('User signature module view element.'), + 'weight' => 90, + ); + // @todo How can this be made both (1) configurable and (2) scriptable + // (e.g., for Forum module)? + //$entity_info = entity_get_info(); + $fields['comment']['full']['display']['user_signature'] = $display_field; + $fields['node']['forum']['display']['user_signature'] = $display_field; + $fields['node']['article']['display']['user_signature'] = $display_field; + + return $fields; +} + +/** + * Implements hook_entity_prepare_view(). + * + * @todo Limit to configured/enabled entity types/bundles, + * or at minimum content entities. + * + * @todo How to adjust entity render cache to account for potential user + * signature changes? + */ +function user_signature_entity_prepare_view($entity_type, array $entities, array $displays, $view_mode) { + if (empty($entities)) { + return; + } + // @todo There is no ContentEntityInterface::getAuthorId() yet. + $getAuthorId = function ($entity) { + if ($entity instanceof \Drupal\node\NodeInterface) { + return $entity->getAuthorId(); + } + return $entity->uid->value; + }; + + // Fetch signatures for all authors, keyed by entity ID. + $uids = array(); + foreach ($entities as $entity) { + $uids[$getAuthorId($entity)] = $getAuthorId($entity); + } + $signatures = db_query("SELECT uid, signature__value AS value, signature__format AS format FROM {user_signature} WHERE uid IN (:uids)", array( + ':uids' => $uids, + ))->fetchAllAssoc('uid', \PDO::FETCH_ASSOC); + + foreach ($entities as $entity) { + if (isset($signatures[$getAuthorId($entity)])) { + $entity->set('user_signature', $signatures[$getAuthorId($entity)]); + } + } +} + +/** + * Implements hook_entity_view(). + */ +function user_signature_entity_view(EntityInterface $entity, EntityViewDisplayInterface $display) { + if ($display->getComponent('user_signature')) { + // @todo How to provide a render element that is only rendered on-demand + // by an (arbitrary) entity Twig template? + $entity->content['user_signature'] = array( + '#markup' => $entity->get('user_signature')->processed, + ); + } +} + +/** + * Returns HTML for a user signature. + * + * @param $variables + * An associative array containing: + * - signature: The user's signature. + * + * @ingroup themeable + * + * @todo Convert into Twig template? Or remove entirely? + * (Comment template contains wrapping markup already.) + */ +function theme_user_signature($variables) { + $signature = $variables['signature']; + $output = ''; + + if ($signature) { + $output .= '
'; + $output .= '
'; + $output .= $signature; + $output .= '
'; + } + + return $output; +} diff --git a/core/modules/user_signature/user_signature.views.inc b/core/modules/user_signature/user_signature.views.inc new file mode 100644 index 0000000..a142c7a --- /dev/null +++ b/core/modules/user_signature/user_signature.views.inc @@ -0,0 +1,39 @@ + array( + 'left_field' => 'uid', + 'field' => 'uid', + ), + ); + + $data['user_signature']['signature__value'] = array( + 'title' => t('Signature'), + 'help' => t("The user's signature."), + 'field' => array( + 'id' => 'markup', + 'format' => array('field' => 'signature__format'), + 'click sortable' => FALSE, + 'no group by' => TRUE, + ), + 'filter' => array( + 'id' => 'string', + ), + ); + + return $data; +}