Update to Drupal 8.0.0-beta15. For more information, see: https://www.drupal.org/node/2563023

This commit is contained in:
Pantheon Automation 2015-09-04 13:20:09 -07:00 committed by Greg Anderson
parent 2720a9ec4b
commit f3791f1da3
1898 changed files with 54300 additions and 11481 deletions

View file

@ -5,7 +5,8 @@
* Builds placeholder replacement tokens for comment-related data.
*/
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Datetime\Entity\DateFormat;
use Drupal\Core\Render\BubbleableMetadata;
@ -135,7 +136,7 @@ function comment_tokens($type, $tokens, array $data, array $options, BubbleableM
// Poster identity information for comments.
case 'hostname':
$replacements[$original] = $sanitize ? SafeMarkup::checkPlain($comment->getHostname()) : $comment->getHostname();
$replacements[$original] = $sanitize ? Html::escape($comment->getHostname()) : $comment->getHostname();
break;
case 'mail':
@ -145,11 +146,11 @@ function comment_tokens($type, $tokens, array $data, array $options, BubbleableM
if ($comment->getOwnerId()) {
$bubbleable_metadata->addCacheableDependency($comment->getOwner());
}
$replacements[$original] = $sanitize ? SafeMarkup::checkPlain($mail) : $mail;
$replacements[$original] = $sanitize ? Html::escape($mail) : $mail;
break;
case 'homepage':
$replacements[$original] = $sanitize ? check_url($comment->getHomepage()) : $comment->getHomepage();
$replacements[$original] = $sanitize ? UrlHelper::filterBadProtocol($comment->getHomepage()) : $comment->getHomepage();
break;
case 'title':
@ -161,7 +162,7 @@ function comment_tokens($type, $tokens, array $data, array $options, BubbleableM
break;
case 'langcode':
$replacements[$original] = $sanitize ? SafeMarkup::checkPlain($comment->language()->getId()) : $comment->language()->getId();
$replacements[$original] = $sanitize ? Html::escape($comment->language()->getId()) : $comment->language()->getId();
break;
// Comment related URLs.

View file

@ -119,7 +119,7 @@ display:
table: comment_field_data
field: changed
relationship: none
plugin_id: date
plugin_id: field
group_type: group
admin_label: ''
label: ''
@ -163,9 +163,11 @@ display:
hide_empty: false
empty_zero: false
hide_alter_empty: true
date_format: 'time ago'
custom_date_format: ''
timezone: ''
type: timestamp_ago
settings:
future_format: '@interval hence'
past_format: '@interval ago'
granularity: 2
entity_type: comment
entity_field: changed
filters:

View file

@ -0,0 +1,35 @@
migrate.source.d6_comment:
type: migrate_source_sql
label: 'Drupal 6 comment'
mapping:
constants:
type: mapping
label: 'Constants'
mapping:
entity_type:
type: string
label: 'Entity type'
migrate.source.d6_comment_variable_per_comment_type:
type: migrate_source_sql
label: 'Drupal 6 comment variable'
mapping:
constants:
type: migrate_entity_constant
label: 'Constants'
migrate.source.d6_comment_entity_form_display_subject:
type: migrate_source_sql
label: 'Drupal 6 comment subject entity form display'
mapping:
constants:
type: migrate_entity_constant
label: 'Constants'
migrate.source.d6_comment_variable:
type: migrate_source_sql
label: 'Drupal 6 comment variable'
mapping:
constants:
type: migrate_entity_constant
label: 'Constants'

View file

@ -11,15 +11,18 @@
"use strict";
/**
* Render "new" comment indicators wherever necessary.
* Renders "new" comment indicators wherever necessary.
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches "new" comment indicators behavior.
*/
Drupal.behaviors.commentNewIndicator = {
attach: function (context) {
// Collect all "new" comment indicator placeholders (and their corresponding
// node IDs) newer than 30 days ago that have not already been read after
// their last comment timestamp.
// Collect all "new" comment indicator placeholders (and their
// corresponding node IDs) newer than 30 days ago that have not already
// been read after their last comment timestamp.
var nodeIDs = [];
var $placeholders = $(context)
.find('[data-comment-timestamp]')
@ -48,6 +51,12 @@
}
};
/**
* Processes the markup for "new comment" indicators.
*
* @param {jQuery} $placeholders
* The elements that should be processed.
*/
function processCommentNewIndicators($placeholders) {
var isFirstNewComment = true;
var newCommentString = Drupal.t('new');

View file

@ -14,12 +14,15 @@
* Render "X new comments" links wherever necessary.
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches new comment links behavior.
*/
Drupal.behaviors.nodeNewCommentsLink = {
attach: function (context) {
// Collect all "X new comments" node link placeholders (and their
// corresponding node IDs) newer than 30 days ago that have not already been
// read after their last comment timestamp.
// corresponding node IDs) newer than 30 days ago that have not already
// been read after their last comment timestamp.
var nodeIDs = [];
var $placeholders = $(context)
.find('[data-history-node-last-comment-timestamp]')
@ -35,7 +38,8 @@
return true;
}
else {
// Remove this placeholder link from the DOM because we won't need it.
// Remove this placeholder link from the DOM because we won't need
// it.
remove($placeholder);
return false;
}
@ -52,6 +56,15 @@
}
};
/**
* Hides a "new comment" element.
*
* @param {jQuery} $placeholder
* The placeholder element of the new comment link.
*
* @return {jQuery}
* The placeholder element passed in as a parameter.
*/
function hide($placeholder) {
return $placeholder
// Find the parent <li>.
@ -62,10 +75,25 @@
.end().hide();
}
/**
* Removes a "new comment" element.
*
* @param {jQuery} $placeholder
* The placeholder element of the new comment link.
*/
function remove($placeholder) {
hide($placeholder).remove();
}
/**
* Shows a "new comment" element.
*
* @param {jQuery} $placeholder
* The placeholder element of the new comment link.
*
* @return {jQuery}
* The placeholder element passed in as a parameter.
*/
function show($placeholder) {
return $placeholder
// Find the parent <li>.
@ -76,6 +104,12 @@
.end().show();
}
/**
* Processes new comment links and adds appropriate text in relevant cases.
*
* @param {jQuery} $placeholders
* The placeholder elements of the current page.
*/
function processNodeNewCommentLinks($placeholders) {
// Figure out which placeholders need the "x new comments" links.
var $placeholdersToUpdate = {};
@ -88,8 +122,8 @@
var nodeID = $placeholder.closest('[data-history-node-id]').attr('data-history-node-id');
var lastViewTimestamp = Drupal.history.getLastRead(nodeID);
// Queue this placeholder's "X new comments" link to be downloaded from the
// server.
// Queue this placeholder's "X new comments" link to be downloaded from
// the server.
if (timestamp > lastViewTimestamp) {
$placeholdersToUpdate[nodeID] = $placeholder;
}
@ -105,8 +139,15 @@
return;
}
// Render the "X new comments" links. Either use the data embedded in the page
// or perform an AJAX request to retrieve the same data.
/**
* Renders the "X new comments" links.
*
* Either use the data embedded in the page or perform an AJAX request to
* retrieve the same data.
*
* @param {object} results
* Data about new comment links indexed by nodeID.
*/
function render(results) {
for (var nodeID in results) {
if (results.hasOwnProperty(nodeID) && $placeholdersToUpdate.hasOwnProperty(nodeID)) {

View file

@ -0,0 +1,45 @@
id: d6_comment
label: Drupal 6 comments
migration_tags:
- Drupal 6
source:
plugin: d6_comment
constants:
entity_type: node
process:
cid: cid
pid:
plugin: migration
migration: d6_comment
source: pid
entity_id: nid
entity_type: 'constants/entity_type'
# field_name & comment_type is calculated in
# \Drupal\migrate_drupal\Plugin\migrate\source\d6\Comment::prepareRow()
field_name: field_name
comment_type: comment_type
subject: subject
uid: uid
name: name
mail: mail
homepage: homepage
hostname: hostname
created: timestamp
changed: timestamp
status: status #In D6, published=0. We reverse the value in prepareRow.
thread: thread
'comment_body/value': comment
'comment_body/format':
plugin: migration
migration: d6_filter_format
source: format
destination:
plugin: entity:comment
migration_dependencies:
required:
- d6_node:*
- d6_comment_type
- d6_comment_entity_display
- d6_comment_entity_form_display
- d6_user
- d6_filter_format

View file

@ -0,0 +1,25 @@
id: d6_comment_entity_display
label: Drupal 6 comment display configuration
migration_tags:
- Drupal 6
source:
plugin: d6_comment_variable
constants:
entity_type: node
field_name: comment
view_mode: default
options:
label: hidden
type: comment_default
weight: 20
process:
entity_type: 'constants/entity_type'
field_name: 'constants/field_name'
view_mode: 'constants/view_mode'
options: 'constants/options'
bundle: node_type
destination:
plugin: component_entity_display
migration_dependencies:
required:
- d6_comment_field_instance

View file

@ -0,0 +1,24 @@
id: d6_comment_entity_form_display
label: Drupal 6 comment field form display configuration
migration_tags:
- Drupal 6
source:
plugin: d6_comment_variable
constants:
entity_type: node
field_name: comment
form_mode: default
options:
type: comment_default
weight: 20
process:
entity_type: 'constants/entity_type'
field_name: 'constants/field_name'
form_mode: 'constants/form_mode'
options: 'constants/options'
bundle: node_type
destination:
plugin: component_entity_form_display
migration_dependencies:
required:
- d6_comment_field_instance

View file

@ -0,0 +1,31 @@
id: d6_comment_entity_form_display_subject
label: Drupal 6 comment subject form display configuration
migration_tags:
- Drupal 6
source:
plugin: d6_comment_variable_per_comment_type
constants:
entity_type: comment
field_name: subject
form_mode: default
options:
type: string_textfield
weight: 10
process:
entity_type: 'constants/entity_type'
field_name: 'constants/field_name'
form_mode: 'constants/form_mode'
options: 'constants/options'
hidden:
plugin: static_map
source: comment_type
default_value: false
map:
comment_no_subject: true # Hide subject field
comment: false
bundle: comment_type
destination:
plugin: component_entity_form_display
migration_dependencies:
required:
- d6_comment_type

View file

@ -0,0 +1,19 @@
id: d6_comment_field
label: Drupal 6 comment field configuration
migration_tags:
- Drupal 6
source:
plugin: d6_comment_variable_per_comment_type
constants:
entity_type: node
type: comment
process:
entity_type: 'constants/entity_type'
field_name: comment_type
type: 'constants/type'
'settings/comment_type': comment_type
destination:
plugin: md_entity:field_storage_config
migration_dependencies:
required:
- d6_comment_type

View file

@ -0,0 +1,33 @@
id: d6_comment_field_instance
label: Drupal 6 comment field instance configuration
migration_tags:
- Drupal 6
source:
plugin: d6_comment_variable
constants:
entity_type: node
label: Comments
required: true
process:
entity_type: 'constants/entity_type'
label: 'constants/label'
required: 'constants/required'
field_name:
plugin: static_map
source: comment_subject_field
default_value: comment
map:
0: comment_no_subject
bundle: node_type
'default_value/0/status': comment
'settings/default_mode': comment_default_mode
'settings/per_page': comment_default_per_page
'settings/anonymous': comment_anonymous
'settings/form_location': comment_form_location
'settings/preview': comment_preview
destination:
plugin: entity:field_config
migration_dependencies:
required:
- d6_comment_field
- d6_node_type

View file

@ -0,0 +1,15 @@
id: d6_comment_type
label: Drupal 6 comment type
migration_tags:
- Drupal 6
source:
plugin: d6_comment_variable_per_comment_type
constants:
entity_type: node
process:
target_entity_type_id: 'constants/entity_type'
id: comment_type
label: label
description: description
destination:
plugin: entity:comment_type

View file

@ -0,0 +1,35 @@
id: d7_comment
label: Drupal 7 comments
migration_tags:
- Drupal 7
source:
plugin: d7_comment
constants:
entity_type: node
process:
cid: cid
pid:
plugin: migration
migration: d7_comment
source: pid
entity_id: nid
entity_type: 'constants/entity_type'
comment_type: comment_type
field_name: comment_type
subject: subject
uid: uid
name: name
mail: mail
homepage: homepage
hostname: hostname
created: created
changed: changed
status: status
thread: thread
comment_body: comment_body
destination:
plugin: entity:comment
migration_dependencies:
required:
- d7_node:*
- d7_comment_type

View file

@ -0,0 +1,24 @@
id: d7_comment_entity_display
label: Drupal 7 comment display configuration
migration_tags:
- Drupal 7
source:
plugin: d7_comment_type
constants:
entity_type: node
view_mode: default
options:
label: hidden
type: comment_default
weight: 20
process:
entity_type: 'constants/entity_type'
field_name: bundle
view_mode: 'constants/view_mode'
options: 'constants/options'
bundle: node_type
destination:
plugin: component_entity_display
migration_dependencies:
required:
- d7_comment_field_instance

View file

@ -0,0 +1,24 @@
id: d7_comment_entity_form_display
label: Drupal 7 comment field form display configuration
migration_tags:
- Drupal 7
source:
plugin: d7_comment_type
constants:
entity_type: node
field_name: comment
form_mode: default
options:
type: comment_default
weight: 20
process:
entity_type: 'constants/entity_type'
field_name: 'constants/field_name'
form_mode: 'constants/form_mode'
options: 'constants/options'
bundle: node_type
destination:
plugin: component_entity_form_display
migration_dependencies:
required:
- d7_comment_field_instance

View file

@ -0,0 +1,30 @@
id: d7_comment_entity_form_display_subject
label: Drupal 7 comment subject form display configuration
migration_tags:
- Drupal 7
source:
plugin: d7_comment_type
constants:
entity_type: comment
field_name: subject
form_mode: default
options:
type: string_textfield
weight: 10
process:
entity_type: 'constants/entity_type'
field_name: 'constants/field_name'
form_mode: 'constants/form_mode'
options: 'constants/options'
hidden:
plugin: static_map
source: subject
map:
0: true
1: false
bundle: bundle
destination:
plugin: component_entity_form_display
migration_dependencies:
required:
- d7_comment_type

View file

@ -0,0 +1,19 @@
id: d7_comment_field
label: Drupal 7 comment field configuration
migration_tags:
- Drupal 7
source:
plugin: d7_comment_type
constants:
entity_type: node
type: comment
process:
entity_type: 'constants/entity_type'
field_name: bundle
type: 'constants/type'
'settings/comment_type': bundle
destination:
plugin: entity:field_storage_config
migration_dependencies:
required:
- d7_comment_type

View file

@ -0,0 +1,27 @@
id: d7_comment_field_instance
label: Drupal 7 comment field instance configuration
migration_tags:
- Drupal 7
source:
plugin: d7_comment_type
constants:
entity_type: node
label: Comments
required: true
process:
entity_type: 'constants/entity_type'
label: 'constants/label'
required: 'constants/required'
field_name: bundle
bundle: node_type
'default_value/0/status': 'constants/required'
'settings/default_mode': default_mode
'settings/per_page': per_page
'settings/anonymous': anonymous
'settings/form_location': form_location
'settings/preview': preview
destination:
plugin: entity:field_config
migration_dependencies:
required:
- d7_comment_field

View file

@ -0,0 +1,17 @@
id: d7_comment_type
label: Drupal 7 comment type
migration_tags:
- Drupal 7
source:
plugin: d7_comment_type
constants:
entity_type: node
process:
target_entity_type_id: 'constants/entity_type'
id: bundle
label: label
destination:
plugin: entity:comment_type
migration_dependencies:
required:
- d7_node_type

View file

@ -80,15 +80,26 @@ class CommentAccessControlHandler extends EntityAccessControlHandler {
// No user can change read-only fields.
$read_only_fields = array(
'hostname',
'uuid',
'changed',
'cid',
'thread',
);
// These fields can be edited during comment creation.
$create_only_fields = [
'comment_type',
'pid',
'uuid',
'entity_id',
'entity_type',
'field_name',
);
'pid',
];
if ($items && ($entity = $items->getEntity()) && $entity->isNew() && in_array($field_definition->getName(), $create_only_fields, TRUE)) {
// We are creating a new comment, user can edit create only fields.
return AccessResult::allowedIfHasPermission($account, 'post comments')->addCacheableDependency($entity);
}
// We are editing an existing comment - create only fields are now read
// only.
$read_only_fields = array_merge($read_only_fields, $create_only_fields);
if (in_array($field_definition->getName(), $read_only_fields, TRUE)) {
return AccessResult::forbidden();
}

View file

@ -8,6 +8,7 @@
namespace Drupal\comment;
use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Link;
use Drupal\Core\Routing\RouteMatchInterface;
@ -47,16 +48,20 @@ class CommentBreadcrumbBuilder implements BreadcrumbBuilderInterface {
* {@inheritdoc}
*/
public function build(RouteMatchInterface $route_match) {
$breadcrumb = [Link::createFromRoute($this->t('Home'), '<front>')];
$breadcrumb = new Breadcrumb();
$breadcrumb->setCacheContexts(['route']);
$breadcrumb->addLink(Link::createFromRoute($this->t('Home'), '<front>'));
$entity = $route_match->getParameter('entity');
$breadcrumb[] = new Link($entity->label(), $entity->urlInfo());
$breadcrumb->addLink(new Link($entity->label(), $entity->urlInfo()));
$breadcrumb->addCacheableDependency($entity);
if (($pid = $route_match->getParameter('pid')) && ($comment = $this->storage->load($pid))) {
/** @var \Drupal\comment\CommentInterface $comment */
$breadcrumb->addCacheableDependency($comment);
// Display link to parent comment.
// @todo Clean-up permalink in https://www.drupal.org/node/2198041
$breadcrumb[] = new Link($comment->getSubject(), $comment->urlInfo());
$breadcrumb->addLink(new Link($comment->getSubject(), $comment->urlInfo()));
}
return $breadcrumb;

View file

@ -78,6 +78,16 @@ class CommentForm extends ContentEntityForm {
$field_definition = $this->entityManager->getFieldDefinitions($entity->getEntityTypeId(), $entity->bundle())[$comment->getFieldName()];
$config = $this->config('user.settings');
// In several places within this function, we vary $form on:
// - The current user's permissions.
// - Whether the current user is authenticated or anonymous.
// - The 'user.settings' configuration.
// - The comment field's definition.
$form['#cache']['contexts'][] = 'user.permissions';
$form['#cache']['contexts'][] = 'user.roles:authenticated';
$this->renderer->addCacheableDependency($form, $config);
$this->renderer->addCacheableDependency($form, $field_definition->getConfig($entity->bundle()));
// Use #comment-form as unique jump target, regardless of entity type.
$form['#id'] = Html::getUniqueId('comment_form');
$form['#theme'] = array('comment_form__' . $entity->getEntityTypeId() . '__' . $entity->bundle() . '__' . $field_name, 'comment_form');
@ -90,10 +100,6 @@ class CommentForm extends ContentEntityForm {
$form['#attributes']['data-user-info-from-browser'] = TRUE;
}
// Vary per role, because we check a permission above and attach an asset
// library only for authenticated users.
$form['#cache']['contexts'][] = 'user.roles';
// If not replying to a comment, use our dedicated page callback for new
// Comments on entities.
if (!$comment->id() && !$comment->hasParentComment()) {
@ -164,6 +170,7 @@ class CommentForm extends ContentEntityForm {
$form['author']['name']['#value'] = $form['author']['name']['#default_value'];
$form['author']['name']['#theme'] = 'username';
$form['author']['name']['#account'] = $this->currentUser;
$form['author']['name']['#cache']['contexts'][] = 'user';
}
elseif($this->currentUser->isAnonymous()) {
$form['author']['name']['#attributes']['data-drupal-default-value'] = $config->get('anonymous');
@ -210,10 +217,6 @@ class CommentForm extends ContentEntityForm {
'#access' => $is_admin,
);
$this->renderer->addCacheableDependency($form, $config);
// The form depends on the field definition.
$this->renderer->addCacheableDependency($form, $field_definition->getConfig($entity->bundle()));
return parent::form($form, $form_state, $comment);
}

View file

@ -7,8 +7,6 @@
namespace Drupal\comment;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
use Drupal\Core\Entity\EntityInterface;
@ -45,7 +43,7 @@ class CommentTypeListBuilder extends ConfigEntityListBuilder {
* {@inheritdoc}
*/
public function buildRow(EntityInterface $entity) {
$row['type'] = SafeMarkup::checkPlain($entity->label());
$row['type'] = $entity->label();
$row['description']['data'] = ['#markup' => $entity->getDescription()];
return $row + parent::buildRow($entity);
}

View file

@ -8,6 +8,7 @@
namespace Drupal\comment\Entity;
use Drupal\Component\Utility\Number;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\comment\CommentInterface;
use Drupal\Core\Entity\EntityChangedTrait;
@ -153,6 +154,11 @@ class Comment extends ContentEntityBase implements CommentInterface {
public function postSave(EntityStorageInterface $storage, $update = TRUE) {
parent::postSave($storage, $update);
// Always invalidate the cache tag for the commented entity.
if ($commented_entity = $this->getCommentedEntity()) {
Cache::invalidateTags($commented_entity->getCacheTagsToInvalidate());
}
$this->releaseThreadLock();
// Update the {comment_entity_statistics} table prior to executing the hook.
\Drupal::service('comment.statistics')->update($this);

View file

@ -8,7 +8,7 @@
namespace Drupal\comment\Form;
use Drupal\comment\CommentStorageInterface;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Utility\Html;
use Drupal\Core\Form\ConfirmFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
@ -100,7 +100,7 @@ class ConfirmDeleteMultiple extends ConfirmFormBase {
'#type' => 'hidden',
'#value' => $cid,
'#prefix' => '<li>',
'#suffix' => SafeMarkup::checkPlain($comment->label()) . '</li>'
'#suffix' => Html::escape($comment->label()) . '</li>'
);
$comment_counter++;
}

View file

@ -159,9 +159,7 @@ class CommentDefaultFormatter extends FormatterBase implements ContainerFactoryP
// should display if the user is an administrator.
$elements['#cache']['contexts'][] = 'user.permissions';
if ($this->currentUser->hasPermission('access comments') || $this->currentUser->hasPermission('administer comments')) {
// This is a listing of Comment entities, so associate its list cache
// tag for correct invalidation.
$output['comments']['#cache']['tags'] = $this->entityManager->getDefinition('comment')->getListCacheTags();
$output['comments'] = [];
if ($entity->get($field_name)->comment_count || $this->currentUser->hasPermission('administer comments')) {
$mode = $comment_settings['default_mode'];
@ -184,30 +182,23 @@ class CommentDefaultFormatter extends FormatterBase implements ContainerFactoryP
// Only show the add comment form if the user has permission.
$elements['#cache']['contexts'][] = 'user.roles';
if ($this->currentUser->hasPermission('post comments')) {
// All users in the "anonymous" role can use the same form: it is fine
// for this form to be stored in the render cache.
if ($this->currentUser->isAnonymous()) {
$comment = $this->storage->create(array(
'entity_type' => $entity->getEntityTypeId(),
'entity_id' => $entity->id(),
'field_name' => $field_name,
'comment_type' => $this->getFieldSetting('comment_type'),
'pid' => NULL,
));
$output['comment_form'] = $this->entityFormBuilder->getForm($comment);
}
// All other users need a user-specific form, which would break the
// render cache: hence use a #lazy_builder callback.
else {
$output['comment_form'] = [
'#lazy_builder' => ['comment.lazy_builders:renderForm', [
$entity->getEntityTypeId(),
$entity->id(),
$field_name,
$this->getFieldSetting('comment_type'),
]],
'#create_placeholder' => TRUE,
];
$output['comment_form'] = [
'#lazy_builder' => ['comment.lazy_builders:renderForm', [
$entity->getEntityTypeId(),
$entity->id(),
$field_name,
$this->getFieldSetting('comment_type'),
]],
];
// @todo Remove this in https://www.drupal.org/node/2543334. Until
// then, \Drupal\Core\Render\Renderer::hasPoorCacheability() isn't
// integrated with cache context bubbling, so this duplicates the
// contexts added by \Drupal\comment\CommentForm::form().
$output['comment_form']['#cache']['contexts'][] = 'user.permissions';
$output['comment_form']['#cache']['contexts'][] = 'user.roles:authenticated';
if ($this->currentUser->isAuthenticated()) {
$output['comment_form']['#cache']['contexts'][] = 'user';
}
}
}

View file

@ -0,0 +1,88 @@
<?php
/**
* @file
* Contains \Drupal\comment\Plugin\migrate\destination\EntityComment.
*/
namespace Drupal\comment\Plugin\migrate\destination;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\State\StateInterface;
use Drupal\migrate\Entity\MigrationInterface;
use Drupal\migrate\Plugin\migrate\destination\EntityContentBase;
use Drupal\migrate\Row;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* @MigrateDestination(
* id = "entity:comment"
* )
*/
class EntityComment extends EntityContentBase {
/**
* The state storage object.
*
* @var \Drupal\Core\State\StateInterface
*/
protected $state;
/**
* Builds an comment entity destination.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param MigrationInterface $migration
* The migration.
* @param EntityStorageInterface $storage
* The storage for this entity type.
* @param array $bundles
* The list of bundles this entity type has.
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager service.
* @param \Drupal\Core\State\StateInterface $state
* The state storage object.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, EntityStorageInterface $storage, array $bundles, EntityManagerInterface $entity_manager, StateInterface $state) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $storage, $bundles, $entity_manager);
$this->state = $state;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
$entity_type = static::getEntityTypeId($plugin_id);
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$migration,
$container->get('entity.manager')->getStorage($entity_type),
array_keys($container->get('entity.manager')->getBundleInfo($entity_type)),
$container->get('entity.manager'),
$container->get('state')
);
}
/**
* {@inheritdoc}
*/
public function import(Row $row, array $old_destination_id_values = array()) {
if ($row->isStub() && ($state = $this->state->get('comment.maintain_entity_statistics', 0))) {
$this->state->set('comment.maintain_entity_statistics', 0);
}
$return = parent::import($row, $old_destination_id_values);
if ($row->isStub() && $state) {
$this->state->set('comment.maintain_entity_statistics', $state);
}
return $return;
}
}

View file

@ -0,0 +1,29 @@
<?php
/**
* @file
* Contains \Drupal\comment\Plugin\migrate\destination\EntityCommentType.
*/
namespace Drupal\comment\Plugin\migrate\destination;
use Drupal\migrate\Plugin\migrate\destination\EntityConfigBase;
use Drupal\migrate\Row;
/**
* @MigrateDestination(
* id = "entity:comment_type"
* )
*/
class EntityCommentType extends EntityConfigBase {
/**
* {@inheritdoc}
*/
public function import(Row $row, array $old_destination_id_values = array()) {
$entity_ids = parent::import($row, $old_destination_id_values);
\Drupal::service('comment.manager')->addBodyField(reset($entity_ids));
return $entity_ids;
}
}

View file

@ -0,0 +1,87 @@
<?php
/**
* @file
* Contains \Drupal\comment\Plugin\migrate\source\d6\Comment.
*/
namespace Drupal\comment\Plugin\migrate\source\d6;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
* Drupal 6 comment source from database.
*
* @MigrateSource(
* id = "d6_comment",
* source_provider = "comment"
* )
*/
class Comment extends DrupalSqlBase {
/**
* {@inheritdoc}
*/
public function query() {
$query = $this->select('comments', 'c')
->fields('c', array('cid', 'pid', 'nid', 'uid', 'subject',
'comment', 'hostname', 'timestamp', 'status', 'thread', 'name',
'mail', 'homepage', 'format'));
$query->innerJoin('node', 'n', 'c.nid = n.nid');
$query->fields('n', array('type'));
$query->orderBy('c.timestamp');
return $query;
}
/**
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
if ($this->variableGet('comment_subject_field_' . $row->getSourceProperty('type'), 1)) {
// Comment subject visible.
$row->setSourceProperty('field_name', 'comment');
$row->setSourceProperty('comment_type', 'comment');
}
else {
$row->setSourceProperty('field_name', 'comment_no_subject');
$row->setSourceProperty('comment_type', 'comment_no_subject');
}
// In D6, status=0 means published, while in D8 means the opposite.
// See https://www.drupal.org/node/237636.
$row->setSourceProperty('status', !$row->getSourceProperty('status'));
return parent::prepareRow($row);
}
/**
* {@inheritdoc}
*/
public function fields() {
return array(
'cid' => $this->t('Comment ID.'),
'pid' => $this->t('Parent comment ID. If set to 0, this comment is not a reply to an existing comment.'),
'nid' => $this->t('The {node}.nid to which this comment is a reply.'),
'uid' => $this->t('The {users}.uid who authored the comment. If set to 0, this comment was created by an anonymous user.'),
'subject' => $this->t('The comment title.'),
'comment' => $this->t('The comment body.'),
'hostname' => $this->t("The author's host name."),
'timestamp' => $this->t('The time that the comment was created, or last edited by its author, as a Unix timestamp.'),
'status' => $this->t('The published status of a comment. (0 = Published, 1 = Not Published)'),
'format' => $this->t('The {filter_formats}.format of the comment body.'),
'thread' => $this->t("The vancode representation of the comment's place in a thread."),
'name' => $this->t("The comment author's name. Uses {users}.name if the user is logged in, otherwise uses the value typed into the comment form."),
'mail' => $this->t("The comment author's email address from the comment form, if user is anonymous, and the 'Anonymous users may/must leave their contact information' setting is turned on."),
'homepage' => $this->t("The comment author's home page address from the comment form, if user is anonymous, and the 'Anonymous users may/must leave their contact information' setting is turned on."),
'type' => $this->t("The {node}.type to which this comment is a reply."),
);
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['cid']['type'] = 'integer';
return $ids;
}
}

View file

@ -0,0 +1,106 @@
<?php
/**
* @file
* Contains \Drupal\comment\Plugin\migrate\source\d6\CommentVariable.
*/
namespace Drupal\comment\Plugin\migrate\source\d6;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
use Drupal\migrate\Plugin\migrate\source\DummyQueryTrait;
/**
* @MigrateSource(
* id = "d6_comment_variable"
* )
*/
class CommentVariable extends DrupalSqlBase {
use DummyQueryTrait;
/**
* {@inheritdoc}
*/
protected function initializeIterator() {
return new \ArrayIterator($this->getCommentVariables());
}
/**
* {@inheritdoc}
*/
public function count() {
return count($this->getCommentVariables());
}
/**
* Retrieves the values of the comment variables grouped by node type.
*
* @return array
*/
protected function getCommentVariables() {
$comment_prefixes = array_keys($this->commentPrefixes());
$variables = array();
$node_types = $this->getDatabase()->query('SELECT type FROM {node_type}')->fetchCol();
foreach ($node_types as $node_type) {
foreach ($comment_prefixes as $prefix) {
$variables[] = $prefix . '_' . $node_type;
}
}
$return = array();
$values = $this->getDatabase()->query('SELECT name, value FROM {variable} WHERE name IN ( :name[] )', array(':name[]' => $variables))->fetchAllKeyed();
foreach ($node_types as $node_type) {
foreach ($comment_prefixes as $prefix) {
$name = $prefix . '_' . $node_type;
if (isset($values[$name])) {
$return[$node_type][$prefix] = unserialize($values[$name]);
}
}
}
// The return key will not be used so move it inside the row. This could
// not be done sooner because otherwise empty rows would be created with
// just the node type in it.
foreach ($return as $node_type => $data) {
$return[$node_type]['node_type'] = $node_type;
$return[$node_type]['comment_type'] = empty($data['comment_subject_field']) ?
'comment_no_subject' : 'comment';
}
return $return;
}
/**
* {@inheritdoc}
*/
public function fields() {
return $this->commentPrefixes() + array(
'node_type' => $this->t('The node type'),
'comment_type' => $this->t('The comment type'),
);
}
/**
* Comment related data for fields.
*/
protected function commentPrefixes() {
return array(
'comment' => $this->t('Default comment setting'),
'comment_default_mode' => $this->t('Default display mode'),
'comment_default_order' => $this->t('Default display order'),
'comment_default_per_page' => $this->t('Default comments per page'),
'comment_controls' => $this->t('Comment controls'),
'comment_anonymous' => $this->t('Anonymous commenting'),
'comment_subject_field' => $this->t('Comment subject field'),
'comment_preview' => $this->t('Preview comment'),
'comment_form_location' => $this->t('Location of comment submission form'),
);
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['node_type']['type'] = 'string';
return $ids;
}
}

View file

@ -0,0 +1,67 @@
<?php
/**
* @file
* Contains \Drupal\comment\Plugin\migrate\source\d6\CommentVariablePerCommentType.
*/
namespace Drupal\comment\Plugin\migrate\source\d6;
/**
* @MigrateSource(
* id = "d6_comment_variable_per_comment_type"
* )
*/
class CommentVariablePerCommentType extends CommentVariable {
/**
* Retrieves the values of the comment variables grouped by comment type.
*
* @return array
*/
protected function getCommentVariables() {
$node_types = parent::getCommentVariables();
// The return key used to separate comment types with hidden subject field.
$return = array();
foreach ($node_types as $node_type => $data) {
// Only 2 comment types depending on subject field visibility.
if (empty($data['comment_subject_field'])) {
// Default label and description should be set in migration.
$return['comment'] = array(
'comment_type' => 'comment',
'label' => $this->t('Default comments'),
'description' => $this->t('Allows commenting on content')
);
}
else {
// Provide a special comment type with hidden subject field.
$return['comment_no_subject'] = array(
'comment_type' => 'comment_no_subject',
'label' => $this->t('Comments without subject field'),
'description' => $this->t('Allows commenting on content, comments without subject field')
);
}
}
return $return;
}
/**
* {@inheritdoc}
*/
public function fields() {
return array(
'comment_type' => $this->t('The comment type'),
'label' => $this->t('The comment type label'),
'description' => $this->t('The comment type description'),
);
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['comment_type']['type'] = 'string';
return $ids;
}
}

View file

@ -0,0 +1,83 @@
<?php
/**
* @file
* Contains \Drupal\comment\Plugin\migrate\source\d7\Comment.
*/
namespace Drupal\comment\Plugin\migrate\source\d7;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\migrate\source\d7\FieldableEntity;
/**
* Drupal 7 comment source from database.
*
* @MigrateSource(
* id = "d7_comment",
* source_provider = "comment"
* )
*/
class Comment extends FieldableEntity {
/**
* {@inheritdoc}
*/
public function query() {
$query = $this->select('comment', 'c')->fields('c');
$query->innerJoin('node', 'n', 'c.nid = n.nid');
$query->addField('n', 'type', 'node_type');
$query->orderBy('c.created');
return $query;
}
/**
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
$cid = $row->getSourceProperty('cid');
$node_type = $row->getSourceProperty('node_type');
$comment_type = 'comment_node_' . $node_type;
$row->setSourceProperty('comment_type', 'comment_node_' . $node_type);
foreach (array_keys($this->getFields('comment', $comment_type)) as $field) {
$row->setSourceProperty($field, $this->getFieldValues('comment', $field, $cid));
}
return parent::prepareRow($row);
}
/**
* {@inheritdoc}
*/
public function fields() {
return array(
'cid' => $this->t('Comment ID.'),
'pid' => $this->t('Parent comment ID. If set to 0, this comment is not a reply to an existing comment.'),
'nid' => $this->t('The {node}.nid to which this comment is a reply.'),
'uid' => $this->t('The {users}.uid who authored the comment. If set to 0, this comment was created by an anonymous user.'),
'subject' => $this->t('The comment title.'),
'comment' => $this->t('The comment body.'),
'hostname' => $this->t("The author's host name."),
'created' => $this->t('The time that the comment was created, as a Unix timestamp.'),
'changed' => $this->t('The time that the comment was edited by its author, as a Unix timestamp.'),
'status' => $this->t('The published status of a comment. (0 = Published, 1 = Not Published)'),
'format' => $this->t('The {filter_formats}.format of the comment body.'),
'thread' => $this->t("The vancode representation of the comment's place in a thread."),
'name' => $this->t("The comment author's name. Uses {users}.name if the user is logged in, otherwise uses the value typed into the comment form."),
'mail' => $this->t("The comment author's email address from the comment form, if user is anonymous, and the 'Anonymous users may/must leave their contact information' setting is turned on."),
'homepage' => $this->t("The comment author's home page address from the comment form, if user is anonymous, and the 'Anonymous users may/must leave their contact information' setting is turned on."),
'type' => $this->t("The {node}.type to which this comment is a reply."),
);
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['cid']['type'] = 'integer';
return $ids;
}
}

View file

@ -0,0 +1,102 @@
<?php
/**
* @file
* Contains \Drupal\comment\Plugin\migrate\source\d7\CommentType.
*/
namespace Drupal\comment\Plugin\migrate\source\d7;
use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
* Drupal 7 comment type source from database.
*
* @MigrateSource(
* id = "d7_comment_type",
* source_provider = "comment"
* )
*/
class CommentType extends DrupalSqlBase {
/**
* A map of D7 node types to their labels.
*
* @var string[]
*/
protected $nodeTypes = array();
/**
* {@inheritdoc}
*/
public function query() {
return $this->select('field_config_instance', 'fci')
->fields('fci', array('bundle'))
->condition('entity_type', 'comment');
}
/**
* {@inheritdoc}
*/
protected function initializeIterator() {
$this->nodeTypes = $this->select('node_type', 'nt')
->fields('nt', array('type', 'name'))
->execute()
->fetchAllKeyed();
return parent::initializeIterator();
}
/**
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
$node_type = substr($row->getSourceProperty('bundle'), 13);
$row->setSourceProperty('node_type', $node_type);
$row->setSourceProperty('default_mode', $this->variableGet("comment_default_mode_$node_type", 1));
$row->setSourceProperty('per_page', $this->variableGet("comment_default_per_page_$node_type", 50));
$row->setSourceProperty('anonymous', $this->variableGet("comment_anonymous_$node_type", FALSE));
$row->setSourceProperty('form_location', $this->variableGet("comment_form_location_$node_type", CommentItemInterface::FORM_BELOW));
$row->setSourceProperty('preview', $this->variableGet("comment_preview_$node_type", TRUE));
$row->setSourceProperty('subject', $this->variableGet("comment_subject_field_$node_type", TRUE));
$label = $this->t('@node_type comment', [
'@node_type' => $this->nodeTypes[$node_type],
]);
$row->setSourceProperty('label', $label);
return parent::prepareRow($row);
}
/**
* {@inheritdoc}
*/
public function fields() {
return array(
'label' => $this->t('The label of the comment type.'),
'bundle' => $this->t('Bundle ID of the comment type.'),
'node_type' => $this->t('The node type to which this comment type is attached.'),
'default_mode' => $this->t('Default comment mode.'),
'per_page' => $this->t('Number of comments visible per page.'),
'anonymous' => $this->t('Whether anonymous comments are allowed.'),
'form_location' => $this->t('Location of the comment form.'),
'preview' => $this->t('Whether previews are enabled for the comment type.'),
'subject' => $this->t('Whether a subject field is enabled for the comment type.'),
);
}
/**
* {@inheritdoc}
*/
public function getIds() {
return array(
'bundle' => array(
'type' => 'string',
),
);
}
}

View file

@ -141,7 +141,7 @@ class NodeNewComments extends NumericField {
':timestamp2' => HISTORY_READ_LIMIT,
));
foreach ($result as $node) {
foreach ($ids[$node->id()] as $id) {
foreach ($ids[$node->nid] as $id) {
$values[$id]->{$this->field_alias} = $node->num_comments;
}
}

View file

@ -7,7 +7,9 @@
namespace Drupal\comment\Tests;
use Drupal\comment\CommentInterface;
use Drupal\comment\CommentManagerInterface;
use Drupal\comment\Entity\Comment;
use Drupal\Core\Entity\EntityInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\system\Tests\Entity\EntityWithUriCacheTagsTestBase;
@ -28,6 +30,16 @@ class CommentCacheTagsTest extends EntityWithUriCacheTagsTestBase {
*/
public static $modules = array('comment');
/**
* @var \Drupal\entity_test\Entity\EntityTest
*/
protected $entityTestCamelid;
/**
* @var \Drupal\entity_test\Entity\EntityTest
*/
protected $entityTestHippopotamidae;
/**
* {@inheritdoc}
*/
@ -57,12 +69,12 @@ class CommentCacheTagsTest extends EntityWithUriCacheTagsTestBase {
$field->setSetting('default_mode', CommentManagerInterface::COMMENT_MODE_FLAT);
$field->save();
// Create a "Camelids" test entity.
$entity_test = entity_create('entity_test', array(
// Create a "Camelids" test entity that the comment will be assigned to.
$this->entityTestCamelid = entity_create('entity_test', array(
'name' => 'Camelids',
'type' => 'bar',
));
$entity_test->save();
$this->entityTestCamelid->save();
// Create a "Llama" comment.
$comment = entity_create('comment', array(
@ -71,7 +83,7 @@ class CommentCacheTagsTest extends EntityWithUriCacheTagsTestBase {
'value' => 'The name "llama" was adopted by European settlers from native Peruvians.',
'format' => 'plain_text',
),
'entity_id' => $entity_test->id(),
'entity_id' => $this->entityTestCamelid->id(),
'entity_type' => 'entity_test',
'field_name' => 'comment',
'status' => \Drupal\comment\CommentInterface::PUBLISHED,
@ -81,6 +93,47 @@ class CommentCacheTagsTest extends EntityWithUriCacheTagsTestBase {
return $comment;
}
/**
* Test that comments correctly invalidate the cache tag of their host entity.
*/
public function testCommentEntity() {
$this->verifyPageCache($this->entityTestCamelid->urlInfo(), 'MISS');
$this->verifyPageCache($this->entityTestCamelid->urlInfo(), 'HIT');
// Create a "Hippopotamus" comment.
$this->entityTestHippopotamidae = entity_create('entity_test', array(
'name' => 'Hippopotamus',
'type' => 'bar',
));
$this->entityTestHippopotamidae->save();
$this->verifyPageCache($this->entityTestHippopotamidae->urlInfo(), 'MISS');
$this->verifyPageCache($this->entityTestHippopotamidae->urlInfo(), 'HIT');
$hippo_comment = Comment::create(array(
'subject' => 'Hippopotamus',
'comment_body' => array(
'value' => 'The common hippopotamus (Hippopotamus amphibius), or hippo, is a large, mostly herbivorous mammal in sub-Saharan Africa',
'format' => 'plain_text',
),
'entity_id' => $this->entityTestHippopotamidae->id(),
'entity_type' => 'entity_test',
'field_name' => 'comment',
'status' => CommentInterface::PUBLISHED,
));
$hippo_comment->save();
// Ensure that a new comment only invalidates the commented entity.
$this->verifyPageCache($this->entityTestCamelid->urlInfo(), 'HIT');
$this->verifyPageCache($this->entityTestHippopotamidae->urlInfo(), 'MISS');
$this->assertText($hippo_comment->getSubject());
// Ensure that updating an existing comment only invalidates the commented
// entity.
$this->entity->save();
$this->verifyPageCache($this->entityTestCamelid->urlInfo(), 'MISS');
$this->verifyPageCache($this->entityTestHippopotamidae->urlInfo(), 'HIT');
}
/**
* {@inheritdoc}

View file

@ -70,17 +70,15 @@ class CommentDefaultFormatterCacheTagsTest extends EntityUnitTestBase {
->getViewBuilder('entity_test')
->view($commented_entity);
$renderer->renderRoot($build);
$cache_context_tags = \Drupal::service('cache_contexts_manager')->convertTokensToKeys($build['#cache']['contexts'])->getCacheTags();
$expected_cache_tags = Cache::mergeTags($cache_context_tags, [
$expected_cache_tags = [
'entity_test_view',
'entity_test:' . $commented_entity->id(),
'comment_list',
'config:core.entity_form_display.comment.comment.default',
'config:field.field.comment.comment.comment_body',
'config:field.field.entity_test.entity_test.comment',
'config:field.storage.comment.comment_body',
'config:user.settings',
]);
];
sort($expected_cache_tags);
$this->assertEqual($build['#cache']['tags'], $expected_cache_tags);
@ -113,11 +111,9 @@ class CommentDefaultFormatterCacheTagsTest extends EntityUnitTestBase {
->getViewBuilder('entity_test')
->view($commented_entity);
$renderer->renderRoot($build);
$cache_context_tags = \Drupal::service('cache_contexts_manager')->convertTokensToKeys($build['#cache']['contexts'])->getCacheTags();
$expected_cache_tags = Cache::mergeTags($cache_context_tags, [
$expected_cache_tags = [
'entity_test_view',
'entity_test:' . $commented_entity->id(),
'comment_list',
'comment_view',
'comment:' . $comment->id(),
'config:filter.format.plain_text',
@ -128,7 +124,7 @@ class CommentDefaultFormatterCacheTagsTest extends EntityUnitTestBase {
'config:field.field.entity_test.entity_test.comment',
'config:field.storage.comment.comment_body',
'config:user.settings',
]);
];
sort($expected_cache_tags);
$this->assertEqual($build['#cache']['tags'], $expected_cache_tags);
}

View file

@ -53,15 +53,23 @@ class CommentFieldAccessTest extends EntityUnitTestBase {
protected $readOnlyFields = array(
'changed',
'hostname',
'uuid',
'cid',
'thread',
'comment_type',
);
/**
* These fields can be edited on create only.
*
* @var array
*/
protected $createOnlyFields = [
'uuid',
'pid',
'comment_type',
'entity_id',
'entity_type',
'field_name',
);
];
/**
* These fields can only be edited by the admin or anonymous users if allowed.
@ -252,6 +260,28 @@ class CommentFieldAccessTest extends EntityUnitTestBase {
}
}
// Check create-only fields.
foreach ($this->createOnlyFields as $field) {
// Check view operation.
foreach ($permutations as $set) {
$may_view = $set['comment']->{$field}->access('view', $set['user']);
$may_update = $set['comment']->{$field}->access('edit', $set['user']);
$this->assertEqual($may_view, $field != 'hostname' && ($set['user']->hasPermission('administer comments') ||
($set['comment']->isPublished() && $set['user']->hasPermission('access comments'))), SafeMarkup::format('User @user !state view field !field on comment @comment', [
'@user' => $set['user']->getUsername(),
'!state' => $may_view ? 'can' : 'cannot',
'@comment' => $set['comment']->getSubject(),
'!field' => $field,
]));
$this->assertEqual($may_update, $set['user']->hasPermission('post comments') && $set['comment']->isNew(), SafeMarkup::format('User @user !state update field !field on comment @comment', [
'@user' => $set['user']->getUsername(),
'!state' => $may_update ? 'can' : 'cannot',
'@comment' => $set['comment']->getSubject(),
'!field' => $field,
]));
}
}
// Check contact fields.
foreach ($this->contactFields as $field) {
// Check view operation.

View file

@ -84,13 +84,13 @@ class CommentFieldsTest extends CommentTestBase {
$this->drupalLogin($this->webUser);
$this->drupalGet('node/' . $node->nid->value);
$elements = $this->cssSelect('.field-type-comment');
$elements = $this->cssSelect('.field--type-comment');
$this->assertEqual(2, count($elements), 'There are two comment fields on the node.');
// Delete the first comment field.
FieldStorageConfig::loadByName('node', 'comment')->delete();
$this->drupalGet('node/' . $node->nid->value);
$elements = $this->cssSelect('.field-type-comment');
$elements = $this->cssSelect('.field--type-comment');
$this->assertEqual(1, count($elements), 'There is one comment field on the node.');
}

View file

@ -27,7 +27,7 @@ abstract class CommentTestBase extends WebTestBase {
*
* @var array
*/
public static $modules = array('comment', 'node', 'history', 'field_ui', 'datetime');
public static $modules = ['block', 'comment', 'node', 'history', 'field_ui', 'datetime'];
/**
* An administrative user with permission to configure comment settings.
@ -86,6 +86,7 @@ abstract class CommentTestBase extends WebTestBase {
// Create a test node authored by the web user.
$this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'uid' => $this->webUser->id()));
$this->drupalPlaceBlock('local_tasks_block');
}
/**

View file

@ -7,7 +7,8 @@
namespace Drupal\comment\Tests;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Component\Utility\Xss;
use Drupal\comment\Entity\Comment;
use Drupal\Core\Render\BubbleableMetadata;
@ -52,26 +53,26 @@ class CommentTokenReplaceTest extends CommentTestBase {
// Generate and test sanitized tokens.
$tests = array();
$tests['[comment:cid]'] = $comment->id();
$tests['[comment:hostname]'] = SafeMarkup::checkPlain($comment->getHostname());
$tests['[comment:hostname]'] = Html::escape($comment->getHostname());
$tests['[comment:author]'] = Xss::filter($comment->getAuthorName());
$tests['[comment:mail]'] = SafeMarkup::checkPlain($this->adminUser->getEmail());
$tests['[comment:homepage]'] = check_url($comment->getHomepage());
$tests['[comment:mail]'] = Html::escape($this->adminUser->getEmail());
$tests['[comment:homepage]'] = UrlHelper::filterBadProtocol($comment->getHomepage());
$tests['[comment:title]'] = Xss::filter($comment->getSubject());
$tests['[comment:body]'] = $comment->comment_body->processed;
$tests['[comment:langcode]'] = SafeMarkup::checkPlain($comment->language()->getId());
$tests['[comment:langcode]'] = Html::escape($comment->language()->getId());
$tests['[comment:url]'] = $comment->url('canonical', $url_options + array('fragment' => 'comment-' . $comment->id()));
$tests['[comment:edit-url]'] = $comment->url('edit-form', $url_options);
$tests['[comment:created]'] = \Drupal::service('date.formatter')->format($comment->getCreatedTime(), 'medium', array('langcode' => $language_interface->getId()));
$tests['[comment:created:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($comment->getCreatedTime(), array('langcode' => $language_interface->getId()));
$tests['[comment:changed:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($comment->getChangedTimeAcrossTranslations(), array('langcode' => $language_interface->getId()));
$tests['[comment:parent:cid]'] = $comment->hasParentComment() ? $comment->getParentComment()->id() : NULL;
$tests['[comment:parent:title]'] = SafeMarkup::checkPlain($parent_comment->getSubject());
$tests['[comment:entity]'] = SafeMarkup::checkPlain($node->getTitle());
$tests['[comment:parent:title]'] = Html::escape($parent_comment->getSubject());
$tests['[comment:entity]'] = Html::escape($node->getTitle());
// Test node specific tokens.
$tests['[comment:entity:nid]'] = $comment->getCommentedEntityId();
$tests['[comment:entity:title]'] = SafeMarkup::checkPlain($node->getTitle());
$tests['[comment:entity:title]'] = Html::escape($node->getTitle());
$tests['[comment:author:uid]'] = $comment->getOwnerId();
$tests['[comment:author:name]'] = SafeMarkup::checkPlain($this->adminUser->getUsername());
$tests['[comment:author:name]'] = Html::escape($this->adminUser->getUsername());
$base_bubbleable_metadata = BubbleableMetadata::createFromObject($comment);
$metadata_tests = [];

View file

@ -38,10 +38,10 @@ class CommentTranslationUITest extends ContentTranslationUITestBase {
protected $defaultCacheContexts = [
'languages:language_interface',
'theme',
'user.permissions',
'timezone',
'url.query_args:_wrapper_format',
'url.query_args.pagers:0',
'user.roles'
'user'
];
/**

View file

@ -0,0 +1,89 @@
<?php
/**
* @file
* Contains \Drupal\comment\Tests\Migrate\d6\MigrateCommentTest.
*/
namespace Drupal\comment\Tests\Migrate\d6;
use Drupal\comment\Tests\CommentTestTrait;
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
/**
* Upgrade comments.
*
* @group migrate_drupal_6
*/
class MigrateCommentTest extends MigrateDrupal6TestBase {
use CommentTestTrait;
static $modules = array('node', 'comment', 'text', 'filter');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('node');
$this->installEntitySchema('comment');
$this->installSchema('comment', ['comment_entity_statistics']);
$this->installConfig(['node', 'comment']);
entity_create('node_type', array('type' => 'page'))->save();
entity_create('node_type', array('type' => 'story'))->save();
$this->addDefaultCommentField('node', 'story');
$this->container->get('entity.manager')->getStorage('comment_type')->create(array(
'id' => 'comment_no_subject',
'label' => 'comment_no_subject',
'target_entity_type_id' => 'node',
))->save();
\Drupal::service('comment.manager')->addBodyField('comment_no_subject');
$node = entity_create('node', array(
'type' => 'story',
'nid' => 1,
'title' => $this->randomString(),
));
$node->enforceIsNew();
$node->save();
$id_mappings = array(
'd6_filter_format' => array(array(array(1), array('filtered_html'))),
'd6_node:*' => array(array(array(1), array(1))),
'd6_user' => array(array(array(0), array(0))),
'd6_comment_type' => array(array(array('comment'), array('comment_no_subject'))),
'd6_comment_entity_display' => array(array(array('story'), array('node', 'story', 'default', 'comment'))),
'd6_comment_entity_form_display' => array(array(array('story'), array('node', 'story', 'default', 'comment'))),
);
$this->prepareMigrations($id_mappings);
$this->executeMigration('d6_comment');
}
/**
* Tests the Drupal 6 to Drupal 8 comment migration.
*/
public function testComments() {
/** @var \Drupal\Core\Entity\EntityStorageInterface $comment_storage */
$comment_storage = $this->container->get('entity.manager')->getStorage('comment');
/** @var \Drupal\comment\CommentInterface $comment */
$comment = $comment_storage->load(1);
$this->assertIdentical('The first comment.', $comment->getSubject());
$this->assertIdentical('The first comment body.', $comment->comment_body->value);
$this->assertIdentical('filtered_html', $comment->comment_body->format);
$this->assertIdentical('0', $comment->pid->target_id);
$this->assertIdentical('1', $comment->getCommentedEntityId());
$this->assertIdentical('node', $comment->getCommentedEntityTypeId());
$this->assertIdentical('en', $comment->language()->getId());
$this->assertIdentical('comment_no_subject', $comment->getTypeId());
$comment = $comment_storage->load(2);
$this->assertIdentical('The response to the second comment.', $comment->subject->value);
$this->assertIdentical('3', $comment->pid->target_id);
$comment = $comment_storage->load(3);
$this->assertIdentical('The second comment.', $comment->subject->value);
$this->assertIdentical('0', $comment->pid->target_id);
}
}

View file

@ -0,0 +1,43 @@
<?php
/**
* @file
* Contains \Drupal\comment\Tests\Migrate\d6\MigrateCommentTypeTest.
*/
namespace Drupal\comment\Tests\Migrate\d6;
use Drupal\comment\Entity\CommentType;
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
/**
* Upgrade comment type.
*
* @group migrate_drupal_6
*/
class MigrateCommentTypeTest extends MigrateDrupal6TestBase {
static $modules = array('node', 'comment', 'text', 'filter');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('node');
$this->installEntitySchema('comment');
$this->installConfig(['node', 'comment']);
$this->executeMigration('d6_comment_type');
}
/**
* Tests the Drupal 6 to Drupal 8 comment type migration.
*/
public function testCommentType() {
$comment_type = CommentType::load('comment');
$this->assertIdentical('node', $comment_type->getTargetEntityTypeId());
$comment_type = CommentType::load('comment_no_subject');
$this->assertIdentical('node', $comment_type->getTargetEntityTypeId());
}
}

View file

@ -0,0 +1,71 @@
<?php
/**
* @file
* Contains \Drupal\comment\Tests\Migrate\d6\MigrateCommentVariableDisplayBase.
*/
namespace Drupal\comment\Tests\Migrate\d6;
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
/**
* Base class for Drupal 6 comment variables to Drupal 8 entity display tests.
*/
abstract class MigrateCommentVariableDisplayBase extends MigrateDrupal6TestBase {
/**
* The ID of migration to run.
*
* This constant needs to be set in the concrete class in order for the test
* to work.
*/
const MIGRATION = '';
/**
* Modules to enable.
*
* @var array
*/
static $modules = array('comment', 'node');
/**
* The node types being tested.
*
* @var array
*/
protected $types = array('page', 'story', 'article');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
entity_create('field_storage_config', array(
'entity_type' => 'node',
'field_name' => 'comment',
'type' => 'comment',
'translatable' => '0',
))->save();
foreach ($this->types as $type) {
entity_create('node_type', array('type' => $type))->save();
entity_create('field_config', array(
'label' => 'Comments',
'description' => '',
'field_name' => 'comment',
'entity_type' => 'node',
'bundle' => $type,
'required' => 1,
))->save();
}
$id_mappings = array(
'd6_comment_field_instance' => array(
array(array('page'), array('node', 'comment', 'page')),
),
);
$this->prepareMigrations($id_mappings);
$this->executeMigration(static::MIGRATION);
}
}

View file

@ -0,0 +1,38 @@
<?php
/**
* @file
* Contains \Drupal\comment\Tests\Migrate\d6\MigrateCommentVariableEntityDisplayTest.
*/
namespace Drupal\comment\Tests\Migrate\d6;
/**
* Upgrade comment variables to entity.display.node.*.default.yml.
*
* @group migrate_drupal_6
*/
class MigrateCommentVariableEntityDisplayTest extends MigrateCommentVariableDisplayBase {
/**
* The migration to run.
*/
const MIGRATION = 'd6_comment_entity_display';
/**
* The node types being used.
*/
protected $types = array('page', 'story', 'article');
/**
* Tests comment variables migrated into an entity display.
*/
public function testCommentEntityDisplay() {
foreach ($this->types as $type) {
$component = entity_get_display('node', $type, 'default')->getComponent('comment');
$this->assertIdentical('hidden', $component['label']);
$this->assertIdentical('comment_default', $component['type']);
$this->assertIdentical(20, $component['weight']);
}
}
}

View file

@ -0,0 +1,61 @@
<?php
/**
* @file
* Contains \Drupal\comment\Tests\Migrate\d6\MigrateCommentVariableEntityFormDisplaySubjectTest.
*/
namespace Drupal\comment\Tests\Migrate\d6;
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
/**
* Upgrade comment subject variable to core.entity_form_display.comment.*.default.yml
*
* @group migrate_drupal_6
*/
class MigrateCommentVariableEntityFormDisplaySubjectTest extends MigrateDrupal6TestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('comment', 'node');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
foreach (['comment', 'comment_no_subject'] as $comment_type) {
entity_create('comment_type', array(
'id' => $comment_type,
'target_entity_type_id' => 'node',
))
->save();
}
// Add some id mappings for the dependant migrations.
$id_mappings = array(
'd6_comment_type' => array(
array(array('comment'), array('comment_no_subject')),
),
);
$this->prepareMigrations($id_mappings);
$this->executeMigration('d6_comment_entity_form_display_subject');
}
/**
* Tests comment subject variable migrated into an entity display.
*/
public function testCommentEntityFormDisplay() {
$component = entity_get_form_display('comment', 'comment', 'default')
->getComponent('subject');
$this->assertIdentical('string_textfield', $component['type']);
$this->assertIdentical(10, $component['weight']);
$component = entity_get_form_display('comment', 'comment_no_subject', 'default')
->getComponent('subject');
$this->assertNull($component);
}
}

View file

@ -0,0 +1,33 @@
<?php
/**
* @file
* Contains \Drupal\comment\Tests\Migrate\d6\MigrateCommentVariableEntityFormDisplayTest.
*/
namespace Drupal\comment\Tests\Migrate\d6;
/**
* Upgrade comment variables to core.entity_form_display.node.*.default.yml.
*
* @group migrate_drupal_6
*/
class MigrateCommentVariableEntityFormDisplayTest extends MigrateCommentVariableDisplayBase {
/**
* The migration to run.
*/
const MIGRATION = 'd6_comment_entity_form_display';
/**
* Tests comment variables migrated into an entity display.
*/
public function testCommentEntityFormDisplay() {
foreach ($this->types as $type) {
$component = entity_get_form_display('node', $type, 'default')->getComponent('comment');
$this->assertIdentical('comment_default', $component['type']);
$this->assertIdentical(20, $component['weight']);
}
}
}

View file

@ -0,0 +1,54 @@
<?php
/**
* @file
* Contains \Drupal\comment\Tests\Migrate\d6\MigrateCommentVariableFieldTest.
*/
namespace Drupal\comment\Tests\Migrate\d6;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
/**
* Upgrade comment variables to field.storage.node.comment.yml.
*
* @group migrate_drupal_6
*/
class MigrateCommentVariableFieldTest extends MigrateDrupal6TestBase {
static $modules = array('comment', 'node');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
foreach (array('page', 'story', 'test') as $type) {
entity_create('node_type', array('type' => $type))->save();
}
foreach (['comment', 'comment_no_subject'] as $comment_type) {
entity_create('comment_type', array(
'id' => $comment_type,
'target_entity_type_id' => 'node',
))
->save();
}
// Add some id mappings for the dependant migrations.
$id_mappings = array(
'd6_comment_type' => array(
array(array('comment'), array('comment_no_subject')),
),
);
$this->prepareMigrations($id_mappings);
$this->executeMigration('d6_comment_field');
}
/**
* Tests comment variables migrated into a field entity.
*/
public function testCommentField() {
$this->assertTrue(is_object(FieldStorageConfig::load('node.comment')));
}
}

View file

@ -0,0 +1,80 @@
<?php
/**
* @file
* Contains \Drupal\comment\Tests\Migrate\d6\MigrateCommentVariableInstanceTest.
*/
namespace Drupal\comment\Tests\Migrate\d6;
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
/**
* Upgrade comment variables to field.instance.node.*.comment.yml.
*
* @group migrate_drupal_6
*/
class MigrateCommentVariableInstanceTest extends MigrateDrupal6TestBase {
static $modules = array('comment', 'node');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Add some id mappings for the dependant migrations.
$id_mappings = array(
'd6_comment_field' => array(
array(array('page'), array('node', 'page')),
),
'd6_node_type' => array(
array(array('page'), array('page')),
),
);
$this->prepareMigrations($id_mappings);
foreach (array('page', 'story', 'article') as $type) {
entity_create('node_type', array('type' => $type))->save();
}
entity_create('field_storage_config', array(
'entity_type' => 'node',
'field_name' => 'comment',
'type' => 'comment',
'translatable' => '0',
))->save();
entity_create('field_storage_config', array(
'entity_type' => 'node',
'field_name' => 'comment_no_subject',
'type' => 'comment',
'translatable' => '0',
))->save();
$this->executeMigration('d6_comment_field_instance');
}
/**
* Test the migrated field instance values.
*/
public function testCommentFieldInstance() {
$node = entity_create('node', array('type' => 'page'));
$this->assertIdentical(0, $node->comment->status);
$this->assertIdentical('comment', $node->comment->getFieldDefinition()->getName());
$settings = $node->comment->getFieldDefinition()->getSettings();
$this->assertIdentical(4, $settings['default_mode']);
$this->assertIdentical(50, $settings['per_page']);
$this->assertIdentical(0, $settings['anonymous']);
$this->assertIdentical(FALSE, $settings['form_location']);
$this->assertIdentical(1, $settings['preview']);
$node = entity_create('node', array('type' => 'story'));
$this->assertIdentical(2, $node->comment_no_subject->status);
$this->assertIdentical('comment_no_subject', $node->comment_no_subject->getFieldDefinition()->getName());
$settings = $node->comment_no_subject->getFieldDefinition()->getSettings();
$this->assertIdentical(2, $settings['default_mode']);
$this->assertIdentical(70, $settings['per_page']);
$this->assertIdentical(1, $settings['anonymous']);
$this->assertIdentical(FALSE, $settings['form_location']);
$this->assertIdentical(0, $settings['preview']);
}
}

View file

@ -0,0 +1,63 @@
<?php
/**
* @file
* Contains \Drupal\comment\Tests\Migrate\d7\MigrateCommentEntityDisplayTest.
*/
namespace Drupal\comment\Tests\Migrate\d7;
use Drupal\Core\Entity\Entity\EntityViewDisplay;
use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
/**
* Tests migration of comment display configuration.
*
* @group comment
*/
class MigrateCommentEntityDisplayTest extends MigrateDrupal7TestBase {
public static $modules = ['node', 'comment', 'text'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig(static::$modules);
$this->executeMigration('d7_node_type');
$this->executeMigration('d7_comment_type');
$this->executeMigration('d7_comment_field');
$this->executeMigration('d7_comment_field_instance');
$this->executeMigration('d7_comment_entity_display');
}
/**
* Asserts a display entity.
*
* @param string $id
* The entity ID.
* @param string $component_id
* The ID of the display component.
*/
protected function assertDisplay($id, $component_id) {
$component = EntityViewDisplay::load($id)->getComponent($component_id);
$this->assertTrue(is_array($component));
$this->assertIdentical('hidden', $component['label']);
$this->assertIdentical('comment_default', $component['type']);
$this->assertIdentical(20, $component['weight']);
}
/**
* Tests the migrated display configuration.
*/
public function testMigration() {
$this->assertDisplay('node.page.default', 'comment_node_page');
$this->assertDisplay('node.article.default', 'comment_node_article');
$this->assertDisplay('node.book.default', 'comment_node_book');
$this->assertDisplay('node.blog.default', 'comment_node_blog');
$this->assertDisplay('node.forum.default', 'comment_node_forum');
$this->assertDisplay('node.test_content_type.default', 'comment_node_test_content_type');
}
}

View file

@ -0,0 +1,58 @@
<?php
/**
* @file
* Contains \Drupal\comment\Tests\Migrate\d7\MigrateCommentEntityFormDisplaySubjectTest.
*/
namespace Drupal\comment\Tests\Migrate\d7;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
/**
* Tests migration of comment form's subject display configuration.
*
* @group comment
*/
class MigrateCommentEntityFormDisplaySubjectTest extends MigrateDrupal7TestBase {
public static $modules = ['node', 'comment', 'text'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig(static::$modules);
$this->executeMigration('d7_node_type');
$this->executeMigration('d7_comment_type');
$this->executeMigration('d7_comment_entity_form_display_subject');
}
/**
* Asserts a display entity.
*
* @param string $id
* The entity ID.
*/
protected function assertDisplay($id) {
$component = EntityFormDisplay::load($id)->getComponent('subject');
$this->assertTrue(is_array($component));
$this->assertIdentical('string_textfield', $component['type']);
$this->assertIdentical(10, $component['weight']);
}
/**
* Tests the migrated display configuration.
*/
public function testMigration() {
$this->assertDisplay('comment.comment_node_page.default');
$this->assertDisplay('comment.comment_node_article.default');
$this->assertDisplay('comment.comment_node_book.default');
$this->assertDisplay('comment.comment_node_blog.default');
$this->assertDisplay('comment.comment_node_forum.default');
$this->assertDisplay('comment.comment_node_test_content_type.default');
}
}

View file

@ -0,0 +1,62 @@
<?php
/**
* @file
* Contains \Drupal\comment\Tests\Migrate\d7\MigrateCommentEntityFormDisplayTest.
*/
namespace Drupal\comment\Tests\Migrate\d7;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
/**
* Tests migration of comment form display configuration.
*
* @group comment
*/
class MigrateCommentEntityFormDisplayTest extends MigrateDrupal7TestBase {
public static $modules = ['node', 'comment', 'text'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig(static::$modules);
$this->executeMigration('d7_node_type');
$this->executeMigration('d7_comment_type');
$this->executeMigration('d7_comment_field');
$this->executeMigration('d7_comment_field_instance');
$this->executeMigration('d7_comment_entity_form_display');
}
/**
* Asserts a display entity.
*
* @param string $id
* The entity ID.
* @param string $component
* The ID of the form component.
*/
protected function assertDisplay($id, $component_id) {
$component = EntityFormDisplay::load($id)->getComponent($component_id);
$this->assertTrue(is_array($component));
$this->assertIdentical('comment_default', $component['type']);
$this->assertIdentical(20, $component['weight']);
}
/**
* Tests the migrated display configuration.
*/
public function testMigration() {
$this->assertDisplay('node.page.default', 'comment');
$this->assertDisplay('node.article.default', 'comment');
$this->assertDisplay('node.book.default', 'comment');
$this->assertDisplay('node.blog.default', 'comment');
$this->assertDisplay('node.forum.default', 'comment');
$this->assertDisplay('node.test_content_type.default', 'comment');
}
}

View file

@ -0,0 +1,89 @@
<?php
/**
* @file
* Contains \Drupal\comment\Tests\Migrate\d7\MigrateCommentFieldInstanceTest.
*/
namespace Drupal\comment\Tests\Migrate\d7;
use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
use Drupal\Core\Field\FieldConfigInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
/**
* Tests creation of comment reference fields for each comment type defined
* in Drupal 7.
*
* @group comment
*/
class MigrateCommentFieldInstanceTest extends MigrateDrupal7TestBase {
public static $modules = ['node', 'comment', 'text'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig(static::$modules);
$this->executeMigration('d7_node_type');
$this->executeMigration('d7_comment_type');
$this->executeMigration('d7_comment_field');
$this->executeMigration('d7_comment_field_instance');
}
/**
* Asserts a comment field entity.
*
* @param string $id
* The entity ID.
* @param string $field_name
* The field name.
* @param string $bundle
* The bundle ID.
* @param int $default_mode
* The field's default_mode setting.
* @param int $per_page
* The field's per_page setting.
* @param bool $anonymous
* The field's anonymous setting.
* @param int $form_location
* The field's form_location setting.
* @param bool $preview
* The field's preview setting.
*/
protected function assertEntity($id, $field_name, $bundle, $default_mode, $per_page, $anonymous, $form_location, $preview) {
$entity = FieldConfig::load($id);
$this->assertTrue($entity instanceof FieldConfigInterface);
/** @var \Drupal\field\FieldConfigInterface $entity */
$this->assertIdentical('node', $entity->getTargetEntityTypeId());
$this->assertIdentical('Comments', $entity->label());
$this->assertTrue($entity->isRequired());
$this->assertIdentical($field_name, $entity->getFieldStorageDefinition()->getName());
$this->assertIdentical($bundle, $entity->getTargetBundle());
$this->assertTrue($entity->get('default_value')[0]['status']);
$this->assertEqual($default_mode, $entity->getSetting('default_mode'));
$this->assertIdentical($per_page, $entity->getSetting('per_page'));
$this->assertEqual($anonymous, $entity->getSetting('anonymous'));
// This assertion fails because 1 !== TRUE. It's extremely strange that
// the form_location setting is returning a boolean, but this appears to
// be a problem with the entity, not with the migration.
// $this->asserIdentical($form_location, $entity->getSetting('form_location'));
$this->assertEqual($preview, $entity->getSetting('preview'));
}
/**
* Tests the migrated fields.
*/
public function testMigration() {
$this->assertEntity('node.page.comment_node_page', 'comment_node_page', 'page', TRUE, 50, FALSE, CommentItemInterface::FORM_BELOW, TRUE);
$this->assertEntity('node.article.comment_node_article', 'comment_node_article', 'article', TRUE, 50, FALSE, CommentItemInterface::FORM_BELOW, TRUE);
$this->assertEntity('node.blog.comment_node_blog', 'comment_node_blog', 'blog', TRUE, 50, FALSE, CommentItemInterface::FORM_BELOW, TRUE);
$this->assertEntity('node.book.comment_node_book', 'comment_node_book', 'book', TRUE, 50, FALSE, CommentItemInterface::FORM_BELOW, TRUE);
$this->assertEntity('node.forum.comment_node_forum', 'comment_node_forum', 'forum', TRUE, 50, FALSE, CommentItemInterface::FORM_BELOW, TRUE);
$this->assertEntity('node.test_content_type.comment_node_test_content_type', 'comment_node_test_content_type', 'test_content_type', TRUE, 30, FALSE, CommentItemInterface::FORM_BELOW, TRUE);
}
}

View file

@ -0,0 +1,64 @@
<?php
/**
* @file
* Contains \Drupal\comment\Tests\Migrate\d7\MigrateCommentFieldTest.
*/
namespace Drupal\comment\Tests\Migrate\d7;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\FieldStorageConfigInterface;
use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
/**
* Tests creation of comment reference fields for each comment type defined
* in Drupal 7.
*
* @group comment
*/
class MigrateCommentFieldTest extends MigrateDrupal7TestBase {
public static $modules = ['node', 'comment', 'text'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig(static::$modules);
$this->executeMigration('d7_node_type');
$this->executeMigration('d7_comment_type');
$this->executeMigration('d7_comment_field');
}
/**
* Asserts a comment field entity.
*
* @param string $id
* The entity ID.
* @param string $comment_type
* The comment type (bundle ID) the field references.
*/
protected function assertEntity($id, $comment_type) {
$entity = FieldStorageConfig::load($id);
$this->assertTrue($entity instanceof FieldStorageConfigInterface);
/** @var \Drupal\field\FieldStorageConfigInterface $entity */
$this->assertIdentical('node', $entity->getTargetEntityTypeId());
$this->assertIdentical('comment', $entity->getType());
$this->assertIdentical($comment_type, $entity->getSetting('comment_type'));
}
/**
* Tests the migrated fields.
*/
public function testMigration() {
$this->assertEntity('node.comment_node_page', 'comment_node_page');
$this->assertEntity('node.comment_node_article', 'comment_node_article');
$this->assertEntity('node.comment_node_blog', 'comment_node_blog');
$this->assertEntity('node.comment_node_book', 'comment_node_book');
$this->assertEntity('node.comment_node_forum', 'comment_node_forum');
$this->assertEntity('node.comment_node_test_content_type', 'comment_node_test_content_type');
}
}

View file

@ -0,0 +1,78 @@
<?php
/**
* @file
* Contains \Drupal\comment\Tests\Migrate\d7\MigrateCommentTest.
*/
namespace Drupal\comment\Tests\Migrate\d7;
use Drupal\comment\CommentInterface;
use Drupal\comment\Entity\Comment;
use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
use Drupal\node\NodeInterface;
use Drupal\user\Entity\User;
/**
* Tests migration of comments from Drupal 7.
*
* @group comment
*/
class MigrateCommentTest extends MigrateDrupal7TestBase {
public static $modules = ['filter', 'node', 'comment', 'text'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig(static::$modules);
$this->installEntitySchema('node');
$this->installEntitySchema('comment');
$this->executeMigration('d7_filter_format');
$this->executeMigration('d7_user_role');
$this->executeMigration('d7_user');
// The test database doesn't include uid 1, so we'll need to create it.
User::create(array(
'uid' => 1,
'name' => 'admin',
'mail' => 'admin@local.host',
))->save();
$this->executeMigration('d7_node_type');
// We only need the test_content_type node migration to run for real, so
// mock all the others.
$this->prepareMigrations(array(
'd7_node:*' => array(
array(array(0), array(0)),
),
));
$this->executeMigration('d7_node__test_content_type');
$this->executeMigration('d7_comment_type');
$this->executeMigration('d7_comment');
}
/**
* Tests migration of comments from Drupal 7.
*/
public function testCommentMigration() {
$comment = Comment::load(1);
$this->assertTrue($comment instanceof CommentInterface);
/** @var \Drupal\comment\CommentInterface $comment */
$this->assertIdentical('A comment', $comment->getSubject());
$this->assertIdentical('1421727536', $comment->getCreatedTime());
$this->assertIdentical('1421727536', $comment->getChangedTime());
$this->assertTrue($comment->getStatus());
$this->assertIdentical('admin', $comment->getAuthorName());
$this->assertIdentical('admin@local.host', $comment->getAuthorEmail());
$this->assertIdentical('This is a comment', $comment->comment_body->value);
$this->assertIdentical('filtered_html', $comment->comment_body->format);
$node = $comment->getCommentedEntity();
$this->assertTrue($node instanceof NodeInterface);
$this->assertIdentical('1', $node->id());
}
}

View file

@ -0,0 +1,61 @@
<?php
/**
* @file
* Contains \Drupal\comment\Tests\Migrate\d7\MigrateCommentTypeTest.
*/
namespace Drupal\comment\Tests\Migrate\d7;
use Drupal\comment\CommentTypeInterface;
use Drupal\comment\Entity\CommentType;
use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
/**
* Tests migration of comment types from Drupal 7.
*
* @group comment
*/
class MigrateCommentTypeTest extends MigrateDrupal7TestBase {
public static $modules = ['node', 'comment', 'text'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig(static::$modules);
$this->executeMigration('d7_node_type');
$this->executeMigration('d7_comment_type');
}
/**
* Asserts a comment type entity.
*
* @param string $id
* The entity ID.
* @param string $label
* The entity label.
*/
protected function assertEntity($id, $label) {
$entity = CommentType::load($id);
$this->assertTrue($entity instanceof CommentTypeInterface);
/** @var \Drupal\comment\CommentTypeInterface $entity */
$this->assertIdentical($label, $entity->label());
$this->assertIdentical('node', $entity->getTargetEntityTypeId());
}
/**
* Tests the migrated comment types.
*/
public function testMigration() {
$this->assertEntity('comment_node_page', 'Basic page comment');
$this->assertEntity('comment_node_article', 'Article comment');
$this->assertEntity('comment_node_blog', 'Blog entry comment');
$this->assertEntity('comment_node_book', 'Book page comment');
$this->assertEntity('comment_node_forum', 'Forum topic comment');
$this->assertEntity('comment_node_test_content_type', 'Test content type comment');
}
}

View file

@ -91,11 +91,11 @@ class CommentFieldNameTest extends CommentTestBase {
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['field_name']->advancedRender($view->result[0]);
});
$this->assertIdentical($this->comment->getFieldName(), $output);
$this->assertEqual($this->comment->getFieldName(), $output);
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['field_name']->advancedRender($view->result[1]);
});
$this->assertIdentical($this->customComment->getFieldName(), $output);
$this->assertEqual($this->customComment->getFieldName(), $output);
}
}

View file

@ -12,7 +12,7 @@ use Drupal\Core\Session\AnonymousUserSession;
use Drupal\user\Entity\Role;
use Drupal\user\Entity\User;
use Drupal\views\Entity\View;
use Drupal\views\Tests\ViewUnitTestBase;
use Drupal\views\Tests\ViewKernelTestBase;
use Drupal\views\Views;
/**
@ -20,7 +20,7 @@ use Drupal\views\Views;
*
* @group comment
*/
class CommentUserNameTest extends ViewUnitTestBase {
class CommentUserNameTest extends ViewKernelTestBase {
/**
* Admin user.
@ -50,6 +50,7 @@ class CommentUserNameTest extends ViewUnitTestBase {
$storage
->create(array(
'uid' => 0,
'name' => '',
'status' => 0,
))
->save();
@ -75,6 +76,7 @@ class CommentUserNameTest extends ViewUnitTestBase {
$comment = Comment::create([
'subject' => 'My comment title',
'uid' => $this->adminUser->id(),
'name' => $this->adminUser->label(),
'entity_type' => 'entity_test',
'comment_type' => 'entity_test',
'status' => 1,

View file

@ -0,0 +1,41 @@
<?php
/**
* @file
* Contains \Drupal\comment\Tests\Views\NodeCommentsTest.
*/
namespace Drupal\comment\Tests\Views;
/**
* Tests comments on nodes.
*
* @group comment
*/
class NodeCommentsTest extends CommentTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = ['history'];
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_new_comments'];
/**
* Test the new comments field plugin.
*/
public function testNewComments() {
$this->drupalGet('test-new-comments');
$this->assertResponse(200);
$new_comments = $this->cssSelect(".views-field-new-comments a:contains('1')");
$this->assertEqual(count($new_comments), 1, 'Found the number of new comments for a certain node.');
}
}

View file

@ -246,10 +246,12 @@ display:
hide_empty: false
empty_zero: false
hide_alter_empty: true
date_format: long
custom_date_format: ''
timezone: ''
plugin_id: date
type: timestamp
settings:
date_format: long
custom_date_format: ''
timezone: ''
plugin_id: field
comment_body:
id: comment_body
table: comment__comment_body

View file

@ -0,0 +1,163 @@
langcode: en
status: true
dependencies:
module:
- comment
- node
- user
id: '2505879'
label: '2505879'
module: views
description: ''
tag: ''
base_table: node_field_data
base_field: nid
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: 0
display_options:
access:
type: perm
options:
perm: 'access content'
cache:
type: tag
options: { }
query:
type: views_query
options:
disable_sql_rewrite: false
distinct: false
replica: false
query_comment: ''
query_tags: { }
pager:
type: full
style:
type: table
row:
type: fields
fields:
title:
id: title
table: node_field_data
field: title
entity_type: node
entity_field: title
alter:
alter_text: false
make_link: false
absolute: false
trim: false
word_boundary: false
ellipsis: false
strip_tags: false
html: false
hide_empty: false
empty_zero: false
settings:
link_to_entity: true
plugin_id: field
relationship: none
group_type: group
admin_label: ''
label: Title
exclude: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_alter_empty: true
click_sort_column: value
type: string
group_column: value
group_columns: { }
group_rows: true
delta_limit: 0
delta_offset: 0
delta_reversed: false
delta_first_last: false
multi_type: separator
separator: ', '
field_api_classes: false
new_comments:
id: new_comments
table: node
field: new_comments
relationship: none
group_type: group
admin_label: ''
label: 'New comments'
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
set_precision: false
precision: 0
decimal: .
prefix: ''
suffix: ''
link_to_comment: true
entity_type: node
plugin_id: node_new_comments
filters: { }
sorts: { }
title: ''
header: { }
footer: { }
empty: { }
relationships: { }
arguments: { }
display_extenders: { }
page_1:
display_plugin: page
id: page_1
display_title: Page
position: 1
display_options:
path: 'test-new-comments'

View file

@ -45,6 +45,10 @@ class CommentLockTest extends UnitTestCase {
$lock->expects($this->exactly(2))
->method($this->anything());
$container->set('lock', $lock);
$cache_tag_invalidator = $this->getMock('Drupal\Core\Cache\CacheTagsInvalidator');
$container->set('cache_tags.invalidator', $cache_tag_invalidator);
\Drupal::setContainer($container);
$methods = get_class_methods('Drupal\comment\Entity\Comment');
unset($methods[array_search('preSave', $methods)]);
@ -70,6 +74,14 @@ class CommentLockTest extends UnitTestCase {
->method('getThread')
->will($this->returnValue(''));
$parent_entity = $this->getMock('\Drupal\Core\Entity\ContentEntityInterface');
$parent_entity->expects($this->atLeastOnce())
->method('getCacheTagsToInvalidate')
->willReturn(['node:1']);
$comment->expects($this->once())
->method('getCommentedEntity')
->willReturn($parent_entity);
$entity_type = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
$comment->expects($this->any())
->method('getEntityType')

View file

@ -0,0 +1,28 @@
<?php
/**
* @file
* Contains \Drupal\Tests\comment\Unit\Migrate\d6\CommentSourceWithHighWaterTest.
*/
namespace Drupal\Tests\comment\Unit\Migrate\d6;
/**
* Tests the Drupal 6 comment source w/ high water handling.
*
* @group comment
*/
class CommentSourceWithHighWaterTest extends CommentTestBase {
const ORIGINAL_HIGH_WATER = 1382255613;
/**
* {@inheritdoc}
*/
protected function setUp() {
$this->migrationConfiguration['highWaterProperty']['field'] = 'timestamp';
array_shift($this->expectedResults);
parent::setUp();
}
}

View file

@ -0,0 +1,17 @@
<?php
/**
* @file
* Contains \Drupal\Tests\comment\Unit\Migrate\d6\CommentTest.
*/
namespace Drupal\Tests\comment\Unit\Migrate\d6;
/**
* Tests D6 comment source plugin.
*
* @group comment
*/
class CommentTest extends CommentTestBase {
}

View file

@ -0,0 +1,85 @@
<?php
/**
* @file
* Contains \Drupal\Tests\comment\Unit\Migrate\d6\CommentTestBase.
*/
namespace Drupal\Tests\comment\Unit\Migrate\d6;
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
/**
* Base class for comment source unit tests.
*/
abstract class CommentTestBase extends MigrateSqlSourceTestCase {
// The plugin system is not working during unit testing so the source plugin
// class needs to be manually specified.
const PLUGIN_CLASS = 'Drupal\comment\Plugin\migrate\source\d6\Comment';
// The fake Migration configuration entity.
protected $migrationConfiguration = array(
// The ID of the entity, can be any string.
'id' => 'test',
// This needs to be the identifier of the actual key: cid for comment, nid
// for node and so on.
'source' => array(
'plugin' => 'd6_comment',
),
);
// We need to set up the database contents; it's easier to do that below.
protected $expectedResults = array(
array(
'cid' => 1,
'pid' => 0,
'nid' => 2,
'uid' => 3,
'subject' => 'subject value 1',
'comment' => 'comment value 1',
'hostname' => 'hostname value 1',
'timestamp' => 1382255613,
'status' => 1,
'thread' => '',
'name' => '',
'mail' => '',
'homepage' => '',
'format' => 'testformat1',
'type' => 'story',
),
array(
'cid' => 2,
'pid' => 1,
'nid' => 3,
'uid' => 4,
'subject' => 'subject value 2',
'comment' => 'comment value 2',
'hostname' => 'hostname value 2',
'timestamp' => 1382255662,
'status' => 1,
'thread' => '',
'name' => '',
'mail' => '',
'homepage' => '',
'format' => 'testformat2',
'type' => 'page',
),
);
/**
* {@inheritdoc}
*/
protected function setUp() {
foreach ($this->expectedResults as $k => $row) {
$this->databaseContents['comments'][$k] = $row;
$this->databaseContents['comments'][$k]['status'] = 1 - $this->databaseContents['comments'][$k]['status'];
}
// Add node table data.
$this->databaseContents['node'][] = array('nid' => 2, 'type' => 'story');
$this->databaseContents['node'][] = array('nid' => 3, 'type' => 'page');
parent::setUp();
}
}

View file

@ -0,0 +1,105 @@
<?php
/**
* @file
* Contains \Drupal\Tests\comment\Unit\Migrate\d7\CommentTest.
*/
namespace Drupal\Tests\comment\Unit\Migrate\d7;
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
/**
* Tests D7 comment source plugin.
*
* @group comment
*/
class CommentTest extends MigrateSqlSourceTestCase {
const PLUGIN_CLASS = 'Drupal\comment\Plugin\migrate\source\d7\Comment';
protected $migrationConfiguration = array(
'id' => 'test',
'source' => array(
'plugin' => 'd7_comment',
),
);
protected $expectedResults = array(
array(
'cid' => '1',
'pid' => '0',
'nid' => '1',
'uid' => '1',
'subject' => 'A comment',
'hostname' => '::1',
'created' => '1421727536',
'changed' => '1421727536',
'status' => '1',
'thread' => '01/',
'name' => 'admin',
'mail' => '',
'homepage' => '',
'language' => 'und',
'comment_body' => array(
array(
'value' => 'This is a comment',
'format' => 'filtered_html',
),
),
),
);
/**
* {@inheritdoc}
*/
protected function setUp() {
$this->databaseContents['comment'] = $this->expectedResults;
unset($this->databaseContents['comment'][0]['comment_body']);
$this->databaseContents['node'] = array(
array(
'nid' => '1',
'vid' => '1',
'type' => 'test_content_type',
'language' => 'en',
'title' => 'A Node',
'uid' => '1',
'status' => '1',
'created' => '1421727515',
'changed' => '1421727515',
'comment' => '2',
'promote' => '1',
'sticky' => '0',
'tnid' => '0',
'translate' => '0',
),
);
$this->databaseContents['field_config_instance'] = array(
array(
'id' => '14',
'field_id' => '1',
'field_name' => 'comment_body',
'entity_type' => 'comment',
'bundle' => 'comment_node_test_content_type',
'data' => 'a:0:{}',
'deleted' => '0',
),
);
$this->databaseContents['field_data_comment_body'] = array(
array(
'entity_type' => 'comment',
'bundle' => 'comment_node_test_content_type',
'deleted' => '0',
'entity_id' => '1',
'revision_id' => '1',
'language' => 'und',
'delta' => '0',
'comment_body_value' => 'This is a comment',
'comment_body_format' => 'filtered_html',
),
);
parent::setUp();
}
}

View file

@ -0,0 +1,103 @@
<?php
/**
* @file
* Contains \Drupal\Tests\comment\Unit\Migrate\d7\CommentTypeTest.
*/
namespace Drupal\Tests\comment\Unit\Migrate\d7;
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
/**
* Tests D7 comment type source plugin.
*
* @group comment
*/
class CommentTypeTest extends MigrateSqlSourceTestCase {
const PLUGIN_CLASS = 'Drupal\comment\Plugin\migrate\source\d7\CommentType';
protected $migrationConfiguration = array(
'id' => 'test',
'source' => array(
'plugin' => 'd7_comment_type',
),
);
protected $expectedResults = array(
array(
'bundle' => 'comment_node_article',
'node_type' => 'article',
'default_mode' => '1',
'per_page' => '50',
'anonymous' => '0',
'form_location' => '1',
'preview' => '0',
'subject' => '1',
'label' => 'Article comment',
),
);
/**
* {@inheritdoc}
*/
protected function setUp() {
$this->databaseContents['node_type'] = array(
array(
'type' => 'article',
'name' => 'Article',
'base' => 'node_content',
'module' => 'node',
'description' => 'Use <em>articles</em> for time-sensitive content like news, press releases or blog posts.',
'help' => 'Help text for articles',
'has_title' => '1',
'title_label' => 'Title',
'custom' => '1',
'modified' => '1',
'locked' => '0',
'disabled' => '0',
'orig_type' => 'article',
),
);
$this->databaseContents['field_config_instance'] = array(
array(
'id' => '14',
'field_id' => '1',
'field_name' => 'comment_body',
'entity_type' => 'comment',
'bundle' => 'comment_node_article',
'data' => 'a:0:{}',
'deleted' => '0',
),
);
$this->databaseContents['variable'] = array(
array(
'name' => 'comment_default_mode_article',
'value' => serialize(1),
),
array(
'name' => 'comment_per_page_article',
'value' => serialize(50),
),
array(
'name' => 'comment_anonymous_article',
'value' => serialize(0),
),
array(
'name' => 'comment_form_location_article',
'value' => serialize(1),
),
array(
'name' => 'comment_preview_article',
'value' => serialize(0),
),
array(
'name' => 'comment_subject_article',
'value' => serialize(1),
),
);
parent::setUp();
}
}