Update to Drupal 8.0.0 beta 14. For more information, see https://drupal.org/node/2544542

This commit is contained in:
Pantheon Automation 2015-08-27 12:03:05 -07:00 committed by Greg Anderson
parent 3b2511d96d
commit 81ccda77eb
2155 changed files with 54307 additions and 46870 deletions

View file

@ -0,0 +1,42 @@
migrate.source.d6_view_mode:
type: migrate_source_sql
label: 'Drupal 6 view mode'
mapping:
constants:
type: mapping
label: 'Constants'
mapping:
targetEntityType:
type: string
label: 'Target entity type'
status:
type: boolean
label: 'Status'
migrate.source.d6_node_type:
type: migrate_source_sql
label: 'Drupal 6 node type'
mapping:
constants:
type: migrate_entity_constant
label: 'Constants'
migrate.source.d6_node:
type: migrate_source_sql
label: 'Drupal 6 node'
mapping:
node_type:
# The node type can be specified both as a string ID of a node type or an
# array of node type IDs, so there is no way to consistently parse this.
type: ignore
label: 'Node type'
migrate.source.d6_node_revision:
type: migrate_source_sql
label: 'Drupal 6 node'
mapping:
node_type:
# The node type can be specified both as a string ID of a node type or an
# array of node type IDs, so there is no way to consistently parse this.
type: ignore
label: 'Node type'

View file

@ -0,0 +1,55 @@
id: d6_node
label: Drupal 6 nodes
migration_tags:
- Drupal 6
source:
plugin: d6_node
process:
nid: nid
vid: vid
type: type
langcode:
plugin: default_value
source: language
default_value: "und"
title: title
uid: node_uid
# Core migrations are designed for replacing the upgrade path and therefore
# all node and user ids are preserved. For that reason we do not need to look-up
# the user id for the node. If you're writing a custom migration, user ids will
# vary from the source site and a lookup as shown below will be required.
# plugin: migration
# migration: d6_user
# source: node_uid
status: status
created: created
changed: changed
promote: promote
sticky: sticky
'body/format':
plugin: migration
migration: d6_filter_format
source: format
'body/value': body
'body/summary': teaser
revision_uid: revision_uid
revision_log: log
revision_timestamp: timestamp
# unmapped d6 fields.
# tnid
# translate
# moderate
# comment
destination:
plugin: entity:node
migration_dependencies:
required:
- d6_user
- d6_node_type
- d6_node_settings
- d6_filter_format
optional:
- d6_field_instance_widget_settings
- d6_field_formatter_settings

View file

@ -0,0 +1,42 @@
id: d6_node_revision
label: Drupal 6 node revisions
migration_tags:
- Drupal 6
source:
plugin: d6_node_revision
process:
nid: nid
vid: vid
type: type
langcode:
plugin: default_value
source: language
default_value: "und"
title: title
uid: node_uid
status: status
created: created
changed: changed
promote: promote
sticky: sticky
'body/format':
plugin: migration
migration: d6_filter_format
source: format
'body/value': body
'body/summary': teaser
revision_uid: revision_uid
revision_log: log
revision_timestamp: timestamp
# unmapped d6 fields.
# tnid
# translate
# moderate
# comment
destination:
plugin: entity_revision:node
migration_dependencies:
required:
- d6_node

View file

@ -0,0 +1,19 @@
id: d6_node_setting_promote
label: Drupal 6 node type 'promote' setting
migration_tags:
- Drupal 6
source:
plugin: d6_node_type
constants:
entity_type: node
field_name: promote
process:
entity_type: 'constants/entity_type'
bundle: type
field_name: 'constants/field_name'
'default_value/0/value': 'options/promote'
destination:
plugin: entity:base_field_override
migration_dependencies:
required:
- d6_node_type

View file

@ -0,0 +1,19 @@
id: d6_node_setting_status
label: Drupal 6 node type 'status' setting
migration_tags:
- Drupal 6
source:
plugin: d6_node_type
constants:
entity_type: node
field_name: status
process:
entity_type: 'constants/entity_type'
bundle: type
field_name: 'constants/field_name'
'default_value/0/value': 'options/status'
destination:
plugin: entity:base_field_override
migration_dependencies:
required:
- d6_node_type

View file

@ -0,0 +1,19 @@
id: d6_node_setting_sticky
label: Drupal 6 node type 'sticky' setting
migration_tags:
- Drupal 6
source:
plugin: d6_node_type
constants:
entity_type: node
field_name: sticky
process:
entity_type: 'constants/entity_type'
bundle: type
field_name: 'constants/field_name'
'default_value/0/value': 'options/sticky'
destination:
plugin: entity:base_field_override
migration_dependencies:
required:
- d6_node_type

View file

@ -0,0 +1,13 @@
id: d6_node_settings
label: Drupal 6 node configuration
migration_tags:
- Drupal 6
source:
plugin: variable
variables:
- node_admin_theme
process:
use_admin_theme: node_admin_theme
destination:
plugin: config
config_name: node.settings

View file

@ -0,0 +1,24 @@
id: d6_node_type
label: Drupal 6 node type configuration
migration_tags:
- Drupal 6
source:
plugin: d6_node_type
constants:
preview: 1 # DRUPAL_OPTIONAL
create_body: false
process:
type: type
name: name
module: module
description: description
help: help
title_label: title_label
'preview_mode': 'constants/preview'
'display_submitted': display_submitted
'new_revision': 'options/revision'
'settings/node/options': options
create_body: has_body
create_body_label: body_label
destination:
plugin: entity:node_type

View file

@ -0,0 +1,39 @@
id: d6_view_modes
label: Drupal 6 view modes
migration_tags:
- Drupal 6
source:
plugin: d6_view_mode
constants:
targetEntityType: node
status: true
process:
mode:
plugin: static_map
source: view_mode
map:
0: normal
1: preview
2: search_index
3: search_result
4: rss
5: print
teaser: teaser
full: full
label:
plugin: static_map
source: view_mode
map:
0: "Normal"
1: "Preview"
2: "Search index"
3: "Search result"
4: "RSS"
5: "Print"
teaser: "Teaser"
full: "Full"
targetEntityType: 'constants/targetEntityType'
status: 'constants/status'
destination:
plugin: entity:entity_view_mode

View file

@ -508,7 +508,9 @@ function template_preprocess_node_add_list(&$variables) {
$variables['types'][$type->id()] = array(
'type' => $type->id(),
'add_link' => \Drupal::l($type->label(), new Url('node.add', array('node_type' => $type->id()))),
'description' => Xss::filterAdmin($type->getDescription()),
'description' => array(
'#markup' => $type->getDescription(),
),
);
}
}

View file

@ -45,3 +45,8 @@ services:
arguments: ['@current_user']
tags:
- { name: cache.context }
node.node_route_context:
class: Drupal\node\ContextProvider\NodeRouteContext
arguments: ['@current_route_match']
tags:
- { name: 'context_provider' }

View file

@ -6,7 +6,9 @@
*/
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Datetime\Entity\DateFormat;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\user\Entity\User;
/**
@ -83,7 +85,7 @@ function node_token_info() {
/**
* Implements hook_tokens().
*/
function node_tokens($type, $tokens, array $data = array(), array $options = array()) {
function node_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {
$token_service = \Drupal::token();
$url_options = array('absolute' => TRUE);
@ -176,29 +178,34 @@ function node_tokens($type, $tokens, array $data = array(), array $options = arr
// Default values for the chained tokens handled below.
case 'author':
$account = $node->getOwner() ? $node->getOwner() : User::load(0);
$bubbleable_metadata->addCacheableDependency($account);
$replacements[$original] = $sanitize ? SafeMarkup::checkPlain($account->label()) : $account->label();
break;
case 'created':
$date_format = DateFormat::load('medium');
$bubbleable_metadata->addCacheableDependency($date_format);
$replacements[$original] = format_date($node->getCreatedTime(), 'medium', '', NULL, $langcode);
break;
case 'changed':
$date_format = DateFormat::load('medium');
$bubbleable_metadata->addCacheableDependency($date_format);
$replacements[$original] = format_date($node->getChangedTime(), 'medium', '', NULL, $langcode);
break;
}
}
if ($author_tokens = $token_service->findWithPrefix($tokens, 'author')) {
$replacements += $token_service->generate('user', $author_tokens, array('user' => $node->getOwner()), $options);
$replacements += $token_service->generate('user', $author_tokens, array('user' => $node->getOwner()), $options, $bubbleable_metadata);
}
if ($created_tokens = $token_service->findWithPrefix($tokens, 'created')) {
$replacements += $token_service->generate('date', $created_tokens, array('date' => $node->getCreatedTime()), $options);
$replacements += $token_service->generate('date', $created_tokens, array('date' => $node->getCreatedTime()), $options, $bubbleable_metadata);
}
if ($changed_tokens = $token_service->findWithPrefix($tokens, 'changed')) {
$replacements += $token_service->generate('date', $changed_tokens, array('date' => $node->getChangedTime()), $options);
$replacements += $token_service->generate('date', $changed_tokens, array('date' => $node->getChangedTime()), $options, $bubbleable_metadata);
}
}

View file

