diff --git a/core/modules/comment/comment.install b/core/modules/comment/comment.install index 40fb1a0..30f300e 100644 --- a/core/modules/comment/comment.install +++ b/core/modules/comment/comment.install @@ -67,12 +67,19 @@ function comment_schema() { 'length' => 255, 'description' => 'The entity_type of the entity to which this comment is a reply.', ), - 'field_id' => array( + 'field_name' => array( 'type' => 'varchar', 'not null' => TRUE, - 'default' => 'node.comment', + 'default' => 'comment', 'length' => 255, - 'description' => 'The field_id of the field that was used to add this comment.', + 'description' => 'The field_name of the field that was used to add this comment.', + ), + 'comment_type' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'default' => 'comment', + 'length' => 32, + 'description' => 'The comment_type of this comment.', ), 'uid' => array( 'type' => 'int', @@ -152,7 +159,7 @@ function comment_schema() { 'comment_num_new' => array( 'entity_id', array('entity_type', 32), - array('field_id', 32), + array('comment_type', 32), 'status', 'created', 'cid', @@ -162,7 +169,7 @@ function comment_schema() { 'comment_entity_langcode' => array( 'entity_id', array('entity_type', 32), - array('field_id', 32), + array('comment_type', 32), 'langcode', ), 'comment_created' => array('created'), @@ -196,12 +203,12 @@ function comment_schema() { 'length' => 255, 'description' => 'The entity_type of the entity to which this comment is a reply.', ), - 'field_id' => array( + 'field_name' => array( 'type' => 'varchar', 'not null' => TRUE, - 'default' => 'node__comment', + 'default' => 'comment', 'length' => 255, - 'description' => 'The field_id of the field that was used to add this comment.', + 'description' => 'The field_name of the field that was used to add this comment.', ), 'cid' => array( 'type' => 'int', @@ -236,7 +243,7 @@ function comment_schema() { 'description' => 'The total number of comments on this entity.', ), ), - 'primary key' => array('entity_id', array('entity_type', 32), array('field_id', 32)), + 'primary key' => array('entity_id', array('entity_type', 32), array('field_name', 32)), 'indexes' => array( 'last_comment_timestamp' => array('last_comment_timestamp'), 'comment_count' => array('comment_count'), diff --git a/core/modules/comment/comment.menu_links.yml b/core/modules/comment/comment.menu_links.yml index 7d715fe..740de41 100644 --- a/core/modules/comment/comment.menu_links.yml +++ b/core/modules/comment/comment.menu_links.yml @@ -3,8 +3,8 @@ comment.admin: route_name: comment.admin parent: system.admin description: 'List and edit site comments and the comment approval queue.' -comment.bundle_list: +comment.type_list: title: 'Comment forms' - route_name: comment.bundle_list + route_name: comment.type_list parent: system.admin_structure description: 'Manage fields and displays settings for comment forms.' diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index 4115444..7ebe93e 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -96,15 +96,10 @@ function comment_help($path, $arg) { */ function comment_entity_bundle_info() { $bundles = array(); - foreach (\Drupal::service('comment.manager')->getAllFields() as $entity_type => $fields) { - foreach ($fields as $field_name => $field_info) { - $sample_bundle = reset($field_info['bundles']); - // We cannot use field info API here because it will result in recursion. - $config = \Drupal::config('field.instance.' . $entity_type . '.' . $sample_bundle . '.' . $field_name); - $bundles['comment'][$entity_type . '__' . $field_name] = array( - 'label' => $config->get('label'), - ); - } + foreach (entity_load_multiple('comment_type') as $comment_type) { + $bundles['comment'][$comment_type->id] = array( + 'label' => $comment_type->label, + ); } return $bundles; } @@ -127,23 +122,21 @@ function comment_uri(CommentInterface $comment) { */ function comment_entity_extra_field_info() { $return = array(); - foreach (\Drupal::service('comment.manager')->getAllFields() as $entity_type => $fields) { - foreach ($fields as $field_name => $field_info) { - $return['comment'][$entity_type . '__' . $field_name] = array( - 'form' => array( - 'author' => array( - 'label' => t('Author'), - 'description' => t('Author textfield'), - 'weight' => -2, - ), - 'subject' => array( - 'label' => t('Subject'), - 'description' => t('Subject textfield'), - 'weight' => -1, - ), + foreach (entity_load_multiple('comment_type') as $comment_type) { + $return['comment'][$comment_type->id] = array( + 'form' => array( + 'author' => array( + 'label' => t('Author'), + 'description' => t('Author textfield'), + 'weight' => -2, ), - ); - } + 'subject' => array( + 'label' => t('Subject'), + 'description' => t('Subject textfield'), + 'weight' => -1, + ), + ), + ); } return $return; @@ -247,9 +240,9 @@ function comment_field_config_delete(FieldConfigInterface $field) { function comment_field_instance_config_delete(FieldInstanceConfigInterface $instance) { if ($instance->getType() == 'comment') { // Delete all comments that used by the entity bundle. - $comments = db_query("SELECT cid FROM {comment} WHERE entity_type = :entity_type AND field_id = :field_id", array( + $comments = db_query("SELECT cid FROM {comment} WHERE entity_type = :entity_type AND field_name = :field_name", array( ':entity_type' => $instance->getEntityTypeId(), - ':field_id' => $instance->getEntityTypeId() . '__' . $instance->getName(), + ':field_name' => $instance->getName(), ))->fetchCol(); entity_delete_multiple('comment', $comments); } @@ -317,7 +310,7 @@ function comment_new_page_count($num_comments, $new_replies, EntityInterface $en ->fields('comment', array('thread')) ->condition('entity_id', $entity->id()) ->condition('entity_type', $entity->getEntityTypeId()) - ->condition('field_id', $entity->getEntityTypeId() . '__' . $field_name) + ->condition('field_name', $field_name) ->condition('status', CommentInterface::PUBLISHED) ->orderBy('created', 'DESC') ->orderBy('cid', 'DESC') @@ -339,11 +332,11 @@ function comment_new_page_count($num_comments, $new_replies, EntityInterface $en // Find the number of the first comment of the first unread thread. $count = db_query('SELECT COUNT(*) FROM {comment} WHERE entity_id = :entity_id AND entity_type = :entity_type - AND field_id = :field_id + AND field_name = :field_name AND status = :status AND SUBSTRING(thread, 1, (LENGTH(thread) - 1)) < :thread', array( ':status' => CommentInterface::PUBLISHED, ':entity_id' => $entity->id(), - ':field_id' => $entity->getEntityTypeId() . '__' . $field_name, + ':field_name' => $field_name, ':entity_type' => $entity->getEntityTypeId(), ':thread' => $first_thread, ))->fetchField(); @@ -555,10 +548,13 @@ function comment_node_view_alter(&$build, EntityInterface $node, EntityViewDispl * The renderable array for the comment addition form. */ function comment_add(EntityInterface $entity, $field_name = 'comment', $pid = NULL) { + /** @var \Drupal\field\FieldConfigInterface $field */ + $field = entity_load('field_config', $entity->getEntityTypeId() . '.' . $field_name); $values = array( 'entity_type' => $entity->getEntityTypeId(), 'entity_id' => $entity->id(), - 'field_id' => $entity->getEntityTypeId() . '__' . $field_name, + 'field_name' => $field_name, + 'comment_type' => $field->getSetting('bundle'), 'pid' => $pid, ); $comment = entity_create('comment', $values); @@ -647,7 +643,7 @@ function comment_get_thread(EntityInterface $entity, $field_name, $mode, $commen $query ->condition('c.entity_id', $entity->id()) ->condition('c.entity_type', $entity->getEntityTypeId()) - ->condition('c.field_id', $entity->getEntityTypeId() . '__' . $field_name) + ->condition('c.field_name', $field_name) ->addTag('entity_access') ->addTag('comment_filter') ->addMetaData('base_table', 'comment') @@ -660,7 +656,7 @@ function comment_get_thread(EntityInterface $entity, $field_name, $mode, $commen $count_query ->condition('c.entity_id', $entity->id()) ->condition('c.entity_type', $entity->getEntityTypeId()) - ->condition('c.field_id', $entity->getEntityTypeId() . '__' . $field_name) + ->condition('c.field_name', $field_name) ->addTag('entity_access') ->addTag('comment_filter') ->addMetaData('base_table', 'comment') @@ -762,21 +758,6 @@ function comment_view_multiple($comments, $view_mode = 'full', $langcode = NULL) /** * Implements hook_form_FORM_ID_alter(). */ -function comment_form_field_ui_field_instance_edit_form_alter(&$form, $form_state) { - if ($form['#field']->getType() == 'comment') { - // Collect translation settings. - if (\Drupal::moduleHandler()->moduleExists('content_translation')) { - array_unshift($form['#submit'], 'comment_translation_configuration_element_submit'); - } - - // Hide required checkbox. - $form['instance']['required']['#access'] = FALSE; - } -} - -/** - * Implements hook_form_FORM_ID_alter(). - */ function comment_form_field_ui_field_overview_form_alter(&$form, $form_state) { $request = \Drupal::request(); if ($form['#entity_type'] == 'comment' && $request->attributes->has('commented_entity_type')) { @@ -817,28 +798,6 @@ function comment_form_field_ui_field_edit_form_alter(&$form, $form_state) { } /** - * Form submission handler for field_ui_field_edit_form(). - * - * This handles the comment translation settings added by - * _comment_field_instance_settings_form_process(). - * - * @see _comment_field_instance_settings_form_process() - */ -function comment_translation_configuration_element_submit($form, &$form_state) { - // The comment translation settings form element is embedded into the instance - // settings form. Hence we need to provide to the regular submit handler a - // manipulated form state to make it process comment settings instead of the - // host entity. - $key = 'language_configuration'; - $comment_form_state = array( - 'content_translation' => array('key' => $key), - 'language' => array($key => array('entity_type' => 'comment', 'bundle' => $form['#field']->name)), - 'values' => array($key => array('content_translation' => $form_state['values']['content_translation'])), - ); - content_translation_language_configuration_element_submit($form, $comment_form_state); -} - -/** * Implements hook_entity_load(). * * @see \Drupal\comment\Plugin\Field\FieldType\CommentItem::propertyDefinitions() @@ -856,14 +815,11 @@ function comment_entity_load($entities, $entity_type) { // comment statistics properties, which are defined on each CommentItem field. $result = \Drupal::service('comment.statistics')->read($entities, $entity_type); foreach ($result as $record) { - $parts = explode('__', $record->field_id, 2); - list(, $field_name) = $parts; - // Skip fields that entity does not have. - if (!$entities[$record->entity_id]->hasField($field_name)) { + if (!$entities[$record->entity_id]->hasField($record->field_name)) { continue; } - $comment_statistics = $entities[$record->entity_id]->get($field_name); + $comment_statistics = $entities[$record->entity_id]->get($record->field_name); $comment_statistics->cid = $record->cid; $comment_statistics->last_comment_timestamp = $record->last_comment_timestamp; $comment_statistics->last_comment_name = $record->last_comment_name; @@ -1111,7 +1067,7 @@ function comment_num_new($entity_id, $entity_type, $field_name = NULL, $timestam ->condition('c.created', $timestamp, '>'); if ($field_name) { // Limit to a particular field. - $query->condition('c.field_id', $entity_type . '__' . $field_name); + $query->condition('c.field_name', $field_name); } return $query->execute() @@ -1144,7 +1100,7 @@ function comment_get_display_ordinal($cid, $instance) { // Count how many comments (c1) are before $cid (c2) in display order. This is // the 0-based display ordinal. $query = db_select('comment', 'c1'); - $query->innerJoin('comment', 'c2', 'c2.entity_id = c1.entity_id AND c2.entity_type = c1.entity_type AND c2.field_id = c1.field_id'); + $query->innerJoin('comment', 'c2', 'c2.entity_id = c1.entity_id AND c2.entity_type = c1.entity_type AND c2.field_name = c1.field_name'); $query->addExpression('COUNT(*)', 'count'); $query->condition('c2.cid', $cid); if (!user_access('administer comments')) { @@ -1480,3 +1436,16 @@ function comment_file_download_access($field, EntityInterface $entity, FileInter return FALSE; } } + +/** + * Loads a comment type. + * + * @param int $id + * The ID of the comment type to load. + * + * @return \Drupal\comment\CommentTypeInterface + * A CommentTypeInterface object or NULL if the requested $id does not exist. + */ +function comment_type_load($id) { + return entity_load('comment_type', $id); +} diff --git a/core/modules/comment/comment.routing.yml b/core/modules/comment/comment.routing.yml index e3ad589..89680ef 100644 --- a/core/modules/comment/comment.routing.yml +++ b/core/modules/comment/comment.routing.yml @@ -66,14 +66,6 @@ comment.new_comments_node_links: requirements: _permission: 'access content' -comment.bundle_list: - path: '/admin/structure/comments' - defaults: - _content: 'Drupal\comment\Controller\AdminController::overviewBundles' - _title: 'Comment forms' - requirements: - _permission: 'administer comments' - # This route is only used by Field UI. comment.bundle: path: '/admin/structure/comments/manage/{bundle}' @@ -87,3 +79,43 @@ comment.node_redirect: requirements: _entity_access: 'node.view' _module_dependencies: 'node' + +comment.type_list: + path: '/admin/structure/comments' + defaults: + _entity_list: 'comment_type' + _title: 'Comment forms' + requirements: + _permission: 'administer comments' + options: + _admin_route: TRUE + +comment.type_delete: + path: '/admin/structure/comment/manage/{comment_type}/delete' + defaults: + _entity_form: 'comment_type.delete' + _title: 'Delete' + requirements: + _entity_access: 'comment_type.delete' + options: + _admin_route: TRUE + +comment.type_add: + path: '/admin/structure/comment/types/add' + defaults: + _entity_form: 'comment_type.add' + _title: 'Add' + requirements: + _permission: 'administer comments' + options: + _admin_route: TRUE + +comment.type_edit: + path: '/admin/structure/comment/manage/{comment_type}' + defaults: + _entity_form: 'comment_type.edit' + _title: 'Edit' + requirements: + _entity_access: 'comment_type.update' + options: + _admin_route: TRUE diff --git a/core/modules/comment/comment.views.inc b/core/modules/comment/comment.views.inc index 6429f28..05e0cd1 100644 --- a/core/modules/comment/comment.views.inc +++ b/core/modules/comment/comment.views.inc @@ -332,9 +332,26 @@ function comment_views_data() { ), ); - $data['comment']['field_id'] = array( - 'title' => t('Comment field id'), - 'help' => t('The Field id from which the comment originated.'), + $data['comment']['field_name'] = array( + 'title' => t('Comment field name'), + 'help' => t('The Field name from which the comment originated.'), + 'field' => array( + 'id' => 'standard', + ), + 'filter' => array( + 'id' => 'string', + ), + 'argument' => array( + 'id' => 'string', + ), + 'sort' => array( + 'id' => 'standard', + ), + ); + + $data['comment']['comment_type'] = array( + 'title' => t('Comment type'), + 'help' => t('The comment type from which the comment originated.'), 'field' => array( 'id' => 'standard', ), @@ -567,9 +584,9 @@ function comment_views_data() { 'id' => 'standard', ), ); - $data['comment_entity_statistics']['field_id'] = array( - 'title' => t('Comment field ID'), - 'help' => t('The field ID from which the comment originated.'), + $data['comment_entity_statistics']['field_name'] = array( + 'title' => t('Comment field name'), + 'help' => t('The field name from which the comment originated.'), 'field' => array( 'id' => 'standard', ), @@ -666,8 +683,8 @@ function comment_views_data_alter(&$data) { 'value' => $entity_type_id, ), array( - 'field' => 'field_id', - 'value' => $entity_type_id . '.' . $field_name, + 'field' => 'field_name', + 'value' => $field_name, ), ), ), diff --git a/core/modules/comment/lib/Drupal/comment/CommentFieldNameItem.php b/core/modules/comment/lib/Drupal/comment/CommentFieldNameItem.php deleted file mode 100644 index 94b8587..0000000 --- a/core/modules/comment/lib/Drupal/comment/CommentFieldNameItem.php +++ /dev/null @@ -1,31 +0,0 @@ -setLabel(t('String value')) - ->setClass('\Drupal\comment\CommentFieldNameValue') - ->setComputed(TRUE); - - return $properties; - } - -} diff --git a/core/modules/comment/lib/Drupal/comment/CommentFieldNameValue.php b/core/modules/comment/lib/Drupal/comment/CommentFieldNameValue.php deleted file mode 100644 index 0190b8d..0000000 --- a/core/modules/comment/lib/Drupal/comment/CommentFieldNameValue.php +++ /dev/null @@ -1,53 +0,0 @@ -value)) { - if (!isset($this->parent)) { - throw new InvalidArgumentException('Computed properties require context for computation.'); - } - $field = $this->parent->getParent(); - $entity = $field->getParent(); - // Field id is of the form {entity_type}__{field_name}. We set the - // optional limit param to explode() in case the user adds a field with __ - // in the name. - $parts = explode('__', $entity->getFieldId(), 2); - if ($parts && count($parts) == 2) { - $this->value = end($parts); - } - } - return $this->value; - } - - /** - * {@inheritdoc} - */ - public function setValue($value, $notify = TRUE) { - if (isset($value)) { - $this->field_name = $value; - // Also set the field id. - $field = $this->parent->getParent(); - $entity = $field->getParent(); - $entity->field_id = $entity->getCommentedEntityTypeId() . '__' . $value; - } - } - -} diff --git a/core/modules/comment/lib/Drupal/comment/CommentFormController.php b/core/modules/comment/lib/Drupal/comment/CommentFormController.php index e9759eb..6860083 100644 --- a/core/modules/comment/lib/Drupal/comment/CommentFormController.php +++ b/core/modules/comment/lib/Drupal/comment/CommentFormController.php @@ -225,7 +225,7 @@ public function form(array $form, array &$form_state) { // Add internal comment properties. $original = $comment->getUntranslated(); - foreach (array('cid', 'pid', 'entity_id', 'entity_type', 'field_id', 'uid', 'langcode') as $key) { + foreach (array('cid', 'pid', 'entity_id', 'entity_type', 'comment_type', 'field_name', 'uid', 'langcode') as $key) { $key_name = key($comment->$key->getFieldDefinition()->getPropertyDefinitions()); $form[$key] = array('#type' => 'value', '#value' => $original->$key->{$key_name}); } diff --git a/core/modules/comment/lib/Drupal/comment/CommentInterface.php b/core/modules/comment/lib/Drupal/comment/CommentInterface.php index 48af294..01f8a99 100644 --- a/core/modules/comment/lib/Drupal/comment/CommentInterface.php +++ b/core/modules/comment/lib/Drupal/comment/CommentInterface.php @@ -67,24 +67,15 @@ public function getCommentedEntityId(); public function getCommentedEntityTypeId(); /** - * Returns the field ID of the comment field the comment is attached to. - * - * @return string - * The field identifier of the field the comment is attached to. - */ - public function getFieldId(); - - /** * Sets the field ID for which this comment is attached. * - * @param string $field_id - * The field identifier, usually formatted: {entity_type}__{field_name}, - * for example, node__comment. + * @param string $field_name + * The field name through which the comment was added. * * @return $this * The class instance that this method is called on. */ - public function setFieldId($field_id); + public function setFieldName($field_name); /** * Returns the name of the field the comment is attached to. diff --git a/core/modules/comment/lib/Drupal/comment/CommentManager.php b/core/modules/comment/lib/Drupal/comment/CommentManager.php index fcb3277..cb2ea80 100644 --- a/core/modules/comment/lib/Drupal/comment/CommentManager.php +++ b/core/modules/comment/lib/Drupal/comment/CommentManager.php @@ -129,7 +129,22 @@ public function getAllFields() { /** * {@inheritdoc} */ - public function addDefaultField($entity_type, $bundle, $field_name = 'comment', $default_value = CommentItemInterface::OPEN) { + public function addDefaultField($entity_type, $bundle, $field_name = 'comment', $default_value = CommentItemInterface::OPEN, $comment_type_id = 'comment') { + $comment_type_storage = $this->entityManager->getStorage('comment_type'); + if (!($comment_type = $comment_type_storage->load($comment_type_id))) { + $comment_type_storage->create(array( + 'id' => $comment_type_id, + 'label' => $comment_type_id, + 'targetEntityTypeId' => $entity_type, + 'description' => 'Default comment field', + ))->save(); + } + else if ($comment_type->targetEntityTypeId !== $entity_type) { + throw new \InvalidArgumentException($this->t('The given comment type id %id can only be used with the %entity_type entity type', array( + '%id' => $comment_type_id, + '%entity_type' => $entity_type, + ))); + } // Make sure the field doesn't already exist. if (!$this->fieldInfo->getField($entity_type, $field_name)) { // Add a default comment field for existing node comments. @@ -139,7 +154,7 @@ public function addDefaultField($entity_type, $bundle, $field_name = 'comment', 'type' => 'comment', 'translatable' => '0', 'settings' => array( - 'description' => 'Default comment field', + 'comment_type' => $comment_type_id, ), )); // Create the field. @@ -200,13 +215,13 @@ public function addDefaultField($entity_type, $bundle, $field_name = 'comment', } } - $this->addBodyField($entity_type, $field_name); + $this->addBodyField($comment_type_id); } /** * {@inheritdoc} */ - public function addBodyField($entity_type, $field_name) { + public function addBodyField($comment_type) { // Create the field if needed. $field = $this->entityManager->getStorage('field_config')->load('comment.comment_body'); if (!$field) { @@ -217,32 +232,30 @@ public function addBodyField($entity_type, $field_name) { )); $field->save(); } - // Create the instance if needed, field name defaults to 'comment'. - $comment_bundle = $entity_type . '__' . $field_name; $field_instance = $this->entityManager ->getStorage('field_instance_config') - ->load("comment.$comment_bundle.comment_body"); + ->load("comment.$comment_type.comment_body"); if (!$field_instance) { // Attaches the body field by default. $field_instance = $this->entityManager->getStorage('field_instance_config')->create(array( 'field_name' => 'comment_body', 'label' => 'Comment', 'entity_type' => 'comment', - 'bundle' => $comment_bundle, + 'bundle' => $comment_type, 'settings' => array('text_processing' => 1), 'required' => TRUE, )); $field_instance->save(); // Assign widget settings for the 'default' form mode. - entity_get_form_display('comment', $comment_bundle, 'default') + entity_get_form_display('comment', $comment_type, 'default') ->setComponent('comment_body', array( 'type' => 'text_textarea', )) ->save(); // Assign display settings for the 'default' view mode. - entity_get_display('comment', $comment_bundle, 'default') + entity_get_display('comment', $comment_type, 'default') ->setComponent('comment_body', array( 'label' => 'hidden', 'type' => 'text_default', @@ -255,17 +268,6 @@ public function addBodyField($entity_type, $field_name) { /** * {@inheritdoc} */ - public function getFieldUIPageTitle($commented_entity_type, $field_name) { - $field_info = $this->fieldInfo->getField($commented_entity_type, $field_name); - $bundles = $field_info->getBundles(); - $sample_bundle = reset($bundles); - $sample_instance = $this->fieldInfo->getInstance($commented_entity_type, $sample_bundle, $field_name); - return String::checkPlain($sample_instance->label); - } - - /** - * {@inheritdoc} - */ public function forbiddenMessage(EntityInterface $entity, $field_name) { if (!isset($this->authenticatedCanPostComments)) { // We only output a link if we are certain that users will get the diff --git a/core/modules/comment/lib/Drupal/comment/CommentManagerInterface.php b/core/modules/comment/lib/Drupal/comment/CommentManagerInterface.php index 52de708..839ad65 100644 --- a/core/modules/comment/lib/Drupal/comment/CommentManagerInterface.php +++ b/core/modules/comment/lib/Drupal/comment/CommentManagerInterface.php @@ -63,31 +63,18 @@ public function getAllFields(); * (optional) Default value, one of CommentItemInterface::HIDDEN, * CommentItemInterface::OPEN, CommentItemInterface::CLOSED. Defaults to * CommentItemInterface::OPEN. + * @param string $comment_type_id + * ID of comment type to use. */ - public function addDefaultField($entity_type, $bundle, $field_name = 'comment', $default_value = CommentItemInterface::OPEN); + public function addDefaultField($entity_type, $bundle, $field_name = 'comment', $default_value = CommentItemInterface::OPEN, $comment_type_id = 'comment'); /** * Creates a comment_body field instance. * - * @param string $entity_type - * The type of the entity to which the comment field attached. - * @param string $field_name - * Name of the comment field to add comment_body field. - */ - public function addBodyField($entity_type, $field_name); - - /** - * Builds human readable page title for field_ui management screens. - * - * @param string $commented_entity_type - * The entity type to which the comment field is attached. - * @param string $field_name - * The comment field for which the overview is to be displayed. - * - * @return string - * The human readable field name. + * @param string $comment_type + * The comment bundle. */ - public function getFieldUIPageTitle($commented_entity_type, $field_name); + public function addBodyField($comment_type); /** * Provides a message if posting comments is forbidden. diff --git a/core/modules/comment/lib/Drupal/comment/CommentStatistics.php b/core/modules/comment/lib/Drupal/comment/CommentStatistics.php index 48505c4..63e9833 100644 --- a/core/modules/comment/lib/Drupal/comment/CommentStatistics.php +++ b/core/modules/comment/lib/Drupal/comment/CommentStatistics.php @@ -94,7 +94,7 @@ public function create(ContentEntityInterface $entity, $fields) { ->fields(array( 'entity_id', 'entity_type', - 'field_id', + 'field_name', 'cid', 'last_comment_timestamp', 'last_comment_name', @@ -125,7 +125,7 @@ public function create(ContentEntityInterface $entity, $fields) { $query->values(array( 'entity_id' => $entity->id(), 'entity_type' => $entity->getEntityTypeId(), - 'field_id' => $entity->getEntityTypeId() . '__' . $field_name, + 'field_name' => $field_name, 'cid' => 0, 'last_comment_timestamp' => $last_comment_timestamp, 'last_comment_name' => NULL, @@ -156,7 +156,7 @@ public function getRankingInfo() { 'alias' => 'ces', // Default to comment field as this is the most common use case for // nodes. - 'on' => "ces.entity_id = i.sid AND ces.entity_type = 'node' AND ces.field_id = 'node__comment'", + 'on' => "ces.entity_id = i.sid AND ces.entity_type = 'node' AND ces.field_name = 'comment'", ), // Inverse law that maps the highest reply count on the site to 1 and 0 // to 0. Note that the CAST here is necessary for PostgreSQL, because the @@ -182,7 +182,7 @@ public function update(CommentInterface $comment) { $query->addExpression('COUNT(cid)'); $count = $query->condition('c.entity_id', $comment->getCommentedEntityId()) ->condition('c.entity_type', $comment->getCommentedEntityTypeId()) - ->condition('c.field_id', $comment->getFieldId()) + ->condition('c.comment_name', $comment->getFieldName()) ->condition('c.status', CommentInterface::PUBLISHED) ->execute() ->fetchField(); @@ -193,7 +193,7 @@ public function update(CommentInterface $comment) { ->fields('c', array('cid', 'name', 'changed', 'uid')) ->condition('c.entity_id', $comment->getCommentedEntityId()) ->condition('c.entity_type', $comment->getCommentedEntityTypeId()) - ->condition('c.field_id', $comment->getFieldId()) + ->condition('c.field_name', $comment->getFieldName()) ->condition('c.status', CommentInterface::PUBLISHED) ->orderBy('c.created', 'DESC') ->range(0, 1) @@ -211,7 +211,7 @@ public function update(CommentInterface $comment) { ->keys(array( 'entity_id' => $comment->getCommentedEntityId(), 'entity_type' => $comment->getCommentedEntityTypeId(), - 'field_id' => $comment->getFieldId(), + 'field_name' => $comment->getFieldName(), )) ->execute(); } @@ -240,7 +240,7 @@ public function update(CommentInterface $comment) { )) ->condition('entity_id', $comment->getCommentedEntityId()) ->condition('entity_type', $comment->getCommentedEntityTypeId()) - ->condition('field_id', $comment->getFieldId()) + ->condition('field_name', $comment->getFieldName()) ->execute(); } } diff --git a/core/modules/comment/lib/Drupal/comment/CommentStorage.php b/core/modules/comment/lib/Drupal/comment/CommentStorage.php index f59a2be..3d31982 100644 --- a/core/modules/comment/lib/Drupal/comment/CommentStorage.php +++ b/core/modules/comment/lib/Drupal/comment/CommentStorage.php @@ -95,7 +95,7 @@ public function updateEntityStatistics(CommentInterface $comment) { public function getMaxThread(EntityInterface $comment) { $query = $this->database->select('comment', 'c') ->condition('entity_id', $comment->getCommentedEntityId()) - ->condition('field_id', $comment->getFieldId()) + ->condition('field_name', $comment->getFieldName()) ->condition('entity_type', $comment->getCommentedEntityTypeId()); $query->addExpression('MAX(thread)', 'thread'); return $query->execute() @@ -108,7 +108,7 @@ public function getMaxThread(EntityInterface $comment) { public function getMaxThreadPerThread(EntityInterface $comment) { $query = $this->database->select('comment', 'c') ->condition('entity_id', $comment->getCommentedEntityId()) - ->condition('field_id', $comment->getFieldId()) + ->condition('field_name', $comment->getFieldName()) ->condition('entity_type', $comment->getCommentedEntityTypeId()) ->condition('thread', $comment->getParentComment()->getThread() . '.%', 'LIKE'); $query->addExpression('MAX(thread)', 'thread'); diff --git a/core/modules/comment/lib/Drupal/comment/CommentTypeFormController.php b/core/modules/comment/lib/Drupal/comment/CommentTypeFormController.php new file mode 100644 index 0000000..295085d --- /dev/null +++ b/core/modules/comment/lib/Drupal/comment/CommentTypeFormController.php @@ -0,0 +1,115 @@ +entity; + + $form['label'] = array( + '#type' => 'textfield', + '#title' => t('Label'), + '#maxlength' => 255, + '#default_value' => $comment_type->label(), + '#description' => t("Provide a label for this comment type to help identify it in the administration pages."), + '#required' => TRUE, + ); + $form['id'] = array( + '#type' => 'machine_name', + '#default_value' => $comment_type->id(), + '#machine_name' => array( + 'exists' => 'comment_type_load', + ), + '#maxlength' => EntityTypeInterface::BUNDLE_MAX_LENGTH, + '#disabled' => !$comment_type->isNew(), + ); + + $form['description'] = array( + '#type' => 'textarea', + '#default_value' => $comment_type->description, + '#description' => t('Enter a description for this comment type.'), + '#title' => t('Description'), + ); + + $options = array(); + // @todo Inject this. + foreach (\Drupal::entityManager()->getDefinitions() as $entity_type) { + if ($entity_type->isFieldable()) { + $options[$entity_type->id()] = $entity_type->getLabel(); + } + } + $form['targetEntityTypeId'] = array( + '#type' => 'select', + '#default_value' => $comment_type->targetEntityTypeId, + '#description' => t('Select the target entity type for this comment type.'), + '#title' => t('Target entity type'), + '#options' => $options, + ); + + if ($this->moduleHandler->moduleExists('content_translation')) { + $form['language'] = array( + '#type' => 'details', + '#title' => t('Language settings'), + '#group' => 'additional_settings', + ); + + $language_configuration = language_get_default_configuration('comment', $comment_type->id()); + $form['language']['language_configuration'] = array( + '#type' => 'language_configuration', + '#entity_information' => array( + 'entity_type' => 'comment', + 'bundle' => $comment_type->id(), + ), + '#default_value' => $language_configuration, + ); + + $form['#submit'][] = 'language_configuration_element_submit'; + } + + $form['actions'] = array('#type' => 'actions'); + $form['actions']['submit'] = array( + '#type' => 'submit', + '#value' => t('Save'), + ); + + return $form; + } + + /** + * {@inheritdoc} + */ + public function save(array $form, array &$form_state) { + $comment_type = $this->entity; + $status = $comment_type->save(); + + $edit_link = \Drupal::linkGenerator()->generateFromUrl($this->t('Edit'), $this->entity->urlInfo()); + if ($status == SAVED_UPDATED) { + drupal_set_message(t('Comment type %label has been updated.', array('%label' => $comment_type->label()))); + watchdog('comment', 'Comment type %label has been updated.', array('%label' => $comment_type->label()), WATCHDOG_NOTICE, $edit_link); + } + else { + drupal_set_message(t('Comment type %label has been added.', array('%label' => $comment_type->label()))); + watchdog('comment', 'Comment type %label has been added.', array('%label' => $comment_type->label()), WATCHDOG_NOTICE, $edit_link); + } + + $form_state['redirect_route']['route_name'] = 'comment.type_list'; + } + +} diff --git a/core/modules/comment/lib/Drupal/comment/CommentTypeInterface.php b/core/modules/comment/lib/Drupal/comment/CommentTypeInterface.php new file mode 100644 index 0000000..861a3e2 --- /dev/null +++ b/core/modules/comment/lib/Drupal/comment/CommentTypeInterface.php @@ -0,0 +1,23 @@ +generateFromUrl($entity->label(), $entity->urlInfo()); + $row['description'] = Xss::filterAdmin($entity->description); + return $row + parent::buildRow($entity); + } + + /** + * {@inheritdoc} + */ + protected function getTitle() { + return $this->t('Comment types'); + } + +} diff --git a/core/modules/comment/lib/Drupal/comment/Controller/AdminController.php b/core/modules/comment/lib/Drupal/comment/Controller/AdminController.php index 9682594..0c47ae2 100644 --- a/core/modules/comment/lib/Drupal/comment/Controller/AdminController.php +++ b/core/modules/comment/lib/Drupal/comment/Controller/AdminController.php @@ -7,12 +7,8 @@ namespace Drupal\comment\Controller; -use Drupal\comment\CommentManagerInterface; -use Drupal\field\FieldInfo; -use Drupal\Component\Utility\String; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Form\FormBuilderInterface; -use Drupal\field_ui\FieldUI; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -47,8 +43,6 @@ class AdminController extends ControllerBase { */ public static function create(ContainerInterface $container) { return new static( - $container->get('field.info'), - $container->get('comment.manager'), $container->get('form_builder') ); } @@ -56,135 +50,14 @@ public static function create(ContainerInterface $container) { /** * Constructs an AdminController object. * - * @param \Drupal\field\FieldInfo $field_info - * The field info service. - * @param \Drupal\comment\CommentManagerInterface $comment_manager - * The comment manager service. * @param \Drupal\Core\Form\FormBuilderInterface $form_builder * The form builder. */ - public function __construct(FieldInfo $field_info, CommentManagerInterface $comment_manager, FormBuilderInterface $form_builder) { - $this->fieldInfo = $field_info; - $this->commentManager = $comment_manager; + public function __construct(FormBuilderInterface $form_builder) { $this->formBuilder = $form_builder; } /** - * Returns an overview of comment fields in use on the site. - * - * @return array - * A renderable array containing a list of comment fields, the entity - * type and bundle combinations on which they are in use and various - * operation links for configuring each field. - */ - public function overviewBundles() { - $header = array( - 'field_name' => $this->t('Field name'), - 'description' => array( - 'data' => $this->t('Description'), - 'class' => array(RESPONSIVE_PRIORITY_MEDIUM), - ), - 'usage' => array( - 'data' => $this->t('Used in'), - 'class' => array(RESPONSIVE_PRIORITY_MEDIUM), - ), - 'type' => $this->t('Type'), - ); - - // Add a column for field UI operations if the Field UI module is enabled. - $field_ui_enabled = $this->moduleHandler()->moduleExists('field_ui'); - if ($field_ui_enabled) { - $header['operations'] = $this->t('Operations'); - } - - $entity_bundles = $this->entityManager()->getAllBundleInfo(); - $entity_types = $this->entityManager()->getDefinitions(); - $rows = array(); - - // Fetch a list of all comment fields. - $fields = $this->commentManager->getAllFields(); - - foreach ($fields as $entity_type => $data) { - foreach ($data as $field_name => $field_info_map) { - $field_info = $this->fieldInfo->getField($entity_type, $field_name); - // Initialize the row. - $row = array( - 'class' => $field_info->get('locked') ? array('field-disabled') : array(''), - ); - - $bundles = $field_info->getBundles(); - $sample_bundle = reset($bundles); - $sample_instance = $this->fieldInfo->getInstance($entity_type, $sample_bundle, $field_name); - - $tokens = array( - '@label' => $sample_instance->label, - '@field_name' => $field_name, - ); - $row['data']['field_name']['data'] = $field_info->get('locked') ? $this->t('@label (@field_name) (Locked)', $tokens) : $this->t('@label (@field_name)', $tokens); - - $row['data']['description']['data'] = $field_info->getSetting('description'); - $row['data']['usage']['data'] = array( - '#theme' => 'item_list', - '#items' => array(), - ); - foreach ($field_info_map['bundles'] as $bundle) { - if (isset($entity_bundles[$entity_type][$bundle])) { - // Add the current instance. - if ($field_ui_enabled && $route_info = FieldUI::getOverviewRouteInfo($entity_type, $bundle)) { - $row['data']['usage']['data']['#items'][] = $this->l($entity_bundles[$entity_type][$bundle]['label'], $route_info['route_name'], $route_info['route_parameters']); - } - else { - $row['data']['usage']['data']['#items'][] = $entity_bundles[$entity_type][$bundle]['label']; - } - } - } - - $row['data']['type']['data'] = String::checkPlain($entity_types[$entity_type]->getLabel()); - - if ($field_ui_enabled) { - if ($this->currentUser()->hasPermission('administer comment fields')) { - $links['fields'] = array( - 'title' => $this->t('Manage fields'), - 'href' => 'admin/structure/comments/manage/' . $entity_type . '__' . $field_name . '/fields', - 'weight' => 5, - ); - } - if ($this->currentUser()->hasPermission('administer comment display')) { - $links['display'] = array( - 'title' => $this->t('Manage display'), - 'href' => 'admin/structure/comments/manage/' . $entity_type . '__' . $field_name . '/display', - 'weight' => 10, - ); - } - if ($this->currentUser()->hasPermission('administer comment form display')) { - $links['form_display'] = array( - 'title' => $this->t('Manage form display'), - 'href' => 'admin/structure/comments/manage/' . $entity_type . '__' . $field_name . '/form-display', - 'weight' => 10, - ); - } - - $row['data']['operations']['data'] = array( - '#type' => 'operations', - '#links' => $links, - ); - } - $rows[$entity_type . '__' . $field_name] = $row; - } - } - - $build['overview'] = array( - '#type' => 'table', - '#header' => $header, - '#rows' => $rows, - '#empty' => $this->t('No comment forms available.'), - ); - $build['#title'] = $this->t('Comment forms'); - - return $build; - } - - /** * Presents an administrative comment listing. * * @param \Symfony\Component\HttpFoundation\Request $request diff --git a/core/modules/comment/lib/Drupal/comment/Controller/CommentController.php b/core/modules/comment/lib/Drupal/comment/Controller/CommentController.php index 7829950..4b615f6 100644 --- a/core/modules/comment/lib/Drupal/comment/Controller/CommentController.php +++ b/core/modules/comment/lib/Drupal/comment/Controller/CommentController.php @@ -267,7 +267,7 @@ public function getReplyForm(Request $request, $entity_type, $entity_id, $field_ 'entity_id' => $entity->id(), 'pid' => $pid, 'entity_type' => $entity->getEntityTypeId(), - 'field_id' => $entity->getEntityTypeId() . '__' . $field_name, + 'field_name' => $field_name, )); $build['comment_form'] = $this->entityFormBuilder()->getForm($comment); diff --git a/core/modules/comment/lib/Drupal/comment/Entity/Comment.php b/core/modules/comment/lib/Drupal/comment/Entity/Comment.php index eb09d5c..f14b310 100644 --- a/core/modules/comment/lib/Drupal/comment/Entity/Comment.php +++ b/core/modules/comment/lib/Drupal/comment/Entity/Comment.php @@ -13,8 +13,6 @@ use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Field\FieldDefinition; -use Drupal\Core\Language\Language; -use Drupal\Core\TypedData\DataDefinition; use Drupal\user\UserInterface; /** @@ -40,7 +38,7 @@ * translatable = TRUE, * entity_keys = { * "id" = "cid", - * "bundle" = "field_id", + * "bundle" = "comment_type", * "label" = "subject", * "uuid" = "uuid" * }, @@ -284,21 +282,15 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ->setLabel(t('Entity type')) ->setDescription(t('The entity type to which this comment is attached.')); - // @todo Convert to the entity_reference field in - // https://drupal.org/node/2149859. - $fields['field_id'] = FieldDefinition::create('string') - ->setLabel(t('Field ID')) - ->setDescription(t('The comment field id.')); + $fields['comment_type'] = FieldDefinition::create('string') + ->setLabel(t('Comment Type')) + ->setDescription(t('The comment type.')); $fields['field_name'] = FieldDefinition::create('string') ->setLabel(t('Comment field name')) ->setDescription(t('The field name through which this comment was added.')) ->setComputed(TRUE); - $item_definition = $fields['field_name']->getItemDefinition(); - $item_definition->setClass('\Drupal\comment\CommentFieldNameItem'); - $fields['field_name']->setItemDefinition($item_definition); - return $fields; } @@ -306,9 +298,9 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { * {@inheritdoc} */ public static function bundleFieldDefinitions(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) { - list($target_type) = explode('__', $bundle, 2); + $comment_type = entity_load('comment_type', $bundle); $fields['entity_id'] = clone $base_field_definitions['entity_id']; - $fields['entity_id']->setSetting('target_type', $target_type); + $fields['entity_id']->setSetting('target_type', $comment_type->targetEntityTypeId); return $fields; } @@ -351,15 +343,8 @@ public function getCommentedEntityTypeId() { /** * {@inheritdoc} */ - public function getFieldId() { - return $this->get('field_id')->value; - } - - /** - * {@inheritdoc} - */ - public function setFieldId($field_id) { - $this->set('field_id', $field_id); + public function setFieldName($field_name) { + $this->set('field_name', $field_name); return $this; } @@ -505,8 +490,10 @@ public function getChangedTime() { * {@inheritdoc} */ public static function preCreate(EntityStorageInterface $storage, array &$values) { - if (empty($values['field_id']) && !empty($values['field_name']) && !empty($values['entity_type'])) { - $values['field_id'] = $values['entity_type'] . '__' . $values['field_name']; + if (empty($values['comment_type']) && !empty($values['field_name']) && !empty($values['entity_type'])) { + /** @var \Drupal\field\FieldConfigInterface $field */ + $field = entity_load('field_config', $values['entity_type'] . '.' . $values['field_name']); + $values['comment_type'] = $field->getSetting('comment_type'); } } diff --git a/core/modules/comment/lib/Drupal/comment/Entity/CommentType.php b/core/modules/comment/lib/Drupal/comment/Entity/CommentType.php new file mode 100644 index 0000000..a8ab7ca --- /dev/null +++ b/core/modules/comment/lib/Drupal/comment/Entity/CommentType.php @@ -0,0 +1,112 @@ +isSyncing()) { + entity_invoke_bundle_hook('create', 'comment', $this->id()); + if (!$this->isSyncing()) { + \Drupal::service('comment.manager')->addBodyField($this->id); + } + } + elseif ($this->getOriginalId() != $this->id) { + entity_invoke_bundle_hook('rename', 'comment', $this->getOriginalId(), $this->id); + } + } + + /** + * {@inheritdoc} + */ + public static function postDelete(EntityStorageInterface $storage, array $entities) { + parent::postDelete($storage, $entities); + + foreach ($entities as $entity) { + entity_invoke_bundle_hook('delete', 'comment', $entity->id()); + } + } + + public function getDescription() { + return $this->description; + } + + public function setDescription($description) { + $this->description = $description; + return $this; + } + + public function getTargetEntityTypeId() { + return $this->targetEntityTypeId; + } +} diff --git a/core/modules/comment/lib/Drupal/comment/Form/CommentTypeDeleteForm.php b/core/modules/comment/lib/Drupal/comment/Form/CommentTypeDeleteForm.php new file mode 100644 index 0000000..81a8d83 --- /dev/null +++ b/core/modules/comment/lib/Drupal/comment/Form/CommentTypeDeleteForm.php @@ -0,0 +1,138 @@ +queryFactory = $query_factory; + $this->commentManager = $comment_manager; + $this->entityManager = $entity_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity.query'), + $container->get('comment.manager'), + $container->get('entity.manager') + ); + } + + /** + * {@inheritdoc} + */ + public function getQuestion() { + return $this->t('Are you sure you want to delete %label?', array('%label' => $this->entity->label())); + } + + /** + * {@inheritdoc} + */ + public function getCancelRoute() { + return array( + 'route_name' => 'comment.type_list', + ); + } + + /** + * {@inheritdoc} + */ + public function getConfirmText() { + return $this->t('Delete'); + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, array &$form_state) { + $comments = $this->queryFactory->get('comment')->condition('comment_type', $this->entity->id())->execute(); + $entity_type = $this->entity->getTargetEntityTypeId(); + $caption = ''; + foreach ($this->commentManager->getFields($entity_type) as $field_name) { + /** @var \Drupal\field\FieldConfigInterface $field */ + if (($field = $this->entityManager->getStorage($entity_type)->load($entity_type . '.' . $field_name)) && $field->getSetting('comment_type') == $this->entity->id()) { + $caption .= '
' . $this->t('%label is used by the %field on your site. You can not remove this comment type until you have removed the field.', array( + '%label' => $this->entity->label(), + '%field' => $field->label(), + )) . '
'; + } + } + + if (!empty($comments)) { + $caption .= '' . $this->translationManager()->formatPlural(count($comments), '%label is used by 1 comment on your site. You can not remove this comment type until you have removed all of the %label comments.', '%label is used by @count comments on your site. You may not remove %label until you have removed all of the %label comments.', array('%label' => $this->entity->label())) . '
'; + } + if ($caption) { + $form['description'] = array('#markup' => $caption); + return $form; + } + else { + return parent::buildForm($form, $form_state); + } + } + + /** + * {@inheritdoc} + */ + public function submit(array $form, array &$form_state) { + $this->entity->delete(); + $form_state['redirect_route']['route_name'] = 'comment.type_list'; + drupal_set_message(t('comment type %label has been deleted.', array('%label' => $this->entity->label()))); + watchdog('comment', 'comment type %label has been deleted.', array('%label' => $this->entity->label()), WATCHDOG_NOTICE); + } + +} diff --git a/core/modules/comment/lib/Drupal/comment/Plugin/Field/FieldType/CommentItem.php b/core/modules/comment/lib/Drupal/comment/Plugin/Field/FieldType/CommentItem.php index 50799b8..3e95617 100644 --- a/core/modules/comment/lib/Drupal/comment/Plugin/Field/FieldType/CommentItem.php +++ b/core/modules/comment/lib/Drupal/comment/Plugin/Field/FieldType/CommentItem.php @@ -7,6 +7,7 @@ namespace Drupal\comment\Plugin\Field\FieldType; +use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\TypedData\DataDefinition; use Drupal\Core\Field\FieldItemBase; @@ -30,7 +31,7 @@ class CommentItem extends FieldItemBase implements CommentItemInterface { */ public static function defaultSettings() { return array( - 'description' => '', + 'comment_type' => 'new', ) + parent::defaultSettings(); } @@ -110,8 +111,6 @@ public function instanceSettingsForm(array $form, array &$form_state) { '#type' => 'details', '#title' => t('Comment form settings'), '#open' => TRUE, - '#bundle' => "{$entity_type}__{$field_name}", - '#process' => array(array(get_class($this), 'processSettingsElement')), '#attributes' => array( 'class' => array('comment-instance-settings-form'), ), @@ -194,41 +193,80 @@ public function isEmpty() { } /** - * Process callback to add submit handler for instance settings form. - * - * Attaches the required translation entity handlers for the instance which - * correlates one to one with the comment bundle. - */ - public static function processSettingsElement($element) { - // Settings should not be stored as nested. - $parents = $element['#parents']; - array_pop($parents); - $element['#parents'] = $parents; - // Add translation entity handlers. - if (\Drupal::moduleHandler()->moduleExists('content_translation')) { - $comment_form = $element; - $comment_form_state['content_translation']['key'] = 'language_configuration'; - $element += content_translation_enable_widget('comment', $element['#bundle'], $comment_form, $comment_form_state); - $element['content_translation']['#parents'] = $element['content_translation']['#array_parents'] = array( - 'content_translation' - ); - } - return $element; - } - - /** * {@inheritdoc} */ public function settingsForm(array $form, array &$form_state, $has_data) { $element = array(); - $element['description'] = array( + // @todo Inject storage controller once typed-data supports container + // injection. + $comment_types = entity_load_multiple('comment_type'); + $options = array('new' => t('Create new')); + $entity_type = $this->getEntity()->getEntityTypeId(); + foreach ($comment_types as $comment_type) { + if ($comment_type->targetEntityTypeId == $entity_type) { + $options[$comment_type->id] = $comment_type->label; + } + } + $element['comment_type'] = array( + '#type' => 'select', + '#title' => t('Comment type'), + '#options' => $options, + '#description' => t('Select the Comment type to use for this comment field.'), + '#default_value' => $this->getSetting('comment_type'), + ); + $element['new_comment_type'] = array( + '#tree' => TRUE, + '#type' => 'fieldset', + '#title' => t('Create new comment type'), + '#states' => array( + 'visible' => array( + ':input[name="field[settings][comment_type]"]' => array('value' => 'new'), + ), + ) + ); + $element['new_comment_type']['label'] = array( + '#type' => 'textfield', + '#title' => t('Label'), + '#maxlength' => 255, + '#default_value' => '', + '#description' => t("Provide a label for the new comment type to help identify it in the administration pages."), + '#required' => TRUE, + ); + $element['new_comment_type']['id'] = array( + '#type' => 'machine_name', + '#default_value' => '', + '#machine_name' => array( + 'exists' => 'comment_type_load', + ), + '#maxlength' => EntityTypeInterface::BUNDLE_MAX_LENGTH, + ); + + $element['new_comment_type']['description'] = array( '#type' => 'textarea', - '#title' => t('Field description'), - '#description' => t('Describe this comment field. The text will be displayed on the Comments Forms page.'), - '#default_value' => $this->getSetting('description'), + '#default_value' => '', + '#description' => t('Enter a description for the new comment type.'), + '#title' => t('Description'), + ); + $element['new_comment_type']['targetEntityTypeId'] = array( + '#type' => 'value', + '#value' => $entity_type, ); + array_unshift($form['#submit'], array($this, 'createNewCommentType')); return $element; } + /** + * Submit handler to create a new comment type if required. + */ + public function createNewCommentType($form, &$form_state) { + $settings = $form_state['values']['field']['settings']; + if ($settings['comment_type'] == 'new') { + // @todo Inject this once typed-data supports ContainerInjectionInterface. + $comment_type = entity_create('comment_type', $settings['new_comment_type']); + $comment_type->save(); + $form_state['values']['field']['settings']['comment_type'] = $comment_type->id(); + } + } + } diff --git a/core/modules/comment/lib/Drupal/comment/Routing/CommentBundleEnhancer.php b/core/modules/comment/lib/Drupal/comment/Routing/CommentBundleEnhancer.php deleted file mode 100644 index 783fcda..0000000 --- a/core/modules/comment/lib/Drupal/comment/Routing/CommentBundleEnhancer.php +++ /dev/null @@ -1,53 +0,0 @@ -entityManager = $entity_manager; - } - - /** - * {@inheritdoc} - */ - public function enhance(array $defaults, Request $request) { - if (isset($defaults['bundle']) && ($bundles = $this->entityManager->getBundleInfo('comment')) && isset($bundles[$defaults['bundle']])) { - list($entity_type, $field_name) = explode('__', $defaults['bundle'], 2); - $defaults['commented_entity_type'] = $entity_type; - $defaults['field_name'] = $field_name; - } - return $defaults; - } - -} diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php index 24a20a9..3aa6eda 100644 --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php @@ -62,7 +62,7 @@ function testCommentDefaultFields() { $this->assertTrue(isset($instances['node__comment']['comment_body']), format_string('The comment_body field is present for comments on type @type', array('@type' => $type_name))); // Test adding a field that defaults to CommentItemInterface::CLOSED. - $this->container->get('comment.manager')->addDefaultField('node', 'test_node_type', 'who_likes_ponies', CommentItemInterface::CLOSED); + $this->container->get('comment.manager')->addDefaultField('node', 'test_node_type', 'who_likes_ponies', CommentItemInterface::CLOSED, 'who_likes_ponies'); $field = entity_load('field_instance_config', 'node.test_node_type.who_likes_ponies'); $this->assertEqual($field->default_value[0]['status'], CommentItemInterface::CLOSED); } diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentLanguageTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentLanguageTest.php index 139bf73..045a945 100644 --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentLanguageTest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentLanguageTest.php @@ -120,7 +120,7 @@ function testCommentLanguage() { ->fields('c', array('cid')) ->condition('entity_id', $node->id()) ->condition('entity_type', 'node') - ->condition('field_id', 'node__comment') + ->condition('field_name', 'comment') ->orderBy('cid', 'DESC') ->range(0, 1) ->execute() diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php index 5e5b4de..1cf9774 100644 --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php @@ -51,7 +51,7 @@ function setupBundle() { parent::setupBundle(); $this->drupalCreateContentType(array('type' => $this->nodeBundle, 'name' => $this->nodeBundle)); // Add a comment field to the article content type. - $this->container->get('comment.manager')->addDefaultField('node', 'article', 'comment_article'); + $this->container->get('comment.manager')->addDefaultField('node', 'article', 'comment_article', CommentItemInterface::OPEN, 'comment_article'); // Create a page content type. $this->drupalCreateContentType(array('type' => 'page', 'name' => 'page')); // Add a comment field to the page content type - this one won't be @@ -85,12 +85,8 @@ function setupTestFields() { /** * Overrides \Drupal\content_translation\Tests\ContentTranslationUITest::createEntity(). */ - protected function createEntity($values, $langcode, $node_bundle = 'node__comment_article') { - // The argument is called 'node_bundle' but its actually just the entity - // bundle. Comment entity's bundle is of the form - // {entity_type}__{field_name}. Based on the passed bundle we need to - // determine the type of node and the name of the comment field. - if ($node_bundle == 'node__comment_article') { + protected function createEntity($values, $langcode, $comment_type = 'comment_article') { + if ($comment_type == 'comment_article') { // This is the article node type, with the 'comment_article' field. $node_type = 'article'; $field_name = 'comment_article'; @@ -108,9 +104,9 @@ protected function createEntity($values, $langcode, $node_bundle = 'node__commen )); $values['entity_id'] = $node->id(); $values['entity_type'] = 'node'; - $values['field_id'] = $node_bundle; + $values['field_name'] = $field_name; $values['uid'] = $node->getOwnerId(); - return parent::createEntity($values, $langcode, $node_bundle); + return parent::createEntity($values, $langcode, $comment_type); } /** @@ -160,7 +156,7 @@ function testTranslateLinkCommentAdminPage() { $this->drupalLogin($this->admin_user); $cid_translatable = $this->createEntity(array(), $this->langcodes[0]); - $cid_untranslatable = $this->createEntity(array(), $this->langcodes[0], 'node__comment'); + $cid_untranslatable = $this->createEntity(array(), $this->langcodes[0], 'comment'); // Verify translation links. $this->drupalGet('admin/content/comment'); diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentTypeTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentTypeTest.php new file mode 100644 index 0000000..31aa0d4 --- /dev/null +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentTypeTest.php @@ -0,0 +1,211 @@ +adminUser = $this->drupalCreateUser($this->permissions); + } + + /** + * Declares test information. + */ + public static function getInfo() { + return array( + 'name' => 'Comment types', + 'description' => 'Ensures that comment type functions work correctly.', + 'group' => 'Comment', + ); + } + + /** + * Tests creating a comment type programmatically and via a form. + */ + public function testCommentTypeCreation() { + // Create a comment type programmaticaly. + $type = $this->createCommentType('other'); + + $comment_type = entity_load('comment_type', 'other'); + $this->assertTrue($comment_type, 'The new comment type has been created.'); + + // Login a test user. + $this->drupalLogin($this->adminUser); + + $this->drupalGet('admin/structure/comment/manage/' . $type->id()); + $this->assertResponse(200, 'The new comment type can be accessed at the edit form.'); + + // Create a comment type via the user interface. + $edit = array( + 'id' => 'foo', + 'label' => 'title for foo', + 'description' => '', + 'targetEntityTypeId' => 'node', + ); + $this->drupalPostForm('admin/structure/comment/types/add', $edit, t('Save')); + $comment_type = entity_load('comment_type', 'foo'); + $this->assertTrue($comment_type, 'The new comment type has been created.'); + + // Check that the comment type was created in site default language. + $default_langcode = \Drupal::languageManager()->getDefaultLanguage()->id; + $this->assertEqual($comment_type->langcode, $default_langcode); + } + + /** + * Tests editing a comment type using the UI. + */ + public function testCommentTypeEditing() { + $this->drupalLogin($this->adminUser); + $this->createCommentType('other'); + + $instance = field_info_instance('comment', 'comment_body', 'other'); + $this->assertEqual($instance->getLabel(), 'Comment', 'Comment body field was found.'); + + // Change the comment type name. + $edit = array( + 'label' => 'Bar', + ); + $this->drupalPostForm('admin/structure/comment/manage/other', $edit, t('Save')); + field_info_cache_clear(); + + $this->drupalGet('admin/structure/comment'); + $this->assertRaw('Bar', 'New name was displayed.'); + $this->clickLink('Edit fields'); + $this->assertEqual(url('admin/structure/comment/manage/other/fields', array('absolute' => TRUE)), $this->getUrl(), 'Original machine name was used in URL.'); + + // Remove the body field. + $this->drupalPostForm('admin/structure/comment/manage/other/fields/comment.other.comment_body/delete', array(), t('Delete')); + // Resave the settings for this type. + $this->drupalPostForm('admin/structure/comment/manage/other', array(), t('Save')); + // Check that the body field doesn't exist. + $this->drupalGet('admin/structure/comment/manage/other/fields'); + $this->assertNoRaw('comment_body', 'Body field was not found.'); + } + + /** + * Tests deleting a comment type that still has content. + */ + public function testCommentTypeDeletion() { + // Create a comment type programmatically. + $type = $this->createCommentType('foo'); + \Drupal::service('comment.manager')->addDefaultField('node', 'page', 'foo', CommentItemInterface::OPEN, 'foo'); + $field = Field::fieldInfo()->getField('node', 'foo'); + + $this->drupalLogin($this->adminUser); + + // Create a node. + $node = entity_create('node', array( + 'type' => 'page', + 'title' => 'foo' + )); + $node->save(); + + // Add a new comment of this type. + $comment = entity_create('comment', array( + 'comment_type' => 'foo', + 'entity_type' => 'node', + 'field_name' => 'foo', + 'entity_id' => $node->id(), + )); + $comment->save(); + + // Attempt to delete the comment type, which should not be allowed. + $this->drupalGet('admin/structure/comment/manage/' . $type->id() . '/delete'); + $this->assertRaw( + t('%label is used by 1 comment on your site. You can not remove this comment type until you have removed all of the %label comments.', array('%label' => $type->label())), + 'The comment type will not be deleted until all comments of that type are removed.' + ); + $this->assertRaw( + t('%label is used by the %field on your site. You can not remove this comment type until you have removed the field.', array( + '%label' => 'foo', + '%field' => 'foo', + )), + 'The comment type will not be deleted until all fields of that type are removed.' + ); + $this->assertNoText(t('This action cannot be undone.'), 'The comment type deletion confirmation form is not available.'); + + // Delete the block and the field. + $comment->delete(); + $field->delete(); + // Attempt to delete the comment type, which should now be allowed. + $this->drupalGet('admin/structure/block/custom-blocks/manage/' . $type->id() . '/delete'); + $this->assertRaw( + t('Are you sure you want to delete %type?', array('%type' => $type->id())), + 'The comment type is available for deletion.' + ); + $this->assertText(t('This action cannot be undone.'), 'The comment type deletion confirmation form is available.'); + } + + /** + * Tests the create new comment type functionality on the CommentItem form. + */ + public function testCreateCommentType() { + $this->fail('You need a test for the new comment-type form on the field instance form'); + } + + /** + * Tests that CommentManager::addDefaultField throws expected Exception. + */ + public function testAddDefaultFieldsException() { + $this->fail('You need a test for the Exception thrown'); + } + + /** + * Creates a comment block type (bundle). + * + * @param string $label + * The block type label. + * + * @return \Drupal\comment\Entity\CommentType + * Created custom block type. + */ + protected function createCommentType($label) { + $bundle = entity_create('comment_type', array( + 'id' => $label, + 'label' => $label, + 'description' => '', + 'targetEntityTypeId' => 'node', + )); + $bundle->save(); + return $bundle; + } + +} diff --git a/core/modules/comment/tests/Drupal/comment/Tests/Routing/CommentBundleEnhancerTest.php b/core/modules/comment/tests/Drupal/comment/Tests/Routing/CommentBundleEnhancerTest.php deleted file mode 100644 index 95fbe8f..0000000 --- a/core/modules/comment/tests/Drupal/comment/Tests/Routing/CommentBundleEnhancerTest.php +++ /dev/null @@ -1,102 +0,0 @@ - 'Comment route enhancer test', - 'description' => 'Tests the comment route enhancer.', - 'group' => 'Comment', - ); - } - - /** - * Data provider for testEnhancer(). - * - * @see testEnhancer() - * - * @return array - * An array of arrays containing strings: - * - The bundle name. - * - The commented entity type. - * - The field name. - */ - public function providerTestEnhancer() { - return array( - array( - 'node__comment', - 'comment', - 'node', - ), - array( - 'node__comment_forum__schnitzel', - 'comment_forum__schnitzel', - 'node', - ), - array( - 'node__field_foobar', - FALSE, - FALSE - ), - ); - } - /** - * Tests the enhancer method. - * - * @param string $bundle - * The bundle name to test. - * @param string $field_name - * The field name expected to be extracted from the bundle. - * @param string $commented_entity_type - * The entity type expected to be extracted from the bundle. - * - * @see \Drupal\comment\Routing\CommentBundleEnhancer::enhancer() - * - * @group Drupal - * @group Routing - * - * @dataProvider providerTestEnhancer - */ - public function testEnhancer($bundle, $field_name, $commented_entity_type) { - $entity_manager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface'); - $entity_manager->expects($this->any()) - ->method('getBundleInfo') - ->will($this->returnValue(array( - 'node__comment' => array(), - // Test two sets of __. - 'node__comment_forum__schnitzel' => array(), - ))); - $route_enhancer = new CommentBundleEnhancer($entity_manager); - - // Test the enhancer. - $request = new Request(); - $defaults = array('bundle' => $bundle); - $new_defaults = $route_enhancer->enhance($defaults, $request); - if ($commented_entity_type) { - // A valid comment bundle. - $this->assertEquals($new_defaults['field_name'], $field_name); - $this->assertEquals($new_defaults['commented_entity_type'], $commented_entity_type); - } - else { - // Non-comment bundle. - $this->assertTrue(empty($new_defaults['field_name'])); - $this->assertTrue(empty($new_defaults['commented_entity_type'])); - } - } - -} diff --git a/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationSettingsTest.php b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationSettingsTest.php index a8e1a0c..241b51f 100644 --- a/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationSettingsTest.php +++ b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationSettingsTest.php @@ -7,6 +7,7 @@ namespace Drupal\content_translation\Tests; +use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface; use Drupal\Core\Language\Language; use Drupal\field\Field as FieldService; use Drupal\simpletest\WebTestBase; @@ -38,7 +39,7 @@ function setUp() { // bundles. $this->drupalCreateContentType(array('type' => 'article')); $this->drupalCreateContentType(array('type' => 'page')); - $this->container->get('comment.manager')->addDefaultField('node', 'article', 'comment_article'); + $this->container->get('comment.manager')->addDefaultField('node', 'article', 'comment_article', CommentItemInterface::OPEN, 'comment_article'); $admin_user = $this->drupalCreateUser(array('access administration pages', 'administer languages', 'administer content translation', 'administer content types', 'administer node fields', 'administer comment fields')); $this->drupalLogin($admin_user); diff --git a/core/modules/forum/forum.install b/core/modules/forum/forum.install index 7f975e9..21161c6 100644 --- a/core/modules/forum/forum.install +++ b/core/modules/forum/forum.install @@ -4,6 +4,7 @@ * @file * Install, update, and uninstall functions for the Forum module. */ +use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface; /** * Implements hook_install(). @@ -83,7 +84,7 @@ function forum_install() { 'include_deleted' => FALSE, )); if (empty($fields)) { - Drupal::service('comment.manager')->addDefaultField('node', 'forum', 'comment_forum'); + Drupal::service('comment.manager')->addDefaultField('node', 'forum', 'comment_forum', CommentItemInterface::OPEN, 'comment_forum'); } } } diff --git a/core/modules/forum/lib/Drupal/forum/ForumManager.php b/core/modules/forum/lib/Drupal/forum/ForumManager.php index 388dd4a..2f28086 100644 --- a/core/modules/forum/lib/Drupal/forum/ForumManager.php +++ b/core/modules/forum/lib/Drupal/forum/ForumManager.php @@ -186,7 +186,7 @@ public function getTopics($tid, AccountInterface $account) { ->extend('Drupal\Core\Database\Query\TableSortExtender'); $query->fields('n', array('nid')); - $query->join('comment_entity_statistics', 'ces', "n.nid = ces.entity_id AND ces.field_id = 'node__comment_forum' AND ces.entity_type = 'node'"); + $query->join('comment_entity_statistics', 'ces', "n.nid = ces.entity_id AND ces.field_name = 'comment_forum' AND ces.entity_type = 'node'"); $query->fields('ces', array( 'cid', 'last_comment_uid', @@ -357,7 +357,7 @@ protected function getLastPost($tid) { // Query "Last Post" information for this forum. $query = $this->connection->select('node_field_data', 'n'); $query->join('forum', 'f', 'n.vid = f.vid AND f.tid = :tid', array(':tid' => $tid)); - $query->join('comment_entity_statistics', 'ces', "n.nid = ces.entity_id AND ces.field_id = 'node__comment_forum' AND ces.entity_type = 'node'"); + $query->join('comment_entity_statistics', 'ces', "n.nid = ces.entity_id AND ces.field_name = 'comment_forum' AND ces.entity_type = 'node'"); $query->join('users', 'u', 'ces.last_comment_uid = u.uid'); $query->addExpression('CASE ces.last_comment_uid WHEN 0 THEN ces.last_comment_name ELSE u.name END', 'last_comment_name'); @@ -395,7 +395,7 @@ protected function getForumStatistics($tid) { if (empty($this->forumStatistics)) { // Prime the statistics. $query = $this->connection->select('node_field_data', 'n'); - $query->join('comment_entity_statistics', 'ces', "n.nid = ces.entity_id AND ces.field_id = 'node__comment_forum' AND ces.entity_type = 'node'"); + $query->join('comment_entity_statistics', 'ces', "n.nid = ces.entity_id AND ces.field_name = 'comment_forum' AND ces.entity_type = 'node'"); $query->join('forum', 'f', 'n.vid = f.vid'); $query->addExpression('COUNT(n.nid)', 'topic_count'); $query->addExpression('SUM(ces.comment_count)', 'comment_count'); @@ -516,14 +516,14 @@ public function unreadTopics($term, $uid) { * {@inheritdoc} */ public function updateIndex($nid) { - $count = $this->connection->query("SELECT COUNT(cid) FROM {comment} c INNER JOIN {forum_index} i ON c.entity_id = i.nid WHERE c.entity_id = :nid AND c.field_id = 'node__comment_forum' AND c.entity_type = 'node' AND c.status = :status", array( + $count = $this->connection->query("SELECT COUNT(cid) FROM {comment} c INNER JOIN {forum_index} i ON c.entity_id = i.nid WHERE c.entity_id = :nid AND c.field_name = 'comment_forum' AND c.entity_type = 'node' AND c.status = :status", array( ':nid' => $nid, ':status' => CommentInterface::PUBLISHED, ))->fetchField(); if ($count > 0) { // Comments exist. - $last_reply = $this->connection->queryRange("SELECT cid, name, created, uid FROM {comment} WHERE entity_id = :nid AND field_id = 'node__comment_forum' AND entity_type = 'node' AND status = :status ORDER BY cid DESC", 0, 1, array( + $last_reply = $this->connection->queryRange("SELECT cid, name, created, uid FROM {comment} WHERE entity_id = :nid AND field_name = 'comment_forum' AND entity_type = 'node' AND status = :status ORDER BY cid DESC", 0, 1, array( ':nid' => $nid, ':status' => CommentInterface::PUBLISHED, ))->fetchObject(); diff --git a/core/modules/forum/lib/Drupal/forum/Tests/ForumUninstallTest.php b/core/modules/forum/lib/Drupal/forum/Tests/ForumUninstallTest.php index 1e4e9bd..fea916b 100644 --- a/core/modules/forum/lib/Drupal/forum/Tests/ForumUninstallTest.php +++ b/core/modules/forum/lib/Drupal/forum/Tests/ForumUninstallTest.php @@ -76,7 +76,7 @@ function testForumUninstallWithField() { // We want to test the handling of removing the forum comment field, so we // ensure there is at least one other comment field attached to a node type // so that comment_entity_load() runs for nodes. - \Drupal::service('comment.manager')->addDefaultField('node', 'forum', 'another_comment_field', CommentItemInterface::OPEN); + \Drupal::service('comment.manager')->addDefaultField('node', 'forum', 'another_comment_field', CommentItemInterface::OPEN, 'another_comment_field'); $this->drupalGet('node/' . $node->nid->value); $this->assertResponse(200);