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

@ -7,7 +7,7 @@
namespace Drupal\node\Controller;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Datetime\DateFormatter;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
@ -59,19 +59,16 @@ class NodeController extends ControllerBase implements ContainerInjectionInterfa
);
}
/**
* Displays add content links for available content types.
*
* Redirects to node/add/[type] if only one content type is available.
*
* @return array
* @return array|\Symfony\Component\HttpFoundation\RedirectResponse
* A render array for a list of the node types that can be added; however,
* if there is only one node type defined for the site, the function
* redirects to the node add page for that one node type and does not return
* at all.
*
* @see node_menu()
* will return a RedirectResponse to the node add page for that one node
* type.
*/
public function addPage() {
$content = array();
@ -194,7 +191,7 @@ class NodeController extends ControllerBase implements ContainerInjectionInterfa
'#context' => [
'date' => $link,
'username' => $this->renderer->renderPlain($username),
'message' => SafeMarkup::xssFilter($revision->revision_log->value),
'message' => ['#markup' => $revision->revision_log->value, '#allowed_tags' => Xss::getHtmlTagList()],
],
],
];
@ -205,7 +202,11 @@ class NodeController extends ControllerBase implements ContainerInjectionInterfa
if ($vid == $node->getRevisionId()) {
$row[0]['class'] = ['revision-current'];
$row[] = [
'data' => SafeMarkup::placeholder($this->t('current revision')),
'data' => [
'#prefix' => '<em>',
'#markup' => $this->t('current revision'),
'#suffix' => '</em>',
],
'class' => ['revision-current'],
];
}

View file