@ -7,18 +7,23 @@
namespace Drupal\node\Cache;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\Context\CalculatedCacheContextInterface;
use Drupal\Core\Cache\Context\UserCacheContext;
use Drupal\Core\Cache\Context\UserCacheContextBase;
/**
* Defines the node access view cache context service.
*
* Cache context ID: 'user.node_grants' (to vary by all operations' grants).
* Calculated cache context ID: 'user.node_grants:%operation', e.g.
* 'user.node_grants:view' (to vary by the view operation's grants).
*
* This allows for node access grants-sensitive caching when listing nodes.
*
* @see node_query_node_access_alter()
* @ingroup node_access
*/
class NodeAccessGrantsCacheContext extends UserCacheContext implements CalculatedCacheContextInterface {
class NodeAccessGrantsCacheContext extends UserCacheContextBase implements CalculatedCacheContextInterface {
/**
* {@inheritdoc}
@ -78,4 +83,24 @@ class NodeAccessGrantsCacheContext extends UserCacheContext implements Calculate
return $operation . '.' . implode(';', $grants_context_parts);
}
/**
* {@inheritdoc}
*/
public function getCacheableMetadata($operation = NULL) {
$cacheable_metadata = new CacheableMetadata();
if (!\Drupal::moduleHandler()->getImplementations('node_grants')) {
return $cacheable_metadata;
}
// The node grants may change if the user is updated. (The max-age is set to
// zero below, but sites may override this cache context, and change it to a
// non-zero value. In such cases, this cache tag is needed for correctness.)
$cacheable_metadata->setCacheTags(['user:' . $this->user->id()]);
// If the site is using node grants, this cache context can not be
// optimized.
return $cacheable_metadata->setCacheMaxAge(0);
}
}

View file

@ -0,0 +1,70 @@
<?php
/**
* @file
* Contains \Drupal\node\ContextProvider\NodeRouteContext.
*/
namespace Drupal\node\ContextProvider;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Core\Plugin\Context\ContextProviderInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\node\Entity\Node;
/**
* Sets the current node as a context on node routes.
*/
class NodeRouteContext implements ContextProviderInterface {
/**
* The route match object.
*
* @var \Drupal\Core\Routing\RouteMatchInterface
*/
protected $routeMatch;
/**
* Constructs a new NodeRouteContext.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match object.
*/
public function __construct(RouteMatchInterface $route_match) {
$this->routeMatch = $route_match;
}
/**
* {@inheritdoc}
*/
public function getRuntimeContexts(array $unqualified_context_ids) {
$result = [];
$context = new Context(new ContextDefinition('entity:node', NULL, FALSE));
if (($route_object = $this->routeMatch->getRouteObject()) && ($route_contexts = $route_object->getOption('parameters')) && isset($route_contexts['node'])) {
if ($node = $this->routeMatch->getParameter('node')) {
$context->setContextValue($node);
}
}
elseif ($this->routeMatch->getRouteName() == 'node.add') {
$node_type = $this->routeMatch->getParameter('node_type');
$context->setContextValue(Node::create(array('type' => $node_type->id())));
}
$cacheability = new CacheableMetadata();
$cacheability->setCacheContexts(['route']);
$context->addCacheableDependency($cacheability);
$result['node'] = $context;
return $result;
}
/**
* {@inheritdoc}
*/
public function getAvailableContexts() {
$context = new Context(new ContextDefinition('entity:node'));
return ['node' => $context];
}
}

View file

@ -8,7 +8,6 @@
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;
@ -172,53 +171,69 @@ class NodeController extends ControllerBase implements ContainerInjectionInterfa
$vids = $node_storage->revisionIds($node);
foreach (array_reverse($vids) as $vid) {
if ($revision = $node_storage->loadRevision($vid)) {
$row = array();
$revision = $node_storage->loadRevision($vid);
$username = [
'#theme' => 'username',
'#account' => $revision->uid->entity,
];
$revision_author = $revision->uid->entity;
if ($vid == $node->getRevisionId()) {
$username = array(
'#theme' => 'username',
'#account' => $revision_author,
);
$row[] = array('data' => $this->t('!date by !username', array('!date' => $node->link($this->dateFormatter->format($revision->revision_timestamp->value, 'short')), '!username' => drupal_render($username)))
. (($revision->revision_log->value != '') ? '<p class="revision-log">' . Xss::filter($revision->revision_log->value) . '</p>' : ''),
'class' => array('revision-current'));
$row[] = array('data' => SafeMarkup::placeholder($this->t('current revision')), 'class' => array('revision-current'));
}
else {
$username = array(
'#theme' => 'username',
'#account' => $revision_author,
);
$row[] = $this->t('!date by !username', array('!date' => $this->l($this->dateFormatter->format($revision->revision_timestamp->value, 'short'), new Url('entity.node.revision', array('node' => $node->id(), 'node_revision' => $vid))), '!username' => drupal_render($username)))
. (($revision->revision_log->value != '') ? '<p class="revision-log">' . Xss::filter($revision->revision_log->value) . '</p>' : '');
if ($revert_permission) {
$links['revert'] = array(
'title' => $this->t('Revert'),
'url' => Url::fromRoute('node.revision_revert_confirm', ['node' => $node->id(), 'node_revision' => $vid]),
);
}
if ($delete_permission) {
$links['delete'] = array(
'title' => $this->t('Delete'),
'url' => Url::fromRoute('node.revision_delete_confirm', ['node' => $node->id(), 'node_revision' => $vid]),
);
}
$row[] = array(
'data' => array(
'#type' => 'operations',
'#links' => $links,
),
);
}
$rows[] = $row;
// Use revision link to link to revisions that are not active.
$date = $this->dateFormatter->format($revision->revision_timestamp->value, 'short');
if ($vid != $node->getRevisionId()) {
$link = $this->l($date, new Url('entity.node.revision', ['node' => $node->id(), 'node_revision' => $vid]));
}
else {
$link = $node->link($date);
}
$row = [];
$column = [
'data' => [
'#type' => 'inline_template',
'#template' => '{% trans %}{{ date }} by {{ username }}{% endtrans %}{% if message %}<p class="revision-log">{{ message }}</p>{% endif %}',
'#context' => [
'date' => $link,
'username' => $this->renderer->renderPlain($username),
'message' => SafeMarkup::xssFilter($revision->revision_log->value),
],
],
];
// @todo Simplify once https://www.drupal.org/node/2334319 lands.
$this->renderer->addCacheableDependency($column['data'], $username);
$row[] = $column;
if ($vid == $node->getRevisionId()) {
$row[0]['class'] = ['revision-current'];
$row[] = [
'data' => SafeMarkup::placeholder($this->t('current revision')),
'class' => ['revision-current'],
];
}
else {
$links = [];
if ($revert_permission) {
$links['revert'] = [
'title' => $this->t('Revert'),
'url' => Url::fromRoute('node.revision_revert_confirm', ['node' => $node->id(), 'node_revision' => $vid]),
];
}
if ($delete_permission) {
$links['delete'] = [
'title' => $this->t('Delete'),
'url' => Url::fromRoute('node.revision_delete_confirm', ['node' => $node->id(), 'node_revision' => $vid]),
];
}
$row[] = [
'data' => [
'#type' => 'operations',
'#links' => $links,
],
];
}
$rows[] = $row;
}
$build['node_revisions_table'] = array(

View file

@ -57,7 +57,7 @@ class NodeViewController extends EntityViewController {
* The page title.
*/
public function title(EntityInterface $node) {
return SafeMarkup::checkPlain($this->entityManager->getTranslationFromContext($node)->label());
return $this->entityManager->getTranslationFromContext($node)->label();
}
}

View file

@ -53,7 +53,9 @@ use Drupal\user\UserInterface;
* "bundle" = "type",
* "label" = "title",
* "langcode" = "langcode",
* "uuid" = "uuid"
* "uuid" = "uuid",
* "status" = "status",
* "uid" = "uid",
* },
* bundle_entity_type = "node_type",
* field_ui_base_route = "entity.node_type.edit_form",
@ -72,6 +74,17 @@ class Node extends ContentEntityBase implements NodeInterface {
use EntityChangedTrait;
/**
* Whether the node is being previewed or not.
*
* The variable is set to public as it will give a considerable performance
* improvement. See https://www.drupal.org/node/2498919.
*
* @var true|null
* TRUE if the node is being previewed and NULL if it is not.
*/
public $in_preview = NULL;
/**
* {@inheritdoc}
*/
@ -258,7 +271,7 @@ class Node extends ContentEntityBase implements NodeInterface {
* {@inheritdoc}
*/
public function isPublished() {
return (bool) $this->get('status')->value;
return (bool) $this->getEntityKey('status');
}
/**
@ -280,7 +293,7 @@ class Node extends ContentEntityBase implements NodeInterface {
* {@inheritdoc}
*/
public function getOwnerId() {
return $this->get('uid')->target_id;
return $this->getEntityKey('uid');
}
/**

View file

@ -32,7 +32,6 @@ interface NodeAccessControlHandlerInterface {
*/
public function acquireGrants(NodeInterface $node);
/**
* Writes a list of grants to the database, deleting any previously saved ones.
*
@ -46,12 +45,6 @@ interface NodeAccessControlHandlerInterface {
*
* @param \Drupal\node\NodeInterface $node
* The node whose grants are being written.
* @param $grants
* A list of grants to write. See hook_node_access_records() for the
* expected structure of the grants array.
* @param $realm
* (optional) If provided, read/write grants for that realm only. Defaults to
* NULL.
* @param $delete
* (optional) If false, does not delete records. This is only for optimization
* purposes, and assumes the caller has already performed a mass delete of

View file

@ -7,7 +7,6 @@
namespace Drupal\node;
use Drupal\Component\Utility\Html;
use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Form\FormStateInterface;
@ -204,9 +203,32 @@ class NodeForm extends ContentEntityForm {
$form['#attached']['library'][] = 'node/form';
$form['#entity_builders']['update_status'] = [$this, 'updateStatus'];
return $form;
}
/**
* Entity builder updating the node status with the submitted value.
*
* @param string $entity_type_id
* The entity type identifier.
* @param \Drupal\node\NodeInterface $node
* The node updated with the submitted values.
* @param array $form
* The complete form array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*
* @see \Drupal\node\NodeForm::form()
*/
function updateStatus($entity_type_id, NodeInterface $node, array $form, FormStateInterface $form_state) {
$element = $form_state->getTriggeringElement();
if (isset($element['#published_status'])) {
$node->setPublished($element['#published_status']);
}
}
/**
* {@inheritdoc}
*/
@ -232,6 +254,8 @@ class NodeForm extends ContentEntityForm {
// Add a "Publish" button.
$element['publish'] = $element['submit'];
// If the "Publish" button is clicked, we want to update the status to "published".
$element['publish']['#published_status'] = TRUE;
$element['publish']['#dropbutton'] = 'save';
if ($node->isNew()) {
$element['publish']['#value'] = t('Save and publish');
@ -240,10 +264,11 @@ class NodeForm extends ContentEntityForm {
$element['publish']['#value'] = $node->isPublished() ? t('Save and keep published') : t('Save and publish');
}
$element['publish']['#weight'] = 0;
array_unshift($element['publish']['#submit'], '::publish');
// Add a "Unpublish" button.
$element['unpublish'] = $element['submit'];
// If the "Unpublish" button is clicked, we want to update the status to "unpublished".
$element['unpublish']['#published_status'] = FALSE;
$element['unpublish']['#dropbutton'] = 'save';
if ($node->isNew()) {
$element['unpublish']['#value'] = t('Save as unpublished');
@ -252,7 +277,6 @@ class NodeForm extends ContentEntityForm {
$element['unpublish']['#value'] = !$node->isPublished() ? t('Save and keep unpublished') : t('Save and unpublish');
}
$element['unpublish']['#weight'] = 10;
array_unshift($element['unpublish']['#submit'], '::unpublish');
// If already published, the 'publish' button is primary.
if ($node->isPublished()) {
@ -273,7 +297,6 @@ class NodeForm extends ContentEntityForm {
'#access' => $preview_mode != DRUPAL_DISABLED && ($node->access('create') || $node->access('update')),
'#value' => t('Preview'),
'#weight' => 20,
'#validate' => array('::validate'),
'#submit' => array('::submitForm', '::preview'),
);
@ -327,34 +350,6 @@ class NodeForm extends ContentEntityForm {
));
}
/**
* Form submission handler for the 'publish' action.
*
* @param $form
* An associative array containing the structure of the form.
* @param $form_state
* The current state of the form.
*/
public function publish(array $form, FormStateInterface $form_state) {
$node = $this->entity;
$node->setPublished(TRUE);
return $node;
}
/**
* Form submission handler for the 'unpublish' action.
*
* @param $form
* An associative array containing the structure of the form.
* @param $form_state
* The current state of the form.
*/
public function unpublish(array $form, FormStateInterface $form_state) {
$node = $this->entity;
$node->setPublished(FALSE);
return $node;
}
/**
* {@inheritdoc}
*/

View file

@ -22,22 +22,12 @@ class NodeStorageSchema extends SqlContentEntityStorageSchema {
protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $reset = FALSE) {
$schema = parent::getEntitySchema($entity_type, $reset);
// Marking the respective fields as NOT NULL makes the indexes more
// performant.
$schema['node_field_data']['fields']['default_langcode']['not null'] = TRUE;
$schema['node_field_revision']['fields']['default_langcode']['not null'] = TRUE;
$schema['node_field_data']['indexes'] += array(
'node__default_langcode' => array('default_langcode'),
'node__frontpage' => array('promote', 'status', 'sticky', 'created'),
'node__status_type' => array('status', 'type', 'nid'),
'node__title_type' => array('title', array('type', 4)),
);
$schema['node_field_revision']['indexes'] += array(
'node__default_langcode' => array('default_langcode'),
);
return $schema;
}
@ -73,7 +63,6 @@ class NodeStorageSchema extends SqlContentEntityStorageSchema {
case 'changed':
case 'created':
case 'langcode':
// @todo Revisit index definitions:
// https://www.drupal.org/node/2015277.
$this->addSharedTableFieldIndex($storage_definition, $schema, TRUE);
@ -81,14 +70,6 @@ class NodeStorageSchema extends SqlContentEntityStorageSchema {
}
}
if ($table_name == 'node_field_revision') {
switch ($field_name) {
case 'langcode':
$this->addSharedTableFieldIndex($storage_definition, $schema, TRUE);
break;
}
}
return $schema;
}

View file

@ -7,8 +7,8 @@
namespace Drupal\node;
use Drupal\Core\Entity\EntityInterface;
use Drupal\content_translation\ContentTranslationHandler;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
/**
@ -76,9 +76,8 @@ class NodeTranslationHandler extends ContentTranslationHandler {
*/
public function entityFormEntityBuild($entity_type, EntityInterface $entity, array $form, FormStateInterface $form_state) {
if ($form_state->hasValue('content_translation')) {
$form_object = $form_state->getFormObject();
$translation = &$form_state->getValue('content_translation');
$translation['status'] = $form_object->getEntity()->isPublished();
$translation['status'] = $entity->isPublished();
// $form['content_translation']['name'] is the equivalent field
// for translation author uid.
$account = $entity->uid->entity;

View file

@ -204,8 +204,8 @@ class NodeTypeForm extends EntityForm {
/**
* {@inheritdoc}
*/
public function validate(array $form, FormStateInterface $form_state) {
parent::validate($form, $form_state);
public function validateForm(array &$form, FormStateInterface $form_state) {
parent::validateForm($form, $form_state);
$id = trim($form_state->getValue('type'));
// '0' is invalid, since elsewhere we check it using empty().

View file

@ -10,7 +10,6 @@ namespace Drupal\node;
use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
use Drupal\Core\Url;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Component\Utility\Xss;
/**
* Defines a class to build a listing of node type entities.
@ -39,7 +38,7 @@ class NodeTypeListBuilder extends ConfigEntityListBuilder {
'data' => $this->getLabel($entity),
'class' => array('menu-label'),
);
$row['description'] = Xss::filterAdmin($entity->getDescription());
$row['description']['data'] = ['#markup' => $entity->getDescription()];
return $row + parent::buildRow($entity);
}

View file

@ -114,6 +114,11 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
'term' => array('column' => 'ti.tid', 'join' => array('table' => 'taxonomy_index', 'alias' => 'ti', 'condition' => 'n.nid = ti.nid')),
);
/**
* A constant for setting and checking the query string.
*/
const ADVANCED_FORM = 'advanced-form';
/**
* {@inheritdoc}
*/
@ -293,7 +298,7 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
}
if ($status & SearchQuery::NO_POSITIVE_KEYWORDS) {
drupal_set_message($this->formatPlural($this->searchSettings->get('index.minimum_word_size'), 'You must include at least one positive keyword with 1 character or more.', 'You must include at least one positive keyword with @count characters or more.'), 'warning');
drupal_set_message($this->formatPlural($this->searchSettings->get('index.minimum_word_size'), 'You must include at least one keyword to match in the content, and punctuation is ignored.', 'You must include at least one keyword to match in the content. Keywords must be at least @count characters, and punctuation is ignored.'), 'warning');
}
return $find;
@ -490,38 +495,59 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
* {@inheritdoc}
*/
public function searchFormAlter(array &$form, FormStateInterface $form_state) {
$parameters = $this->getParameters();
$keys = $this->getKeywords();
$used_advanced = !empty($parameters[self::ADVANCED_FORM]);
if ($used_advanced) {
$f = isset($parameters['f']) ? (array) $parameters['f'] : array();
$defaults = $this->parseAdvancedDefaults($f, $keys);
}
else {
$defaults = array('keys' => $keys);
}
$form['basic']['keys']['#default_value'] = $defaults['keys'];
// Add advanced search keyword-related boxes.
$form['advanced'] = array(
'#type' => 'details',
'#title' => t('Advanced search'),
'#attributes' => array('class' => array('search-advanced')),
'#access' => $this->account && $this->account->hasPermission('use advanced search'),
'#open' => $used_advanced,
);
$form['advanced']['keywords-fieldset'] = array(
'#type' => 'fieldset',
'#title' => t('Keywords'),
);
$form['advanced']['keywords'] = array(
'#prefix' => '<div class="criterion">',
'#suffix' => '</div>',
);
$form['advanced']['keywords-fieldset']['keywords']['or'] = array(
'#type' => 'textfield',
'#title' => t('Containing any of the words'),
'#size' => 30,
'#maxlength' => 255,
'#default_value' => isset($defaults['or']) ? $defaults['or'] : '',
);
$form['advanced']['keywords-fieldset']['keywords']['phrase'] = array(
'#type' => 'textfield',
'#title' => t('Containing the phrase'),
'#size' => 30,
'#maxlength' => 255,
'#default_value' => isset($defaults['phrase']) ? $defaults['phrase'] : '',
);
$form['advanced']['keywords-fieldset']['keywords']['negative'] = array(
'#type' => 'textfield',
'#title' => t('Containing none of the words'),
'#size' => 30,
'#maxlength' => 255,
'#default_value' => isset($defaults['negative']) ? $defaults['negative'] : '',
);
// Add node types.
@ -536,7 +562,9 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
'#prefix' => '<div class="criterion">',
'#suffix' => '</div>',
'#options' => $types,
'#default_value' => isset($defaults['type']) ? $defaults['type'] : array(),
);
$form['advanced']['submit'] = array(
'#type' => 'submit',
'#value' => t('Advanced search'),
@ -563,6 +591,7 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
'#prefix' => '<div class="criterion">',
'#suffix' => '</div>',
'#options' => $language_options,
'#default_value' => isset($defaults['language']) ? $defaults['language'] : array(),
);
}
}
@ -574,6 +603,7 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
// Read keyword and advanced search information from the form values,
// and put these into the GET parameters.
$keys = trim($form_state->getValue('keys'));
$advanced = FALSE;
// Collect extra filters.
$filters = array();
@ -582,6 +612,7 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
// checkboxes to 0.
foreach ($form_state->getValue('type') as $type) {
if ($type) {
$advanced = TRUE;
$filters[] = 'type:' . $type;
}
}
@ -590,11 +621,13 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
if ($form_state->hasValue('term') && is_array($form_state->getValue('term'))) {
foreach ($form_state->getValue('term') as $term) {
$filters[] = 'term:' . $term;
$advanced = TRUE;
}
}
if ($form_state->hasValue('language') && is_array($form_state->getValue('language'))) {
foreach ($form_state->getValue('language') as $language) {
if ($language) {
$advanced = TRUE;
$filters[] = 'language:' . $language;
}
}
@ -602,15 +635,18 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
if ($form_state->getValue('or') != '') {
if (preg_match_all('/ ("[^"]+"|[^" ]+)/i', ' ' . $form_state->getValue('or'), $matches)) {
$keys .= ' ' . implode(' OR ', $matches[1]);
$advanced = TRUE;
}
}
if ($form_state->getValue('negative') != '') {
if (preg_match_all('/ ("[^"]+"|[^" ]+)/i', ' ' . $form_state->getValue('negative'), $matches)) {
$keys .= ' -' . implode(' -', $matches[1]);
$advanced = TRUE;
}
}
if ($form_state->getValue('phrase') != '') {
$keys .= ' "' . str_replace('"', ' ', $form_state->getValue('phrase')) . '"';
$advanced = TRUE;
}
$keys = trim($keys);
@ -621,10 +657,69 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
if ($filters) {
$query['f'] = $filters;
}
// Record that the person used the advanced search form, if they did.
if ($advanced) {
$query[self::ADVANCED_FORM] = '1';
}
return $query;
}
/**
* Parses the advanced search form default values.
*
* @param array $f
* The 'f' query parameter set up in self::buildUrlSearchQuery(), which
* contains the advanced query values.
* @param string $keys
* The search keywords string, which contains some information from the
* advanced search form.
*
* @return array
* Array of default form values for the advanced search form, including
* a modified 'keys' element for the bare search keywords.
*/
protected function parseAdvancedDefaults($f, $keys) {
$defaults = array();
// Split out the advanced search parameters.
foreach ($f as $advanced) {
list($key, $value) = explode(':', $advanced, 2);
if (!isset($defaults[$key])) {
$defaults[$key] = array();
}
$defaults[$key][] = $value;
}
// Split out the negative, phrase, and OR parts of keywords.
// For phrases, the form only supports one phrase.
$matches = array();
$keys = ' ' . $keys . ' ';
if (preg_match('/ "([^"]+)" /', $keys, $matches)) {
$keys = str_replace($matches[0], ' ', $keys);
$defaults['phrase'] = $matches[1];
}
// Negative keywords: pull all of them out.
if (preg_match_all('/ -([^ ]+)/', $keys, $matches)) {
$keys = str_replace($matches[0], ' ', $keys);
$defaults['negative'] = implode(' ', $matches[1]);
}
// OR keywords: pull up to one set of them out of the query.
if (preg_match('/ [^ ]+( OR [^ ]+)+ /', $keys, $matches)) {
$keys = str_replace($matches[0], ' ', $keys);
$words = explode(' OR ', trim($matches[0]));
$defaults['or'] = implode(' ', $words);
}
// Put remaining keywords string back into keywords.
$defaults['keys'] = trim($keys);
return $defaults;
}
/**
* Gathers ranking definitions from hook_ranking().
*

View file

@ -0,0 +1,35 @@
<?php
/**
* @file
* Contains \Drupal\node\Plugin\migrate\process\d6\NodeUpdate7008.
*/
namespace Drupal\node\Plugin\migrate\process\d6;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;
/**
* Split the 'administer nodes' permission from 'access content overview'.
*
* @MigrateProcessPlugin(
* id = "node_update_7008"
* )
*/
class NodeUpdate7008 extends ProcessPluginBase {
/**
* {@inheritdoc}
*
* Split the 'administer nodes' permission from 'access content overview'.
*/
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
if ($value === 'administer nodes') {
return array($value, 'access content overview');
}
return $value;
}
}

View file

@ -0,0 +1,144 @@
<?php
/**
* @file
* Contains \Drupal\node\Plugin\migrate\source\d6\Node.
*/
namespace Drupal\node\Plugin\migrate\source\d6;
use Drupal\migrate\Row;
use Drupal\migrate\Plugin\SourceEntityInterface;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
* Drupal 6 node source from database.
*
* @MigrateSource(
* id = "d6_node"
* )
*/
class Node extends DrupalSqlBase implements SourceEntityInterface {
/**
* The join options between the node and the node_revisions table.
*/
const JOIN = 'n.vid = nr.vid';
/**
* The default filter format.
*
* @var string
*/
protected $filterDefaultFormat;
/**
* {@inheritdoc}
*/
public function query() {
// Select node in its last revision.
$query = $this->select('node_revisions', 'nr')
->fields('n', array(
'nid',
'type',
'language',
'status',
'created',
'changed',
'comment',
'promote',
'moderate',
'sticky',
'tnid',
'translate',
))
->fields('nr', array(
'vid',
'title',
'body',
'teaser',
'log',
'timestamp',
'format',
));
$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}
*/
protected function initializeIterator() {
$this->filterDefaultFormat = $this->variableGet('filter_default_format', '1');
return parent::initializeIterator();
}
/**
* {@inheritdoc}
*/
public function fields() {
$fields = array(
'nid' => $this->t('Node ID'),
'type' => $this->t('Type'),
'title' => $this->t('Title'),
'body' => $this->t('Body'),
'format' => $this->t('Format'),
'teaser' => $this->t('Teaser'),
'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 prepareRow(Row $row) {
// format = 0 can happen when the body field is hidden. Set the format to 1
// to avoid migration map issues (since the body field isn't used anyway).
if ($row->getSourceProperty('format') === '0') {
$row->setSourceProperty('format', $this->filterDefaultFormat);
}
return parent::prepareRow($row);
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['nid']['type'] = 'integer';
$ids['nid']['alias'] = 'n';
return $ids;
}
/**
* {@inheritdoc}
*/
public function bundleMigrationRequired() {
return FALSE;
}
/**
* {@inheritdoc}
*/
public function entityTypeId() {
return 'node';
}
}

View file

@ -0,0 +1,45 @@
<?php
/**
* @file
* Contains \Drupal\node\Plugin\migrate\source\d6\NodeRevision.
*/
namespace Drupal\node\Plugin\migrate\source\d6;
/**
* Drupal 6 node revision source from database.
*
* @MigrateSource(
* id = "d6_node_revision"
* )
*/
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,126 @@
<?php
/**
* @file
* Contains \Drupal\node\Plugin\migrate\source\d6\NodeType.
*/
namespace Drupal\node\Plugin\migrate\source\d6;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
* Drupal 6 Node types source from database.
*
* @MigrateSource(
* id = "d6_node_type"
* )
*/
class NodeType extends DrupalSqlBase {
/**
* The teaser length
*
* @var int
*/
protected $teaserLength;
/**
* Node preview optional / required.
*
* @var int
*/
protected $nodePreview;
/**
* An array of theme settings.
*
* @var array
*/
protected $themeSettings;
/**
* {@inheritdoc}
*/
public function query() {
return $this->select('node_type', 't')
->fields('t', array(
'type',
'name',
'module',
'description',
'help',
'title_label',
'has_body',
'body_label',
'min_word_count',
'custom',
'modified',
'locked',
'orig_type',
))
->orderBy('t.type');
}
/**
* {@inheritdoc}
*/
public function fields() {
return array(
'type' => $this->t('Machine name of the node type.'),
'name' => $this->t('Human name of the node type.'),
'module' => $this->t('The module providing 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.'),
'has_body' => $this->t('Flag indicating the node type has a body field.'),
'body_label' => $this->t('Body label.'),
'min_word_count' => $this->t('Minimum word count for the body field.'),
'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);
$this->themeSettings = $this->variableGet('theme_settings', array());
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);
$submitted = isset($this->themeSettings['toggle_node_info_' . $type]) ? $this->themeSettings['toggle_node_info_' . $type] : FALSE;
$row->setSourceProperty('display_submitted', $submitted);
return parent::prepareRow($row);
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['type']['type'] = 'string';
return $ids;
}
}

View file

@ -0,0 +1,81 @@
<?php
/**
* @file
* Contains \Drupal\node\Plugin\migrate\source\d6\ViewMode.
*/
namespace Drupal\node\Plugin\migrate\source\d6;
/**
* The view mode source.
*
* @MigrateSource(
* id = "d6_view_mode",
* source_provider = "content"
* )
*/
class ViewMode extends ViewModeBase {
/**
* {@inheritdoc}
*/
protected function initializeIterator() {
$rows = array();
$result = $this->prepareQuery()->execute();
while ($field_row = $result->fetchAssoc()) {
$field_row['display_settings'] = unserialize($field_row['display_settings']);
foreach ($this->getViewModes() as $view_mode) {
if (isset($field_row['display_settings'][$view_mode]) && empty($field_row['display_settings'][$view_mode]['exclude'])) {
if (!isset($rows[$view_mode])) {
$rows[$view_mode]['entity_type'] = 'node';
$rows[$view_mode]['view_mode'] = $view_mode;
}
}
}
}
return new \ArrayIterator($rows);
}
/**
* {@inheritdoc}
*/
public function query() {
$query = $this->select('content_node_field_instance', 'cnfi')
->fields('cnfi', array(
'display_settings',
));
return $query;
}
/**
* {@inheritdoc}
*/
public function fields() {
return array(
'display_settings' => $this->t('Serialize data with display settings.'),
);
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['view_mode']['type'] = 'string';
return $ids;
}
/**
* {@inheritdoc}
*/
public function calculateDependencies() {
$this->dependencies = parent::calculateDependencies();
if (isset($this->configuration['constants']['targetEntityType'])) {
$this->addDependency('module', $this->entityManager->getDefinition($this->configuration['constants']['targetEntityType'])->getProvider());
}
return $this->dependencies;
}
}

View file

@ -0,0 +1,53 @@
<?php
/**
* @file
* Contains \Drupal\node\Plugin\migrate\source\d6\ViewModeBase.
*/
namespace Drupal\node\Plugin\migrate\source\d6;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
* A base class for migrations that require view mode info.
*/
abstract class ViewModeBase extends DrupalSqlBase {
/**
* {@inheritdoc}
*/
public function count() {
return count($this->initializeIterator());
}
/**
* Get a list of D6 view modes.
*
* Drupal 6 supported the following view modes.
* NODE_BUILD_NORMAL = 0
* NODE_BUILD_PREVIEW = 1
* NODE_BUILD_SEARCH_INDEX = 2
* NODE_BUILD_SEARCH_RESULT = 3
* NODE_BUILD_RSS = 4
* NODE_BUILD_PRINT = 5
* teaser
* full
*
* @return array
* The view mode names.
*/
public function getViewModes() {
return array(
0,
1,
2,
3,
4,
5,
'teaser',
'full',
);
}
}

View file

@ -0,0 +1,92 @@
<?php
/**
* @file
* Contains Drupal\node\ProxyClass\ParamConverter\NodePreviewConverter.
*/
/**
* This file was generated via php core/scripts/generate-proxy-class.php 'Drupal\node\ParamConverter\NodePreviewConverter' "core/modules/node/src".
*/
namespace Drupal\node\ProxyClass\ParamConverter {
/**
* Provides a proxy class for \Drupal\node\ParamConverter\NodePreviewConverter.
*
* @see \Drupal\Component\ProxyBuilder
*/
class NodePreviewConverter implements \Drupal\Core\ParamConverter\ParamConverterInterface
{
use \Drupal\Core\DependencyInjection\DependencySerializationTrait;
/**
* The id of the original proxied service.
*
* @var string
*/
protected $drupalProxyOriginalServiceId;
/**
* The real proxied service, after it was lazy loaded.
*
* @var \Drupal\node\ParamConverter\NodePreviewConverter
*/
protected $service;
/**
* The service container.
*
* @var \Symfony\Component\DependencyInjection\ContainerInterface
*/
protected $container;
/**
* Constructs a ProxyClass Drupal proxy object.
*
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
* The container.
* @param string $drupal_proxy_original_service_id
* The service ID of the original service.
*/
public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container, $drupal_proxy_original_service_id)
{
$this->container = $container;
$this->drupalProxyOriginalServiceId = $drupal_proxy_original_service_id;
}
/**
* Lazy loads the real service from the container.
*
* @return object
* Returns the constructed real service.
*/
protected function lazyLoadItself()
{
if (!isset($this->service)) {
$this->service = $this->container->get($this->drupalProxyOriginalServiceId);
}
return $this->service;
}
/**
* {@inheritdoc}
*/
public function convert($value, $definition, $name, array $defaults)
{
return $this->lazyLoadItself()->convert($value, $definition, $name, $defaults);
}
/**
* {@inheritdoc}
*/
public function applies($definition, $name, \Symfony\Component\Routing\Route $route)
{
return $this->lazyLoadItself()->applies($definition, $name, $route);
}
}
}

View file

@ -0,0 +1,52 @@
<?php
/**
* @file
* Contains \Drupal\node\Tests\AssertButtonsTrait.
*/
namespace Drupal\node\Tests;
/**
* Asserts that buttons are present on a page.
*/
trait AssertButtonsTrait {
/**
* Assert method to verify the buttons in the dropdown element.
*
* @param array $buttons
* A collection of buttons to assert for on the page.
* @param bool $dropbutton
* Whether to check if the buttons are in a dropbutton widget or not.
*/
public function assertButtons($buttons, $dropbutton = TRUE) {
// Try to find a Save button.
$save_button = $this->xpath('//input[@type="submit"][@value="Save"]');
// Verify that the number of buttons passed as parameters is
// available in the dropbutton widget.
if ($dropbutton) {
$i = 0;
$count = count($buttons);
// Assert there is no save button.
$this->assertTrue(empty($save_button));
// Dropbutton elements.
$elements = $this->xpath('//div[@class="dropbutton-wrapper"]//input[@type="submit"]');
$this->assertEqual($count, count($elements));
foreach ($elements as $element) {
$value = isset($element['value']) ? (string) $element['value'] : '';
$this->assertEqual($buttons[$i], $value);
$i++;
}
}
else {
// Assert there is a save button.
$this->assertTrue(!empty($save_button));
$this->assertNoRaw('dropbutton-wrapper');
}
}
}

View file

@ -0,0 +1,90 @@
<?php
/**
* @file
* Contains \Drupal\node\Tests\Migrate\d6\MigrateNodeBundleSettingsTest.
*/
namespace Drupal\node\Tests\Migrate\d6;
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
/**
* Test migrating node settings into the base_field_bundle_override config entity.
*
* @group node
*/
class MigrateNodeBundleSettingsTest extends MigrateDrupal6TestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('node');
/**
* {@inheritdoc}
*/
public function setUp() {
parent::setUp();
// Setup the bundles.
entity_create('node_type', array('type' => 'test_page'))->save();
entity_create('node_type', array('type' => 'test_planet'))->save();
entity_create('node_type', array('type' => 'test_story'))->save();
entity_create('node_type', array('type' => 'test_event'))->save();
entity_create('node_type', array('type' => 'story'))->save();
entity_create('node_type', array('type' => 'article'))->save();
entity_create('node_type', array('type' => 'company'))->save();
entity_create('node_type', array('type' => 'employee'))->save();
entity_create('node_type', array('type' => 'page'))->save();
entity_create('node_type', array('type' => 'sponsor'))->save();
entity_create('node_type', array('type' => 'event'))->save();
entity_create('node_type', array('type' => 'book'))->save();
// Create a config entity that already exists.
entity_create('base_field_override', array('field_name' => 'promote', 'entity_type' => 'node', 'bundle' => 'page',))->save();
$id_mappings = array(
'd6_node_type' => array(
array(array('test_page'), array('test_page')),
array(array('test_planet'), array('test_planet')),
array(array('test_story'), array('test_story')),
array(array('test_event'), array('test_event')),
array(array('story'), array('story')),
),
);
$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');
}
/**
* Tests Drupal 6 node type settings to Drupal 8 migration.
*/
public function testNodeBundleSettings() {
// Test settings on test_page bundle.
$node = entity_create('node', array('type' => 'test_page'));
$this->assertIdentical(1, $node->status->value);
$this->assertIdentical(1, $node->promote->value);
$this->assertIdentical(1, $node->sticky->value);
// Test settings for test_story bundle.
$node = entity_create('node', array('type' => 'test_story'));
$this->assertIdentical(1, $node->status->value);
$this->assertIdentical(1, $node->promote->value);
$this->assertIdentical(0, $node->sticky->value);
// Test settings for the test_event bundle.
$node = entity_create('node', array('type' => 'test_event'));
$this->assertIdentical(0, $node->status->value);
$this->assertIdentical(0, $node->promote->value);
$this->assertIdentical(1, $node->sticky->value);
}
}

View file

@ -0,0 +1,47 @@
<?php
/**
* @file
* Contains \Drupal\node\Tests\Migrate\d6\MigrateNodeConfigsTest.
*/
namespace Drupal\node\Tests\Migrate\d6;
use Drupal\config\Tests\SchemaCheckTestTrait;
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
/**
* Upgrade variables to node.settings.yml.
*
* @group node
*/
class MigrateNodeConfigsTest extends MigrateDrupal6TestBase {
use SchemaCheckTestTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('node');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->loadDumps(['Variable.php']);
$this->executeMigration('d6_node_settings');
}
/**
* Tests Drupal 6 node settings to Drupal 8 migration.
*/
public function testNodeSettings() {
$config = $this->config('node.settings');
$this->assertIdentical(FALSE, $config->get('use_admin_theme'));
$this->assertConfigSchema(\Drupal::service('config.typed'), 'node.settings', $config->get());
}
}

View file

@ -0,0 +1,69 @@
<?php
/**
* @file
* Contains \Drupal\node\Tests\Migrate\d6\MigrateNodeRevisionTest.
*/
namespace Drupal\node\Tests\Migrate\d6;
use Drupal\Core\Database\Database;
/**
* Node content revisions migration.
*
* @group node
*/
class MigrateNodeRevisionTest extends MigrateNodeTestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$id_mappings = 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) {
$user = entity_create('user', $row);
$user->enforceIsNew();
$user->save();
}
$this->executeMigration('d6_node_revision');
}
/**
* Test node revisions migration from Drupal 6 to 8.
*/
public function testNodeRevision() {
$node = \Drupal::entityManager()->getStorage('node')->loadRevision(2);
/** @var \Drupal\node\NodeInterface $node */
$this->assertIdentical('1', $node->id());
$this->assertIdentical('2', $node->getRevisionId());
$this->assertIdentical('und', $node->langcode->value);
$this->assertIdentical('Test title rev 2', $node->getTitle());
$this->assertIdentical('body test rev 2', $node->body->value);
$this->assertIdentical('teaser test rev 2', $node->body->summary);
$this->assertIdentical('2', $node->getRevisionAuthor()->id());
$this->assertIdentical('modified rev 2', $node->revision_log->value);
$this->assertIdentical('1390095702', $node->getRevisionCreationTime());
$node = \Drupal::entityManager()->getStorage('node')->loadRevision(5);
$this->assertIdentical('1', $node->id());
$this->assertIdentical('body test rev 3', $node->body->value);
$this->assertIdentical('1', $node->getRevisionAuthor()->id());
$this->assertIdentical('modified rev 3', $node->revision_log->value);
$this->assertIdentical('1390095703', $node->getRevisionCreationTime());
}
}

View file

@ -0,0 +1,94 @@
<?php
/**
* @file
* Contains \Drupal\node\Tests\Migrate\d6\MigrateNodeTest.
*/
namespace Drupal\node\Tests\Migrate\d6;
use Drupal\migrate\MigrateExecutable;
use Drupal\Core\Database\Database;
use Drupal\node\Entity\Node;
/**
* Node content migration.
*
* @group node
*/
class MigrateNodeTest extends MigrateNodeTestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
/** @var \Drupal\migrate\entity\Migration $migration */
$migration = entity_load('migration', 'd6_node');
$executable = new MigrateExecutable($migration, $this);
$executable->import();
// This is required for the second import below.
db_truncate($migration->getIdMap()->mapTableName())->execute();
$this->standalone = TRUE;
}
/**
* Test node migration from Drupal 6 to 8.
*/
public function testNode() {
$node = Node::load(1);
$this->assertIdentical('1', $node->id(), 'Node 1 loaded.');
$this->assertIdentical('und', $node->langcode->value);
$this->assertIdentical('test', $node->body->value);
$this->assertIdentical('test', $node->body->summary);
$this->assertIdentical('filtered_html', $node->body->format);
$this->assertIdentical('story', $node->getType(), 'Node has the correct bundle.');
$this->assertIdentical('Test title', $node->getTitle(), 'Node has the correct title.');
$this->assertIdentical('1388271197', $node->getCreatedTime(), 'Node has the correct created time.');
$this->assertIdentical(FALSE, $node->isSticky());
$this->assertIdentical('1', $node->getOwnerId());
$this->assertIdentical('1420861423', $node->getRevisionCreationTime());
/** @var \Drupal\node\NodeInterface $node_revision */
$node_revision = \Drupal::entityManager()->getStorage('node')->loadRevision(1);
$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);
// It is pointless to run the second half from MigrateDrupal6Test.
if (empty($this->standalone)) {
return;
}
// Test that we can re-import using the EntityContentBase destination.
$connection = Database::getConnection('default', 'migrate');
$connection->update('node_revisions')
->fields(array(
'title' => 'New node title',
'format' => 2,
))
->condition('vid', 1)
->execute();
$connection->delete('content_field_test_two')
->condition('delta', 1)
->execute();
/** @var \Drupal\migrate\entity\Migration $migration */
$migration = entity_load('migration', 'd6_node');
$executable = new MigrateExecutable($migration, $this);
$executable->import();
$node = Node::load(1);
$this->assertIdentical('New node title', $node->getTitle());
// Test a multi-column fields are correctly upgraded.
$this->assertIdentical('test', $node->body->value);
$this->assertIdentical('full_html', $node->body->format);
$node = Node::load(3);
// Test that format = 0 from source maps to filtered_html.
$this->assertIdentical('filtered_html', $node->body->format);
}
}

View file

@ -0,0 +1,113 @@
<?php
/**
* @file
* Contains \Drupal\node\Tests\Migrate\d6\MigrateNodeTestBase.
*/
namespace Drupal\node\Tests\Migrate\d6;
use Drupal\migrate\Entity\MigrationInterface;
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
use Drupal\user\Entity\User;
/**
* Base class for Node migration tests.
*/
abstract class MigrateNodeTestBase extends MigrateDrupal6TestBase {
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']);
// Create a new user which needs to have UID 1, because that is expected by
// the assertions from
// \Drupal\migrate_drupal\Tests\d6\MigrateNodeRevisionTest.
User::create([
'uid' => 1,
'name' => $this->randomMachineName(),
'status' => 1,
])->enforceIsNew(TRUE)->save();
$node_type = entity_create('node_type', array('type' => 'test_planet'));
$node_type->save();
node_add_body_field($node_type);
$node_type = entity_create('node_type', array('type' => 'story'));
$node_type->save();
node_add_body_field($node_type);
$id_mappings = array(
'd6_node_type' => array(
array(array('test_story'), array('story')),
),
'd6_filter_format' => array(
array(array(1), array('filtered_html')),
array(array(2), array('full_html')),
),
'd6_user' => array(
array(array(1), array(1)),
array(array(2), array(2)),
),
'd6_field_instance_widget_settings' => array(
array(
array('page', 'field_test'),
array('node', 'page', 'default', 'test'),
),
),
'd6_field_formatter_settings' => array(
array(
array('page', 'default', 'node', 'field_test'),
array('node', 'page', 'default', 'field_test'),
),
),
);
$this->prepareMigrations($id_mappings);
$migration = entity_load('migration', 'd6_node_settings');
$migration->setMigrationResult(MigrationInterface::RESULT_COMPLETED);
// Create a test node.
$node = entity_create('node', array(
'type' => 'story',
'nid' => 1,
'vid' => 1,
'revision_log' => '',
));
$node->enforceIsNew();
$node->save();
$node = entity_create('node', array(
'type' => 'test_planet',
'nid' => 3,
'vid' => 4,
'revision_log' => '',
));
$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

@ -0,0 +1,83 @@
<?php
/**
* @file
* Contains \Drupal\node\Tests\Migrate\d6\MigrateNodeTypeTest.
*/
namespace Drupal\node\Tests\Migrate\d6;
use Drupal\field\Entity\FieldConfig;
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
use Drupal\node\Entity\NodeType;
/**
* Upgrade node types to node.type.*.yml.
*
* @group node
*/
class MigrateNodeTypeTest extends MigrateDrupal6TestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('node', 'text', 'filter');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig(array('node'));
$this->loadDumps(['NodeType.php', 'Variable.php']);
$this->executeMigration('d6_node_type');
}
/**
* Tests Drupal 6 node type to Drupal 8 migration.
*/
public function testNodeType() {
$migration = entity_load('migration', 'd6_node_type');
// Test the test_page content type.
$node_type_page = NodeType::load('test_page');
$this->assertIdentical('test_page', $node_type_page->id(), 'Node type test_page loaded');
$this->assertIdentical(TRUE, $node_type_page->displaySubmitted());
$this->assertIdentical(FALSE, $node_type_page->isNewRevision());
$this->assertIdentical(DRUPAL_OPTIONAL, $node_type_page->getPreviewMode());
$this->assertIdentical($migration->getIdMap()->lookupDestinationID(array('test_page')), array('test_page'));
// Test we have a body field.
$field = FieldConfig::loadByName('node', 'test_page', 'body');
$this->assertIdentical('This is the body field label', $field->getLabel(), 'Body field was found.');
// Test the test_story content type.
$node_type_story = NodeType::load('test_story');
$this->assertIdentical('test_story', $node_type_story->id(), 'Node type test_story loaded');
$this->assertIdentical(TRUE, $node_type_story->displaySubmitted());
$this->assertIdentical(FALSE, $node_type_story->isNewRevision());
$this->assertIdentical(DRUPAL_OPTIONAL, $node_type_story->getPreviewMode());
$this->assertIdentical($migration->getIdMap()->lookupDestinationID(array('test_story')), array('test_story'));
// Test we don't have a body field.
$field = FieldConfig::loadByName('node', 'test_story', 'body');
$this->assertIdentical(NULL, $field, 'No body field found');
// Test the test_event content type.
$node_type_event = NodeType::load('test_event');
$this->assertIdentical('test_event', $node_type_event->id(), 'Node type test_event loaded');
$this->assertIdentical(TRUE, $node_type_event->displaySubmitted());
$this->assertIdentical(TRUE, $node_type_event->isNewRevision());
$this->assertIdentical(DRUPAL_OPTIONAL, $node_type_event->getPreviewMode());
$this->assertIdentical($migration->getIdMap()->lookupDestinationID(array('test_event')), array('test_event'));
// Test we have a body field.
$field = FieldConfig::loadByName('node', 'test_event', 'body');
$this->assertIdentical('Body', $field->getLabel(), 'Body field was found.');
}
}