@ -20,7 +20,7 @@ class NodeViewController extends EntityViewController {
* {@inheritdoc}
*/
public function view(EntityInterface $node, $view_mode = 'full', $langcode = NULL) {
$build = parent::view($node);
$build = parent::view($node, $view_mode, $langcode);
foreach ($node->uriRelationships() as $rel) {
// Set the node path as the canonical URL to prevent duplicate content.

View file

@ -387,7 +387,6 @@ class Node extends ContentEntityBase implements NodeInterface {
->setRequired(TRUE)
->setTranslatable(TRUE)
->setRevisionable(TRUE)
->setDefaultValue('')
->setSetting('max_length', 255)
->setDisplayOptions('view', array(
'label' => 'hidden',

View file

@ -88,7 +88,7 @@ class NodeForm extends ContentEntityForm {
// Rebuild the form.
$form_state->setRebuild();
$this->entity = $preview->getFormObject()->getEntity();
unset($this->entity->in_preview);
$this->entity->in_preview = NULL;
// Remove the stale temp store entry for existing nodes.
if (!$this->entity->isNew()) {

View file

@ -7,7 +7,6 @@
namespace Drupal\node;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Datetime\DateFormatter;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityListBuilder;
@ -119,7 +118,7 @@ class NodeListBuilder extends EntityListBuilder {
'#suffix' => ' ' . drupal_render($mark),
'#url' => $uri,
);
$row['type'] = SafeMarkup::checkPlain(node_get_type_label($entity));
$row['type'] = node_get_type_label($entity);
$row['author']['data'] = array(
'#theme' => 'username',
'#account' => $entity->getOwner(),

View file

@ -12,7 +12,7 @@ use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\node\Entity\NodeType;
/**
* Defines a class containing permission callbacks.
* Provides dynamic permissions for nodes of different types.
*/
class NodePermissions {
@ -20,7 +20,7 @@ class NodePermissions {
use UrlGeneratorTrait;
/**
* Gets an array of node type permissions.
* Returns an array of node type permissions.
*
* @return array
* The node type permissions.
@ -37,13 +37,13 @@ class NodePermissions {
}
/**
* Builds a standard list of node permissions for a given type.
* Returns a list of node permissions for a given node type.
*
* @param \Drupal\node\Entity\NodeType $type
* The machine name of the node type.
* The node type.
*
* @return array
* An array of permission names and descriptions.
* An associative array of permission names and descriptions.
*/
protected function buildPermissions(NodeType $type) {
$type_id = $type->id();

View file

@ -9,7 +9,6 @@ namespace Drupal\node;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
@ -55,7 +54,7 @@ class NodeTypeForm extends EntityForm {
$type = $this->entity;
if ($this->operation == 'add') {
$form['#title'] = SafeMarkup::checkPlain($this->t('Add content type'));
$form['#title'] = $this->t('Add content type');
$fields = $this->entityManager->getBaseFieldDefinitions('node');
// Create a node with a fake bundle using the type's UUID so that we can
// get the default values for workflow settings.

View file

@ -35,7 +35,7 @@ class NodeTypeListBuilder extends ConfigEntityListBuilder {
*/
public function buildRow(EntityInterface $entity) {
$row['title'] = array(
'data' => $this->getLabel($entity),
'data' => $entity->label(),
'class' => array('menu-label'),
);
$row['description']['data'] = ['#markup' => $entity->getDescription()];

View file

@ -7,7 +7,6 @@
namespace Drupal\node\Plugin\Search;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Config\Config;
use Drupal\Core\Database\Connection;
@ -332,11 +331,9 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
unset($build['#theme']);
$build['#pre_render'][] = array($this, 'removeSubmittedInfo');
// Fetch comment count for snippet.
$rendered = SafeMarkup::set(
$this->renderer->renderPlain($build) . ' ' .
SafeMarkup::escape($this->moduleHandler->invoke('comment', 'node_update_index', array($node, $item->langcode)))
);
// Fetch comments for snippet.
$rendered = $this->renderer->renderPlain($build);
$rendered .= ' ' . $this->moduleHandler->invoke('comment', 'node_update_index', array($node, $item->langcode));
$extra = $this->moduleHandler->invokeAll('node_search_result', array($node, $item->langcode));
@ -348,7 +345,7 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
$result = array(
'link' => $node->url('canonical', array('absolute' => TRUE, 'language' => $language)),
'type' => SafeMarkup::checkPlain($type->label()),
'type' => $type->label(),
'title' => $node->label(),
'node' => $node,
'extra' => $extra,
@ -448,9 +445,15 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
$build = $node_render->view($node, 'search_index', $language->getId());
unset($build['#theme']);
$rendered = $this->renderer->renderPlain($build);
$text = '<h1>' . SafeMarkup::checkPlain($node->label($language->getId())) . '</h1>' . $rendered;
// Add the title to text so it is searchable.
$build['search_title'] = [
'#prefix' => '<h1>',
'#plain_text' => $node->label($language->getId()),
'#suffix' => '</h1>',
'#weight' => -1000
];
$text = $this->renderer->renderPlain($build);
// Fetch extra data normally not visible.
$extra = $this->moduleHandler->invokeAll('node_update_index', array($node, $language->getId()));

View file

@ -0,0 +1,78 @@
<?php
/**
* @file
* Contains \Drupal\node\Plugin\migrate\builder\d6\Node.
*/
namespace Drupal\node\Plugin\migrate\builder\d6;
use Drupal\migrate\Entity\Migration;
use Drupal\migrate\Entity\MigrationInterface;
use Drupal\migrate_drupal\Plugin\migrate\builder\d6\CckBuilder;
/**
* @PluginID("d6_node")
*/
class Node extends CckBuilder {
/**
* Already-instantiated cckfield plugins, keyed by ID.
*
* @var \Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface[]
*/
protected $cckPluginCache = [];
/**
* Gets a cckfield plugin instance.
*
* @param string $field_type
* The field type (plugin ID).
* @param \Drupal\migrate\Entity\MigrationInterface|NULL $migration
* The migration, if any.
*
* @return \Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface
* The cckfield plugin instance.
*/
protected function getCckPlugin($field_type, MigrationInterface $migration = NULL) {
if (empty($this->cckPluginCache[$field_type])) {
$this->cckPluginCache[$field_type] = $this->cckPluginManager->createInstance($field_type, [], $migration);
}
return $this->cckPluginCache[$field_type];
}
/**
* {@inheritdoc}
*/
public function buildMigrations(array $template) {
$migrations = [];
foreach ($this->getSourcePlugin('d6_node_type', $template['source']) as $row) {
$node_type = $row->getSourceProperty('type');
$values = $template;
$values['id'] = $template['id'] . '__' . $node_type;
$label = $template['label'];
$values['label'] = $this->t("@label (@type)", ['@label' => $label, '@type' => $node_type]);
$values['source']['node_type'] = $node_type;
$migration = Migration::create($values);
$fields = $this->getSourcePlugin('d6_field_instance', ['node_type' => $node_type] + $template['source']);
foreach ($fields as $field) {
$data = $field->getSource();
if ($this->cckPluginManager->hasDefinition($data['type'])) {
$this->getCckPlugin($data['type'])
->processCckFieldValues($migration, $data['field_name'], $data);
}
else {
$migration->setProcessOfProperty($data['field_name'], $data['field_name']);
}
}
$migrations[] = $migration;
}
return $migrations;
}
}

View file

@ -0,0 +1,52 @@
<?php
/**
* @file
* Contains \Drupal\node\Plugin\migrate\builder\d7\Node.
*/
namespace Drupal\node\Plugin\migrate\builder\d7;
use Drupal\migrate\Entity\Migration;
use Drupal\migrate\Plugin\migrate\builder\BuilderBase;
/**
* @PluginID("d7_node")
*/
class Node extends BuilderBase {
/**
* {@inheritdoc}
*/
public function buildMigrations(array $template) {
$migrations = [];
$fields = [];
foreach ($this->getSourcePlugin('d7_field_instance', $template['source']) as $field) {
$entity_type = $field->getSourceProperty('entity_type');
$bundle = $field->getSourceProperty('bundle');
$field_name = $field->getSourceProperty('field_name');
$fields[$entity_type][$bundle][$field_name] = $field->getSource();
}
foreach ($this->getSourcePlugin('d7_node_type', $template['source']) as $node_type) {
$bundle = $node_type->getSourceProperty('type');
$values = $template;
$values['id'] .= '__' . $bundle;
$values['label'] = $this->t('@label (@type)', ['@label' => $values['label'], '@type' => $node_type->getSourceProperty('name')]);
$values['source']['node_type'] = $bundle;
$migration = Migration::create($values);
if (isset($fields['node'][$bundle])) {
foreach (array_keys($fields['node'][$bundle]) as $field) {
$migration->setProcessOfProperty($field, $field);
}
}
$migrations[] = $migration;
}
return $migrations;
}
}

View file

@ -0,0 +1,32 @@
<?php
/**
* @file
* Contains \Drupal\node\Plugin\migrate\destination\EntityNodeType.
*/
namespace Drupal\node\Plugin\migrate\destination;
use Drupal\migrate\Plugin\migrate\destination\EntityConfigBase;
use Drupal\migrate\Row;
/**
* @MigrateDestination(
* id = "entity:node_type"
* )
*/
class EntityNodeType extends EntityConfigBase {
/**
* {@inheritdoc}
*/
public function import(Row $row, array $old_destination_id_values = array()) {
$entity_ids = parent::import($row, $old_destination_id_values);
if ($row->getDestinationProperty('create_body')) {
$node_type = $this->storage->load(reset($entity_ids));
node_add_body_field($node_type, $row->getDestinationProperty('create_body_label'));
}
return $entity_ids;
}
}

View file

@ -8,7 +8,6 @@
namespace Drupal\node\Plugin\migrate\source\d6;
use Drupal\migrate\Row;
use Drupal\migrate\Plugin\SourceEntityInterface;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
@ -18,7 +17,7 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
* id = "d6_node"
* )
*/
class Node extends DrupalSqlBase implements SourceEntityInterface {
class Node extends DrupalSqlBase {
/**
* The join options between the node and the node_revisions table.
@ -32,6 +31,13 @@ class Node extends DrupalSqlBase implements SourceEntityInterface {
*/
protected $filterDefaultFormat;
/**
* Cached field and field instance definitions.
*
* @var array
*/
protected $fieldInfo;
/**
* {@inheritdoc}
*/
@ -115,9 +121,132 @@ class Node extends DrupalSqlBase implements SourceEntityInterface {
if ($row->getSourceProperty('format') === '0') {
$row->setSourceProperty('format', $this->filterDefaultFormat);
}
if ($this->moduleExists('content') && $this->getModuleSchemaVersion('content') >= 6001) {
foreach ($this->getFieldValues($row) as $field => $values) {
$row->setSourceProperty($field, $values);
}
}
return parent::prepareRow($row);
}
/**
* Gets CCK field values for a node.
*
* @param \Drupal\migrate\Row $node
* The node.
*
* @return array
* CCK field values, keyed by field name.
*/
protected function getFieldValues(Row $node) {
$values = [];
foreach ($this->getFieldInfo($node->getSourceProperty('type')) as $field => $info) {
$values[$field] = $this->getCckData($info, $node);
}
return $values;
}
/**
* Gets CCK field and instance definitions from the database.
*
* @param string $node_type
* The node type for which to get field info.
*
* @return array
* Field and instance information for the node type, keyed by field name.
*/
protected function getFieldInfo($node_type) {
if (!isset($this->fieldInfo)) {
$this->fieldInfo = [];
// Query the database directly for all CCK field info.
$query = $this->select('content_node_field_instance', 'cnfi');
$query->join('content_node_field', 'cnf', 'cnf.field_name = cnfi.field_name');
$query->fields('cnfi');
$query->fields('cnf');
foreach ($query->execute() as $field) {
$this->fieldInfo[ $field['type_name'] ][ $field['field_name'] ] = $field;
}
foreach ($this->fieldInfo as $type => $fields) {
foreach ($fields as $field => $info) {
foreach ($info as $property => $value) {
if ($property == 'db_columns' || preg_match('/_settings$/', $property)) {
$this->fieldInfo[$type][$field][$property] = unserialize($value);
}
}
}
}
}
return isset($this->fieldInfo[$node_type]) ? $this->fieldInfo[$node_type] : [];
}
/**
* Retrieves raw CCK field data for a node.
*
* @param array $field
* A field and instance definition from getFieldInfo().
* @param \Drupal\migrate\Row $node
* The node.
*
* @return array
* The field values, keyed by delta.
*/
protected function getCckData(array $field, Row $node) {
$field_table = 'content_' . $field['field_name'];
$node_table = 'content_type_' . $node->getSourceProperty('type');
/** @var \Drupal\Core\Database\Schema $db */
$db = $this->getDatabase()->schema();
if ($db->tableExists($field_table)) {
$query = $this->select($field_table, 't');
// If the delta column does not exist, add it as an expression to
// normalize the query results.
if ($db->fieldExists($field_table, 'delta')) {
$query->addField('t', 'delta');
}
else {
$query->addExpression(0, 'delta');
}
}
elseif ($db->tableExists($node_table)) {
$query = $this->select($node_table, 't');
// Every row should have a delta of 0.
$query->addExpression(0, 'delta');
}
if (isset($query)) {
$columns = array_keys($field['db_columns']);
// Add every column in the field's schema.
foreach ($columns as $column) {
$query->addField('t', $field['field_name'] . '_' . $column, $column);
}
return $query
// This call to isNotNull() is a kludge which relies on the convention
// that CCK field schemas usually define their most important
// column first. A better way would be to allow cckfield plugins to
// alter the query directly before it's run, but this will do for
// the time being.
->isNotNull($field['field_name'] . '_' . $columns[0])
->condition('nid', $node->getSourceProperty('nid'))
->condition('vid', $node->getSourceProperty('vid'))
->execute()
->fetchAllAssoc('delta');
}
else {
return [];
}
}
/**
* {@inheritdoc}
*/
@ -127,18 +256,4 @@ class Node extends DrupalSqlBase implements SourceEntityInterface {
return $ids;
}
/**
* {@inheritdoc}
*/
public function bundleMigrationRequired() {
return FALSE;
}
/**
* {@inheritdoc}
*/
public function entityTypeId() {
return 'node';
}
}

View file

@ -0,0 +1,109 @@
<?php
/**
* @file
* Contains \Drupal\node\Plugin\migrate\source\d7\Node.
*/
namespace Drupal\node\Plugin\migrate\source\d7;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\migrate\source\d7\FieldableEntity;
/**
* Drupal 7 node source from database.
*
* @MigrateSource(
* id = "d7_node",
* source_provider = "node"
* )
*/
class Node extends FieldableEntity {
/**
* The join options between the node and the node_revisions table.
*/
const JOIN = 'n.vid = nr.vid';
/**
* {@inheritdoc}
*/
public function query() {
// Select node in its last revision.
$query = $this->select('node_revision', 'nr')
->fields('n', array(
'nid',
'type',
'language',
'status',
'created',
'changed',
'comment',
'promote',
'sticky',
'tnid',
'translate',
))
->fields('nr', array(
'vid',
'title',
'log',
'timestamp',
));
$query->addField('n', 'uid', 'node_uid');
$query->addField('nr', 'uid', 'revision_uid');
$query->innerJoin('node', 'n', static::JOIN);
if (isset($this->configuration['node_type'])) {
$query->condition('type', $this->configuration['node_type']);
}
return $query;
}
/**
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
// Get Field API field values.
foreach (array_keys($this->getFields('node', $row->getSourceProperty('type'))) as $field) {
$nid = $row->getSourceProperty('nid');
$vid = $row->getSourceProperty('vid');
$row->setSourceProperty($field, $this->getFieldValues('node', $field, $nid, $vid));
}
return parent::prepareRow($row);
}
/**
* {@inheritdoc}
*/
public function fields() {
$fields = array(
'nid' => $this->t('Node ID'),
'type' => $this->t('Type'),
'title' => $this->t('Title'),
'node_uid' => $this->t('Node authored by (uid)'),
'revision_uid' => $this->t('Revision authored by (uid)'),
'created' => $this->t('Created timestamp'),
'changed' => $this->t('Modified timestamp'),
'status' => $this->t('Published'),
'promote' => $this->t('Promoted to front page'),
'sticky' => $this->t('Sticky at top of lists'),
'revision' => $this->t('Create new revision'),
'language' => $this->t('Language (fr, en, ...)'),
'tnid' => $this->t('The translation set id for this node'),
'timestamp' => $this->t('The timestamp the latest revision of this node was created.'),
);
return $fields;
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['nid']['type'] = 'integer';
$ids['nid']['alias'] = 'n';
return $ids;
}
}

View file

@ -0,0 +1,46 @@
<?php
/**
* @file
* Contains \Drupal\node\Plugin\migrate\source\d7\NodeRevision.
*/
namespace Drupal\node\Plugin\migrate\source\d7;
/**
* Drupal 7 node revision source from database.
*
* @MigrateSource(
* id = "d7_node_revision",
* source_provider = "node"
* )
*/
class NodeRevision extends Node {
/**
* The join options between the node and the node_revisions_table.
*/
const JOIN = 'n.nid = nr.nid AND n.vid <> nr.vid';
/**
* {@inheritdoc}
*/
public function fields() {
// Use all the node fields plus the vid that identifies the version.
return parent::fields() + array(
'vid' => t('The primary identifier for this version.'),
'log' => $this->t('Revision Log message'),
'timestamp' => $this->t('Revision timestamp'),
);
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['vid']['type'] = 'integer';
$ids['vid']['alias'] = 'nr';
return $ids;
}
}

View file

@ -0,0 +1,120 @@
<?php
/**
* @file
* Contains \Drupal\node\Plugin\migrate\source\d7\NodeType.
*/
namespace Drupal\node\Plugin\migrate\source\d7;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
* Drupal 7 Node types source from database.
*
* @MigrateSource(
* id = "d7_node_type",
* source_provider = "node"
* )
*/
class NodeType extends DrupalSqlBase {
/**
* The teaser length
*
* @var int
*/
protected $teaserLength;
/**
* Node preview optional / required.
*
* @var int
*/
protected $nodePreview;
/**
* {@inheritdoc}
*/
public function query() {
return $this->select('node_type', 't')->fields('t');
}
/**
* {@inheritdoc}
*/
public function fields() {
return array(
'type' => $this->t('Machine name of the node type.'),
'name' => $this->t('Human name of the node type.'),
'description' => $this->t('Description of the node type.'),
'help' => $this->t('Help text for the node type.'),
'title_label' => $this->t('Title label.'),
'disabled' => $this->t('Flag indicating the node type is enable'),
'base' => $this->t('base node.'),
'custom' => $this->t('Flag.'),
'modified' => $this->t('Flag.'),
'locked' => $this->t('Flag.'),
'orig_type' => $this->t('The original type.'),
'teaser_length' => $this->t('Teaser length'),
);
}
/**
* {@inheritdoc}
*/
protected function initializeIterator() {
$this->teaserLength = $this->variableGet('teaser_length', 600);
$this->nodePreview = $this->variableGet('node_preview', 0);
return parent::initializeIterator();
}
/**
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
$row->setSourceProperty('teaser_length', $this->teaserLength);
$row->setSourceProperty('node_preview', $this->nodePreview);
$type = $row->getSourceProperty('type');
$source_options = $this->variableGet('node_options_' . $type, array('promote', 'sticky'));
$options = array();
foreach (array('promote', 'sticky', 'status', 'revision') as $item) {
$options[$item] = in_array($item, $source_options);
}
$row->setSourceProperty('options', $options);
// Don't create a body field until we prove that this node type has one.
$row->setSourceProperty('create_body', FALSE);
if ($this->moduleExists('field')) {
// Find body field for this node type.
$body = $this->select('field_config_instance', 'fci')
->fields('fci', array('data'))
->condition('entity_type', 'node')
->condition('bundle', $row->getSourceProperty('type'))
->condition('field_name', 'body')
->execute()
->fetchAssoc();
if ($body) {
$row->setSourceProperty('create_body', TRUE);
$body['data'] = unserialize($body['data']);
$row->setSourceProperty('body_label', $body['data']['label']);
}
}
$row->setSourceProperty('display_submitted', $this->variableGet('node_submitted_' . $type, TRUE));
return parent::prepareRow($row);
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['type']['type'] = 'string';
return $ids;
}
}

View file

@ -7,7 +7,6 @@
namespace Drupal\node\Plugin\views\argument;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\node\NodeStorageInterface;
use Drupal\views\Plugin\views\argument\NumericArgument;
use Symfony\Component\DependencyInjection\ContainerInterface;
@ -62,7 +61,7 @@ class Nid extends NumericArgument {
$nodes = $this->nodeStorage->loadMultiple($this->value);
foreach ($nodes as $node) {
$titles[] = SafeMarkup::checkPlain($node->label());
$titles[] = $node->label();
}
return $titles;
}

View file

@ -7,7 +7,6 @@
namespace Drupal\node\Plugin\views\argument;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Database\Connection;
use Drupal\views\Plugin\views\argument\NumericArgument;
use Symfony\Component\DependencyInjection\ContainerInterface;
@ -84,7 +83,7 @@ class Vid extends NumericArgument {
foreach ($results as $result) {
$nodes[$result['nid']]->set('title', $result['title']);
$titles[] = SafeMarkup::checkPlain($nodes[$result['nid']]->label());
$titles[] = $nodes[$result['nid']]->label();
}
return $titles;

View file

@ -84,7 +84,11 @@ class NodeRevision extends WizardPluginBase {
$display_options['fields']['changed']['alter']['html'] = FALSE;
$display_options['fields']['changed']['hide_empty'] = FALSE;
$display_options['fields']['changed']['empty_zero'] = FALSE;
$display_options['fields']['changed']['plugin_id'] = 'date';
$display_options['fields']['changed']['plugin_id'] = 'field';
$display_options['fields']['changed']['type'] = 'timestamp';
$display_options['fields']['changed']['settings']['date_format'] = 'medium';
$display_options['fields']['changed']['settings']['custom_date_format'] = '';
$display_options['fields']['changed']['settings']['timezone'] = '';
/* Field: Content revision: Title */
$display_options['fields']['title']['id'] = 'title';

View file

@ -0,0 +1,75 @@
<?php
/**
* @file
* Contains \Drupal\node\Tests\Migrate\d6\MigrateNodeBuilderTest.
*/
namespace Drupal\node\Tests\Migrate\d6;
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
use Drupal\migrate\Entity\Migration;
/**
* @group migrate_drupal_6
*/
class MigrateNodeBuilderTest extends MigrateDrupal6TestBase {
public static $modules = ['migrate', 'migrate_drupal', 'node'];
/**
* Asserts various aspects of a migration entity.
*
* @param string $id
* The migration ID.
* @param string $label
* The label.
*/
protected function assertEntity($id, $label) {
$migration = Migration::load($id);
$this->assertTrue($migration instanceof Migration);
$this->assertIdentical($id, $migration->Id());
$this->assertIdentical($label, $migration->label());
}
/**
* Tests creating migrations from a template, using a builder plugin.
*/
public function testCreateMigrations() {
$templates = [
'd6_node' => [
'id' => 'd6_node',
'label' => 'Drupal 6 nodes',
'builder' => [
'plugin' => 'd6_node',
],
'source' => [
'plugin' => 'd6_node',
],
'process' => [
'nid' => 'nid',
'vid' => 'vid',
'uid' => 'uid',
],
'destination' => [
'plugin' => 'entity:node',
],
],
];
$migrations = \Drupal::service('migrate.migration_builder')->createMigrations($templates);
$this->assertIdentical(11, count($migrations));
$this->assertEntity('d6_node__article', 'Drupal 6 nodes (article)');
$this->assertEntity('d6_node__company', 'Drupal 6 nodes (company)');
$this->assertEntity('d6_node__employee', 'Drupal 6 nodes (employee)');
$this->assertEntity('d6_node__event', 'Drupal 6 nodes (event)');
$this->assertEntity('d6_node__page', 'Drupal 6 nodes (page)');
$this->assertEntity('d6_node__sponsor', 'Drupal 6 nodes (sponsor)');
$this->assertEntity('d6_node__story', 'Drupal 6 nodes (story)');
$this->assertEntity('d6_node__test_event', 'Drupal 6 nodes (test_event)');
$this->assertEntity('d6_node__test_page', 'Drupal 6 nodes (test_page)');
$this->assertEntity('d6_node__test_planet', 'Drupal 6 nodes (test_planet)');
$this->assertEntity('d6_node__test_story', 'Drupal 6 nodes (test_story)');
}
}

View file

@ -12,7 +12,7 @@ use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
/**
* Test migrating node settings into the base_field_bundle_override config entity.
*
* @group node
* @group migrate_drupal_6
*/
class MigrateNodeBundleSettingsTest extends MigrateDrupal6TestBase {
@ -57,7 +57,6 @@ class MigrateNodeBundleSettingsTest extends MigrateDrupal6TestBase {
);
$this->prepareMigrations($id_mappings);
$this->loadDumps(['NodeType.php', 'Variable.php']);
$this->executeMigration('d6_node_setting_promote');
$this->executeMigration('d6_node_setting_status');
$this->executeMigration('d6_node_setting_sticky');

View file

@ -13,7 +13,7 @@ use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
/**
* Upgrade variables to node.settings.yml.
*
* @group node
* @group migrate_drupal_6
*/
class MigrateNodeConfigsTest extends MigrateDrupal6TestBase {
@ -31,7 +31,6 @@ class MigrateNodeConfigsTest extends MigrateDrupal6TestBase {
*/
protected function setUp() {
parent::setUp();
$this->loadDumps(['Variable.php']);
$this->executeMigration('d6_node_settings');
}

View file

@ -8,11 +8,12 @@
namespace Drupal\node\Tests\Migrate\d6;
use Drupal\Core\Database\Database;
use Drupal\migrate\Entity\Migration;
/**
* Node content revisions migration.
*
* @group node
* @group migrate_drupal_6
*/
class MigrateNodeRevisionTest extends MigrateNodeTestBase {
@ -23,14 +24,12 @@ class MigrateNodeRevisionTest extends MigrateNodeTestBase {
parent::setUp();
$id_mappings = array(
'd6_node' => array(
'd6_node:*' => array(
array(array(1), array(1)),
),
);
$this->prepareMigrations($id_mappings);
$this->loadDumps(['Users.php']);
// Create our users for the node authors.
$query = Database::getConnection('default', 'migrate')->query('SELECT * FROM {users} WHERE uid NOT IN (0, 1)');
while(($row = $query->fetchAssoc()) !== FALSE) {
@ -39,7 +38,8 @@ class MigrateNodeRevisionTest extends MigrateNodeTestBase {
$user->save();
}
$this->executeMigration('d6_node_revision');
$migrations = Migration::loadMultiple(['d6_node_revision:*']);
array_walk($migrations, [$this, 'executeMigration']);
}
/**

View file

@ -7,14 +7,14 @@
namespace Drupal\node\Tests\Migrate\d6;
use Drupal\migrate\MigrateExecutable;
use Drupal\migrate\Entity\Migration;
use Drupal\Core\Database\Database;
use Drupal\node\Entity\Node;
/**
* Node content migration.
*
* @group node
* @group migrate_drupal_6
*/
class MigrateNodeTest extends MigrateNodeTestBase {
@ -23,13 +23,13 @@ class MigrateNodeTest extends MigrateNodeTestBase {
*/
protected function setUp() {
parent::setUp();
/** @var \Drupal\migrate\entity\Migration $migration */
$migration = entity_load('migration', 'd6_node');
$executable = new MigrateExecutable($migration, $this);
$executable->import();
// Each node type is imported separately. In this test, we're asserting
// on story and test_planet nodes.
$this->executeMigration('d6_node__test_planet');
$this->executeMigration('d6_node__story');
// This is required for the second import below.
db_truncate($migration->getIdMap()->mapTableName())->execute();
\Drupal::database()->truncate(Migration::load('d6_node__story')->getIdMap()->mapTableName())->execute();
$this->standalone = TRUE;
}
@ -55,7 +55,7 @@ class MigrateNodeTest extends MigrateNodeTestBase {
$this->assertIdentical('Test title', $node_revision->getTitle());
$this->assertIdentical('1', $node_revision->getRevisionAuthor()->id(), 'Node revision has the correct user');
// This is empty on the first revision.
$this->assertIdentical('', $node_revision->revision_log->value);
$this->assertIdentical(NULL, $node_revision->revision_log->value);
// It is pointless to run the second half from MigrateDrupal6Test.
if (empty($this->standalone)) {
@ -75,10 +75,8 @@ class MigrateNodeTest extends MigrateNodeTestBase {
->condition('delta', 1)
->execute();
/** @var \Drupal\migrate\entity\Migration $migration */
$migration = entity_load('migration', 'd6_node');
$executable = new MigrateExecutable($migration, $this);
$executable->import();
$migration = Migration::load('d6_node__story');
$this->executeMigration($migration);
$node = Node::load(1);
$this->assertIdentical('New node title', $node->getTitle());

View file

@ -82,6 +82,7 @@ abstract class MigrateNodeTestBase extends MigrateDrupal6TestBase {
'nid' => 1,
'vid' => 1,
'revision_log' => '',
'title' => $this->randomString(),
));
$node->enforceIsNew();
$node->save();
@ -91,23 +92,10 @@ abstract class MigrateNodeTestBase extends MigrateDrupal6TestBase {
'nid' => 3,
'vid' => 4,
'revision_log' => '',
'title' => $this->randomString(),
));
$node->enforceIsNew();
$node->save();
$this->loadDumps([
'Node.php',
'NodeRevisions.php',
'ContentTypeStory.php',
'ContentTypeTestPlanet.php',
'NodeType.php',
'Variable.php',
'ContentNodeFieldInstance.php',
'ContentNodeField.php',
'ContentFieldTest.php',
'ContentFieldTestTwo.php',
'ContentFieldMultivalue.php',
]);
}
}

View file

@ -14,7 +14,7 @@ use Drupal\node\Entity\NodeType;
/**
* Upgrade node types to node.type.*.yml.
*
* @group node
* @group migrate_drupal_6
*/
class MigrateNodeTypeTest extends MigrateDrupal6TestBase {
@ -30,9 +30,7 @@ class MigrateNodeTypeTest extends MigrateDrupal6TestBase {
*/
protected function setUp() {
parent::setUp();
$this->installConfig(array('node'));
$this->loadDumps(['NodeType.php', 'Variable.php']);
$this->executeMigration('d6_node_type');
}

View file

@ -13,7 +13,7 @@ use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
/**
* Migrate view modes.
*
* @group node
* @group migrate_drupal_6
*/
class MigrateViewModesTest extends MigrateDrupal6TestBase {
@ -29,13 +29,6 @@ class MigrateViewModesTest extends MigrateDrupal6TestBase {
*/
protected function setUp() {
parent::setUp();
$this->loadDumps([
'ContentNodeFieldInstance.php',
'ContentNodeField.php',
'ContentFieldTest.php',
'ContentFieldTestTwo.php',
'ContentFieldMultivalue.php',
]);
$this->executeMigration('d6_view_modes');
}

View file

@ -0,0 +1,45 @@
<?php
/**
* @file
* Contains \Drupal\node\Tests\Migrate\d7\MigrateNodeSettingsTest.
*/
namespace Drupal\node\Tests\Migrate\d7;
use Drupal\config\Tests\SchemaCheckTestTrait;
use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
/**
* Upgrade variables to node.settings config object.
*
* @group node
*/
class MigrateNodeSettingsTest extends MigrateDrupal7TestBase {
use SchemaCheckTestTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['node'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigration('d7_node_settings');
}
/**
* Tests migration of node variables to node.settings config object.
*/
public function testAggregatorSettings() {
$config = $this->config('node.settings');
$this->assertEqual(1, $config->get('use_admin_theme'));
}
}

View file

@ -0,0 +1,112 @@
<?php
/**
* @file
* Contains \Drupal\node\Tests\Migrate\d7\MigrateNodeTest.
*/
namespace Drupal\node\Tests\Migrate\d7;
use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
use Drupal\node\Entity\Node;
use Drupal\node\NodeInterface;
/**
* Tests node migration.
*
* @group node
*/
class MigrateNodeTest extends MigrateDrupal7TestBase {
static $modules = array('node', 'text', 'filter', 'entity_reference');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('node');
$this->installConfig(['node']);
$this->installSchema('node', ['node_access']);
$this->installSchema('system', ['sequences']);
$this->executeMigration('d7_user_role');
$this->executeMigration('d7_user');
$this->executeMigration('d7_node_type');
$this->executeMigration('d7_node__test_content_type');
}
/**
* Asserts various aspects of a node.
*
* @param string $id
* The node ID.
* @param string $type
* The node type.
* @param string $langcode
* The expected language code.
* @param string $title
* The expected title.
* @param int $uid
* The expected author ID.
* @param bool $status
* The expected status of the node.
* @param int $created
* The expected creation time.
* @param int $changed
* The expected modification time.
* @param bool $promoted
* Whether the node is expected to be promoted to the front page.
* @param bool $sticky
* Whether the node is expected to be sticky.
*/
protected function assertEntity($id, $type, $langcode, $title, $uid, $status, $created, $changed, $promoted, $sticky) {
/** @var \Drupal\node\NodeInterface $node */
$node = Node::load($id);
$this->assertTrue($node instanceof NodeInterface);
$this->assertIdentical($type, $node->getType());
$this->assertIdentical($langcode, $node->langcode->value);
$this->assertIdentical($title, $node->getTitle());
$this->assertIdentical($uid, $node->getOwnerId());
$this->assertIdentical($status, $node->isPublished());
$this->assertIdentical($created, $node->getCreatedTime());
if (isset($changed)) {
$this->assertIdentical($changed, $node->getChangedTime());
}
$this->assertIdentical($promoted, $node->isPromoted());
$this->assertIdentical($sticky, $node->isSticky());
}
/**
* Asserts various aspects of a node revision.
*
* @param int $id
* The revision ID.
* @param string $title
* The expected title.
* @param int $uid
* The revision author ID.
* @param string $log
* The revision log message.
* @param int $timestamp
* The revision's time stamp.
*/
protected function assertRevision($id, $title, $uid, $log, $timestamp) {
$revision = \Drupal::entityManager()->getStorage('node')->loadRevision($id);
$this->assertTrue($revision instanceof NodeInterface);
$this->assertIdentical($title, $revision->getTitle());
$this->assertIdentical($uid, $revision->getRevisionAuthor()->id());
$this->assertIdentical($log, $revision->revision_log->value);
$this->assertIdentical($timestamp, $revision->getRevisionCreationTime());
}
/**
* Test node migration from Drupal 7 to 8.
*/
public function testNode() {
$this->assertEntity(1, 'test_content_type', 'en', 'A Node', '2', TRUE, '1421727515', '1441032132', TRUE, FALSE);
$this->assertRevision(1, 'A Node', '2', NULL, '1441032132');
}
}

View file

@ -0,0 +1,60 @@
<?php
/**
* @file
* Contains \Drupal\node\Tests\Migrate\d7\MigrateNodeTitleLabelTest.
*/
namespace Drupal\node\Tests\Migrate\d7;
use Drupal\Core\Field\Entity\BaseFieldOverride;
use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
/**
* Tests migration of the title field label for node types.
*
* @group node
*/
class MigrateNodeTitleLabelTest extends MigrateDrupal7TestBase {
public static $modules = ['node', 'text'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig(static::$modules);
$this->installEntitySchema('node');
$this->executeMigration('d7_node_type');
$this->executeMigration('d7_node_title_label');
}
/**
* Asserts various aspects of a base_field_override entity.
*
* @param string $id
* The override ID.
* @param string $label
* The label's expected (overridden) value.
*/
protected function assertEntity($id, $label) {
$override = BaseFieldOverride::load($id);
$this->assertTrue($override instanceof BaseFieldOverride);
/** @var \Drupal\Core\Field\Entity\BaseFieldOverride $override */
$this->assertIdentical($label, $override->getLabel());
}
/**
* Tests migration of node title field overrides.
*/
public function testMigration() {
$this->assertEntity('node.article.title', 'Title');
$this->assertEntity('node.blog.title', 'Title');
$this->assertEntity('node.book.title', 'Title');
$this->assertEntity('node.forum.title', 'Subject');
$this->assertEntity('node.page.title', 'Title');
$this->assertEntity('node.test_content_type.title', 'Title');
}
}

View file

@ -0,0 +1,85 @@
<?php
/**
* @file
* Contains \Drupal\node\Tests\Migrate\d7\MigrateNodeTypeTest.
*/
namespace Drupal\node\Tests\Migrate\d7;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\FieldConfigInterface;
use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
use Drupal\node\Entity\NodeType;
use Drupal\node\NodeTypeInterface;
/**
* Upgrade node types to node.type.*.yml.
*
* @group node
*/
class MigrateNodeTypeTest extends MigrateDrupal7TestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('node', 'text', 'filter');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig(array('node'));
$this->executeMigration('d7_node_type');
}
/**
* Tests a single node type.
*
* @dataProvider testNodeTypeDataProvider
* @param string $id
* The node type ID.
* @param string $label
* The expected label.
* @param string $description
* The expected node type description.
* @param string $help
* The expected help text.
*/
protected function assertEntity($id, $label, $description, $help, $display_submitted, $new_revision, $body_label = NULL) {
/** @var \Drupal\node\NodeTypeInterface $entity */
$entity = NodeType::load($id);
$this->assertTrue($entity instanceof NodeTypeInterface);
$this->assertIdentical($label, $entity->label());
$this->assertIdentical($description, $entity->getDescription());
$this->assertIdentical($help, $entity->getHelp());
$this->assertIdentical($display_submitted, $entity->displaySubmitted(), 'Submission info is displayed');
$this->assertIdentical($new_revision, $entity->isNewRevision(), 'Is a new revision');
if ($body_label) {
/** @var \Drupal\field\FieldConfigInterface $body */
$body = FieldConfig::load('node.' . $id . '.body');
$this->assertTrue($body instanceof FieldConfigInterface);
$this->assertIdentical($body_label, $body->label());
}
}
/**
* Tests Drupal 7 node type to Drupal 8 migration.
*/
public function testNodeType() {
$this->assertEntity('article', 'Article', 'Use <em>articles</em> for time-sensitive content like news, press releases or blog posts.', 'Help text for articles', TRUE, FALSE, "Body");
$this->assertEntity('blog', 'Blog entry', 'Use for multi-user blogs. Every user gets a personal blog.', 'Blog away, good sir!', TRUE, FALSE, 'Body');
// book's display_submitted flag is not set, so it will default to TRUE.
$this->assertEntity('book', 'Book page', '<em>Books</em> have a built-in hierarchical navigation. Use for handbooks or tutorials.', '', TRUE, TRUE, "Body");
$this->assertEntity('forum', 'Forum topic', 'A <em>forum topic</em> starts a new discussion thread within a forum.', 'No name-calling, no flame wars. Be nice.', TRUE, FALSE, 'Body');
$this->assertEntity('page', 'Basic page', "Use <em>basic pages</em> for your static content, such as an 'About us' page.", 'Help text for basic pages', FALSE, FALSE, "Body");
// This node type does not carry a body field.
$this->assertEntity('test_content_type', 'Test content type', 'This is the description of the test content type.', 'Help text for test content type', FALSE, TRUE);
}
}

View file

@ -0,0 +1,41 @@
<?php
/**
* @file
* Contains \Drupal\node\Tests\Migrate\d7\NodeBuilderTest.
*/
namespace Drupal\node\Tests\Migrate\d7;
use Drupal\migrate\Entity\Migration;
use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
/**
* Tests the d7_node builder.
*
* @group node
*/
class NodeBuilderTest extends MigrateDrupal7TestBase {
public static $modules = ['node'];
public function testBuilder() {
$process = Migration::load('d7_node__test_content_type')->getProcess();
$this->assertIdentical('field_boolean', $process['field_boolean'][0]['source']);
$this->assertIdentical('field_email', $process['field_email'][0]['source']);
$this->assertIdentical('field_phone', $process['field_phone'][0]['source']);
$this->assertIdentical('field_date', $process['field_date'][0]['source']);
$this->assertIdentical('field_date_with_end_time', $process['field_date_with_end_time'][0]['source']);
$this->assertIdentical('field_file', $process['field_file'][0]['source']);
$this->assertIdentical('field_float', $process['field_float'][0]['source']);
$this->assertIdentical('field_images', $process['field_images'][0]['source']);
$this->assertIdentical('field_integer', $process['field_integer'][0]['source']);
$this->assertIdentical('field_link', $process['field_link'][0]['source']);
$this->assertIdentical('field_text_list', $process['field_text_list'][0]['source']);
$this->assertIdentical('field_integer_list', $process['field_integer_list'][0]['source']);
$this->assertIdentical('field_long_text', $process['field_long_text'][0]['source']);
$this->assertIdentical('field_term_reference', $process['field_term_reference'][0]['source']);
$this->assertIdentical('field_text', $process['field_text'][0]['source']);
}
}

View file

@ -111,6 +111,7 @@ class NodeAccessLanguageAwareCombinationTest extends NodeTestBase {
'private' => FALSE,
));
$translation = $node->getTranslation('ca');
$translation->title->value = $this->randomString();
$translation->field_private->value = 0;
$node->save();
@ -121,6 +122,7 @@ class NodeAccessLanguageAwareCombinationTest extends NodeTestBase {
'private' => TRUE,
));
$translation = $node->getTranslation('ca');
$translation->title->value = $this->randomString();
$translation->field_private->value = 0;
$node->save();
@ -131,6 +133,7 @@ class NodeAccessLanguageAwareCombinationTest extends NodeTestBase {
'private' => FALSE,
));
$translation = $node->getTranslation('ca');
$translation->title->value = $this->randomString();
$translation->field_private->value = 0;
$node->save();
@ -141,6 +144,7 @@ class NodeAccessLanguageAwareCombinationTest extends NodeTestBase {
'private' => FALSE,
));
$translation = $node->getTranslation('ca');
$translation->title->value = $this->randomString();
$translation->field_private->value = 1;
$node->save();
@ -151,6 +155,7 @@ class NodeAccessLanguageAwareCombinationTest extends NodeTestBase {
'private' => FALSE,
));
$translation = $node->getTranslation('ca');
$translation->title->value = $this->randomString();
$translation->field_private->value = 1;
$node->save();
@ -161,6 +166,7 @@ class NodeAccessLanguageAwareCombinationTest extends NodeTestBase {
'private' => TRUE,
));
$translation = $node->getTranslation('ca');
$translation->title->value = $this->randomString();
$translation->field_private->value = 1;
$node->save();

View file

@ -104,6 +104,7 @@ class NodeAccessLanguageAwareTest extends NodeTestBase {
'field_private' => array(array('value' => 0)),
));
$translation = $node->getTranslation('ca');
$translation->title->value = $this->randomString();
$translation->field_private->value = 0;
$node->save();
@ -113,6 +114,7 @@ class NodeAccessLanguageAwareTest extends NodeTestBase {
'field_private' => array(array('value' => 0)),
));
$translation = $node->getTranslation('ca');
$translation->title->value = $this->randomString();
$translation->field_private->value = 1;
$node->save();
@ -122,6 +124,7 @@ class NodeAccessLanguageAwareTest extends NodeTestBase {
'field_private' => array(array('value' => 1)),
));
$translation = $node->getTranslation('ca');
$translation->title->value = $this->randomString();
$translation->field_private->value = 0;
$node->save();
@ -131,6 +134,7 @@ class NodeAccessLanguageAwareTest extends NodeTestBase {
'field_private' => array(array('value' => 1)),
));
$translation = $node->getTranslation('ca');
$translation->title->value = $this->randomString();
$translation->field_private->value = 1;
$node->save();

View file

@ -0,0 +1,77 @@
<?php
/**
* @file
* Contains \Drupal\node\Tests\NodeAccessMenuLinkTest.
*/
namespace Drupal\node\Tests;
use Drupal\user\RoleInterface;
/**
* Tests the interaction of the node access system with menu links.
*
* @group node
*/
class NodeAccessMenuLinkTest extends NodeTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('menu_ui', 'block');
/**
* A user with permission to manage menu links and create nodes.
*
* @var \Drupal\user\UserInterface
*/
protected $contentAdminUser;
protected function setUp() {
parent::setUp();
$this->drupalPlaceBlock('system_menu_block:main');
$this->contentAdminUser = $this->drupalCreateUser(array(
'access content',
'administer content types',
'administer menu'
));
$this->config('user.role.' . RoleInterface::ANONYMOUS_ID)->set('permissions', array())->save();
}
/**
* SA-CORE-2015-003: Tests menu links to nodes when node access is restricted.
*/
function testNodeAccessMenuLink() {
$menu_link_title = $this->randomString();
$this->drupalLogin($this->contentAdminUser);
$edit = [
'title[0][value]' => $this->randomString(),
'body[0][value]' => $this->randomString(),
'menu[enabled]' => 1,
'menu[title]' => $menu_link_title,
];
$this->drupalPostForm('node/add/page', $edit, t('Save'));
$this->assertLink($menu_link_title);
// Ensure anonymous users without "access content" permission do not see
// this menu link.
$this->drupalLogout();
$this->drupalGet('');
$this->assertNoLink($menu_link_title);
// Ensure anonymous users with "access content" permission see this menu
// link.
$this->config('user.role.' . RoleInterface::ANONYMOUS_ID)->set('permissions', array('access content'))->save();
$this->drupalGet('');
$this->assertLink($menu_link_title);
}
}

View file

@ -8,6 +8,7 @@
namespace Drupal\node\Tests;
use Drupal\block\Entity\Block;
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
use Drupal\user\RoleInterface;
@ -100,17 +101,11 @@ class NodeBlockFunctionalTest extends NodeTestBase {
$this->assertText($node3->label(), 'Node found in block.');
// Check to make sure nodes are in the right order.
$this->assertTrue($this->xpath('//div[@id="block-test-block"]//table/tbody/tr[position() = 1]/td/a[text() = "' . $node3->label() . '"]'), 'Nodes were ordered correctly in block.');
$this->assertTrue($this->xpath('//div[@id="block-test-block"]//div[@class="item-list"]/ul/li[1]/div/span/a[text() = "' . $node3->label() . '"]'), 'Nodes were ordered correctly in block.');
$this->drupalLogout();
$this->drupalLogin($this->adminUser);
// Verify that the More link is shown and leads to the admin content page.
$this->drupalGet('');
$this->clickLink('More');
$this->assertResponse('200');
$this->assertUrl('admin/content');
// Set the number of recent nodes to show to 10.
$block->getPlugin()->setConfigurationValue('items_per_page', 10);
$block->save();
@ -125,7 +120,7 @@ class NodeBlockFunctionalTest extends NodeTestBase {
$this->assertText($node3->label(), 'Node found in block.');
$this->assertText($node4->label(), 'Node found in block.');
$this->assertCacheContexts(['languages:language_content', 'languages:language_interface', 'theme', 'user']);
$this->assertCacheContexts(['languages:language_content', 'languages:language_interface', 'theme', 'url.query_args:' . MainContentViewSubscriber::WRAPPER_FORMAT, 'user']);
// Enable the "Powered by Drupal" block only on article nodes.
$edit = [
@ -150,16 +145,16 @@ class NodeBlockFunctionalTest extends NodeTestBase {
$this->drupalGet('');
$label = $block->label();
$this->assertNoText($label, 'Block was not displayed on the front page.');
$this->assertCacheContexts(['languages:language_content', 'languages:language_interface', 'theme', 'user', 'route']);
$this->assertCacheContexts(['languages:language_content', 'languages:language_interface', 'theme', 'url.query_args:' . MainContentViewSubscriber::WRAPPER_FORMAT, 'user', 'route']);
$this->drupalGet('node/add/article');
$this->assertText($label, 'Block was displayed on the node/add/article page.');
$this->assertCacheContexts(['languages:language_content', 'languages:language_interface', 'theme', 'user', 'route']);
$this->assertCacheContexts(['languages:language_content', 'languages:language_interface', 'theme', 'url.path', 'url.query_args', 'user', 'route']);
$this->drupalGet('node/' . $node1->id());
$this->assertText($label, 'Block was displayed on the node/N when node is of type article.');
$this->assertCacheContexts(['languages:language_content', 'languages:language_interface', 'theme', 'user', 'route', 'timezone']);
$this->assertCacheContexts(['languages:language_content', 'languages:language_interface', 'theme', 'url.query_args:' . MainContentViewSubscriber::WRAPPER_FORMAT, 'user', 'route', 'timezone']);
$this->drupalGet('node/' . $node5->id());
$this->assertNoText($label, 'Block was not displayed on nodes of type page.');
$this->assertCacheContexts(['languages:language_content', 'languages:language_interface', 'theme', 'user', 'route', 'timezone']);
$this->assertCacheContexts(['languages:language_content', 'languages:language_interface', 'theme', 'url.query_args:' . MainContentViewSubscriber::WRAPPER_FORMAT, 'user', 'route', 'timezone']);
$this->drupalLogin($this->adminUser);
$this->drupalGet('admin/structure/block');

View file

@ -203,7 +203,7 @@ class NodeCreationTest extends NodeTestBase {
$query = db_query("SELECT wid, variables FROM {watchdog}");
foreach ($query as $row) {
$variables = (array) unserialize($row->variables);
if (isset($variables['!message']) && $variables['!message'] === 'Test exception for rollback.') {
if (isset($variables['@message']) && $variables['@message'] === 'Test exception for rollback.') {
$matches[] = $row->wid;
}
}

View file

@ -8,6 +8,7 @@
namespace Drupal\node\Tests;
use Drupal\comment\Tests\CommentTestTrait;
use Drupal\Component\Utility\Html;
/**
* Tests node title.
@ -85,5 +86,22 @@ class NodeTitleTest extends NodeTestBase {
// Test that 0 appears in the template <h1>.
$xpath = '//h1';
$this->assertEqual(current($this->xpath($xpath)), 0, 'Node title is displayed as 0.', 'Node');
// Test edge case where node title contains special characters.
$edge_case_title = 'article\'s "title".';
$settings = array(
'title' => $edge_case_title,
);
$node = $this->drupalCreateNode($settings);
// Test that the title appears as <title>. The title will be escaped on the
// the page.
$edge_case_title_escaped = Html::escape($edge_case_title);
$this->drupalGet('node/' . $node->id());
$this->assertTitle($edge_case_title_escaped . ' | Drupal', 'Page title is equal to article\'s "title".', 'Node');
// Test that the title appears as <title> when reloading the node page.
$this->drupalGet('node/' . $node->id());
$this->assertTitle($edge_case_title_escaped . ' | Drupal', 'Page title is equal to article\'s "title".', 'Node');
}
}

View file

@ -7,6 +7,8 @@
namespace Drupal\node\Tests;
use Drupal\Component\Utility\Html;
/**
* Create a node with dangerous tags in its title and test that they are
* escaped.
@ -34,8 +36,8 @@ class NodeTitleXSSTest extends NodeTestBase {
$node = $this->drupalCreateNode($settings);
$this->drupalGet('node/' . $node->id());
// assertTitle() decodes HTML-entities inside the <title> element.
$this->assertTitle($title . ' | Drupal', 'Title is displayed when viewing a node.');
// Titles should be escaped.
$this->assertTitle(Html::escape($title) . ' | Drupal', 'Title is displayed when viewing a node.');
$this->assertNoRaw($xss, 'Harmful tags are escaped when viewing a node.');
$this->drupalGet('node/' . $node->id() . '/edit');

View file

@ -7,9 +7,9 @@
namespace Drupal\node\Tests;
use Drupal\Component\Utility\Html;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\system\Tests\System\TokenReplaceUnitTestBase;
use Drupal\Component\Utility\SafeMarkup;
/**
* Generates text using placeholders for dummy content to check node token
@ -65,15 +65,15 @@ class NodeTokenReplaceTest extends TokenReplaceUnitTestBase {
$tests['[node:vid]'] = $node->getRevisionId();
$tests['[node:type]'] = 'article';
$tests['[node:type-name]'] = 'Article';
$tests['[node:title]'] = SafeMarkup::checkPlain($node->getTitle());
$tests['[node:title]'] = Html::escape($node->getTitle());
$tests['[node:body]'] = $node->body->processed;
$tests['[node:summary]'] = $node->body->summary_processed;
$tests['[node:langcode]'] = SafeMarkup::checkPlain($node->language()->getId());
$tests['[node:langcode]'] = Html::escape($node->language()->getId());
$tests['[node:url]'] = $node->url('canonical', $url_options);
$tests['[node:edit-url]'] = $node->url('edit-form', $url_options);
$tests['[node:author]'] = SafeMarkup::checkPlain($account->getUsername());
$tests['[node:author]'] = Html::escape($account->getUsername());
$tests['[node:author:uid]'] = $node->getOwnerId();
$tests['[node:author:name]'] = SafeMarkup::checkPlain($account->getUsername());
$tests['[node:author:name]'] = Html::escape($account->getUsername());
$tests['[node:created:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($node->getCreatedTime(), array('langcode' => $this->interfaceLanguage->getId()));
$tests['[node:changed:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($node->getChangedTime(), array('langcode' => $this->interfaceLanguage->getId()));

View file

@ -27,13 +27,14 @@ class NodeTranslationUITest extends ContentTranslationUITestBase {
protected $defaultCacheContexts = [
'languages:language_interface',
'theme',
'user.permissions',
'route.name',
'route.menu_active_trails:account',
'route.menu_active_trails:footer',
'route.menu_active_trails:main',
'route.menu_active_trails:tools',
'timezone',
'user.roles'
'url',
'user'
];
/**

View file

@ -55,6 +55,11 @@ class NodeValidationTest extends EntityUnitTestBase {
$this->assertEqual($violations[0]->getPropertyPath(), 'title');
$this->assertEqual($violations[0]->getMessage(), 'This value should not be null.');
$node->set('title', '');
$violations = $node->validate();
$this->assertEqual(count($violations), 1, 'Violation found when title is set to an empty string.');
$this->assertEqual($violations[0]->getPropertyPath(), 'title');
// Make the title valid again.
$node->set('title', $this->randomString());
// Save the node so that it gets an ID and a changed date.

View file

@ -41,7 +41,7 @@ class NodeViewTest extends NodeTestBase {
$this->assertTrue(mb_strlen($title, 'utf-8') < strlen($title), 'Title has multi-byte characters.');
$node = $this->drupalCreateNode(array('title' => $title));
$this->drupalGet($node->urlInfo());
$result = $this->xpath('//span[contains(@class, "field-name-title")]');
$result = $this->xpath('//span[contains(@class, "field--name-title")]');
$this->assertEqual((string) $result[0], $title, 'The passed title was returned.');
}

View file

@ -16,11 +16,19 @@ class PageEditTest extends NodeTestBase {
protected $webUser;
protected $adminUser;
/**
* Modules to enable.
*
* @var string[]
*/
public static $modules = ['block', 'node', 'datetime'];
protected function setUp() {
parent::setUp();
$this->webUser = $this->drupalCreateUser(array('edit own page content', 'create page content'));
$this->adminUser = $this->drupalCreateUser(array('bypass node access', 'administer nodes'));
$this->drupalPlaceBlock('local_tasks_block');
}
/**

View file

@ -7,6 +7,7 @@
namespace Drupal\node\Tests;
use Drupal\comment\Tests\CommentTestTrait;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Language\LanguageInterface;
@ -21,13 +22,14 @@ use Drupal\node\Entity\NodeType;
class PagePreviewTest extends NodeTestBase {
use EntityReferenceTestTrait;
use CommentTestTrait;
/**
* Enable the node and taxonomy modules to test both on the preview.
* Enable the comment, node and taxonomy modules to test on the preview.
*
* @var array
*/
public static $modules = array('node', 'taxonomy');
public static $modules = array('node', 'taxonomy', 'comment');
/**
* The name of the created field.
@ -38,6 +40,7 @@ class PagePreviewTest extends NodeTestBase {
protected function setUp() {
parent::setUp();
$this->addDefaultCommentField('node', 'page');
$web_user = $this->drupalCreateUser(array('edit own page content', 'create page content'));
$this->drupalLogin($web_user);
@ -139,6 +142,14 @@ class PagePreviewTest extends NodeTestBase {
$this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
$this->assertFieldByName($term_key, $edit[$term_key] . ' (' . $this->term->id() . ')', 'Term field displayed.');
// Return to page preview to check everything is as expected.
$this->drupalPostForm(NULL, array(), t('Preview'));
$this->assertTitle(t('@title | Drupal', array('@title' => $edit[$title_key])), 'Basic page title is preview.');
$this->assertText($edit[$title_key], 'Title displayed.');
$this->assertText($edit[$body_key], 'Body displayed.');
$this->assertText($edit[$term_key], 'Term displayed.');
$this->assertLink(t('Back to content editing'));
// Assert the content is kept when reloading the page.
$this->drupalGet('node/add/page', array('query' => array('uuid' => $uuid)));
$this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');

View file

@ -0,0 +1,68 @@
<?php
/**
* @file
* Contains \Drupal\node\Tests\NodeFieldTokensTest.
*/
namespace Drupal\node\Tests\Views;
use Drupal\views\Views;
use Drupal\node\Tests\Views\NodeTestBase;
/**
* Tests replacement of Views tokens supplied by the Node module.
*
* @group node
* @see \Drupal\node\Tests\NodeTokenReplaceTest
*/
class NodeFieldTokensTest extends NodeTestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = array('test_node_tokens');
/**
* Tests token replacement for Views tokens supplied by the Node module.
*/
public function testViewsTokenReplacement() {
// Create the Article content type with a standard body field.
/* @var $node_type \Drupal\node\NodeTypeInterface */
$node_type = entity_create('node_type', ['type' => 'article', 'name' => 'Article']);
$node_type->save();
node_add_body_field($node_type);
// Create a user and a node.
$account = $this->createUser();
$body = $this->randomMachineName(32);
$summary = $this->randomMachineName(16);
/** @var $node \Drupal\node\NodeInterface */
$node = entity_create('node', [
'type' => 'article',
'tnid' => 0,
'uid' => $account->id(),
'title' => 'Testing Views tokens',
'body' => [['value' => $body, 'summary' => $summary, 'format' => 'plain_text']],
]);
$node->save();
$this->drupalGet('test_node_tokens');
// Body: {{ body }}<br />
$this->assertRaw("Body: <p>$body</p>");
// Raw value: {{ body__value }}<br />
$this->assertRaw("Raw value: $body");
// Raw summary: {{ body__summary }}<br />
$this->assertRaw("Raw summary: $summary");
// Raw format: {{ body__format }}<br />
$this->assertRaw("Raw format: plain_text");
}
}

View file

@ -7,6 +7,7 @@
namespace Drupal\node\Tests\Views;
use Drupal\Core\Language\LanguageInterface;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\views\Plugin\views\PluginBase;
@ -65,6 +66,9 @@ class NodeLanguageTest extends NodeTestBase {
// "English", or "Spanish", as there is a language field in the view
// that prints out those words.
$this->nodeTitles = array(
LanguageInterface::LANGCODE_NOT_SPECIFIED => array(
'First node und',
),
'es' => array(
'Primero nodo es',
'Segundo nodo es',
@ -90,6 +94,13 @@ class NodeLanguageTest extends NodeTestBase {
}
$node->save();
}
// Create non-translatable nodes.
foreach ($this->nodeTitles[LanguageInterface::LANGCODE_NOT_SPECIFIED] as $index => $title) {
$node = $this->drupalCreateNode(array('title' => $title, 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED, 'type' => 'page', 'promote' => 1));
$node->body->value = $this->randomMachineName(32);
$node->save();
}
$this->container->get('router.builder')->rebuild();
$user = $this->drupalCreateUser(array('access content overview', 'access content'));
@ -146,6 +157,10 @@ class NodeLanguageTest extends NodeTestBase {
// Test the front page view filter. Only node titles in the current language
// should be displayed on the front page by default.
foreach ($this->nodeTitles as $langcode => $titles) {
// The frontpage view does not display content without a language.
if ($langcode == LanguageInterface::LANGCODE_NOT_SPECIFIED) {
continue;
}
$this->drupalGet(($langcode == 'en' ? '' : "$langcode/") . 'node');
foreach ($titles as $title) {
$this->assertText($title);
@ -188,6 +203,9 @@ class NodeLanguageTest extends NodeTestBase {
$config->set('display.default.display_options.filters.langcode.value', array(PluginBase::VIEWS_QUERY_LANGUAGE_SITE_DEFAULT => PluginBase::VIEWS_QUERY_LANGUAGE_SITE_DEFAULT));
$config->save();
foreach ($this->nodeTitles as $langcode => $titles) {
if ($langcode == LanguageInterface::LANGCODE_NOT_SPECIFIED) {
continue;
}
$this->drupalGet(($langcode == 'en' ? '' : "$langcode/") . 'node');
foreach ($this->nodeTitles as $control_langcode => $control_titles) {
foreach ($control_titles as $title) {

View file

@ -26,7 +26,7 @@ class NodeRevisionWizardTest extends WizardTestBase {
// Create two nodes with two revision.
$node_storage = \Drupal::entityManager()->getStorage('node');
/** @var \Drupal\node\NodeInterface $node */
$node = $node_storage->create(array('type' => 'article', 'created' => REQUEST_TIME + 40));
$node = $node_storage->create(array('title' => $this->randomString(), 'type' => 'article', 'created' => REQUEST_TIME + 40));
$node->save();
$node = $node->createDuplicate();
@ -34,7 +34,7 @@ class NodeRevisionWizardTest extends WizardTestBase {
$node->created->value = REQUEST_TIME + 20;
$node->save();
$node = $node_storage->create(array('type' => 'article', 'created' => REQUEST_TIME + 30));
$node = $node_storage->create(array('title' => $this->randomString(), 'type' => 'article', 'created' => REQUEST_TIME + 30));
$node->save();
$node = $node->createDuplicate();