View file

@ -0,0 +1,54 @@
<?php
/**
* @file
* Contains \Drupal\node\Tests\Migrate\d6\MigrateViewModesTest.
*/
namespace Drupal\node\Tests\Migrate\d6;
use Drupal\Core\Entity\Entity\EntityViewMode;
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
/**
* Migrate view modes.
*
* @group node
*/
class MigrateViewModesTest extends MigrateDrupal6TestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('node');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->loadDumps([
'ContentNodeFieldInstance.php',
'ContentNodeField.php',
'ContentFieldTest.php',
'ContentFieldTestTwo.php',
'ContentFieldMultivalue.php',
]);
$this->executeMigration('d6_view_modes');
}
/**
* Tests Drupal 6 view modes to Drupal 8 migration.
*/
public function testViewModes() {
// Test a new view mode.
$view_mode = EntityViewMode::load('node.preview');
$this->assertIdentical(FALSE, is_null($view_mode), 'Preview view mode loaded.');
$this->assertIdentical('Preview', $view_mode->label(), 'View mode has correct label.');
// Test the Id Map.
$this->assertIdentical(array('node', 'preview'), entity_load('migration', 'd6_view_modes')->getIdMap()->lookupDestinationID(array(1)));
}
}

View file

@ -8,6 +8,7 @@
namespace Drupal\node\Tests;
use Drupal\block\Entity\Block;
use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
use Drupal\user\RoleInterface;
/**
@ -17,6 +18,8 @@ use Drupal\user\RoleInterface;
*/
class NodeBlockFunctionalTest extends NodeTestBase {
use AssertPageCacheContextsAndTagsTrait;
/**
* An administrative user for testing.
*
@ -122,6 +125,8 @@ 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']);
// Enable the "Powered by Drupal" block only on article nodes.
$edit = [
'id' => strtolower($this->randomMachineName()),
@ -145,12 +150,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->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->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->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->drupalLogin($this->adminUser);
$this->drupalGet('admin/structure/block');

View file

@ -7,6 +7,8 @@
namespace Drupal\node\Tests;
use Drupal\Core\Cache\Cache;
/**
* Tests changing view modes for nodes.
*
@ -37,6 +39,7 @@ class NodeEntityViewModeAlterTest extends NodeTestBase {
// Set the flag to alter the view mode and view the node.
\Drupal::state()->set('node_test_change_view_mode', 'teaser');
Cache::invalidateTags(['rendered']);
$this->drupalGet('node/' . $node->id());
// Check that teaser mode is viewed.

View file

@ -14,6 +14,8 @@ namespace Drupal\node\Tests;
*/
class NodeFormButtonsTest extends NodeTestBase {
use AssertButtonsTrait;
/**
* A normal logged in user.
*
@ -134,42 +136,4 @@ class NodeFormButtonsTest extends NodeTestBase {
$node_3 = $node_storage->load(3);
$this->assertFalse($node_3->isPublished(), 'Node is unpublished');
}
/**
* Assert method to verify the buttons in the dropdown element.
*
* @param array $buttons
* A collection of buttons to assert for on the page.
* @param bool $dropbutton
* Whether to check if the buttons are in a dropbutton widget or not.
*/
public function assertButtons($buttons, $dropbutton = TRUE) {
// Try to find a Save button.
$save_button = $this->xpath('//input[@type="submit"][@value="Save"]');
// Verify that the number of buttons passed as parameters is
// available in the dropbutton widget.
if ($dropbutton) {
$i = 0;
$count = count($buttons);
// Assert there is no save button.
$this->assertTrue(empty($save_button));
// Dropbutton elements.
$elements = $this->xpath('//div[@class="dropbutton-wrapper"]//input[@type="submit"]');
$this->assertEqual($count, count($elements));
foreach ($elements as $element) {
$value = isset($element['value']) ? (string) $element['value'] : '';
$this->assertEqual($buttons[$i], $value);
$i++;
}
}
else {
// Assert there is a save button.
$this->assertTrue(!empty($save_button));
$this->assertNoRaw('dropbutton-wrapper');
}
}
}

View file

@ -39,7 +39,7 @@ class NodeListBuilderTest extends KernelTestBase {
$build = $list_builder->render();
$this->container->get('renderer')->renderRoot($build);
$this->assertEqual(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'url.query_args.pagers:0', 'user.node_grants:view'], $build['#cache']['contexts']);
$this->assertEqual(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'url.query_args.pagers:0', 'user.node_grants:view', 'user.permissions'], $build['#cache']['contexts']);
}
}

View file

@ -7,6 +7,8 @@
namespace Drupal\node\Tests;
use Drupal\Core\Url;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
/**
@ -16,27 +18,31 @@ use Drupal\node\Entity\NodeType;
*/
class NodeRevisionsUiTest extends NodeTestBase {
/**
* @var \Drupal\user\Entity\User
*/
protected $editor;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Create and log in user.
$web_user = $this->drupalCreateUser(
array(
'administer nodes',
'edit any page content'
)
);
$this->drupalLogin($web_user);
// Create users.
$this->editor = $this->drupalCreateUser([
'administer nodes',
'edit any page content',
'view page revisions',
'access user profiles',
]);
}
/**
* Checks that unchecking 'Create new revision' works when editing a node.
*/
function testNodeFormSaveWithoutRevision() {
$this->drupalLogin($this->editor);
$node_storage = $this->container->get('entity.manager')->getStorage('node');
// Set page revision setting 'create new revision'. This will mean new
@ -73,6 +79,60 @@ class NodeRevisionsUiTest extends NodeTestBase {
$node_storage->resetCache(array($node->id()));
$node_revision = $node_storage->load($node->id());
$this->assertNotEqual($node_revision->getRevisionId(), $node->getRevisionId(), "After an existing node is saved with 'Create new revision' checked, a new revision is created.");
}
/**
* Checks HTML double escaping of revision logs.
*/
public function testNodeRevisionDoubleEscapeFix() {
$this->drupalLogin($this->editor);
$nodes = [];
// Create the node.
$node = $this->drupalCreateNode();
$username = [
'#theme' => 'username',
'#account' => $this->editor,
];
$editor = \Drupal::service('renderer')->renderPlain($username);
// Get original node.
$nodes[] = clone $node;
// Create revision with a random title and body and update variables.
$node->title = $this->randomMachineName();
$node->body = [
'value' => $this->randomMachineName(32),
'format' => filter_default_format(),
];
$node->setNewRevision();
$revision_log = 'Revision <em>message</em> with markup.';
$node->revision_log->value = $revision_log;
$node->save();
// Make sure we get revision information.
$node = Node::load($node->id());
$nodes[] = clone $node;
$this->drupalGet('node/' . $node->id() . '/revisions');
// Assert the old revision message.
$date = format_date($nodes[0]->revision_timestamp->value, 'short');
$url = new Url('entity.node.revision', ['node' => $nodes[0]->id(), 'node_revision' => $nodes[0]->getRevisionId()]);
$old_revision_message = t('!date by !username', [
'!date' => \Drupal::l($date, $url),
'!username' => $editor,
]);
$this->assertRaw($old_revision_message);
// Assert the current revision message.
$date = format_date($nodes[1]->revision_timestamp->value, 'short');
$current_revision_message = t('!date by !username', [
'!date' => $nodes[1]->link($date),
'!username' => $editor,
]);
$current_revision_message .= '<p class="revision-log">' . $revision_log . '</p>';
$this->assertRaw($current_revision_message);
}
}

View file

@ -7,6 +7,7 @@
namespace Drupal\node\Tests;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\system\Tests\System\TokenReplaceUnitTestBase;
use Drupal\Component\Utility\SafeMarkup;
@ -76,12 +77,35 @@ class NodeTokenReplaceTest extends TokenReplaceUnitTestBase {
$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()));
$base_bubbleable_metadata = BubbleableMetadata::createFromObject($node);
$metadata_tests = [];
$metadata_tests['[node:nid]'] = $base_bubbleable_metadata;
$metadata_tests['[node:vid]'] = $base_bubbleable_metadata;
$metadata_tests['[node:type]'] = $base_bubbleable_metadata;
$metadata_tests['[node:type-name]'] = $base_bubbleable_metadata;
$metadata_tests['[node:title]'] = $base_bubbleable_metadata;
$metadata_tests['[node:body]'] = $base_bubbleable_metadata;
$metadata_tests['[node:summary]'] = $base_bubbleable_metadata;
$metadata_tests['[node:langcode]'] = $base_bubbleable_metadata;
$metadata_tests['[node:url]'] = $base_bubbleable_metadata;
$metadata_tests['[node:edit-url]'] = $base_bubbleable_metadata;
$bubbleable_metadata = clone $base_bubbleable_metadata;
$metadata_tests['[node:author]'] = $bubbleable_metadata->addCacheTags(['user:1']);
$metadata_tests['[node:author:uid]'] = $bubbleable_metadata;
$metadata_tests['[node:author:name]'] = $bubbleable_metadata;
$bubbleable_metadata = clone $base_bubbleable_metadata;
$metadata_tests['[node:created:since]'] = $bubbleable_metadata->setCacheMaxAge(0);
$metadata_tests['[node:changed:since]'] = $bubbleable_metadata;
// Test to make sure that we generated something for each token.
$this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated.');
foreach ($tests as $input => $expected) {
$output = $this->tokenService->replace($input, array('node' => $node), array('langcode' => $this->interfaceLanguage->getId()));
$bubbleable_metadata = new BubbleableMetadata();
$output = $this->tokenService->replace($input, array('node' => $node), array('langcode' => $this->interfaceLanguage->getId()), $bubbleable_metadata);
$this->assertEqual($output, $expected, format_string('Sanitized node token %token replaced.', array('%token' => $input)));
$this->assertEqual($bubbleable_metadata, $metadata_tests[$input]);
}
// Generate and test unsanitized tokens.

View file

@ -12,6 +12,7 @@ use Drupal\content_translation\Tests\ContentTranslationUITestBase;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Url;
use Drupal\node\Entity\Node;
use Drupal\language\Entity\ConfigurableLanguage;
/**
* Tests the Node Translation UI.
@ -20,6 +21,21 @@ use Drupal\node\Entity\Node;
*/
class NodeTranslationUITest extends ContentTranslationUITestBase {
/**
* {inheritdoc}
*/
protected $defaultCacheContexts = [
'languages:language_interface',
'theme',
'user.permissions',
'route.menu_active_trails:account',
'route.menu_active_trails:footer',
'route.menu_active_trails:main',
'route.menu_active_trails:tools',
'timezone',
'user.roles'
];
/**
* Modules to enable.
*
@ -57,6 +73,42 @@ class NodeTranslationUITest extends ContentTranslationUITestBase {
$this->doUninstallTest();
}
/**
* Tests changing the published status on a node without fields.
*/
function testPublishedStatusNoFields() {
// Test changing the published status of an article without fields.
$this->drupalLogin($this->administrator);
// Delete all fields.
$this->drupalGet('admin/structure/types/manage/article/fields');
$this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.' . $this->fieldName . '/delete', array(), t('Delete'));
$this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.field_tags/delete', array(), t('Delete'));
$this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.field_image/delete', array(), t('Delete'));
// Add a node.
$default_langcode = $this->langcodes[0];
$values[$default_langcode] = array('title' => array(array('value' => $this->randomMachineName())));
$entity_id = $this->createEntity($values[$default_langcode], $default_langcode);
$entity = entity_load($this->entityTypeId, $entity_id, TRUE);
// Add a content translation.
$langcode = 'fr';
$language = ConfigurableLanguage::load($langcode);
$values[$langcode] = array('title' => array(array('value' => $this->randomMachineName())));
$add_url = Url::fromRoute('content_translation.translation_add_' . $entity->getEntityTypeId(), [
$entity->getEntityTypeId() => $entity->id(),
'source' => $default_langcode,
'target' => $langcode
], array('language' => $language));
$this->drupalPostForm($add_url, $this->getEditValues($values, $langcode), t('Save and unpublish (this translation)'));
$entity = entity_load($this->entityTypeId, $this->entityId, TRUE);
$translation = $entity->getTranslation($langcode);
// Make sure we unpublished the node correctly.
$this->assertFalse($this->manager->getTranslationMetadata($translation)->isPublished(), 'The translation has been correctly unpublished.');
}
/**
* Overrides \Drupal\content_translation\Tests\ContentTranslationUITestBase::getTranslatorPermission().
*/

View file

@ -191,7 +191,7 @@ class FrontPageTest extends ViewTestBase {
*/
public function testCacheTagsWithCachePluginNone() {
$this->enablePageCaching();
$this->assertFrontPageViewCacheTags(FALSE);
$this->doTestFrontPageViewCacheTags(FALSE);
}
/**
@ -207,7 +207,7 @@ class FrontPageTest extends ViewTestBase {
]);
$view->save();
$this->assertFrontPageViewCacheTags(TRUE);
$this->doTestFrontPageViewCacheTags(TRUE);
}
/**
@ -227,7 +227,7 @@ class FrontPageTest extends ViewTestBase {
]);
$view->save();
$this->assertFrontPageViewCacheTags(TRUE);
$this->doTestFrontPageViewCacheTags(TRUE);
}
/**
@ -236,7 +236,7 @@ class FrontPageTest extends ViewTestBase {
* @param bool $do_assert_views_caches
* Whether to check Views' result & output caches.
*/
protected function assertFrontPageViewCacheTags($do_assert_views_caches) {
protected function doTestFrontPageViewCacheTags($do_assert_views_caches) {
$view = Views::getView('frontpage');
$view->setDisplay('page_1');
@ -248,24 +248,33 @@ class FrontPageTest extends ViewTestBase {
'user.permissions',
// Default cache contexts of the renderer.
'theme',
'url.query_args.pagers:0',
'url.query_args',
// Attached feed.
'url.site',
];
$cache_context_tags = \Drupal::service('cache_contexts_manager')->convertTokensToKeys($cache_contexts)->getCacheTags();
// Test before there are any nodes.
$empty_node_listing_cache_tags = [
'config:views.view.frontpage',
'node_list',
];
$render_cache_tags = Cache::mergeTags($empty_node_listing_cache_tags, $cache_context_tags);
$render_cache_tags = Cache::mergeTags($render_cache_tags, ['config:system.site']);
$this->assertViewsCacheTags(
$view,
$empty_node_listing_cache_tags,
$do_assert_views_caches,
$empty_node_listing_cache_tags
$render_cache_tags
);
$expected_tags = Cache::mergeTags($empty_node_listing_cache_tags, $cache_context_tags);
$expected_tags = Cache::mergeTags($expected_tags, ['rendered', 'config:user.role.anonymous', 'config:system.site']);
$this->assertPageCacheContextsAndTags(
Url::fromRoute('view.frontpage.page_1'),
$cache_contexts,
Cache::mergeTags($empty_node_listing_cache_tags, ['rendered', 'config:user.role.anonymous'])
$expected_tags
);
// Create some nodes on the frontpage view. Add more than 10 nodes in order
@ -307,12 +316,15 @@ class FrontPageTest extends ViewTestBase {
'node:14',
'node:15',
];
$first_page_output_cache_tags = Cache::mergeTags($first_page_result_cache_tags, [
'config:filter.format.plain_text',
'node_view',
'user_view',
'user:0',
]);
$cache_context_tags = \Drupal::service('cache_contexts_manager')->convertTokensToKeys($cache_contexts)->getCacheTags();
$first_page_output_cache_tags = Cache::mergeTags($first_page_result_cache_tags, $cache_context_tags);
$first_page_output_cache_tags = Cache::mergeTags($first_page_output_cache_tags, [
'config:filter.format.plain_text',
'node_view',
'user_view',
'user:0',
]
);
$view->setDisplay('page_1');
$view->setCurrentPage(0);
$this->assertViewsCacheTags(

View file

@ -170,6 +170,7 @@ function node_test_node_insert(NodeInterface $node) {
// Set the node title to the node ID and save.
if ($node->getTitle() == 'new') {
$node->setTitle('Node '. $node->id());
$node->setNewRevision(FALSE);
$node->save();
}
}

View file

@ -0,0 +1,142 @@
<?php
/**
* @file
* Contains \Drupal\Tests\node\Unit\Plugin\migrate\source\d6\NodeByNodeTypeTest.
*/
namespace Drupal\Tests\node\Unit\Plugin\migrate\source\d6;
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
/**
* Tests D6 node source plugin with 'node_type' configuration.
*
* @group node
*/
class NodeByNodeTypeTest extends MigrateSqlSourceTestCase {
const PLUGIN_CLASS = 'Drupal\node\Plugin\migrate\source\d6\Node';
// The fake Migration configuration entity.
protected $migrationConfiguration = array(
'id' => 'test',
// Leave it empty for now.
'idlist' => array(),
// The fake configuration for the source.
'source' => array(
'plugin' => 'd6_node',
'node_type' => 'page',
),
);
protected $expectedResults = array(
array(
// Node fields.
'nid' => 1,
'vid' => 1,
'type' => 'page',
'language' => 'en',
'title' => 'node title 1',
'uid' => 1,
'status' => 1,
'timestamp' => 1279051598,
'created' => 1279051598,
'changed' => 1279051598,
'comment' => 2,
'promote' => 1,
'moderate' => 0,
'sticky' => 0,
'tnid' => 0,
'translate' => 0,
// Node revision fields.
'body' => 'body for node 1',
'teaser' => 'teaser for node 1',
'format' => 1,
'log' => 'log message 1',
),
array(
// Node fields.
'nid' => 2,
'vid' => 2,
'type' => 'page',
'language' => 'en',
'title' => 'node title 2',
'uid' => 1,
'status' => 1,
'timestamp' => 1279290908,
'created' => 1279290908,
'changed' => 1279308993,
'comment' => 0,
'promote' => 1,
'moderate' => 0,
'sticky' => 0,
'tnid' => 0,
'translate' => 0,
// Node revision fields.
'body' => 'body for node 2',
'teaser' => 'teaser for node 2',
'format' => 1,
'log' => 'log message 2',
),
);
/**
* {@inheritdoc}
*/
protected function setUp() {
$database_contents = $this->expectedResults;
array_walk($this->expectedResults, function (&$row) {
$row['node_uid'] = $row['uid'];
$row['revision_uid'] = $row['uid'] + 1;
unset($row['uid']);
});
$database_contents[] = array(
// Node fields.
'nid' => 5,
'vid' => 5,
'type' => 'article',
'language' => 'en',
'title' => 'node title 5',
'uid' => 1,
'status' => 1,
'timestamp' => 1279290908,
'created' => 1279290908,
'changed' => 1279308993,
'comment' => 0,
'promote' => 1,
'moderate' => 0,
'sticky' => 0,
'tnid' => 0,
'translate' => 0,
// Node revision fields.
'body' => 'body for node 5',
'teaser' => 'body for node 5',
'format' => 1,
'log' => 'log message 3',
);
// Add another row with an article node and make sure it is not migrated.
foreach ($database_contents as $k => $row) {
foreach (array('nid', 'vid', 'title', 'uid', 'body', 'teaser', 'format', 'timestamp', 'log') as $field) {
$this->databaseContents['node_revisions'][$k][$field] = $row[$field];
switch ($field) {
case 'nid': case 'vid':
break;
case 'uid':
$this->databaseContents['node_revisions'][$k]['uid']++;
break;
default:
unset($row[$field]);
break;
}
}
$this->databaseContents['node'][$k] = $row;
}
parent::setUp();
}
}

View file

@ -0,0 +1,179 @@
<?php
/**
* @file
* Contains \Drupal\Tests\node\Unit\Plugin\migrate\source\d6\NodeRevisionByNodeTypeTest.
*/
namespace Drupal\Tests\node\Unit\Plugin\migrate\source\d6;
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
/**
* Tests D6 node revision source plugin.
*
* @group node
*/
class NodeRevisionByNodeTypeTest extends MigrateSqlSourceTestCase {
const PLUGIN_CLASS = 'Drupal\node\Plugin\migrate\source\d6\NodeRevision';
// The fake Migration configuration entity.
protected $migrationConfiguration = [
'id' => 'test',
// Leave it empty for now.
'idlist' => [],
// The fake configuration for the source.
'source' => [
'plugin' => 'd6_node_revision',
'node_type' => 'page',
],
'sourceIds' => [
'vid' => [
'alias' => 'v',
],
],
'destinationIds' => [
'vid' => [
// This is where the field schema would go.
],
],
];
protected $databaseContents = [
'node' => [
[
'nid' => 1,
'type' => 'page',
'language' => 'en',
'status' => 1,
'created' => 1279051598,
'changed' => 1279051598,
'comment' => 2,
'promote' => 1,
'moderate' => 0,
'sticky' => 0,
'tnid' => 0,
'translate' => 0,
'vid' => 4,
'uid' => 1,
'title' => 'title for revision 4 (node 1)',
],
[
'nid' => 2,
'type' => 'article',
'language' => 'en',
'status' => 1,
'created' => 1279290908,
'changed' => 1279308993,
'comment' => 0,
'promote' => 1,
'moderate' => 0,
'sticky' => 0,
'tnid' => 0,
'translate' => 0,
'vid' => 2,
'uid' => 1,
'title' => 'title for revision 2 (node 2)',
],
],
'node_revisions' => [
[
'nid' => 1,
'vid' => 1,
'uid' => 1,
'title' => 'title for revision 1 (node 1)',
'body' => 'body for revision 1 (node 1)',
'teaser' => 'teaser for revision 1 (node 1)',
'log' => 'log for revision 1 (node 1)',
'format' => 1,
'timestamp' => 1279051598,
],
[
'nid' => 1,
'vid' => 3,
'uid' => 1,
'title' => 'title for revision 3 (node 1)',
'body' => 'body for revision 3 (node 1)',
'teaser' => 'teaser for revision 3 (node 1)',
'log' => 'log for revision 3 (node 1)',
'format' => 1,
'timestamp' => 1279051598,
],
[
'nid' => 1,
'vid' => 4,
'uid' => 1,
'title' => 'title for revision 4 (node 1)',
'body' => 'body for revision 4 (node 1)',
'teaser' => 'teaser for revision 4 (node 1)',
'log' => 'log for revision 4 (node 1)',
'format' => 1,
'timestamp' => 1279051598,
],
[
'nid' => 2,
'vid' => 2,
'uid' => 1,
'title' => 'title for revision 2 (node 2)',
'body' => 'body for revision 2 (node 2)',
'teaser' => 'teaser for revision 2 (node 2)',
'log' => 'log for revision 2 (node 2)',
'format' => 1,
'timestamp' => 1279308993,
],
],
];
// There are three revisions of nid 1; vid 4 is the current one. The
// NodeRevision plugin should capture every revision EXCEPT that one.
// nid 2 will be ignored because $this->migrationConfiguration specifies
// a particular node type.
protected $expectedResults = [
[
'nid' => 1,
'type' => 'page',
'language' => 'en',
'status' => 1,
'created' => 1279051598,
'changed' => 1279051598,
'comment' => 2,
'promote' => 1,
'moderate' => 0,
'sticky' => 0,
'tnid' => 0,
'translate' => 0,
'vid' => 1,
'node_uid' => 1,
'revision_uid' => 1,
'title' => 'title for revision 1 (node 1)',
'body' => 'body for revision 1 (node 1)',
'teaser' => 'teaser for revision 1 (node 1)',
'log' => 'log for revision 1 (node 1)',
'format' => 1,
],
[
'nid' => 1,
'type' => 'page',
'language' => 'en',
'status' => 1,
'created' => 1279051598,
'changed' => 1279051598,
'comment' => 2,
'promote' => 1,
'moderate' => 0,
'sticky' => 0,
'tnid' => 0,
'translate' => 0,
'vid' => 3,
'node_uid' => 1,
'revision_uid' => 1,
'title' => 'title for revision 3 (node 1)',
'body' => 'body for revision 3 (node 1)',
'teaser' => 'teaser for revision 3 (node 1)',
'log' => 'log for revision 3 (node 1)',
'format' => 1,
],
];
}

View file

@ -0,0 +1,181 @@
<?php
/**
* @file
* Contains \Drupal\Tests\node\Unit\Plugin\migrate\source\d6\NodeRevisionTest.
*/
namespace Drupal\Tests\node\Unit\Plugin\migrate\source\d6;
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
/**
* Tests D6 node revision source plugin.
*
* @group node
*/
class NodeRevisionTest extends MigrateSqlSourceTestCase {
const PLUGIN_CLASS = 'Drupal\node\Plugin\migrate\source\d6\NodeRevision';
// The fake Migration configuration entity.
protected $migrationConfiguration = [
'id' => 'test',
// Leave it empty for now.
'idlist' => [],
// The fake configuration for the source.
'source' => [
'plugin' => 'd6_node_revision',
],
'sourceIds' => [
'vid' => [
'alias' => 'v',
],
],
'destinationIds' => [
'vid' => [
// This is where the field schema would go.
],
],
];
protected $databaseContents = [
'node' => [
[
'nid' => 1,
'type' => 'page',
'language' => 'en',
'status' => 1,
'created' => 1279051598,
'changed' => 1279051598,
'comment' => 2,
'promote' => 1,
'moderate' => 0,
'sticky' => 0,
'tnid' => 0,
'translate' => 0,
'vid' => 4,
'uid' => 1,
'title' => 'title for revision 1 (node 1)',
],
[
'nid' => 2,
'type' => 'article',
'language' => 'en',
'status' => 1,
'created' => 1279290908,
'changed' => 1279308993,
'comment' => 0,
'promote' => 1,
'moderate' => 0,
'sticky' => 0,
'tnid' => 0,
'translate' => 0,
'vid' => 2,
'uid' => 1,
'title' => 'title for revision 2 (node 2)',
],
],
'node_revisions' => [
[
'nid' => 1,
'vid' => 1,
'uid' => 1,
'title' => 'title for revision 1 (node 1)',
'body' => 'body for revision 1 (node 1)',
'teaser' => 'teaser for revision 1 (node 1)',
'log' => 'log for revision 1 (node 1)',
'format' => 1,
'timestamp' => 1279051598,
],
[
'nid' => 1,
'vid' => 3,
'uid' => 1,
'title' => 'title for revision 3 (node 1)',
'body' => 'body for revision 3 (node 1)',
'teaser' => 'teaser for revision 3 (node 1)',
'log' => 'log for revision 3 (node 1)',
'format' => 1,
'timestamp' => 1279051598,
],
[
'nid' => 1,
'vid' => 4,
'uid' => 1,
'title' => 'title for revision 4 (node 1)',
'body' => 'body for revision 4 (node 1)',
'teaser' => 'teaser for revision 4 (node 1)',
'log' => 'log for revision 4 (node 1)',
'format' => 1,
'timestamp' => 1279051598,
],
[
'nid' => 2,
'vid' => 2,
'uid' => 1,
'title' => 'title for revision 2 (node 2)',
'body' => 'body for revision 2 (node 2)',
'teaser' => 'teaser for revision 2 (node 2)',
'log' => 'log for revision 2 (node 2)',
'format' => 1,
'timestamp' => 1279308993,
],
],
];
// There are three revisions of nid 1, but the NodeRevision source ignores
// the current revision. So only two revisions will be returned here. nid 2
// is ignored because it only has one revision (the current one).
protected $expectedResults = [
[
// Node fields.
'nid' => 1,
'type' => 'page',
'language' => 'en',
'status' => 1,
'created' => 1279051598,
'changed' => 1279051598,
'comment' => 2,
'promote' => 1,
'moderate' => 0,
'sticky' => 0,
'tnid' => 0,
'translate' => 0,
// Node revision fields.
'vid' => 1,
'node_uid' => 1,
'revision_uid' => 1,
'title' => 'title for revision 1 (node 1)',
'body' => 'body for revision 1 (node 1)',
'teaser' => 'teaser for revision 1 (node 1)',
'log' => 'log for revision 1 (node 1)',
'format' => 1,
],
[
// Node fields.
'nid' => 1,
'type' => 'page',
'language' => 'en',
'status' => 1,
'created' => 1279051598,
'changed' => 1279051598,
'comment' => 2,
'promote' => 1,
'moderate' => 0,
'sticky' => 0,
'tnid' => 0,
'translate' => 0,
// Node revision fields.
'vid' => 3,
'node_uid' => 1,
'revision_uid' => 1,
'title' => 'title for revision 3 (node 1)',
'body' => 'body for revision 3 (node 1)',
'teaser' => 'teaser for revision 3 (node 1)',
'log' => 'log for revision 3 (node 1)',
'format' => 1,
],
];
}

View file

@ -0,0 +1,136 @@
<?php
/**
* @file
* Contains \Drupal\Tests\node\Unit\Plugin\migrate\source\d6\NodeTest.
*/
namespace Drupal\Tests\node\Unit\Plugin\migrate\source\d6;
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
/**
* Tests D6 node source plugin.
*
* @group node
*/
class NodeTest extends MigrateSqlSourceTestCase {
const PLUGIN_CLASS = 'Drupal\node\Plugin\migrate\source\d6\Node';
// The fake Migration configuration entity.
protected $migrationConfiguration = array(
'id' => 'test',
// Leave it empty for now.
'idlist' => array(),
// The fake configuration for the source.
'source' => array(
'plugin' => 'd6_node',
),
);
protected $expectedResults = array(
array(
// Node fields.
'nid' => 1,
'vid' => 1,
'type' => 'page',
'language' => 'en',
'title' => 'node title 1',
'uid' => 1,
'status' => 1,
'created' => 1279051598,
'changed' => 1279051598,
'comment' => 2,
'promote' => 1,
'moderate' => 0,
'sticky' => 0,
'tnid' => 0,
'translate' => 0,
// Node revision fields.
'body' => 'body for node 1',
'teaser' => 'teaser for node 1',
'log' => '',
'timestamp' => 1279051598,
'format' => 1,
),
array(
// Node fields.
'nid' => 2,
'vid' => 2,
'type' => 'page',
'language' => 'en',
'title' => 'node title 2',
'uid' => 1,
'status' => 1,
'created' => 1279290908,
'changed' => 1279308993,
'comment' => 0,
'promote' => 1,
'moderate' => 0,
'sticky' => 0,
'tnid' => 0,
'translate' => 0,
// Node revision fields.
'body' => 'body for node 2',
'teaser' => 'teaser for node 2',
'log' => '',
'timestamp' => 1279308993,
'format' => 1,
),
array(
// Node fields.
'nid' => 5,
'vid' => 5,
'type' => 'article',
'language' => 'en',
'title' => 'node title 5',
'uid' => 1,
'status' => 1,
'created' => 1279290908,
'changed' => 1279308993,
'comment' => 0,
'promote' => 1,
'moderate' => 0,
'sticky' => 0,
'tnid' => 0,
'translate' => 0,
// Node revision fields.
'body' => 'body for node 5',
'teaser' => 'body for node 5',
'log' => '',
'timestamp' => 1279308993,
'format' => 1,
),
);
/**
* {@inheritdoc}
*/
protected function setUp() {
foreach ($this->expectedResults as $k => $row) {
foreach (array('nid', 'vid', 'title', 'uid', 'body', 'teaser', 'format', 'timestamp', 'log') as $field) {
$this->databaseContents['node_revisions'][$k][$field] = $row[$field];
switch ($field) {
case 'nid': case 'vid':
break;
case 'uid':
$this->databaseContents['node_revisions'][$k]['uid']++;
break;
default:
unset($row[$field]);
break;
}
}
$this->databaseContents['node'][$k] = $row;
}
array_walk($this->expectedResults, function (&$row) {
$row['node_uid'] = $row['uid'];
$row['revision_uid'] = $row['uid'] + 1;
unset($row['uid']);
});
parent::setUp();
}
}

View file

@ -0,0 +1,77 @@
<?php
/**
* @file
* Contains \Drupal\Tests\node\Unit\Plugin\migrate\source\d6\NodeTypeTest.
*/
namespace Drupal\Tests\node\Unit\Plugin\migrate\source\d6;
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
/**
* Tests D6 node type source plugin.
*
* @group node
*/
class NodeTypeTest 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\node\Plugin\migrate\source\d6\NodeType';
// The fake Migration configuration entity.
protected $migrationConfiguration = array(
// The ID of the entity, can be any string.
'id' => 'test_nodetypes',
// Leave it empty for now.
'idlist' => array(),
'source' => array(
'plugin' => 'd6_nodetype',
),
);
// We need to set up the database contents; it's easier to do that below.
// These are sample result queries.
protected $expectedResults = array(
array(
'type' => 'page',
'name' => 'Page',
'module' => 'node',
'description' => 'A <em>page</em>, similar in form to a <em>story</em>, is a simple method for creating and displaying information that rarely changes, such as an "About us" section of a website. By default, a <em>page</em> entry does not allow visitor comments and is not featured on the site\'s initial home page.',
'help' => '',
'title_label' => 'Title',
'has_body' => 1,
'body_label' => 'Body',
'min_word_count' => 0,
'custom' => 1,
'modified' => 0,
'locked' => 0,
'orig_type' => 'page',
),
array(
'type' => 'story',
'name' => 'Story',
'module' => 'node',
'description' => 'A <em>story</em>, similar in form to a <em>page</em>, is ideal for creating and displaying content that informs or engages website visitors. Press releases, site announcements, and informal blog-like entries may all be created with a <em>story</em> entry. By default, a <em>story</em> entry is automatically featured on the site\'s initial home page, and provides the ability to post comments.',
'help' => '',
'title_label' => 'Title',
'has_body' => 1,
'body_label' => 'Body',
'min_word_count' => 0,
'custom' => 1,
'modified' => 0,
'locked' => 0,
'orig_type' => 'story',
),
);
/**
* Prepopulate contents with results.
*/
protected function setUp() {
$this->databaseContents['node_type'] = $this->expectedResults;
parent::setUp();
}
}

View file

@ -0,0 +1,80 @@
<?php
/**
* @file
* Contains \Drupal\Tests\node\Unit\Plugin\migrate\source\d6\ViewModeTest.
*/
namespace Drupal\Tests\node\Unit\Plugin\migrate\source\d6;
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
/**
* Tests D6 view mode source plugin.
*
* @group node
*/
class ViewModeTest 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\node\Plugin\migrate\source\d6\ViewMode';
// The fake Migration configuration entity.
protected $migrationConfiguration = array(
// The ID of the entity, can be any string.
'id' => 'view_mode_test',
// Leave it empty for now.
'idlist' => array(),
'source' => array(
'plugin' => 'd6_field_instance_view_mode',
),
);
protected $expectedResults = array(
array(
'entity_type' => 'node',
'view_mode' => '4',
),
array(
'entity_type' => 'node',
'view_mode' => 'teaser',
),
array(
'entity_type' => 'node',
'view_mode' => 'full',
),
);
/**
* {@inheritdoc}
*/
protected function setUp() {
$this->databaseContents['content_node_field_instance'][] = array(
'display_settings' => serialize(array(
'weight' => '31',
'parent' => '',
'label' => array(
'format' => 'above',
),
'teaser' => array(
'format' => 'default',
'exclude' => 0,
),
'full' => array(
'format' => 'default',
'exclude' => 0,
),
4 => array(
'format' => 'default',
'exclude' => 0,
),
)),
);
parent::setUp();
}
}