Update to drupal 8.0.0-rc1. For more information, see https://www.drupal.org/node/2582663

This commit is contained in:
Greg Anderson 2015-10-08 11:40:12 -07:00
parent eb34d130a8
commit f32e58e4b1
8476 changed files with 211648 additions and 170042 deletions

View file

@ -92,15 +92,11 @@ class NodeRevisionAccessCheck implements AccessInterface {
* performed.
* @param string $op
* (optional) The specific operation being checked. Defaults to 'view.'
* @param string|null $langcode
* (optional) Language code for the variant of the node. Different language
* variants might have different permissions associated. If NULL, the
* original langcode of the node is used. Defaults to NULL.
*
* @return bool
* TRUE if the operation may be performed, FALSE otherwise.
*/
public function checkAccess(NodeInterface $node, AccountInterface $account, $op = 'view', $langcode = NULL) {
public function checkAccess(NodeInterface $node, AccountInterface $account, $op = 'view') {
$map = array(
'view' => 'view all revisions',
'update' => 'revert all revisions',
@ -119,13 +115,9 @@ class NodeRevisionAccessCheck implements AccessInterface {
return FALSE;
}
// If no language code was provided, default to the node revision's langcode.
if (empty($langcode)) {
$langcode = $node->language()->getId();
}
// Statically cache access by revision ID, language code, user account ID,
// and operation.
$langcode = $node->language()->getId();
$cid = $node->getRevisionId() . ':' . $langcode . ':' . $account->id() . ':' . $op;
if (!isset($this->access[$cid])) {
@ -149,7 +141,7 @@ class NodeRevisionAccessCheck implements AccessInterface {
else {
// First check the access to the default revision and finally, if the
// node passed in is not the default revision then access to that, too.
$this->access[$cid] = $this->nodeAccess->access($this->nodeStorage->load($node->id()), $op, $langcode, $account) && ($node->isDefaultRevision() || $this->nodeAccess->access($node, $op, $langcode, $account));
$this->access[$cid] = $this->nodeAccess->access($this->nodeStorage->load($node->id()), $op, $account) && ($node->isDefaultRevision() || $this->nodeAccess->access($node, $op, $account));
}
}

View file

@ -0,0 +1,29 @@
<?php
/**
* @file
* Contains \Drupal\node\ConfigTranslation\NodeTypeMapper.
*/
namespace Drupal\node\ConfigTranslation;
use Drupal\config_translation\ConfigEntityMapper;
use Drupal\Core\Config\Entity\ConfigEntityInterface;
/**
* Provides a configuration mapper for node types.
*/
class NodeTypeMapper extends ConfigEntityMapper {
/**
* {@inheritdoc}
*/
public function setEntity(ConfigEntityInterface $entity) {
parent::setEntity($entity);
// Adds the title label to the translation form.
$node_type = $entity->id();
$this->addConfigName("core.base_field_override.node.$node_type.title");
}
}

View file

@ -13,12 +13,15 @@ use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Core\Plugin\Context\ContextProviderInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\node\Entity\Node;
use Drupal\Core\StringTranslation\StringTranslationTrait;
/**
* Sets the current node as a context on node routes.
*/
class NodeRouteContext implements ContextProviderInterface {
use StringTranslationTrait;
/**
* The route match object.
*
@ -41,18 +44,22 @@ class NodeRouteContext implements ContextProviderInterface {
*/
public function getRuntimeContexts(array $unqualified_context_ids) {
$result = [];
$context = new Context(new ContextDefinition('entity:node', NULL, FALSE));
$context_definition = new ContextDefinition('entity:node', NULL, FALSE);
$value = NULL;
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);
$value = $node;
}
}
elseif ($this->routeMatch->getRouteName() == 'node.add') {
$node_type = $this->routeMatch->getParameter('node_type');
$context->setContextValue(Node::create(array('type' => $node_type->id())));
$value = Node::create(array('type' => $node_type->id()));
}
$cacheability = new CacheableMetadata();
$cacheability->setCacheContexts(['route']);
$context = new Context($context_definition, $value);
$context->addCacheableDependency($cacheability);
$result['node'] = $context;
@ -63,7 +70,7 @@ class NodeRouteContext implements ContextProviderInterface {
* {@inheritdoc}
*/
public function getAvailableContexts() {
$context = new Context(new ContextDefinition('entity:node'));
$context = new Context(new ContextDefinition('entity:node', $this->t('Node from URL')));
return ['node' => $context];
}

View file

@ -9,8 +9,9 @@ namespace Drupal\node\Controller;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Datetime\DateFormatter;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Url;
use Drupal\node\NodeTypeInterface;
@ -25,7 +26,7 @@ class NodeController extends ControllerBase implements ContainerInjectionInterfa
/**
* The date formatter service.
*
* @var \Drupal\Core\Datetime\DateFormatter
* @var \Drupal\Core\Datetime\DateFormatterInterface
*/
protected $dateFormatter;
@ -39,12 +40,12 @@ class NodeController extends ControllerBase implements ContainerInjectionInterfa
/**
* Constructs a NodeController object.
*
* @param \Drupal\Core\Datetime\DateFormatter $date_formatter
* @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
* The date formatter service.
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer service.
*/
public function __construct(DateFormatter $date_formatter, RendererInterface $renderer) {
public function __construct(DateFormatterInterface $date_formatter, RendererInterface $renderer) {
$this->dateFormatter = $date_formatter;
$this->renderer = $renderer;
}
@ -71,13 +72,22 @@ class NodeController extends ControllerBase implements ContainerInjectionInterfa
* type.
*/
public function addPage() {
$build = [
'#theme' => 'node_add_list',
'#cache' => [
'tags' => $this->entityManager()->getDefinition('node_type')->getListCacheTags(),
],
];
$content = array();
// Only use node types the user has access to.
foreach ($this->entityManager()->getStorage('node_type')->loadMultiple() as $type) {
if ($this->entityManager()->getAccessControlHandler('node')->createAccess($type->id())) {
$access = $this->entityManager()->getAccessControlHandler('node')->createAccess($type->id(), NULL, [], TRUE);
if ($access->isAllowed()) {
$content[$type->id()] = $type;
}
$this->renderer->addCacheableDependency($build, $access);
}
// Bypass the node/add listing if only one content type is available.
@ -86,10 +96,9 @@ class NodeController extends ControllerBase implements ContainerInjectionInterfa
return $this->redirect('node.add', array('node_type' => $type->id()));
}
return array(
'#theme' => 'node_add_list',
'#content' => $content,
);
$build['#content'] = $content;
return $build;
}
/**
@ -153,11 +162,14 @@ class NodeController extends ControllerBase implements ContainerInjectionInterfa
*/
public function revisionOverview(NodeInterface $node) {
$account = $this->currentUser();
$langcode = $this->languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->getId();
$langname = $this->languageManager()->getLanguageName($langcode);
$languages = $node->getTranslationLanguages();
$has_translations = (count($languages) > 1);
$node_storage = $this->entityManager()->getStorage('node');
$type = $node->getType();
$build = array();
$build['#title'] = $this->t('Revisions for %title', array('%title' => $node->label()));
$build['#title'] = $has_translations ? $this->t('@langname revisions for %title', ['@langname' => $langname, '%title' => $node->label()]) : $this->t('Revisions for %title', ['%title' => $node->label()]);
$header = array($this->t('Revision'), $this->t('Operations'));
$revert_permission = (($account->hasPermission("revert $type revisions") || $account->hasPermission('revert all revisions') || $account->hasPermission('administer nodes')) && $node->access('update'));
@ -167,74 +179,83 @@ class NodeController extends ControllerBase implements ContainerInjectionInterfa
$vids = $node_storage->revisionIds($node);
$latest_revision = TRUE;
foreach (array_reverse($vids) as $vid) {
/** @var \Drupal\node\NodeInterface $revision */
$revision = $node_storage->loadRevision($vid);
$username = [
'#theme' => 'username',
'#account' => $revision->uid->entity,
];
// 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' => ['#markup' => $revision->revision_log->value, '#allowed_tags' => Xss::getHtmlTagList()],
],
],
];
// @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' => [
'#prefix' => '<em>',
'#markup' => $this->t('current revision'),
'#suffix' => '</em>',
],
'class' => ['revision-current'],
if ($revision->hasTranslation($langcode) && $revision->getTranslation($langcode)->isRevisionTranslationAffected()) {
$username = [
'#theme' => 'username',
'#account' => $revision->uid->entity,
];
}
else {
$links = [];
if ($revert_permission) {
$links['revert'] = [
'title' => $this->t('Revert'),
'url' => Url::fromRoute('node.revision_revert_confirm', ['node' => $node->id(), 'node_revision' => $vid]),
// 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' => ['#markup' => $revision->revision_log->value, '#allowed_tags' => Xss::getHtmlTagList()],
],
],
];
// @todo Simplify once https://www.drupal.org/node/2334319 lands.
$this->renderer->addCacheableDependency($column['data'], $username);
$row[] = $column;
if ($latest_revision) {
$row[] = [
'data' => [
'#prefix' => '<em>',
'#markup' => $this->t('Current revision'),
'#suffix' => '</em>',
],
];
foreach ($row as &$current) {
$current['class'] = ['revision-current'];
}
$latest_revision = FALSE;
}
else {
$links = [];
if ($revert_permission) {
$links['revert'] = [
'title' => $this->t('Revert'),
'url' => $has_translations ?
Url::fromRoute('node.revision_revert_translation_confirm', ['node' => $node->id(), 'node_revision' => $vid, 'langcode' => $langcode]) :
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,
],
];
}
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;
}
$rows[] = $row;
}
$build['node_revisions_table'] = array(

View file

@ -7,7 +7,6 @@
namespace Drupal\node\Controller;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\Controller\EntityViewController;
@ -61,7 +60,7 @@ class NodePreviewController extends EntityViewController {
* The page title.
*/
public function title(EntityInterface $node_preview) {
return SafeMarkup::checkPlain($this->entityManager->getTranslationFromContext($node_preview)->label());
return $this->entityManager->getTranslationFromContext($node_preview)->label();
}
}

View file

@ -91,10 +91,15 @@ class Node extends ContentEntityBase implements NodeInterface {
public function preSave(EntityStorageInterface $storage) {
parent::preSave($storage);
// If no owner has been set explicitly, make the current user the owner.
if (!$this->getOwner()) {
$this->setOwnerId(\Drupal::currentUser()->id());
foreach (array_keys($this->getTranslationLanguages()) as $langcode) {
$translation = $this->getTranslation($langcode);
// If no owner has been set explicitly, make the anonymous user the owner.
if (!$translation->getOwner()) {
$translation->setOwnerId(0);
}
}
// If no revision author has been set explicitly, make the node owner the
// revision author.
if (!$this->getRevisionAuthor()) {
@ -176,30 +181,9 @@ class Node extends ContentEntityBase implements NodeInterface {
return \Drupal::entityManager()
->getAccessControlHandler($this->entityTypeId)
->access($this, $operation, $this->prepareLangcode(), $account, $return_as_object);
->access($this, $operation, $account, $return_as_object);
}
/**
* {@inheritdoc}
*/
public function prepareLangcode() {
$langcode = $this->language()->getId();
// If the Language module is enabled, try to use the language from content
// negotiation.
if (\Drupal::moduleHandler()->moduleExists('language')) {
// Load languages the node exists in.
$node_translations = $this->getTranslationLanguages();
// Load the language from content negotiation.
$content_negotiation_langcode = \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->getId();
// If there is a translation available, use it.
if (isset($node_translations[$content_negotiation_langcode])) {
$langcode = $content_negotiation_langcode;
}
}
return $langcode;
}
/**
* {@inheritdoc}
*/
@ -231,13 +215,6 @@ class Node extends ContentEntityBase implements NodeInterface {
return $this;
}
/**
* {@inheritdoc}
*/
public function getChangedTime() {
return $this->get('changed')->value;
}
/**
* {@inheritdoc}
*/
@ -404,7 +381,6 @@ class Node extends ContentEntityBase implements NodeInterface {
->setDescription(t('The username of the content author.'))
->setRevisionable(TRUE)
->setSetting('target_type', 'user')
->setSetting('handler', 'default')
->setDefaultValueCallback('Drupal\node\Entity\Node::getCurrentUserId')
->setTranslatable(TRUE)
->setDisplayOptions('view', array(
@ -497,7 +473,7 @@ class Node extends ContentEntityBase implements NodeInterface {
->setLabel(t('Revision log message'))
->setDescription(t('Briefly describe the changes you have made.'))
->setRevisionable(TRUE)
->setTranslatable(TRUE)
->setDefaultValue('')
->setDisplayOptions('form', array(
'type' => 'string_textarea',
'weight' => 25,

View file

@ -86,7 +86,11 @@ class NodePreviewForm extends FormBase implements ContainerInjectionInterface {
'#options' => array('attributes' => array('class' => array('node-preview-backlink'))) + $query_options,
);
$view_mode_options = $this->getViewModeOptions($node);
$view_mode_options = $this->entityManager->getViewModeOptionsByBundle('node', $node->bundle());
// Unset view modes that are not used in the front end.
unset($view_mode_options['rss']);
unset($view_mode_options['search_index']);
$form['uuid'] = array(
'#type' => 'value',
@ -124,46 +128,4 @@ class NodePreviewForm extends FormBase implements ContainerInjectionInterface {
));
}
/**
* Gets the list of available view modes for the current node.
*
* @param EntityInterface $node
* The node being previewed.
*
* @return array
* List of available view modes for the current node.
*/
protected function getViewModeOptions(EntityInterface $node) {
$load_ids = array();
$view_mode_options = array();
// Load all the node's view modes.
$view_modes = $this->entityManager->getViewModes('node');
// Get the list of available view modes for the current node's bundle.
$ids = $this->configFactory->listAll('core.entity_view_display.node.' . $node->bundle());
foreach ($ids as $id) {
$config_id = str_replace('core.entity_view_display' . '.', '', $id);
$load_ids[] = $config_id;
}
$displays = entity_load_multiple('entity_view_display', $load_ids);
// Generate the display options array.
foreach ($displays as $display) {
$view_mode_name = $display->get('mode');
// Skip view modes that are not used in the front end.
if (in_array($view_mode_name, array('rss', 'search_index'))) {
continue;
}
if ($display->status()) {
$view_mode_options[$view_mode_name] = ($view_mode_name == 'default') ? t('Default') : $view_modes[$view_mode_name]['label'];
}
}
return $view_mode_options;
}
}

View file

@ -7,6 +7,7 @@
namespace Drupal\node\Form;
use Drupal\Core\Datetime\DateFormatter;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Form\ConfirmFormBase;
use Drupal\Core\Form\FormStateInterface;
@ -33,14 +34,24 @@ class NodeRevisionRevertForm extends ConfirmFormBase {
*/
protected $nodeStorage;
/**
* The date formatter service.
*
* @var \Drupal\Core\Datetime\DateFormatter
*/
protected $dateFormatter;
/**
* Constructs a new NodeRevisionRevertForm.
*
* @param \Drupal\Core\Entity\EntityStorageInterface $node_storage
* The node storage.
* @param \Drupal\Core\Datetime\DateFormatter $date_formatter
* The date formatter service.
*/
public function __construct(EntityStorageInterface $node_storage) {
public function __construct(EntityStorageInterface $node_storage, DateFormatter $date_formatter) {
$this->nodeStorage = $node_storage;
$this->dateFormatter = $date_formatter;
}
/**
@ -48,7 +59,8 @@ class NodeRevisionRevertForm extends ConfirmFormBase {
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity.manager')->getStorage('node')
$container->get('entity.manager')->getStorage('node'),
$container->get('date.formatter')
);
}
@ -63,7 +75,7 @@ class NodeRevisionRevertForm extends ConfirmFormBase {
* {@inheritdoc}
*/
public function getQuestion() {
return t('Are you sure you want to revert to the revision from %revision-date?', array('%revision-date' => format_date($this->revision->getRevisionCreationTime())));
return t('Are you sure you want to revert to the revision from %revision-date?', ['%revision-date' => $this->dateFormatter->format($this->revision->getRevisionCreationTime())]);
}
/**
@ -101,17 +113,16 @@ class NodeRevisionRevertForm extends ConfirmFormBase {
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$revision = $this->prepareRevertedRevision($this->revision);
// The revision timestamp will be updated when the revision is saved. Keep
// the original one for the confirmation message.
$original_revision_timestamp = $this->revision->getRevisionCreationTime();
// The revision timestamp will be updated when the revision is saved. Keep the
// original one for the confirmation message.
$original_revision_timestamp = $revision->getRevisionCreationTime();
$revision->revision_log = t('Copy of the revision from %date.', array('%date' => format_date($original_revision_timestamp)));
$this->revision = $this->prepareRevertedRevision($this->revision, $form_state);
$this->revision->revision_log = t('Copy of the revision from %date.', ['%date' => $this->dateFormatter->format($original_revision_timestamp)]);
$this->revision->save();
$revision->save();
$this->logger('content')->notice('@type: reverted %title revision %revision.', array('@type' => $this->revision->bundle(), '%title' => $this->revision->label(), '%revision' => $this->revision->getRevisionId()));
drupal_set_message(t('@type %title has been reverted to the revision from %revision-date.', array('@type' => node_get_type_label($this->revision), '%title' => $this->revision->label(), '%revision-date' => format_date($original_revision_timestamp))));
$this->logger('content')->notice('@type: reverted %title revision %revision.', ['@type' => $this->revision->bundle(), '%title' => $this->revision->label(), '%revision' => $this->revision->getRevisionId()]);
drupal_set_message(t('@type %title has been reverted to the revision from %revision-date.', ['@type' => node_get_type_label($this->revision), '%title' => $this->revision->label(), '%revision-date' => $this->dateFormatter->format($original_revision_timestamp)]));
$form_state->setRedirect(
'entity.node.version_history',
array('node' => $this->revision->id())
@ -123,34 +134,13 @@ class NodeRevisionRevertForm extends ConfirmFormBase {
*
* @param \Drupal\node\NodeInterface $revision
* The revision to be reverted.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*
* @return \Drupal\node\NodeInterface
* The prepared revision ready to be stored.
*/
protected function prepareRevertedRevision(NodeInterface $revision) {
/** @var \Drupal\node\NodeInterface $default_revision */
$default_revision = $this->nodeStorage->load($revision->id());
// If the entity is translated, make sure only translations affected by the
// specified revision are reverted.
$languages = $default_revision->getTranslationLanguages();
if (count($languages) > 1) {
// @todo Instead of processing all the available translations, we should
// let the user decide which translations should be reverted. See
// https://www.drupal.org/node/2465907.
foreach ($languages as $langcode => $language) {
if ($revision->hasTranslation($langcode) && !$revision->getTranslation($langcode)->isRevisionTranslationAffected()) {
$revision_translation = $revision->getTranslation($langcode);
$default_translation = $default_revision->getTranslation($langcode);
foreach ($default_revision->getFieldDefinitions() as $field_name => $definition) {
if ($definition->isTranslatable()) {
$revision_translation->set($field_name, $default_translation->get($field_name)->getValue());
}
}
}
}
}
protected function prepareRevertedRevision(NodeInterface $revision, FormStateInterface $form_state) {
$revision->setNewRevision();
$revision->isDefaultRevision(TRUE);

View file

@ -0,0 +1,123 @@
<?php
/**
* @file
* Contains \Drupal\node\Form\NodeRevisionRevertTranslationForm.
*/
namespace Drupal\node\Form;
use Drupal\Core\Datetime\DateFormatter;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\node\NodeInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides a form for reverting a node revision for a single translation.
*/
class NodeRevisionRevertTranslationForm extends NodeRevisionRevertForm {
/**
* The language to be reverted.
*
* @var string
*/
protected $langcode;
/**
* The language manager.
*
* @var \Drupal\Core\Language\LanguageManagerInterface
*/
protected $languageManager;
/**
* Constructs a new NodeRevisionRevertTranslationForm.
*
* @param \Drupal\Core\Entity\EntityStorageInterface $node_storage
* The node storage.
* @param \Drupal\Core\Datetime\DateFormatter $date_formatter
* The date formatter service.
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
* The language manager.
*/
public function __construct(EntityStorageInterface $node_storage, DateFormatter $date_formatter, LanguageManagerInterface $language_manager) {
parent::__construct($node_storage, $date_formatter);
$this->languageManager = $language_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity.manager')->getStorage('node'),
$container->get('date.formatter'),
$container->get('language_manager')
);
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'node_revision_revert_translation_confirm';
}
/**
* {@inheritdoc}
*/
public function getQuestion() {
return t('Are you sure you want to revert @language translation to the revision from %revision-date?', ['@language' => $this->languageManager->getLanguageName($this->langcode), '%revision-date' => $this->dateFormatter->format($this->revision->getRevisionCreationTime())]);
}
/**
* {@inheritdoc}
*/
public function getDescription() {
return '';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state, $node_revision = NULL, $langcode = NULL) {
$this->langcode = $langcode;
$form = parent::buildForm($form, $form_state, $node_revision);
$form['revert_untranslated_fields'] = array(
'#type' => 'checkbox',
'#title' => $this->t('Revert content shared among translations'),
'#default_value' => FALSE,
);
return $form;
}
/**
* {@inheritdoc}
*/
protected function prepareRevertedRevision(NodeInterface $revision, FormStateInterface $form_state) {
$revert_untranslated_fields = $form_state->getValue('revert_untranslated_fields');
/** @var \Drupal\node\NodeInterface $default_revision */
$latest_revision = $this->nodeStorage->load($revision->id());
$latest_revision_translation = $latest_revision->getTranslation($this->langcode);
$revision_translation = $revision->getTranslation($this->langcode);
foreach ($latest_revision_translation->getFieldDefinitions() as $field_name => $definition) {
if ($definition->isTranslatable() || $revert_untranslated_fields) {
$latest_revision_translation->set($field_name, $revision_translation->get($field_name)->getValue());
}
}
$latest_revision_translation->setNewRevision();
$latest_revision_translation->isDefaultRevision(TRUE);
return $latest_revision_translation;
}
}

View file

@ -60,7 +60,7 @@ class NodeAccessControlHandler extends EntityAccessControlHandler implements Nod
/**
* {@inheritdoc}
*/
public function access(EntityInterface $entity, $operation, $langcode = LanguageInterface::LANGCODE_DEFAULT, AccountInterface $account = NULL, $return_as_object = FALSE) {
public function access(EntityInterface $entity, $operation, AccountInterface $account = NULL, $return_as_object = FALSE) {
$account = $this->prepareUser($account);
if ($account->hasPermission('bypass node access')) {
@ -71,7 +71,7 @@ class NodeAccessControlHandler extends EntityAccessControlHandler implements Nod
$result = AccessResult::forbidden()->cachePerPermissions();
return $return_as_object ? $result : $result->isAllowed();
}
$result = parent::access($entity, $operation, $langcode, $account, TRUE)->cachePerPermissions();
$result = parent::access($entity, $operation, $account, TRUE)->cachePerPermissions();
return $return_as_object ? $result : $result->isAllowed();
}
@ -97,13 +97,12 @@ class NodeAccessControlHandler extends EntityAccessControlHandler implements Nod
/**
* {@inheritdoc}
*/
protected function checkAccess(EntityInterface $node, $operation, $langcode, AccountInterface $account) {
protected function checkAccess(EntityInterface $node, $operation, AccountInterface $account) {
/** @var \Drupal\node\NodeInterface $node */
/** @var \Drupal\node\NodeInterface $translation */
$translation = $node->getTranslation($langcode);
// Fetch information from the node object if possible.
$status = $translation->isPublished();
$uid = $translation->getOwnerId();
$status = $node->isPublished();
$uid = $node->getOwnerId();
// Check if authors can view their own unpublished nodes.
if ($operation === 'view' && !$status && $account->hasPermission('view own unpublished content') && $account->isAuthenticated() && $account->id() == $uid) {
@ -111,7 +110,7 @@ class NodeAccessControlHandler extends EntityAccessControlHandler implements Nod
}
// Evaluate node grants.
return $this->grantStorage->access($node, $operation, $langcode, $account);
return $this->grantStorage->access($node, $operation, $account);
}
/**

View file

@ -83,7 +83,10 @@ class NodeForm extends ContentEntityForm {
if ($preview = $store->get($uuid)) {
/** @var $preview \Drupal\Core\Form\FormStateInterface */
$form_state = $preview;
foreach ($preview->getValues() as $name => $value) {
$form_state->setValue($name, $value);
}
// Rebuild the form.
$form_state->setRebuild();
@ -350,24 +353,6 @@ class NodeForm extends ContentEntityForm {
));
}
/**
* {@inheritdoc}
*/
public function buildEntity(array $form, FormStateInterface $form_state) {
/** @var \Drupal\node\NodeInterface $entity */
$entity = parent::buildEntity($form, $form_state);
// A user might assign the node author by entering a user name in the node
// form, which we then need to translate to a user ID.
// @todo: Remove it when https://www.drupal.org/node/2322525 is pushed.
if (!empty($form_state->getValue('uid')[0]['target_id']) && $account = User::load($form_state->getValue('uid')[0]['target_id'])) {
$entity->setOwnerId($account->id());
}
else {
$entity->setOwnerId(0);
}
return $entity;
}
/**
* {@inheritdoc}
*/

View file

@ -67,14 +67,14 @@ class NodeGrantDatabaseStorage implements NodeGrantDatabaseStorageInterface {
/**
* {@inheritdoc}
*/
public function access(NodeInterface $node, $operation, $langcode, AccountInterface $account) {
public function access(NodeInterface $node, $operation, AccountInterface $account) {
// If no module implements the hook or the node does not have an id there is
// no point in querying the database for access grants.
if (!$this->moduleHandler->getImplementations('node_grants') || !$node->id()) {
// Return the equivalent of the default grant, defined by
// self::writeDefault().
if ($operation === 'view') {
return AccessResult::allowedIf($node->getTranslation($langcode)->isPublished())->cacheUntilEntityChanges($node);
return AccessResult::allowedIf($node->isPublished())->cacheUntilEntityChanges($node);
}
else {
return AccessResult::neutral();
@ -89,7 +89,7 @@ class NodeGrantDatabaseStorage implements NodeGrantDatabaseStorageInterface {
// Check for grants for this node and the correct langcode.
$nids = $query->andConditionGroup()
->condition('nid', $node->id())
->condition('langcode', $langcode);
->condition('langcode', $node->language()->getId());
// If the node is published, also take the default grant into account. The
// default is saved with a node ID of 0.
$status = $node->isPublished();

View file

@ -102,8 +102,6 @@ interface NodeGrantDatabaseStorageInterface {
* @param string $operation
* The entity operation. Usually one of 'view', 'edit', 'create' or
* 'delete'.
* @param string $langcode
* The language code for which to check access.
* @param \Drupal\Core\Session\AccountInterface $account
* The user for which to check access.
*
@ -115,7 +113,7 @@ interface NodeGrantDatabaseStorageInterface {
* @see hook_node_access_records()
* @see \Drupal\node\NodeGrantDatabaseStorageInterface::writeDefault()
*/
public function access(NodeInterface $node, $operation, $langcode, AccountInterface $account);
public function access(NodeInterface $node, $operation, AccountInterface $account);
/**
* Counts available node grants.

View file

@ -160,12 +160,4 @@ interface NodeInterface extends ContentEntityInterface, EntityChangedInterface,
*/
public function setRevisionAuthorId($uid);
/**
* Prepares the langcode for a node.
*
* @return string
* The langcode for this node.
*/
public function prepareLangcode();
}

View file

@ -7,7 +7,7 @@
namespace Drupal\node;
use Drupal\Core\Datetime\DateFormatter;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityListBuilder;
use Drupal\Core\Entity\EntityStorageInterface;
@ -26,7 +26,7 @@ class NodeListBuilder extends EntityListBuilder {
/**
* The date formatter service.
*
* @var \Drupal\Core\Datetime\DateFormatter
* @var \Drupal\Core\Datetime\DateFormatterInterface
*/
protected $dateFormatter;
@ -44,12 +44,12 @@ class NodeListBuilder extends EntityListBuilder {
* The entity type definition.
* @param \Drupal\Core\Entity\EntityStorageInterface $storage
* The entity storage class.
* @param \Drupal\Core\Datetime\DateFormatter $date_formatter
* @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
* The date formatter service.
* @param \Drupal\Core\Routing\RedirectDestinationInterface $redirect_destination
* The redirect destination service.
*/
public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, DateFormatter $date_formatter, RedirectDestinationInterface $redirect_destination) {
public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, DateFormatterInterface $date_formatter, RedirectDestinationInterface $redirect_destination) {
parent::__construct($entity_type, $storage);
$this->dateFormatter = $date_formatter;

View file

@ -78,10 +78,8 @@ class NodeTranslationHandler extends ContentTranslationHandler {
if ($form_state->hasValue('content_translation')) {
$translation = &$form_state->getValue('content_translation');
$translation['status'] = $entity->isPublished();
// $form['content_translation']['name'] is the equivalent field
// for translation author uid.
$account = $entity->uid->entity;
$translation['name'] = $account ? $account->getUsername() : '';
$translation['uid'] = $account ? $account->id() : 0;
$translation['created'] = format_date($entity->created->value, 'custom', 'Y-m-d H:i:s O');
}
parent::entityFormEntityBuild($entity_type, $entity, $form, $form_state);

View file

@ -22,16 +22,25 @@ class NodeTypeAccessControlHandler extends EntityAccessControlHandler {
/**
* {@inheritdoc}
*/
protected function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) {
if ($operation == 'delete') {
if ($entity->isLocked()) {
return AccessResult::forbidden()->cacheUntilEntityChanges($entity);
}
else {
return parent::checkAccess($entity, $operation, $langcode, $account)->cacheUntilEntityChanges($entity);
}
protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
switch ($operation) {
case 'view':
return AccessResult::allowedIfHasPermission($account, 'access content');
break;
case 'delete':
if ($entity->isLocked()) {
return AccessResult::forbidden()->cacheUntilEntityChanges($entity);
}
else {
return parent::checkAccess($entity, $operation, $account)->cacheUntilEntityChanges($entity);
}
break;
default:
return parent::checkAccess($entity, $operation, $account);
break;
}
return parent::checkAccess($entity, $operation, $langcode, $account);
}
}

View file

@ -7,18 +7,17 @@
namespace Drupal\node;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\BundleEntityFormBase;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\language\Entity\ContentLanguageSettings;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Form controller for node type forms.
*/
class NodeTypeForm extends EntityForm {
class NodeTypeForm extends BundleEntityFormBase {
/**
* The entity manager.
@ -31,7 +30,7 @@ class NodeTypeForm extends EntityForm {
* Constructs the NodeTypeForm object.
*
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager
* The entity manager.
*/
public function __construct(EntityManagerInterface $entity_manager) {
$this->entityManager = $entity_manager;
@ -96,7 +95,7 @@ class NodeTypeForm extends EntityForm {
'#title' => t('Description'),
'#type' => 'textarea',
'#default_value' => $type->getDescription(),
'#description' => t('Describe this content type. The text will be displayed on the <em>Add content</em> page.'),
'#description' => t('This text will be displayed on the <em>Add new content</em> page.'),
);
$form['additional_settings'] = array(
@ -148,7 +147,8 @@ class NodeTypeForm extends EntityForm {
// Prepare workflow options to be used for 'checkboxes' form element.
$keys = array_keys(array_filter($workflow_options));
$workflow_options = array_combine($keys, $keys);
$form['workflow']['options'] = array('#type' => 'checkboxes',
$form['workflow']['options'] = array(
'#type' => 'checkboxes',
'#title' => t('Default options'),
'#default_value' => $workflow_options,
'#options' => array(
@ -187,7 +187,8 @@ class NodeTypeForm extends EntityForm {
'#default_value' => $type->displaySubmitted(),
'#description' => t('Author username and publish date will be displayed.'),
);
return $form;
return $this->protectBundleIdElement($form);
}
/**
@ -247,7 +248,7 @@ class NodeTypeForm extends EntityForm {
// @todo Make it possible to get default values without an entity.
// https://www.drupal.org/node/2318187
$node = $this->entityManager->getStorage('node')->create(array('type' => $type->id()));
foreach (array('status', 'promote', 'sticky') as $field_name) {
foreach (array('status', 'promote', 'sticky') as $field_name) {
$value = (bool) $form_state->getValue(['options', $field_name]);
if ($node->$field_name->value != $value) {
$fields[$field_name]->getConfig($type->id())->setDefaultValue($value)->save();

View file

@ -60,8 +60,8 @@ class NodeTypeListBuilder extends ConfigEntityListBuilder {
*/
public function render() {
$build = parent::render();
$build['table']['#empty'] = $this->t('No content types available. <a href="@link">Add content type</a>.', [
'@link' => Url::fromRoute('node.type_add')->toString()
$build['table']['#empty'] = $this->t('No content types available. <a href=":link">Add content type</a>.', [
':link' => Url::fromRoute('node.type_add')->toString()
]);
return $build;
}

View file

@ -21,13 +21,13 @@ class NodeViewBuilder extends EntityViewBuilder {
/**
* {@inheritdoc}
*/
public function buildComponents(array &$build, array $entities, array $displays, $view_mode, $langcode = NULL) {
public function buildComponents(array &$build, array $entities, array $displays, $view_mode) {
/** @var \Drupal\node\NodeInterface[] $entities */
if (empty($entities)) {
return;
}
parent::buildComponents($build, $entities, $displays, $view_mode, $langcode);
parent::buildComponents($build, $entities, $displays, $view_mode);
foreach ($entities as $id => $entity) {
$bundle = $entity->bundle();
@ -38,10 +38,9 @@ class NodeViewBuilder extends EntityViewBuilder {
'#lazy_builder' => [get_called_class() . '::renderLinks', [
$entity->id(),
$view_mode,
$langcode,
$entity->language()->getId(),
!empty($entity->in_preview),
]],
'#create_placeholder' => TRUE,
);
}
@ -61,8 +60,8 @@ class NodeViewBuilder extends EntityViewBuilder {
/**
* {@inheritdoc}
*/
protected function getBuildDefaults(EntityInterface $entity, $view_mode, $langcode) {
$defaults = parent::getBuildDefaults($entity, $view_mode, $langcode);
protected function getBuildDefaults(EntityInterface $entity, $view_mode) {
$defaults = parent::getBuildDefaults($entity, $view_mode);
// Don't cache nodes that are in 'preview' mode.
if (isset($defaults['#cache']) && isset($entity->in_preview)) {
@ -149,9 +148,9 @@ class NodeViewBuilder extends EntityViewBuilder {
/**
* {@inheritdoc}
*/
protected function alterBuild(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode, $langcode = NULL) {
protected function alterBuild(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
/** @var \Drupal\node\NodeInterface $entity */
parent::alterBuild($build, $entity, $display, $view_mode, $langcode);
parent::alterBuild($build, $entity, $display, $view_mode);
if ($entity->id()) {
$build['#contextual_links']['node'] = array(
'route_parameters' =>array('node' => $entity->id()),

View file

@ -24,7 +24,7 @@ class NodeViewsData extends EntityViewsData {
$data['node_field_data']['table']['base']['access query tag'] = 'node_access';
$data['node_field_data']['table']['wizard_id'] = 'node';
$data['node_field_data']['nid']['field']['argument'] = [
$data['node_field_data']['nid']['argument'] = [
'id' => 'node_nid',
'name field' => 'title',
'numeric' => TRUE,

View file

@ -50,27 +50,4 @@ class SyndicateBlock extends BlockBase {
);
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form = parent::buildConfigurationForm($form, $form_state);
// @see ::getCacheMaxAge()
$form['cache']['#disabled'] = TRUE;
$form['cache']['max_age']['#value'] = Cache::PERMANENT;
$form['cache']['#description'] = $this->t('This block is always cached forever, it is not configurable.');
return $form;
}
/**
* {@inheritdoc}
*/
public function getCacheMaxAge() {
// The 'Syndicate' block is permanently cacheable, because its
// contents can never change.
return Cache::PERMANENT;
}
}

View file

@ -7,7 +7,7 @@
namespace Drupal\node\Plugin\EntityReferenceSelection;
use Drupal\Core\Entity\Plugin\EntityReferenceSelection\SelectionBase;
use Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection;
use Drupal\Core\Form\FormStateInterface;
/**
@ -21,7 +21,7 @@ use Drupal\Core\Form\FormStateInterface;
* weight = 1
* )
*/
class NodeSelection extends SelectionBase {
class NodeSelection extends DefaultSelection {
/**
* {@inheritdoc}

View file

@ -8,6 +8,7 @@
namespace Drupal\node\Plugin\Search;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Config\Config;
use Drupal\Core\Database\Connection;
use Drupal\Core\Database\Query\SelectExtender;
@ -167,6 +168,8 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
$this->renderer = $renderer;
$this->account = $account;
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->addCacheTags(['node_list']);
}
/**
@ -333,9 +336,10 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
// Fetch comments for snippet.
$rendered = $this->renderer->renderPlain($build);
$rendered .= ' ' . $this->moduleHandler->invoke('comment', 'node_update_index', array($node, $item->langcode));
$this->addCacheableDependency(CacheableMetadata::createFromRenderArray($build));
$rendered .= ' ' . $this->moduleHandler->invoke('comment', 'node_update_index', [$node]);
$extra = $this->moduleHandler->invokeAll('node_search_result', array($node, $item->langcode));
$extra = $this->moduleHandler->invokeAll('node_search_result', [$node]);
$language = $this->languageManager->getLanguage($item->langcode);
$username = array(
@ -354,6 +358,14 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
'langcode' => $node->language()->getId(),
);
$this->addCacheableDependency($node);
// We have to separately add the node owner's cache tags because search
// module doesn't use the rendering system, it does its own rendering
// without taking cacheability metadata into account. So we have to do it
// explicitly here.
$this->addCacheableDependency($node->getOwner());
if ($type->displaySubmitted()) {
$result += array(
'user' => $this->renderer->renderPlain($username),
@ -449,14 +461,14 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
// Add the title to text so it is searchable.
$build['search_title'] = [
'#prefix' => '<h1>',
'#plain_text' => $node->label($language->getId()),
'#plain_text' => $node->label(),
'#suffix' => '</h1>',
'#weight' => -1000
];
$text = $this->renderer->renderPlain($build);
// Fetch extra data normally not visible.
$extra = $this->moduleHandler->invokeAll('node_update_index', array($node, $language->getId()));
$extra = $this->moduleHandler->invokeAll('node_update_index', [$node]);
foreach ($extra as $t) {
$text .= $t;
}
@ -554,7 +566,7 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
);
// Add node types.
$types = array_map(array('\Drupal\Component\Utility\SafeMarkup', 'checkPlain'), node_type_get_names());
$types = array_map(array('\Drupal\Component\Utility\Html', 'escape'), node_type_get_names());
$form['advanced']['types-fieldset'] = array(
'#type' => 'fieldset',
'#title' => t('Types'),

View file

@ -8,45 +8,35 @@
namespace Drupal\node\Plugin\migrate\builder\d6;
use Drupal\migrate\Entity\Migration;
use Drupal\migrate\Entity\MigrationInterface;
use Drupal\migrate_drupal\Plugin\migrate\builder\d6\CckBuilder;
use Drupal\migrate\Exception\RequirementsException;
use Drupal\migrate_drupal\Plugin\migrate\builder\CckBuilder;
/**
* @PluginID("d6_node")
*/
class Node extends CckBuilder {
/**
* Already-instantiated cckfield plugins, keyed by ID.
*
* @var \Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface[]
*/
protected $cckPluginCache = [];
/**
* Gets a cckfield plugin instance.
*
* @param string $field_type
* The field type (plugin ID).
* @param \Drupal\migrate\Entity\MigrationInterface|NULL $migration
* The migration, if any.
*
* @return \Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface
* The cckfield plugin instance.
*/
protected function getCckPlugin($field_type, MigrationInterface $migration = NULL) {
if (empty($this->cckPluginCache[$field_type])) {
$this->cckPluginCache[$field_type] = $this->cckPluginManager->createInstance($field_type, [], $migration);
}
return $this->cckPluginCache[$field_type];
}
/**
* {@inheritdoc}
*/
public function buildMigrations(array $template) {
$migrations = [];
// Read all CCK field instance definitions in the source database.
$fields = array();
$source_plugin = $this->getSourcePlugin('d6_field_instance', $template['source']);
try {
$source_plugin->checkRequirements();
foreach ($source_plugin as $field) {
$info = $field->getSource();
$fields[$info['type_name']][$info['field_name']] = $info;
}
}
catch (RequirementsException $e) {
// Don't do anything; $fields will be empty.
}
foreach ($this->getSourcePlugin('d6_node_type', $template['source']) as $row) {
$node_type = $row->getSourceProperty('type');
$values = $template;
@ -56,16 +46,15 @@ class Node extends CckBuilder {
$values['source']['node_type'] = $node_type;
$migration = Migration::create($values);
$fields = $this->getSourcePlugin('d6_field_instance', ['node_type' => $node_type] + $template['source']);
foreach ($fields as $field) {
$data = $field->getSource();
if ($this->cckPluginManager->hasDefinition($data['type'])) {
$this->getCckPlugin($data['type'])
->processCckFieldValues($migration, $data['field_name'], $data);
}
else {
$migration->setProcessOfProperty($data['field_name'], $data['field_name']);
if (isset($fields[$node_type])) {
foreach ($fields[$node_type] as $field => $info) {
if ($this->cckPluginManager->hasDefinition($info['type'])) {
$this->getCckPlugin($info['type'])
->processCckFieldValues($migration, $field, $info);
}
else {
$migration->setProcessOfProperty($field, $field);
}
}
}

View file

@ -8,12 +8,12 @@
namespace Drupal\node\Plugin\migrate\builder\d7;
use Drupal\migrate\Entity\Migration;
use Drupal\migrate\Plugin\migrate\builder\BuilderBase;
use Drupal\migrate_drupal\Plugin\migrate\builder\CckBuilder;
/**
* @PluginID("d7_node")
*/
class Node extends BuilderBase {
class Node extends CckBuilder {
/**
* {@inheritdoc}
@ -21,12 +21,11 @@ class Node extends BuilderBase {
public function buildMigrations(array $template) {
$migrations = [];
$fields = [];
// Read all field instance definitions in the source database.
$fields = array();
foreach ($this->getSourcePlugin('d7_field_instance', $template['source']) as $field) {
$entity_type = $field->getSourceProperty('entity_type');
$bundle = $field->getSourceProperty('bundle');
$field_name = $field->getSourceProperty('field_name');
$fields[$entity_type][$bundle][$field_name] = $field->getSource();
$info = $field->getSource();
$fields[$info['entity_type']][$info['bundle']][$info['field_name']] = $info;
}
foreach ($this->getSourcePlugin('d7_node_type', $template['source']) as $node_type) {
@ -38,8 +37,14 @@ class Node extends BuilderBase {
$migration = Migration::create($values);
if (isset($fields['node'][$bundle])) {
foreach (array_keys($fields['node'][$bundle]) as $field) {
$migration->setProcessOfProperty($field, $field);
foreach ($fields['node'][$bundle] as $field => $data) {
if ($this->cckPluginManager->hasDefinition($data['type'])) {
$this->getCckPlugin($data['type'])
->processCckFieldValues($migration, $field, $data);
}
else {
$migration->setProcessOfProperty($field, $field);
}
}
}

View file

@ -7,7 +7,6 @@
namespace Drupal\node\Plugin\views\argument;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\views\Plugin\views\argument\StringArgument;
use Symfony\Component\DependencyInjection\ContainerInterface;
@ -76,7 +75,7 @@ class Type extends StringArgument {
function node_type($type_name) {
$type = $this->nodeTypeStorage->load($type_name);
$output = $type ? $type->label() : $this->t('Unknown content type');
return SafeMarkup::checkPlain($output);
return $output;
}
}

View file

@ -7,8 +7,9 @@
namespace Drupal\node\Plugin\views\argument_default;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheableDependencyInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\views\Plugin\CacheablePluginInterface;
use Drupal\views\Plugin\views\argument_default\ArgumentDefaultPluginBase;
use Drupal\node\NodeInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
@ -23,7 +24,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
* title = @Translation("Content ID from URL")
* )
*/
class Node extends ArgumentDefaultPluginBase implements CacheablePluginInterface {
class Node extends ArgumentDefaultPluginBase implements CacheableDependencyInterface {
/**
* The route match.
@ -75,8 +76,8 @@ class Node extends ArgumentDefaultPluginBase implements CacheablePluginInterface
/**
* {@inheritdoc}
*/
public function isCacheable() {
return TRUE;
public function getCacheMaxAge() {
return Cache::PERMANENT;
}
/**

View file

@ -7,7 +7,6 @@
namespace Drupal\node\Plugin\views\row;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\views\Plugin\views\row\RssPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
@ -78,7 +77,7 @@ class Rss extends RssPluginBase {
public function summaryTitle() {
$options = $this->buildOptionsForm_summary_options();
return SafeMarkup::checkPlain($options[$this->options['view_mode']]);
return $options[$this->options['view_mode']];
}
public function preRender($values) {
@ -122,7 +121,7 @@ class Rss extends RssPluginBase {
),
array(
'key' => 'dc:creator',
'value' => $node->getOwner()->getUsername(),
'value' => $node->getOwner()->getDisplayName(),
),
array(
'key' => 'guid',

View file

@ -22,7 +22,7 @@ class NodeImportChangeTest extends KernelTestBase {
*
* @var array
*/
public static $modules = array('node', 'field', 'text', 'system', 'node_test_config', 'user', 'entity_reference');
public static $modules = ['node', 'field', 'text', 'system', 'node_test_config', 'user'];
/**
* Set the default field storage backend for fields created during tests.
@ -44,16 +44,16 @@ class NodeImportChangeTest extends KernelTestBase {
// Simulate config data to import:
// - a modified version (modified label) of the node type config.
$active = $this->container->get('config.storage');
$staging = $this->container->get('config.storage.staging');
$this->copyConfig($active, $staging);
$sync = $this->container->get('config.storage.sync');
$this->copyConfig($active, $sync);
$node_type = $active->read($node_type_config_name);
$new_label = 'Test update import field';
$node_type['name'] = $new_label;
// Save as files in the staging directory.
$staging->write($node_type_config_name, $node_type);
// Save as files in the sync directory.
$sync->write($node_type_config_name, $node_type);
// Import the content of the staging directory.
// Import the content of the sync directory.
$this->configImporter()->import();
// Check that the updated config was correctly imported.

View file

@ -23,7 +23,7 @@ class NodeImportCreateTest extends KernelTestBase {
*
* @var array
*/
public static $modules = array('node', 'field', 'text', 'system', 'user', 'entity_reference');
public static $modules = array('node', 'field', 'text', 'system', 'user');
/**
* Set the default field storage backend for fields created during tests.
@ -61,19 +61,19 @@ class NodeImportCreateTest extends KernelTestBase {
// Simulate config data to import.
$active = $this->container->get('config.storage');
$staging = $this->container->get('config.storage.staging');
$this->copyConfig($active, $staging);
$sync = $this->container->get('config.storage.sync');
$this->copyConfig($active, $sync);
// Manually add new node type.
$src_dir = drupal_get_path('module', 'node_test_config') . '/staging';
$target_dir = $this->configDirectories[CONFIG_STAGING_DIRECTORY];
$src_dir = drupal_get_path('module', 'node_test_config') . '/sync';
$target_dir = $this->configDirectories[CONFIG_SYNC_DIRECTORY];
$this->assertTrue(file_unmanaged_copy("$src_dir/$node_type_config_name.yml", "$target_dir/$node_type_config_name.yml"));
// Import the content of the staging directory.
// Import the content of the sync directory.
$this->configImporter()->import();
// Check that the content type was created.
$node_type = NodeType::load($node_type_id);
$this->assertTrue($node_type, 'Import node type from staging was created.');
$this->assertTrue($node_type, 'Import node type from sync was created.');
$this->assertFalse(FieldConfig::loadByName('node', $node_type_id, 'body'));
}

View file

@ -7,6 +7,7 @@
namespace Drupal\node\Tests\Migrate\d6;
use Drupal\migrate\Entity\MigrationInterface;
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
use Drupal\migrate\Entity\Migration;
@ -15,7 +16,10 @@ use Drupal\migrate\Entity\Migration;
*/
class MigrateNodeBuilderTest extends MigrateDrupal6TestBase {
public static $modules = ['migrate', 'migrate_drupal', 'node'];
/**
* @var MigrationInterface[]
*/
protected $builtMigrations = [];
/**
* Asserts various aspects of a migration entity.
@ -26,10 +30,10 @@ class MigrateNodeBuilderTest extends MigrateDrupal6TestBase {
* The label.
*/
protected function assertEntity($id, $label) {
$migration = Migration::load($id);
$migration = $this->builtMigrations[$id];
$this->assertTrue($migration instanceof Migration);
$this->assertIdentical($id, $migration->Id());
$this->assertIdentical($label, $migration->label());
$this->assertIdentical($id, $migration->id());
$this->assertEqual($label, $migration->label());
}
/**
@ -58,7 +62,11 @@ class MigrateNodeBuilderTest extends MigrateDrupal6TestBase {
];
$migrations = \Drupal::service('migrate.migration_builder')->createMigrations($templates);
$this->assertIdentical(11, count($migrations));
// Key the array.
foreach ($migrations as $migration) {
$this->builtMigrations[$migration->id()] = $migration;
}
$this->assertIdentical(11, count($this->builtMigrations));
$this->assertEntity('d6_node__article', 'Drupal 6 nodes (article)');
$this->assertEntity('d6_node__company', 'Drupal 6 nodes (company)');
$this->assertEntity('d6_node__employee', 'Drupal 6 nodes (employee)');

View file

@ -7,7 +7,9 @@
namespace Drupal\node\Tests\Migrate\d6;
use Drupal\Core\Field\Entity\BaseFieldOverride;
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
use Drupal\node\Entity\Node;
/**
* Test migrating node settings into the base_field_bundle_override config entity.
@ -16,71 +18,46 @@ use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
*/
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();
$this->installConfig(['node']);
$this->executeMigration('d6_node_type');
// Create a config entity that already exists.
entity_create('base_field_override', array('field_name' => 'promote', 'entity_type' => 'node', 'bundle' => 'page',))->save();
BaseFieldOverride::create([
'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->executeMigration('d6_node_setting_promote');
$this->executeMigration('d6_node_setting_status');
$this->executeMigration('d6_node_setting_sticky');
$this->executeMigrations([
'd6_node_setting_promote',
'd6_node_setting_status',
'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'));
$node = Node::create(['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'));
$node = Node::create(['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'));
$node = Node::create(['type' => 'test_event']);
$this->assertIdentical(0, $node->status->value);
$this->assertIdentical(0, $node->promote->value);
$this->assertIdentical(1, $node->sticky->value);

View file

@ -19,13 +19,6 @@ class MigrateNodeConfigsTest extends MigrateDrupal6TestBase {
use SchemaCheckTestTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('node');
/**
* {@inheritdoc}
*/

View file

@ -7,7 +7,6 @@
namespace Drupal\node\Tests\Migrate\d6;
use Drupal\Core\Database\Database;
use Drupal\migrate\Entity\Migration;
/**
@ -22,24 +21,7 @@ class MigrateNodeRevisionTest extends MigrateNodeTestBase {
*/
protected function setUp() {
parent::setUp();
$id_mappings = array(
'd6_node:*' => array(
array(array(1), array(1)),
),
);
$this->prepareMigrations($id_mappings);
// 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();
}
$migrations = Migration::loadMultiple(['d6_node_revision:*']);
array_walk($migrations, [$this, 'executeMigration']);
$this->executeMigrations(['d6_node:*', 'd6_node_revision:*']);
}
/**

View file

@ -0,0 +1,37 @@
<?php
/**
* @file
* Contains \Drupal\node\Tests\Migrate\d6\MigrateNodeSettingPromoteTest.
*/
namespace Drupal\node\Tests\Migrate\d6;
use Drupal\Core\Field\Entity\BaseFieldOverride;
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
/**
* @group migrate_drupal_6
*/
class MigrateNodeSettingPromoteTest extends MigrateDrupal6TestBase {
public static $modules = ['node', 'text'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig(['node']);
$this->executeMigration('d6_node_type');
$this->executeMigration('d6_node_setting_promote');
}
/**
* Tests migration of the promote checkbox's settings.
*/
public function testMigration() {
$this->assertIdentical('Promoted to front page', BaseFieldOverride::load('node.article.promote')->label());
}
}

View file

@ -0,0 +1,37 @@
<?php
/**
* @file
* Contains \Drupal\node\Tests\Migrate\d6\MigrateNodeSettingStickyTest.
*/
namespace Drupal\node\Tests\Migrate\d6;
use Drupal\Core\Field\Entity\BaseFieldOverride;
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
/**
* @group migrate_drupal_6
*/
class MigrateNodeSettingStickyTest extends MigrateDrupal6TestBase {
public static $modules = ['node', 'text'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig(['node']);
$this->executeMigration('d6_node_type');
$this->executeMigration('d6_node_setting_sticky');
}
/**
* Tests migration of the sticky checkbox's settings.
*/
public function testMigration() {
$this->assertIdentical('Sticky at the top of lists', BaseFieldOverride::load('node.article.sticky')->label());
}
}

View file

@ -23,14 +23,10 @@ class MigrateNodeTest extends MigrateNodeTestBase {
*/
protected function setUp() {
parent::setUp();
// Each node type is imported separately. In this test, we're asserting
// on story and test_planet nodes.
$this->executeMigration('d6_node__test_planet');
$this->executeMigration('d6_node__story');
$this->executeMigrations(['d6_node:*']);
// This is required for the second import below.
\Drupal::database()->truncate(Migration::load('d6_node__story')->getIdMap()->mapTableName())->execute();
$this->standalone = TRUE;
}
/**
@ -57,11 +53,6 @@ class MigrateNodeTest extends MigrateNodeTestBase {
// This is empty on the first revision.
$this->assertIdentical(NULL, $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')
@ -83,10 +74,6 @@ class MigrateNodeTest extends MigrateNodeTestBase {
// 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

@ -16,8 +16,6 @@ use Drupal\user\Entity\User;
*/
abstract class MigrateNodeTestBase extends MigrateDrupal6TestBase {
static $modules = array('node', 'text', 'filter', 'entity_reference');
/**
* {@inheritdoc}
*/
@ -36,66 +34,11 @@ abstract class MigrateNodeTestBase extends MigrateDrupal6TestBase {
'uid' => 1,
'name' => $this->randomMachineName(),
'status' => 1,
])->enforceIsNew(TRUE)->save();
])->enforceIsNew()->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' => '',
'title' => $this->randomString(),
));
$node->enforceIsNew();
$node->save();
$node = entity_create('node', array(
'type' => 'test_planet',
'nid' => 3,
'vid' => 4,
'revision_log' => '',
'title' => $this->randomString(),
));
$node->enforceIsNew();
$node->save();
$this->migrateUsers(FALSE);
$this->migrateFields();
$this->executeMigration('d6_node_settings');
}
}

View file

@ -8,6 +8,7 @@
namespace Drupal\node\Tests\Migrate\d6;
use Drupal\field\Entity\FieldConfig;
use Drupal\migrate\Entity\Migration;
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
use Drupal\node\Entity\NodeType;
@ -18,19 +19,12 @@ use Drupal\node\Entity\NodeType;
*/
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->installConfig(['node']);
$this->executeMigration('d6_node_type');
}
@ -38,14 +32,14 @@ class MigrateNodeTypeTest extends MigrateDrupal6TestBase {
* Tests Drupal 6 node type to Drupal 8 migration.
*/
public function testNodeType() {
$migration = entity_load('migration', 'd6_node_type');
$id_map = Migration::load('d6_node_type')->getIdMap();
// 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'));
$this->assertIdentical($id_map->lookupDestinationID(array('test_page')), array('test_page'));
// Test we have a body field.
$field = FieldConfig::loadByName('node', 'test_page', 'body');
@ -58,7 +52,7 @@ class MigrateNodeTypeTest extends MigrateDrupal6TestBase {
$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'));
$this->assertIdentical($id_map->lookupDestinationID(array('test_story')), array('test_story'));
// Test we don't have a body field.
$field = FieldConfig::loadByName('node', 'test_story', 'body');
@ -71,7 +65,7 @@ class MigrateNodeTypeTest extends MigrateDrupal6TestBase {
$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'));
$this->assertIdentical($id_map->lookupDestinationID(array('test_event')), array('test_event'));
// Test we have a body field.
$field = FieldConfig::loadByName('node', 'test_event', 'body');

View file

@ -8,6 +8,7 @@
namespace Drupal\node\Tests\Migrate\d6;
use Drupal\Core\Entity\Entity\EntityViewMode;
use Drupal\migrate\Entity\Migration;
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
/**
@ -17,13 +18,6 @@ use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
*/
class MigrateViewModesTest extends MigrateDrupal6TestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('node');
/**
* {@inheritdoc}
*/
@ -40,8 +34,8 @@ class MigrateViewModesTest extends MigrateDrupal6TestBase {
$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)));
// Test the ID map.
$this->assertIdentical(array('node', 'preview'), Migration::load('d6_view_modes')->getIdMap()->lookupDestinationID(array(1)));
}
}

View file

@ -18,7 +18,17 @@ use Drupal\node\NodeInterface;
*/
class MigrateNodeTest extends MigrateDrupal7TestBase {
static $modules = array('node', 'text', 'filter', 'entity_reference');
static $modules = array(
'comment',
'datetime',
'filter',
'image',
'link',
'node',
'taxonomy',
'telephone',
'text',
);
/**
* {@inheritdoc}
@ -27,14 +37,21 @@ class MigrateNodeTest extends MigrateDrupal7TestBase {
parent::setUp();
$this->installEntitySchema('node');
$this->installConfig(['node']);
$this->installEntitySchema('comment');
$this->installEntitySchema('taxonomy_term');
$this->installConfig(static::$modules);
$this->installSchema('node', ['node_access']);
$this->installSchema('system', ['sequences']);
$this->executeMigration('d7_user_role');
$this->executeMigration('d7_user');
$this->executeMigration('d7_node_type');
$this->executeMigration('d7_node__test_content_type');
$this->executeMigrations([
'd7_user_role',
'd7_user',
'd7_node_type',
'd7_comment_type',
'd7_field',
'd7_field_instance',
'd7_node__test_content_type',
]);
}
/**
@ -107,6 +124,16 @@ class MigrateNodeTest extends MigrateDrupal7TestBase {
public function testNode() {
$this->assertEntity(1, 'test_content_type', 'en', 'A Node', '2', TRUE, '1421727515', '1441032132', TRUE, FALSE);
$this->assertRevision(1, 'A Node', '2', NULL, '1441032132');
$node = Node::load(1);
$this->assertTrue($node->field_boolean->value);
$this->assertIdentical('99-99-99-99', $node->field_phone->value);
// Use assertEqual() here instead, since SQLite interprets floats strictly.
$this->assertEqual('1', $node->field_float->value);
$this->assertIdentical('5', $node->field_integer->value);
$this->assertIdentical('Some more text', $node->field_text_list[0]->value);
$this->assertIdentical('7', $node->field_integer_list[0]->value);
$this->assertIdentical('qwerty', $node->field_text->value);
}
}

View file

@ -26,8 +26,7 @@ class MigrateNodeTitleLabelTest extends MigrateDrupal7TestBase {
parent::setUp();
$this->installConfig(static::$modules);
$this->installEntitySchema('node');
$this->executeMigration('d7_node_type');
$this->executeMigration('d7_node_title_label');
$this->executeMigrations(['d7_node_type', 'd7_node_title_label']);
}
/**

View file

@ -30,21 +30,21 @@ class NodeAccessLanguageAwareCombinationTest extends NodeTestBase {
/**
* A set of nodes to use in testing.
*
* @var array
* @var \Drupal\node\NodeInterface[]
*/
protected $nodes = array();
/**
* A normal authenticated user.
*
* @var \Drupal\user\Entity\UserInterface.
* @var \Drupal\user\UserInterface.
*/
protected $webUser;
/**
* User 1.
*
* @var \Drupal\user\Entity\UserInterface.
* @var \Drupal\user\UserInterface.
*/
protected $adminUser;
@ -110,7 +110,7 @@ class NodeAccessLanguageAwareCombinationTest extends NodeTestBase {
'field_private' => array(array('value' => 0)),
'private' => FALSE,
));
$translation = $node->getTranslation('ca');
$translation = $node->addTranslation('ca');
$translation->title->value = $this->randomString();
$translation->field_private->value = 0;
$node->save();
@ -121,7 +121,7 @@ class NodeAccessLanguageAwareCombinationTest extends NodeTestBase {
'field_private' => array(array('value' => 0)),
'private' => TRUE,
));
$translation = $node->getTranslation('ca');
$translation = $node->addTranslation('ca');
$translation->title->value = $this->randomString();
$translation->field_private->value = 0;
$node->save();
@ -132,7 +132,7 @@ class NodeAccessLanguageAwareCombinationTest extends NodeTestBase {
'field_private' => array(array('value' => 1)),
'private' => FALSE,
));
$translation = $node->getTranslation('ca');
$translation = $node->addTranslation('ca');
$translation->title->value = $this->randomString();
$translation->field_private->value = 0;
$node->save();
@ -143,7 +143,7 @@ class NodeAccessLanguageAwareCombinationTest extends NodeTestBase {
'field_private' => array(array('value' => 0)),
'private' => FALSE,
));
$translation = $node->getTranslation('ca');
$translation = $node->addTranslation('ca');
$translation->title->value = $this->randomString();
$translation->field_private->value = 1;
$node->save();
@ -154,7 +154,7 @@ class NodeAccessLanguageAwareCombinationTest extends NodeTestBase {
'field_private' => array(array('value' => 1)),
'private' => FALSE,
));
$translation = $node->getTranslation('ca');
$translation = $node->addTranslation('ca');
$translation->title->value = $this->randomString();
$translation->field_private->value = 1;
$node->save();
@ -165,7 +165,7 @@ class NodeAccessLanguageAwareCombinationTest extends NodeTestBase {
'field_private' => array(array('value' => 1)),
'private' => TRUE,
));
$translation = $node->getTranslation('ca');
$translation = $node->addTranslation('ca');
$translation->title->value = $this->randomString();
$translation->field_private->value = 1;
$node->save();
@ -200,78 +200,58 @@ class NodeAccessLanguageAwareCombinationTest extends NodeTestBase {
$expected_node_access = array('view' => TRUE, 'update' => FALSE, 'delete' => FALSE);
$expected_node_access_no_access = array('view' => FALSE, 'update' => FALSE, 'delete' => FALSE);
// When the node and both translations are public, access should only be
// denied when a translation that does not exist is requested.
// When the node and both translations are public, access should always be
// granted.
$this->assertNodeAccess($expected_node_access, $this->nodes['public_both_public'], $this->webUser);
$this->assertNodeAccess($expected_node_access, $this->nodes['public_both_public'], $this->webUser, 'hu');
$this->assertNodeAccess($expected_node_access, $this->nodes['public_both_public'], $this->webUser, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_both_public'], $this->webUser, 'en');
$this->assertNodeAccess($expected_node_access, $this->nodes['public_both_public']->getTranslation('hu'), $this->webUser);
$this->assertNodeAccess($expected_node_access, $this->nodes['public_both_public']->getTranslation('ca'), $this->webUser);
// If the node is marked private but both existing translations are not,
// access should still be granted, because the grants are additive.
$this->assertNodeAccess($expected_node_access, $this->nodes['private_both_public'], $this->webUser);
$this->assertNodeAccess($expected_node_access, $this->nodes['private_both_public'], $this->webUser, 'hu');
$this->assertNodeAccess($expected_node_access, $this->nodes['private_both_public'], $this->webUser, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_both_public'], $this->webUser, 'en');
$this->assertNodeAccess($expected_node_access, $this->nodes['private_both_public']->getTranslation('hu'), $this->webUser);
$this->assertNodeAccess($expected_node_access, $this->nodes['private_both_public']->getTranslation('ca'), $this->webUser);
// If the node is marked private, but a existing translation is public,
// access should only be granted for the public translation. For a
// translation that does not exist yet (English translation), the access is
// denied. With the Hungarian translation marked as private, but the Catalan
// translation public, the access is granted.
// access should only be granted for the public translation. With the
// Hungarian translation marked as private, but the Catalan translation
// public, the access is granted.
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_hu_private'], $this->webUser);
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_hu_private'], $this->webUser, 'hu');
$this->assertNodeAccess($expected_node_access, $this->nodes['public_hu_private'], $this->webUser, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_hu_private'], $this->webUser, 'en');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_hu_private']->getTranslation('hu'), $this->webUser);
$this->assertNodeAccess($expected_node_access, $this->nodes['public_hu_private']->getTranslation('ca'), $this->webUser);
// With the Catalan translation marked as private, but the node public,
// access is granted for the existing Hungarian translation, but not for the
// Catalan nor the English ones.
// Catalan.
$this->assertNodeAccess($expected_node_access, $this->nodes['public_ca_private'], $this->webUser);
$this->assertNodeAccess($expected_node_access, $this->nodes['public_ca_private'], $this->webUser, 'hu');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_ca_private'], $this->webUser, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_ca_private'], $this->webUser, 'en');
$this->assertNodeAccess($expected_node_access, $this->nodes['public_ca_private']->getTranslation('hu'), $this->webUser);
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_ca_private']->getTranslation('ca'), $this->webUser);
// With both translations marked as private, but the node public, access
// should be denied in all cases.
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_both_private'], $this->webUser);
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_both_private'], $this->webUser, 'hu');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_both_private'], $this->webUser, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_both_private'], $this->webUser, 'en');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_both_private']->getTranslation('hu'), $this->webUser);
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_both_private']->getTranslation('ca'), $this->webUser);
// If the node and both its existing translations are private, access should
// be denied in all cases.
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_both_private'], $this->webUser);
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_both_private'], $this->webUser, 'hu');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_both_private'], $this->webUser, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_both_private'], $this->webUser, 'en');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_both_private']->getTranslation('hu'), $this->webUser);
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_both_private']->getTranslation('ca'), $this->webUser);
// No access for all languages as the language aware node access module
// denies access.
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_no_language_private'], $this->webUser);
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_no_language_private'], $this->webUser, 'hu');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_no_language_private'], $this->webUser, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_no_language_private'], $this->webUser, 'en');
// Access only for request with no language defined.
$this->assertNodeAccess($expected_node_access, $this->nodes['public_no_language_public'], $this->webUser);
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_no_language_public'], $this->webUser, 'hu');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_no_language_public'], $this->webUser, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_no_language_public'], $this->webUser, 'en');
// No access for all languages as both node access modules deny access.
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_no_language_private'], $this->webUser);
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_no_language_private'], $this->webUser, 'hu');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_no_language_private'], $this->webUser, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_no_language_private'], $this->webUser, 'en');
// No access for all languages as the non language aware node access module
// denies access.
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_no_language_public'], $this->webUser);
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_no_language_public'], $this->webUser, 'hu');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_no_language_public'], $this->webUser, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_no_language_public'], $this->webUser, 'en');
// Query the node table with the node access tag in several languages.

View file

@ -29,7 +29,7 @@ class NodeAccessLanguageAwareTest extends NodeTestBase {
/**
* A set of nodes to use in testing.
*
* @var array
* @var \Drupal\node\NodeInterface[]
*/
protected $nodes = array();
@ -103,7 +103,7 @@ class NodeAccessLanguageAwareTest extends NodeTestBase {
'langcode' => 'hu',
'field_private' => array(array('value' => 0)),
));
$translation = $node->getTranslation('ca');
$translation = $node->addTranslation('ca');
$translation->title->value = $this->randomString();
$translation->field_private->value = 0;
$node->save();
@ -113,7 +113,7 @@ class NodeAccessLanguageAwareTest extends NodeTestBase {
'langcode' => 'hu',
'field_private' => array(array('value' => 0)),
));
$translation = $node->getTranslation('ca');
$translation = $node->addTranslation('ca');
$translation->title->value = $this->randomString();
$translation->field_private->value = 1;
$node->save();
@ -123,7 +123,7 @@ class NodeAccessLanguageAwareTest extends NodeTestBase {
'langcode' => 'hu',
'field_private' => array(array('value' => 1)),
));
$translation = $node->getTranslation('ca');
$translation = $node->addTranslation('ca');
$translation->title->value = $this->randomString();
$translation->field_private->value = 0;
$node->save();
@ -133,7 +133,7 @@ class NodeAccessLanguageAwareTest extends NodeTestBase {
'langcode' => 'hu',
'field_private' => array(array('value' => 1)),
));
$translation = $node->getTranslation('ca');
$translation = $node->addTranslation('ca');
$translation->title->value = $this->randomString();
$translation->field_private->value = 1;
$node->save();
@ -157,60 +157,42 @@ class NodeAccessLanguageAwareTest extends NodeTestBase {
$expected_node_access_no_access = array('view' => FALSE, 'update' => FALSE, 'delete' => FALSE);
// When both Hungarian and Catalan are marked as public, access to the
// Hungarian translation should be granted when no language is specified or
// Hungarian translation should be granted with the default entity object or
// when the Hungarian translation is specified explicitly.
$this->assertNodeAccess($expected_node_access, $this->nodes['both_public'], $this->webUser);
$this->assertNodeAccess($expected_node_access, $this->nodes['both_public'], $this->webUser, 'hu');
$this->assertNodeAccess($expected_node_access, $this->nodes['both_public']->getTranslation('hu'), $this->webUser);
// Access to the Catalan translation should also be granted.
$this->assertNodeAccess($expected_node_access, $this->nodes['both_public'], $this->webUser, 'ca');
// There is no English translation, so a request to access the English
// translation is denied.
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['both_public'], $this->webUser, 'en');
$this->assertNodeAccess($expected_node_access, $this->nodes['both_public']->getTranslation('ca'), $this->webUser);
// When Hungarian is marked as private, access to the Hungarian translation
// should be denied when no language is specified or when the Hungarian
// should be denied with the default entity object or when the Hungarian
// translation is specified explicitly.
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['hu_private'], $this->webUser);
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['hu_private'], $this->webUser, 'hu');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['hu_private']->getTranslation('hu'), $this->webUser);
// Access to the Catalan translation should be granted.
$this->assertNodeAccess($expected_node_access, $this->nodes['hu_private'], $this->webUser, 'ca');
// There is no English translation, so a request to access the English
// translation is denied.
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['hu_private'], $this->webUser, 'en');
$this->assertNodeAccess($expected_node_access, $this->nodes['hu_private']->getTranslation('ca'), $this->webUser);
// When Catalan is marked as private, access to the Hungarian translation
// should be granted when no language is specified or when the Hungarian
// should be granted with the default entity object or when the Hungarian
// translation is specified explicitly.
$this->assertNodeAccess($expected_node_access, $this->nodes['ca_private'], $this->webUser);
$this->assertNodeAccess($expected_node_access, $this->nodes['ca_private'], $this->webUser, 'hu');
$this->assertNodeAccess($expected_node_access, $this->nodes['ca_private']->getTranslation('hu'), $this->webUser);
// Access to the Catalan translation should be granted.
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['ca_private'], $this->webUser, 'ca');
// There is no English translation, so a request to access the English
// translation is denied.
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['ca_private'], $this->webUser, 'en');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['ca_private']->getTranslation('ca'), $this->webUser);
// When both translations are marked as private, access should be denied
// regardless of the language specified.
// regardless of the entity object specified.
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['both_private'], $this->webUser);
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['both_private'], $this->webUser, 'hu');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['both_private'], $this->webUser, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['both_private'], $this->webUser, 'en');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['both_private']->getTranslation('hu'), $this->webUser);
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['both_private']->getTranslation('ca'), $this->webUser);
// When no language is specified for a private node, access to every
// language is denied.
// When no language is specified for a private node, access to every node
// translation is denied.
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['no_language_private'], $this->webUser);
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['no_language_private'], $this->webUser, 'hu');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['no_language_private'], $this->webUser, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['no_language_private'], $this->webUser, 'en');
// When no language is specified for a public node, access should be granted
// only for the existing language (not specified), so only the request with
// no language will give access, as this request will be made with the
// langcode of the node, which is "not specified".
// When no language is specified for a public node, access should be
// granted.
$this->assertNodeAccess($expected_node_access, $this->nodes['no_language_public'], $this->webUser);
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['no_language_public'], $this->webUser, 'hu');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['no_language_public'], $this->webUser, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['no_language_public'], $this->webUser, 'en');
// Query the node table with the node access tag in several languages.

View file

@ -62,13 +62,7 @@ class NodeAccessLanguageTest extends NodeTestBase {
$this->assertNodeAccess($expected_node_access, $node_public_hu, $web_user);
// Tests that Hungarian provided specifically results in the same.
$this->assertNodeAccess($expected_node_access, $node_public_hu, $web_user, 'hu');
// There is no specific Catalan version of this node and Croatian is not
// even set up on the system in this scenario, so the user will not get
// access to these nodes.
$this->assertNodeAccess($expected_node_access_no_access, $node_public_hu, $web_user, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $node_public_hu, $web_user, 'hr');
$this->assertNodeAccess($expected_node_access, $node_public_hu->getTranslation('hu'), $web_user);
// Creating a public node with no special langcode, like when no language
// module enabled.
@ -81,15 +75,6 @@ class NodeAccessLanguageTest extends NodeTestBase {
// Tests that access is granted if requested with no language.
$this->assertNodeAccess($expected_node_access, $node_public_no_language, $web_user);
// Tests that access is not granted if requested with Hungarian language.
$this->assertNodeAccess($expected_node_access_no_access, $node_public_no_language, $web_user, 'hu');
// There is no specific Catalan version of this node and Croatian is not
// even set up on the system in this scenario, so the user will not get
// access to these nodes.
$this->assertNodeAccess($expected_node_access_no_access, $node_public_no_language, $web_user, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $node_public_no_language, $web_user, 'hr');
// Reset the node access cache and turn on our test node access code.
\Drupal::entityManager()->getAccessControlHandler('node')->resetCache();
\Drupal::state()->set('node_access_test_secret_catalan', 1);
@ -100,23 +85,20 @@ class NodeAccessLanguageTest extends NodeTestBase {
$this->assertNodeAccess($expected_node_access, $node_public_no_language, $web_user);
$this->assertNodeAccess($expected_node_access_no_access, $node_public_ca, $web_user);
// Tests that Hungarian is still not accessible.
$this->assertNodeAccess($expected_node_access_no_access, $node_public_no_language, $web_user, 'hu');
$this->assertNodeAccess($expected_node_access_no_access, $node_public_ca, $web_user, 'hu');
// Tests that Hungarian node is still accessible.
$this->assertNodeAccess($expected_node_access, $node_public_hu, $web_user, 'hu');
$this->assertNodeAccess($expected_node_access, $node_public_hu, $web_user);
$this->assertNodeAccess($expected_node_access, $node_public_hu->getTranslation('hu'), $web_user);
// Tests that Catalan is still not accessible.
$this->assertNodeAccess($expected_node_access_no_access, $node_public_no_language, $web_user, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $node_public_ca, $web_user, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $node_public_ca->getTranslation('ca'), $web_user);
// Make Catalan accessible.
\Drupal::state()->set('node_access_test_secret_catalan', 0);
// Tests that Catalan is accessible on a node with a Catalan version as the
// static cache has not been reset.
$this->assertNodeAccess($expected_node_access_no_access, $node_public_ca, $web_user, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $node_public_ca, $web_user);
$this->assertNodeAccess($expected_node_access_no_access, $node_public_ca->getTranslation('ca'), $web_user);
\Drupal::entityManager()->getAccessControlHandler('node')->resetCache();
@ -124,18 +106,12 @@ class NodeAccessLanguageTest extends NodeTestBase {
$this->assertNodeAccess($expected_node_access, $node_public_no_language, $web_user);
$this->assertNodeAccess($expected_node_access, $node_public_ca, $web_user);
// Tests that Hungarian is still not accessible.
$this->assertNodeAccess($expected_node_access_no_access, $node_public_no_language, $web_user, 'hu');
$this->assertNodeAccess($expected_node_access_no_access, $node_public_ca, $web_user, 'hu');
// Tests that Hungarian node is still accessible.
$this->assertNodeAccess($expected_node_access, $node_public_hu, $web_user, 'hu');
// Tests that Catalan is still not accessible on a node without a language.
$this->assertNodeAccess($expected_node_access_no_access, $node_public_no_language, $web_user, 'ca');
$this->assertNodeAccess($expected_node_access, $node_public_hu, $web_user);
$this->assertNodeAccess($expected_node_access, $node_public_hu->getTranslation('hu'), $web_user);
// Tests that Catalan is accessible on a node with a Catalan version.
$this->assertNodeAccess($expected_node_access, $node_public_ca, $web_user, 'ca');
$this->assertNodeAccess($expected_node_access, $node_public_ca->getTranslation('ca'), $web_user);
}
/**
@ -155,13 +131,7 @@ class NodeAccessLanguageTest extends NodeTestBase {
$this->assertNodeAccess($expected_node_access_no_access, $node_private_hu, $web_user);
// Tests that Hungarian provided specifically results in the same.
$this->assertNodeAccess($expected_node_access_no_access, $node_private_hu, $web_user, 'hu');
// There is no specific Catalan version of this node and Croatian is not
// even set up on the system in this scenario, so the user will not get
// access to these nodes.
$this->assertNodeAccess($expected_node_access_no_access, $node_private_hu, $web_user, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $node_private_hu, $web_user, 'hr');
$this->assertNodeAccess($expected_node_access_no_access, $node_private_hu->getTranslation('hu'), $web_user);
// Creating a private node with no special langcode, like when no language
// module enabled.
@ -174,15 +144,6 @@ class NodeAccessLanguageTest extends NodeTestBase {
// Tests that access is not granted if requested with no language.
$this->assertNodeAccess($expected_node_access_no_access, $node_private_no_language, $web_user);
// Tests that access is not granted if requested with Hungarian language.
$this->assertNodeAccess($expected_node_access_no_access, $node_private_no_language, $web_user, 'hu');
// There is no specific Catalan version of this node and Croatian is not
// even set up on the system in this scenario, so the user will not get
// access to these nodes.
$this->assertNodeAccess($expected_node_access_no_access, $node_private_no_language, $web_user, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $node_private_no_language, $web_user, 'hr');
// Reset the node access cache and turn on our test node access code.
\Drupal::entityManager()->getAccessControlHandler('node')->resetCache();
\Drupal::state()->set('node_access_test_secret_catalan', 1);
@ -190,12 +151,6 @@ class NodeAccessLanguageTest extends NodeTestBase {
// Tests that access is not granted if requested with no language.
$this->assertNodeAccess($expected_node_access_no_access, $node_private_no_language, $web_user);
// Tests that Hungarian is still not accessible.
$this->assertNodeAccess($expected_node_access_no_access, $node_private_no_language, $web_user, 'hu');
// Tests that Catalan is still not accessible.
$this->assertNodeAccess($expected_node_access_no_access, $node_private_no_language, $web_user, 'ca');
// Creating a private node with langcode Catalan to test that the
// node_access_test_secret_catalan flag works.
$private_ca_user = $this->drupalCreateUser(array('access content', 'node test view'));
@ -203,19 +158,23 @@ class NodeAccessLanguageTest extends NodeTestBase {
$this->assertTrue($node_private_ca->language()->getId() == 'ca', 'Node created as Catalan.');
// Tests that Catalan is still not accessible to either user.
$this->assertNodeAccess($expected_node_access_no_access, $node_private_ca, $web_user, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $node_private_ca, $private_ca_user, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $node_private_ca, $web_user);
$this->assertNodeAccess($expected_node_access_no_access, $node_private_ca->getTranslation('ca'), $web_user);
$this->assertNodeAccess($expected_node_access_no_access, $node_private_ca, $private_ca_user);
$this->assertNodeAccess($expected_node_access_no_access, $node_private_ca->getTranslation('ca'), $private_ca_user);
\Drupal::entityManager()->getAccessControlHandler('node')->resetCache();
\Drupal::state()->set('node_access_test_secret_catalan', 0);
// Tests that Catalan is still not accessible for a user with no access to
// private nodes.
$this->assertNodeAccess($expected_node_access_no_access, $node_private_ca, $web_user, 'ca');
$this->assertNodeAccess($expected_node_access_no_access, $node_private_ca, $web_user);
$this->assertNodeAccess($expected_node_access_no_access, $node_private_ca->getTranslation('ca'), $web_user);
// Tests that Catalan is accessible by a user with the permission to see
// private nodes.
$this->assertNodeAccess($expected_node_access, $node_private_ca, $private_ca_user, 'ca');
$this->assertNodeAccess($expected_node_access, $node_private_ca, $private_ca_user);
$this->assertNodeAccess($expected_node_access, $node_private_ca->getTranslation('ca'), $private_ca_user);
}
/**

View file

@ -46,7 +46,7 @@ class NodeAccessRebuildNodeGrantsTest extends NodeTestBase {
));
// Default realm access and node records are present.
$this->assertTrue(\Drupal::service('node.grant_storage')->access($node, 'view', 'en', $this->webUser), 'The expected node access records are present');
$this->assertTrue(\Drupal::service('node.grant_storage')->access($node, 'view', $this->webUser), 'The expected node access records are present');
$this->assertEqual(1, \Drupal::service('node.grant_storage')->checkAll($this->webUser), 'There is an all realm access record');
$this->assertTrue(\Drupal::state()->get('node.node_access_needs_rebuild'), 'Node access permissions need to be rebuilt');
@ -57,7 +57,7 @@ class NodeAccessRebuildNodeGrantsTest extends NodeTestBase {
// Test if the rebuild has been successful.
$this->assertNull(\Drupal::state()->get('node.node_access_needs_rebuild'), 'Node access permissions have been rebuilt');
$this->assertTrue(\Drupal::service('node.grant_storage')->access($node, 'view', 'en', $this->webUser), 'The expected node access records are present');
$this->assertTrue(\Drupal::service('node.grant_storage')->access($node, 'view', $this->webUser), 'The expected node access records are present');
$this->assertFalse(\Drupal::service('node.grant_storage')->checkAll($this->webUser), 'There is no all realm access record');
}

View file

@ -118,18 +118,29 @@ class NodeAdminTest extends NodeTestBase {
function testContentAdminPages() {
$this->drupalLogin($this->adminUser);
$nodes['published_page'] = $this->drupalCreateNode(array('type' => 'page'));
$nodes['published_article'] = $this->drupalCreateNode(array('type' => 'article'));
$nodes['unpublished_page_1'] = $this->drupalCreateNode(array('type' => 'page', 'uid' => $this->baseUser1->id(), 'status' => 0));
$nodes['unpublished_page_2'] = $this->drupalCreateNode(array('type' => 'page', 'uid' => $this->baseUser2->id(), 'status' => 0));
// Use an explicit changed time to ensure the expected order in the content
// admin listing. We want these to appear in the table in the same order as
// they appear in the following code, and the 'content' View has a table
// style configuration with a default sort on the 'changed' field DESC.
$time = time();
$nodes['published_page'] = $this->drupalCreateNode(array('type' => 'page', 'changed' => $time--));
$nodes['published_article'] = $this->drupalCreateNode(array('type' => 'article', 'changed' => $time--));
$nodes['unpublished_page_1'] = $this->drupalCreateNode(array('type' => 'page', 'changed' => $time--, 'uid' => $this->baseUser1->id(), 'status' => 0));
$nodes['unpublished_page_2'] = $this->drupalCreateNode(array('type' => 'page', 'changed' => $time, 'uid' => $this->baseUser2->id(), 'status' => 0));
// Verify view, edit, and delete links for any content.
$this->drupalGet('admin/content');
$this->assertResponse(200);
$node_type_labels = $this->xpath('//td[contains(@class, "views-field-type")]');
$delta = 0;
foreach ($nodes as $node) {
$this->assertLinkByHref('node/' . $node->id());
$this->assertLinkByHref('node/' . $node->id() . '/edit');
$this->assertLinkByHref('node/' . $node->id() . '/delete');
// Verify that we can see the content type label.
$this->assertEqual(trim((string) $node_type_labels[$delta]), $node->type->entity->label());
$delta++;
}
// Verify filtering by publishing status.

View file

@ -148,7 +148,7 @@ class NodeBlockFunctionalTest extends NodeTestBase {
$this->assertCacheContexts(['languages:language_content', 'languages:language_interface', 'theme', 'url.query_args:' . MainContentViewSubscriber::WRAPPER_FORMAT, 'user', 'route']);
$this->drupalGet('node/add/article');
$this->assertText($label, 'Block was displayed on the node/add/article page.');
$this->assertCacheContexts(['languages:language_content', 'languages:language_interface', 'theme', 'url.path', 'url.query_args', 'user', 'route']);
$this->assertCacheContexts(['languages:language_content', 'languages:language_interface', 'session', 'theme', 'url.path', 'url.query_args', 'user', 'route']);
$this->drupalGet('node/' . $node1->id());
$this->assertText($label, 'Block was displayed on the node/N when node is of type article.');
$this->assertCacheContexts(['languages:language_content', 'languages:language_interface', 'theme', 'url.query_args:' . MainContentViewSubscriber::WRAPPER_FORMAT, 'user', 'route', 'timezone']);

View file

@ -27,7 +27,7 @@ class NodeBodyFieldStorageTest extends KernelTestBase {
*
* @var array
*/
public static $modules = array('user', 'system', 'field', 'node', 'text', 'filter', 'entity_reference');
public static $modules = ['user', 'system', 'field', 'node', 'text', 'filter'];
protected function setUp() {
parent::setUp();

View file

@ -52,7 +52,7 @@ class NodeCreationTest extends NodeTestBase {
$this->drupalPostForm('node/add/page', $edit, t('Save'));
// Check that the Basic page has been created.
$this->assertRaw(t('!post %title has been created.', array('!post' => 'Basic page', '%title' => $edit['title[0][value]'])), 'Basic page created.');
$this->assertRaw(t('@post %title has been created.', array('@post' => 'Basic page', '%title' => $edit['title[0][value]'])), 'Basic page created.');
// Check that the node exists in the database.
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
@ -141,7 +141,7 @@ class NodeCreationTest extends NodeTestBase {
$this->assertText(t('Test page text'));
// Confirm that the node was created.
$this->assertRaw(t('!post %title has been created.', array('!post' => 'Basic page', '%title' => $edit['title[0][value]'])));
$this->assertRaw(t('@post %title has been created.', array('@post' => 'Basic page', '%title' => $edit['title[0][value]'])));
}
/**

View file

@ -2,20 +2,41 @@
/**
* @file
* Contains \Drupal\node\Tests\PageEditTest.
* Contains \Drupal\node\Tests\NodeEditFormTest.
*/
namespace Drupal\node\Tests;
use Drupal\node\NodeInterface;
/**
* Create a node and test node edit functionality.
*
* @group node
*/
class PageEditTest extends NodeTestBase {
class NodeEditFormTest extends NodeTestBase {
/**
* A normal logged in user.
*
* @var \Drupal\user\UserInterface
*/
protected $webUser;
/**
* A user with permission to bypass content access checks.
*
* @var \Drupal\user\UserInterface
*/
protected $adminUser;
/**
* The node storage.
*
* @var \Drupal\node\NodeStorageInterface
*/
protected $nodeStorage;
/**
* Modules to enable.
*
@ -29,12 +50,14 @@ class PageEditTest extends NodeTestBase {
$this->webUser = $this->drupalCreateUser(array('edit own page content', 'create page content'));
$this->adminUser = $this->drupalCreateUser(array('bypass node access', 'administer nodes'));
$this->drupalPlaceBlock('local_tasks_block');
$this->nodeStorage = $this->container->get('entity.manager')->getStorage('node');
}
/**
* Checks node edit functionality.
*/
function testPageEdit() {
public function testNodeEdit() {
$this->drupalLogin($this->webUser);
$title_key = 'title[0][value]';
@ -54,9 +77,10 @@ class PageEditTest extends NodeTestBase {
$this->assertUrl($node->url('edit-form', ['absolute' => TRUE]));
// Check that the title and body fields are displayed with the correct values.
$active = '<span class="visually-hidden">' . t('(active tab)') . '</span>';
$link_text = t('!local-task-title!active', array('!local-task-title' => t('Edit'), '!active' => $active));
$this->assertText(strip_tags($link_text), 0, 'Edit tab found and marked active.');
// As you see the expected link text has no HTML, but we are using
$link_text = 'Edit<span class="visually-hidden">(active tab)</span>';
// @todo Ideally assertLink would support HTML, but it doesn't.
$this->assertRaw($link_text, 'Edit tab found and marked active.');
$this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
$this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
@ -98,8 +122,7 @@ class PageEditTest extends NodeTestBase {
/**
* Tests changing a node's "authored by" field.
*/
function testPageAuthoredBy() {
$node_storage = $this->container->get('entity.manager')->getStorage('node');
public function testNodeEditAuthoredBy() {
$this->drupalLogin($this->adminUser);
// Create node to edit.
@ -113,18 +136,69 @@ class PageEditTest extends NodeTestBase {
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
$this->assertIdentical($node->getOwnerId(), $this->adminUser->id(), 'Node authored by admin user.');
$this->checkVariousAuthoredByValues($node, 'uid[0][target_id]');
// Check that normal users cannot change the authored by information.
$this->drupalLogin($this->webUser);
$this->drupalGet('node/' . $node->id() . '/edit');
$this->assertNoFieldByName('uid[0][target_id]');
// Now test with the Autcomplete (Tags) field widget.
/** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display */
$form_display = \Drupal::entityManager()->getStorage('entity_form_display')->load('node.page.default');
$widget = $form_display->getComponent('uid');
$widget['type'] = 'entity_reference_autocomplete_tags';
$widget['settings'] = [
'match_operator' => 'CONTAINS',
'size' => 60,
'placeholder' => '',
];
$form_display->setComponent('uid', $widget);
$form_display->save();
$this->drupalLogin($this->adminUser);
// Save the node without making any changes.
$this->drupalPostForm('node/' . $node->id() . '/edit', [], t('Save and keep published'));
$this->nodeStorage->resetCache(array($node->id()));
$node = $this->nodeStorage->load($node->id());
$this->assertIdentical($this->webUser->id(), $node->getOwner()->id());
$this->checkVariousAuthoredByValues($node, 'uid[target_id]');
// Hide the 'authored by' field from the form.
$form_display->removeComponent('uid')->save();
// Check that saving the node without making any changes keeps the proper
// author ID.
$this->drupalPostForm('node/' . $node->id() . '/edit', [], t('Save and keep published'));
$this->nodeStorage->resetCache(array($node->id()));
$node = $this->nodeStorage->load($node->id());
$this->assertIdentical($this->webUser->id(), $node->getOwner()->id());
}
/**
* Checks that the "authored by" works correctly with various values.
*
* @param \Drupal\node\NodeInterface $node
* A node object.
* @param string $form_element_name
* The name of the form element to populate.
*/
protected function checkVariousAuthoredByValues(NodeInterface $node, $form_element_name) {
// Try to change the 'authored by' field to an invalid user name.
$edit = array(
'uid[0][target_id]' => 'invalid-name',
$form_element_name => 'invalid-name',
);
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save and keep published'));
$this->assertRaw(t('There are no entities matching "%name".', array('%name' => 'invalid-name')));
// Change the authored by field to the anonymous user (uid 0).
$edit['uid[0][target_id]'] = 'Anonymous (0)';
// Change the authored by field to an empty string, which should assign
// authorship to the anonymous user (uid 0).
$edit[$form_element_name] = '';
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save and keep published'));
$node_storage->resetCache(array($node->id()));
$node = $node_storage->load($node->id());
$this->nodeStorage->resetCache(array($node->id()));
$node = $this->nodeStorage->load($node->id());
$uid = $node->getOwnerId();
// Most SQL database drivers stringify fetches but entities are not
// necessarily stored in a SQL database. At the same time, NULL/FALSE/""
@ -133,15 +207,11 @@ class PageEditTest extends NodeTestBase {
// Change the authored by field to another user's name (that is not
// logged in).
$edit['uid[0][target_id]'] = $this->webUser->getUsername();
$edit[$form_element_name] = $this->webUser->getUsername();
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save and keep published'));
$node_storage->resetCache(array($node->id()));
$node = $node_storage->load($node->id());
$this->nodeStorage->resetCache(array($node->id()));
$node = $this->nodeStorage->load($node->id());
$this->assertIdentical($node->getOwnerId(), $this->webUser->id(), 'Node authored by normal user.');
// Check that normal users cannot change the authored by information.
$this->drupalLogin($this->webUser);
$this->drupalGet('node/' . $node->id() . '/edit');
$this->assertNoFieldByName('uid[0][target_id]');
}
}

View file

@ -0,0 +1,76 @@
<?php
/**
* @file
* Contains \Drupal\node\Tests\NodeFormSaveChangedTimeTest.
*/
namespace Drupal\node\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Tests updating the changed time after API and FORM entity save.
*
* @group node
*/
class NodeFormSaveChangedTimeTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array(
'node',
);
/**
* An user with permissions to create and edit articles.
*
* @var \Drupal\user\UserInterface
*/
protected $authorUser;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Create a node type.
$this->drupalCreateContentType(array(
'type' => 'article',
'name' => 'Article',
));
$this->authorUser = $this->drupalCreateUser(['access content', 'create article content', 'edit any article content'], 'author');
$this->drupalLogin($this->authorUser);
// Create one node of the above node type .
$this->drupalCreateNode(array(
'type' => 'article',
));
}
/**
* Test the changed time after API and FORM save without changes.
*/
public function testChangedTimeAfterSaveWithoutChanges() {
$node = entity_load('node', 1);
$changed_timestamp = $node->getChangedTime();
$node->save();
$node = entity_load('node', 1, TRUE);
$this->assertEqual($changed_timestamp, $node->getChangedTime(), "The entity's changed time wasn't updated after API save without changes.");
// Ensure different save timestamps.
sleep(1);
// Save the node on the regular node edit form.
$this->drupalPostForm('node/1/edit', array(), t('Save'));
$node = entity_load('node', 1, TRUE);
$this->assertNotEqual($changed_timestamp, $node->getChangedTime(), "The entity's changed time was updated after form save without changes.");
}
}

View file

@ -0,0 +1,83 @@
<?php
/**
* @file
* Contains Drupal\node\Tests\NodeOwnerTest.
*/
namespace Drupal\node\Tests;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\system\Tests\Entity\EntityUnitTestBase;
/**
* Tests node owner functionality.
*
* @group Entity
*/
class NodeOwnerTest extends EntityUnitTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('node', 'language');
protected function setUp() {
parent::setUp();
// Create the node bundles required for testing.
$type = NodeType::create(array(
'type' => 'page',
'name' => 'page',
));
$type->save();
// Enable two additional languages.
ConfigurableLanguage::createFromLangcode('de')->save();
ConfigurableLanguage::createFromLangcode('it')->save();
$this->installSchema('node', 'node_access');
}
/**
* Tests node owner functionality.
*/
public function testOwner() {
$user = $this->createUser();
$container = \Drupal::getContainer();
$container->get('current_user')->setAccount($user);
// Create a test node.
$english = Node::create(array(
'type' => 'page',
'title' => $this->randomMachineName(),
'language' => 'en',
));
$english->save();
$this->assertEqual($user->id(), $english->getOwnerId());
$german = $english->addTranslation('de');
$german->title = $this->randomString();
$italian = $english->addTranslation('it');
$italian->title = $this->randomString();
// Node::preSave() sets owner to anonymous user if owner is nor set.
$english->set('uid', ['target_id' => NULL]);
$german->set('uid', ['target_id' => NULL]);
$italian->set('uid', ['target_id' => NULL]);
// Entity::save() saves all translations!
$italian->save();
$this->assertEqual(0, $english->getOwnerId());
$this->assertEqual(0, $german->getOwnerId());
$this->assertEqual(0, $italian->getOwnerId());
}
}

View file

@ -45,16 +45,16 @@ class NodeRSSContentTest extends NodeTestBase {
$this->drupalGet('rss.xml');
// Check that content added in 'rss' view mode appear in RSS feed.
$rss_only_content = t('Extra data that should appear only in the RSS feed for node !nid.', array('!nid' => $node->id()));
$rss_only_content = t('Extra data that should appear only in the RSS feed for node @nid.', array('@nid' => $node->id()));
$this->assertText($rss_only_content, 'Node content designated for RSS appear in RSS feed.');
// Check that content added in view modes other than 'rss' doesn't
// appear in RSS feed.
$non_rss_content = t('Extra data that should appear everywhere except the RSS feed for node !nid.', array('!nid' => $node->id()));
$non_rss_content = t('Extra data that should appear everywhere except the RSS feed for node @nid.', array('@nid' => $node->id()));
$this->assertNoText($non_rss_content, 'Node content not designed for RSS does not appear in RSS feed.');
// Check that extra RSS elements and namespaces are added to RSS feed.
$test_element = '<testElement>' . t('Value of testElement RSS element for node !nid.', array('!nid' => $node->id())) . '</testElement>';
$test_element = '<testElement>' . t('Value of testElement RSS element for node @nid.', array('@nid' => $node->id())) . '</testElement>';
$test_ns = 'xmlns:drupaltest="http://example.com/test-namespace"';
$this->assertRaw($test_element, 'Extra RSS elements appear in RSS feed.');
$this->assertRaw($test_ns, 'Extra namespaces appear in RSS feed.');

View file

@ -7,6 +7,9 @@
namespace Drupal\node\Tests;
use Drupal\Core\Url;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\node\Entity\Node;
use Drupal\node\NodeInterface;
@ -34,9 +37,22 @@ class NodeRevisionsTest extends NodeTestBase {
ConfigurableLanguage::createFromLangcode('it')->save();
/** @var \Drupal\content_translation\ContentTranslationManagerInterface $manager */
$manager = \Drupal::service('content_translation.manager');
$manager->setEnabled('node', 'article', TRUE);
$field_storage_definition = array(
'field_name' => 'untranslatable_string_field',
'entity_type' => 'node',
'type' => 'string',
'cardinality' => 1,
'translatable' => FALSE,
);
$field_storage = FieldStorageConfig::create($field_storage_definition);
$field_storage->save();
$field_definition = array(
'field_storage' => $field_storage,
'bundle' => 'page',
);
$field = FieldConfig::create($field_definition);
$field->save();
// Create and log in user.
$web_user = $this->drupalCreateUser(
@ -75,6 +91,7 @@ class NodeRevisionsTest extends NodeTestBase {
'value' => $this->randomMachineName(32),
'format' => filter_default_format(),
);
$node->untranslatable_string_field->value = $this->randomString();
$node->setNewRevision();
$node->save();
@ -227,6 +244,9 @@ class NodeRevisionsTest extends NodeTestBase {
public function testRevisionTranslationRevert() {
// Create a node and a few revisions.
$node = $this->drupalCreateNode(['langcode' => 'en']);
$initial_revision_id = $node->getRevisionId();
$initial_title = $node->label();
$this->createRevisions($node, 2);
// Translate the node and create a few translation revisions.
@ -234,6 +254,7 @@ class NodeRevisionsTest extends NodeTestBase {
$this->createRevisions($translation, 3);
$revert_id = $node->getRevisionId();
$translated_title = $translation->label();
$untranslatable_string = $node->untranslatable_string_field->value;
// Create a new revision for the default translation in-between a series of
// translation revisions.
@ -247,7 +268,12 @@ class NodeRevisionsTest extends NodeTestBase {
// Now revert the a translation revision preceding the last default
// translation revision, and check that the desired value was reverted but
// the default translation value was preserved.
$this->drupalPostForm("node/" . $node->id() . "/revisions/" . $revert_id . "/revert", [], t('Revert'));
$revert_translation_url = Url::fromRoute('node.revision_revert_translation_confirm', [
'node' => $node->id(),
'node_revision' => $revert_id,
'langcode' => 'it',
]);
$this->drupalPostForm($revert_translation_url, [], t('Revert'));
/** @var \Drupal\node\NodeStorage $node_storage */
$node_storage = $this->container->get('entity.manager')->getStorage('node');
$node_storage->resetCache();
@ -256,6 +282,38 @@ class NodeRevisionsTest extends NodeTestBase {
$this->assertTrue($node->getRevisionId() > $translation_revision_id);
$this->assertEqual($node->label(), $default_translation_title);
$this->assertEqual($node->getTranslation('it')->label(), $translated_title);
$this->assertNotEqual($node->untranslatable_string_field->value, $untranslatable_string);
$latest_revision_id = $translation->getRevisionId();
// Now revert the a translation revision preceding the last default
// translation revision again, and check that the desired value was reverted
// but the default translation value was preserved. But in addition the
// untranslated field will be reverted as well.
$this->drupalPostForm($revert_translation_url, ['revert_untranslated_fields' => TRUE], t('Revert'));
$node_storage->resetCache();
/** @var \Drupal\node\NodeInterface $node */
$node = $node_storage->load($node->id());
$this->assertTrue($node->getRevisionId() > $latest_revision_id);
$this->assertEqual($node->label(), $default_translation_title);
$this->assertEqual($node->getTranslation('it')->label(), $translated_title);
$this->assertEqual($node->untranslatable_string_field->value, $untranslatable_string);
$latest_revision_id = $translation->getRevisionId();
// Now revert the entity revision to the initial one where the translation
// didn't exist.
$revert_url = Url::fromRoute('node.revision_revert_confirm', [
'node' => $node->id(),
'node_revision' => $initial_revision_id,
]);
$this->drupalPostForm($revert_url, [], t('Revert'));
$node_storage->resetCache();
/** @var \Drupal\node\NodeInterface $node */
$node = $node_storage->load($node->id());
$this->assertTrue($node->getRevisionId() > $latest_revision_id);
$this->assertEqual($node->label(), $initial_title);
$this->assertFalse($node->hasTranslation('it'));
}
/**
@ -269,6 +327,7 @@ class NodeRevisionsTest extends NodeTestBase {
protected function createRevisions(NodeInterface $node, $count) {
for ($i = 0; $i < $count; $i++) {
$node->title = $this->randomString();
$node->untranslatable_string_field->value = $this->randomString();
$node->setNewRevision(TRUE);
$node->save();
}

View file

@ -119,20 +119,11 @@ class NodeRevisionsUiTest extends NodeTestBase {
// 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);
$this->assertRaw(\Drupal::l($date, $url) . ' by ' . $editor);
// 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);
$this->assertRaw($nodes[1]->link($date) . ' by ' . $editor . '<p class="revision-log">' . $revision_log . '</p>');
}
}

View file

@ -8,6 +8,7 @@
namespace Drupal\node\Tests;
use Drupal\Core\Session\AccountInterface;
use Drupal\node\NodeInterface;
use Drupal\simpletest\WebTestBase;
/**
@ -55,20 +56,14 @@ abstract class NodeTestBase extends WebTestBase {
* and account, with each key as the name of an operation (e.g. 'view',
* 'delete') and each value a Boolean indicating whether access to that
* operation should be granted.
* @param \Drupal\node\Entity\Node $node
* @param \Drupal\node\NodeInterface $node
* The node object to check.
* @param \Drupal\Core\Session\AccountInterface $account
* The user account for which to check access.
* @param string|null $langcode
* (optional) The language code indicating which translation of the node
* to check. If NULL, the untranslated (fallback) access is checked.
*/
function assertNodeAccess(array $ops, $node, AccountInterface $account, $langcode = NULL) {
function assertNodeAccess(array $ops, NodeInterface $node, AccountInterface $account) {
foreach ($ops as $op => $result) {
if (empty($langcode)) {
$langcode = $node->prepareLangcode();
}
$this->assertEqual($result, $this->accessHandler->access($node, $op, $langcode, $account), $this->nodeAccessAssertMessage($op, $result, $langcode));
$this->assertEqual($result, $this->accessHandler->access($node, $op, $account), $this->nodeAccessAssertMessage($op, $result, $node->language()->getId()));
}
}

View file

@ -7,6 +7,7 @@
namespace Drupal\node\Tests;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Component\Utility\Html;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\system\Tests\System\TokenReplaceUnitTestBase;
@ -55,11 +56,11 @@ class NodeTokenReplaceTest extends TokenReplaceUnitTestBase {
'tnid' => 0,
'uid' => $account->id(),
'title' => '<blink>Blinking Text</blink>',
'body' => array(array('value' => $this->randomMachineName(32), 'summary' => $this->randomMachineName(16), 'format' => 'plain_text')),
'body' => [['value' => 'Regular NODE body for the test.', 'summary' => 'Fancy NODE summary.', 'format' => 'plain_text']],
));
$node->save();
// Generate and test sanitized tokens.
// Generate and test tokens.
$tests = array();
$tests['[node:nid]'] = $node->id();
$tests['[node:vid]'] = $node->getRevisionId();
@ -68,12 +69,12 @@ class NodeTokenReplaceTest extends TokenReplaceUnitTestBase {
$tests['[node:title]'] = Html::escape($node->getTitle());
$tests['[node:body]'] = $node->body->processed;
$tests['[node:summary]'] = $node->body->summary_processed;
$tests['[node:langcode]'] = Html::escape($node->language()->getId());
$tests['[node:langcode]'] = $node->language()->getId();
$tests['[node:url]'] = $node->url('canonical', $url_options);
$tests['[node:edit-url]'] = $node->url('edit-form', $url_options);
$tests['[node:author]'] = Html::escape($account->getUsername());
$tests['[node:author]'] = $account->getUsername();
$tests['[node:author:uid]'] = $node->getOwnerId();
$tests['[node:author:name]'] = Html::escape($account->getUsername());
$tests['[node:author:name]'] = $account->getUsername();
$tests['[node:created:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($node->getCreatedTime(), array('langcode' => $this->interfaceLanguage->getId()));
$tests['[node:changed:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($node->getChangedTime(), array('langcode' => $this->interfaceLanguage->getId()));
@ -104,32 +105,20 @@ class NodeTokenReplaceTest extends TokenReplaceUnitTestBase {
foreach ($tests as $input => $expected) {
$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($output, $expected, format_string('Node token %token replaced.', ['%token' => $input]));
$this->assertEqual($bubbleable_metadata, $metadata_tests[$input]);
}
// Generate and test unsanitized tokens.
$tests['[node:title]'] = $node->getTitle();
$tests['[node:body]'] = $node->body->value;
$tests['[node:summary]'] = $node->body->summary;
$tests['[node:langcode]'] = $node->language()->getId();
$tests['[node:author:name]'] = $account->getUsername();
foreach ($tests as $input => $expected) {
$output = $this->tokenService->replace($input, array('node' => $node), array('langcode' => $this->interfaceLanguage->getId(), 'sanitize' => FALSE));
$this->assertEqual($output, $expected, format_string('Unsanitized node token %token replaced.', array('%token' => $input)));
}
// Repeat for a node without a summary.
$node = entity_create('node', array(
'type' => 'article',
'uid' => $account->id(),
'title' => '<blink>Blinking Text</blink>',
'body' => array(array('value' => $this->randomMachineName(32), 'format' => 'plain_text')),
'body' => [['value' => 'A string that looks random like TR5c2I', 'format' => 'plain_text']],
));
$node->save();
// Generate and test sanitized token - use full body as expected value.
// Generate and test token - use full body as expected value.
$tests = array();
$tests['[node:summary]'] = $node->body->processed;
@ -138,15 +127,7 @@ class NodeTokenReplaceTest extends TokenReplaceUnitTestBase {
foreach ($tests as $input => $expected) {
$output = $this->tokenService->replace($input, array('node' => $node), array('language' => $this->interfaceLanguage));
$this->assertEqual($output, $expected, format_string('Sanitized node token %token replaced for node without a summary.', array('%token' => $input)));
}
// Generate and test unsanitized tokens.
$tests['[node:summary]'] = $node->body->value;
foreach ($tests as $input => $expected) {
$output = $this->tokenService->replace($input, array('node' => $node), array('language' => $this->interfaceLanguage, 'sanitize' => FALSE));
$this->assertEqual($output, $expected, format_string('Unsanitized node token %token replaced for node without a summary.', array('%token' => $input)));
$this->assertEqual($output, $expected, new FormattableMarkup('Node token %token replaced for node without a summary.', ['%token' => $input]));
}
}

View file

@ -26,12 +26,9 @@ class NodeTranslationUITest extends ContentTranslationUITestBase {
*/
protected $defaultCacheContexts = [
'languages:language_interface',
'session',
'theme',
'route.name',
'route.menu_active_trails:account',
'route.menu_active_trails:footer',
'route.menu_active_trails:main',
'route.menu_active_trails:tools',
'route',
'timezone',
'url',
'user'

View file

@ -1,145 +0,0 @@
<?php
/**
* @file
* Contains \Drupal\node\Tests\NodeTypeRenameConfigImportTest.
*/
namespace Drupal\node\Tests;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Config\Entity\ConfigEntityStorage;
use Drupal\simpletest\WebTestBase;
use Drupal\node\Entity\NodeType;
/**
* Tests importing renamed node type via configuration synchronization.
*
* @group node
*/
class NodeTypeRenameConfigImportTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('node', 'text', 'config');
/**
* A normal logged in user.
*
* @var \Drupal\user\UserInterface
*/
protected $webUser;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->webUser = $this->drupalCreateUser(array('synchronize configuration'));
$this->drupalLogin($this->webUser);
}
/**
* Tests configuration renaming.
*/
public function testConfigurationRename() {
$content_type = $this->drupalCreateContentType(array(
'type' => Unicode::strtolower($this->randomMachineName(16)),
'name' => $this->randomMachineName(),
));
$staged_type = $content_type->id();
// Check the default status value for a node of this type.
$node = entity_create('node', array('type' => $staged_type));
$this->assertTrue($node->status->value, 'Node status defaults to TRUE.');
// Override a core base field.
$fields = \Drupal::entityManager()->getFieldDefinitions($content_type->getEntityType()->getBundleOf(), $content_type->id());
$fields['status']->getConfig($content_type->id())->setDefaultValue(FALSE)->save();
$active = $this->container->get('config.storage');
$staging = $this->container->get('config.storage.staging');
$config_name = $content_type->getEntityType()->getConfigPrefix() . '.' . $content_type->id();
// Emulate a staging operation.
$this->copyConfig($active, $staging);
// Change the machine name of the content type.
$content_type->set('type', Unicode::strtolower($this->randomMachineName(8)));
$content_type->save();
$active_type = $content_type->id();
// Ensure the base field override has been renamed and the value is correct.
$node = entity_create('node', array('type' => $active_type));
$this->assertFalse($node->status->value, 'Node status defaults to FALSE.');
$renamed_config_name = $content_type->getEntityType()->getConfigPrefix() . '.' . $content_type->id();
$this->assertTrue($active->exists($renamed_config_name), 'The content type has the new name in the active store.');
$this->assertFalse($active->exists($config_name), "The content type's old name does not exist active store.");
$this->configImporter()->reset();
$this->assertEqual(0, count($this->configImporter()->getUnprocessedConfiguration('create')), 'There are no configuration items to create.');
$this->assertEqual(0, count($this->configImporter()->getUnprocessedConfiguration('delete')), 'There are no configuration items to delete.');
$this->assertEqual(0, count($this->configImporter()->getUnprocessedConfiguration('update')), 'There are no configuration items to update.');
// We expect that changing the machine name of the content type will
// rename five configuration entities: the node type, the body field
// instance, two entity form displays, and the entity view display.
// @see \Drupal\node\Entity\NodeType::postSave()
$expected = array(
'node.type.' . $active_type . '::node.type.' . $staged_type,
'core.base_field_override.node.' . $active_type . '.status::core.base_field_override.node.' . $staged_type . '.status',
'core.entity_form_display.node.' . $active_type . '.default::core.entity_form_display.node.' . $staged_type . '.default',
'core.entity_view_display.node.' . $active_type . '.default::core.entity_view_display.node.' . $staged_type . '.default',
'core.entity_view_display.node.' . $active_type . '.teaser::core.entity_view_display.node.' . $staged_type . '.teaser',
'field.field.node.' . $active_type . '.body::field.field.node.' . $staged_type . '.body',
);
$renames = $this->configImporter()->getUnprocessedConfiguration('rename');
$this->assertIdentical($expected, $renames);
$this->drupalGet('admin/config/development/configuration');
foreach ($expected as $rename) {
$names = $this->configImporter()->getStorageComparer()->extractRenameNames($rename);
$this->assertText(SafeMarkup::format('!source_name to !target_name', array('!source_name' => $names['old_name'], '!target_name' => $names['new_name'])));
// Test that the diff link is present for each renamed item.
$href = \Drupal::urlGenerator()->getPathFromRoute('config.diff', array('source_name' => $names['old_name'], 'target_name' => $names['new_name']));
$this->assertLinkByHref($href);
$hrefs[$rename] = $href;
}
// Ensure that the diff works for each renamed item.
foreach ($hrefs as $rename => $href) {
$this->drupalGet($href);
$names = $this->configImporter()->getStorageComparer()->extractRenameNames($rename);
$config_entity_type = \Drupal::service('config.manager')->getEntityTypeIdByName($names['old_name']);
$entity_type = \Drupal::entityManager()->getDefinition($config_entity_type);
$old_id = ConfigEntityStorage::getIDFromConfigName($names['old_name'], $entity_type->getConfigPrefix());
$new_id = ConfigEntityStorage::getIDFromConfigName($names['new_name'], $entity_type->getConfigPrefix());
// Because table columns can be on multiple lines, need to assert a regex
// pattern rather than normal text.
$id_key = $entity_type->getKey('id');
$text = "$id_key: $old_id";
$this->assertTextPattern('/\-\s+' . preg_quote($text, '/') . '/', "'-$text' found.");
$text = "$id_key: $new_id";
$this->assertTextPattern('/\+\s+' . preg_quote($text, '/') . '/', "'+$text' found.");
}
// Run the import.
$this->drupalPostForm('admin/config/development/configuration', array(), t('Import all'));
$this->assertText(t('There are no configuration changes to import.'));
$this->assertFalse(NodeType::load($active_type), 'The content no longer exists with the old name.');
$content_type = NodeType::load($staged_type);
$this->assertIdentical($staged_type, $content_type->id());
// Ensure the base field override has been renamed and the value is correct.
$node = entity_create('node', array('type' => $staged_type));
$this->assertFALSE($node->status->value, 'Node status defaults to FALSE.');
}
}

View file

@ -64,6 +64,13 @@ class NodeTypeTest extends NodeTestBase {
// Create a content type via the user interface.
$web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types'));
$this->drupalLogin($web_user);
$this->drupalGet('node/add');
$this->assertCacheTag('config:node_type_list');
$this->assertCacheContext('user.permissions');
$elements = $this->cssSelect('dl.node-type-list dt');
$this->assertEqual(3, count($elements));
$edit = array(
'name' => 'foo',
'title_label' => 'title for foo',
@ -72,6 +79,10 @@ class NodeTypeTest extends NodeTestBase {
$this->drupalPostForm('admin/structure/types/add', $edit, t('Save and manage fields'));
$type_exists = (bool) NodeType::load('foo');
$this->assertTrue($type_exists, 'The new content type has been created in the database.');
$this->drupalGet('node/add');
$elements = $this->cssSelect('dl.node-type-list dt');
$this->assertEqual(4, count($elements));
}
/**
@ -99,10 +110,9 @@ class NodeTypeTest extends NodeTestBase {
$this->assertRaw('Foo', 'New title label was displayed.');
$this->assertNoRaw('Title', 'Old title label was not displayed.');
// Change the name, machine name and description.
// Change the name and the description.
$edit = array(
'name' => 'Bar',
'type' => 'bar',
'description' => 'Lorem ipsum.',
);
$this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type'));
@ -111,16 +121,15 @@ class NodeTypeTest extends NodeTestBase {
$this->assertRaw('Bar', 'New name was displayed.');
$this->assertRaw('Lorem ipsum', 'New description was displayed.');
$this->clickLink('Bar');
$this->assertUrl(\Drupal::url('node.add', ['node_type' => 'bar'], ['absolute' => TRUE]), [], 'New machine name was used in URL.');
$this->assertRaw('Foo', 'Title field was found.');
$this->assertRaw('Body', 'Body field was found.');
// Remove the body field.
$this->drupalPostForm('admin/structure/types/manage/bar/fields/node.bar.body/delete', array(), t('Delete'));
$this->drupalPostForm('admin/structure/types/manage/page/fields/node.page.body/delete', array(), t('Delete'));
// Resave the settings for this type.
$this->drupalPostForm('admin/structure/types/manage/bar', array(), t('Save content type'));
$this->drupalPostForm('admin/structure/types/manage/page', array(), t('Save content type'));
// Check that the body field doesn't exist.
$this->drupalGet('node/add/bar');
$this->drupalGet('node/add/page');
$this->assertNoRaw('Body', 'Body field was not found.');
}
@ -219,8 +228,8 @@ class NodeTypeTest extends NodeTestBase {
// Navigate to content type administration screen
$this->drupalGet('admin/structure/types');
$this->assertRaw(t('No content types available. <a href="@link">Add content type</a>.', [
'@link' => Url::fromRoute('node.type_add')->toString()
$this->assertRaw(t('No content types available. <a href=":link">Add content type</a>.', [
':link' => Url::fromRoute('node.type_add')->toString()
]), 'Empty text when there are no content types in the system is correct.');
}

View file

@ -0,0 +1,123 @@
<?php
/**
* @file
* Contains \Drupal\node\Tests\NodeTypeTranslationTest.
*/
namespace Drupal\node\Tests;
use Drupal\Component\Utility\Unicode;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\simpletest\WebTestBase;
/**
* Ensures that node types translation work correctly.
*
* @group node
*/
class NodeTypeTranslationTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array(
'config_translation',
'node',
);
/**
* Languages to enable.
*
* @var array
*/
protected $langcodes = array('fr');
/**
* Administrator user for tests.
*
* @var \Drupal\user\UserInterface
*/
protected $adminUser;
protected function setUp() {
parent::setUp();
$admin_permissions = array(
'administer content types',
'administer site configuration',
'administer themes',
'translate configuration',
);
// Create and login user.
$this->adminUser = $this->drupalCreateUser($admin_permissions);
// Add languages.
foreach ($this->langcodes as $langcode) {
ConfigurableLanguage::createFromLangcode($langcode)->save();
}
}
/**
* Tests the node type translation.
*/
public function testNodeTypeTranslation() {
$type = Unicode::strtolower($this->randomMachineName(16));
$name = $this->randomString();
$this->drupalLogin($this->adminUser);
$this->drupalCreateContentType(array('type' => $type, 'name' => $name));
// Translate the node type name.
$langcode = $this->langcodes[0];
$translated_name = $langcode . '-' . $name;
$edit = array(
"translation[config_names][node.type.$type][name]" => $translated_name,
);
// Edit the title label to avoid having an exception when we save the translation.
$this->drupalPostForm("admin/structure/types/manage/$type", array('title_label' => 'Edited title'), t('Save content type'));
$this->drupalPostForm("admin/structure/types/manage/$type/translate/$langcode/add", $edit, t('Save translation'));
// Check the name is translated without admin theme for editing.
$this->drupalPostForm('admin/appearance', array('use_admin_theme' => '0'), t('Save configuration'));
$this->drupalGet("$langcode/node/add/$type");
$this->assertRaw(t('Create @name', array('@name' => $translated_name)));
// Check the name is translated with admin theme for editing.
$this->drupalPostForm('admin/appearance', array('use_admin_theme' => '1'), t('Save configuration'));
$this->drupalGet("$langcode/node/add/$type");
$this->assertRaw(t('Create @name', array('@name' => $translated_name)));
}
/**
* Tests the node type title label translation.
*/
public function testNodeTypeTitleLabelTranslation() {
$type = Unicode::strtolower($this->randomMachineName(16));
$name = $this->randomString();
$this->drupalLogin($this->adminUser);
$this->drupalCreateContentType(array('type' => $type, 'name' => $name));
$langcode = $this->langcodes[0];
// Edit the title label for it to be displayed on the translation form.
$this->drupalPostForm("admin/structure/types/manage/$type", array('title_label' => 'Edited title'), t('Save content type'));
// Assert that the title label is displayed on the translation form with the right value.
$this->drupalGet("admin/structure/types/manage/$type/translate/$langcode/add");
$this->assertRaw(t('Label'));
$this->assertRaw(t('Edited title'));
// Translate the title label.
$this->drupalPostForm(NULL, array("translation[config_names][core.base_field_override.node.$type.title][label]" => 'Translated title'), t('Save translation'));
// Assert that the right title label is displayed on the node add form.
$this->drupalGet("node/add/$type");
$this->assertRaw(t('Edited title'));
$this->drupalGet("$langcode/node/add/$type");
$this->assertRaw(t('Translated title'));
}
}

View file

@ -11,7 +11,9 @@ use Drupal\comment\Tests\CommentTestTrait;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Language\LanguageInterface;
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\node\Entity\NodeType;
/**
@ -29,7 +31,7 @@ class PagePreviewTest extends NodeTestBase {
*
* @var array
*/
public static $modules = array('node', 'taxonomy', 'comment');
public static $modules = array('node', 'taxonomy', 'comment', 'image', 'file');
/**
* The name of the created field.
@ -68,6 +70,25 @@ class PagePreviewTest extends NodeTestBase {
$this->term = $term;
// Create an image field.
FieldStorageConfig::create([
'field_name' => 'field_image',
'entity_type' => 'node',
'type' => 'image',
'settings' => [],
'cardinality' => FieldStorageConfig::CARDINALITY_UNLIMITED,
])->save();
$field_config = FieldConfig::create([
'field_name' => 'field_image',
'label' => 'Images',
'entity_type' => 'node',
'bundle' => 'page',
'required' => FALSE,
'settings' => [],
]);
$field_config->save();
// Create a field.
$this->fieldName = Unicode::strtolower($this->randomMachineName());
$handler_settings = array(
@ -95,6 +116,17 @@ class PagePreviewTest extends NodeTestBase {
'type' => 'entity_reference_label',
))
->save();
entity_get_form_display('node', 'page', 'default')
->setComponent('field_image', array(
'type' => 'image_image',
'settings' => [],
))
->save();
entity_get_display('node', 'page', 'default')
->setComponent('field_image')
->save();
}
/**
@ -107,14 +139,21 @@ class PagePreviewTest extends NodeTestBase {
// Fill in node creation form and preview node.
$edit = array();
$edit[$title_key] = $this->randomMachineName(8);
$edit[$title_key] = '<em>' . $this->randomMachineName(8) . '</em>';
$edit[$body_key] = $this->randomMachineName(16);
$edit[$term_key] = $this->term->getName();
$this->drupalPostForm('node/add/page', $edit, t('Preview'));
// Upload an image.
$test_image = current($this->drupalGetTestFiles('image', 39325));
$edit['files[field_image_0][]'] = drupal_realpath($test_image->uri);
$this->drupalPostForm('node/add/page', $edit, t('Upload'));
// Add an alt tag and preview the node.
$this->drupalPostForm(NULL, ['field_image[0][alt]' => 'Picture of llamas'], t('Preview'));
// Check that the preview is displaying the title, body and term.
$this->assertTitle(t('@title | Drupal', array('@title' => $edit[$title_key])), 'Basic page title is preview.');
$this->assertText($edit[$title_key], 'Title displayed.');
$this->assertEscaped($edit[$title_key], 'Title displayed and escaped.');
$this->assertText($edit[$body_key], 'Body displayed.');
$this->assertText($edit[$term_key], 'Term displayed.');
$this->assertLink(t('Back to content editing'));
@ -141,11 +180,12 @@ class PagePreviewTest extends NodeTestBase {
$this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
$this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
$this->assertFieldByName($term_key, $edit[$term_key] . ' (' . $this->term->id() . ')', 'Term field displayed.');
$this->assertFieldByName('field_image[0][alt]', 'Picture of llamas');
// Return to page preview to check everything is as expected.
$this->drupalPostForm(NULL, array(), t('Preview'));
$this->assertTitle(t('@title | Drupal', array('@title' => $edit[$title_key])), 'Basic page title is preview.');
$this->assertText($edit[$title_key], 'Title displayed.');
$this->assertEscaped($edit[$title_key], 'Title displayed and escaped.');
$this->assertText($edit[$body_key], 'Body displayed.');
$this->assertText($edit[$term_key], 'Term displayed.');
$this->assertLink(t('Back to content editing'));
@ -156,8 +196,9 @@ class PagePreviewTest extends NodeTestBase {
$this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
$this->assertFieldByName($term_key, $edit[$term_key] . ' (' . $this->term->id() . ')', 'Term field displayed.');
// Save the node.
$this->drupalPostForm('node/add/page', $edit, t('Save'));
// Save the node - this is a new POST, so we need to upload the image.
$this->drupalPostForm('node/add/page', $edit, t('Upload'));
$this->drupalPostForm(NULL, ['field_image[0][alt]' => 'Picture of llamas'], t('Save'));
$node = $this->drupalGetNodeByTitle($edit[$title_key]);
// Check the term was displayed on the saved node.

View file

@ -85,7 +85,7 @@ class BulkFormAccessTest extends NodeTestBase {
$this->assertTrue($node->isPublished(), 'Node is initially published.');
// Ensure that the node can not be edited.
$this->assertEqual(FALSE, $this->accessHandler->access($node, 'update', $node->prepareLangcode(), $account), 'The node may not be edited.');
$this->assertEqual(FALSE, $this->accessHandler->access($node, 'update', $account), 'The node may not be edited.');
// Test editing the node using the bulk form.
$edit = array(
@ -155,9 +155,9 @@ class BulkFormAccessTest extends NodeTestBase {
$this->drupalLogin($account);
// Ensure that the private node can not be deleted.
$this->assertEqual(FALSE, $this->accessHandler->access($private_node, 'delete', $private_node->prepareLangcode(), $account), 'The private node may not be deleted.');
$this->assertEqual(FALSE, $this->accessHandler->access($private_node, 'delete', $account), 'The private node may not be deleted.');
// Ensure that the public node may be deleted.
$this->assertEqual(TRUE, $this->accessHandler->access($own_node, 'delete', $own_node->prepareLangcode(), $account), 'The own node may be deleted.');
$this->assertEqual(TRUE, $this->accessHandler->access($own_node, 'delete', $account), 'The own node may be deleted.');
// Try to delete the node using the bulk form.
$edit = array(

View file

@ -73,7 +73,7 @@ class FrontPageTest extends ViewTestBase {
'user',
],
];
$this->assertIdentical($expected, $view->calculateDependencies());
$this->assertIdentical($expected, $view->getDependencies());
$view->setDisplay('page_1');
$this->executeView($view);

View file

@ -0,0 +1,85 @@
<?php
/**
* @file
* Contains \Drupal\node\Tests\Views\NidArgumentTest.
*/
namespace Drupal\node\Tests\Views;
use Drupal\node\Entity\Node;
use Drupal\views\Tests\ViewKernelTestBase;
use Drupal\views\Tests\ViewTestData;
use Drupal\views\Views;
/**
* Tests the nid argument handler.
*
* @group node
* @see \Drupal\node\Plugin\views\argument\Nid
*/
class NidArgumentTest extends ViewKernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['node', 'field', 'text', 'node_test_config', 'user', 'node_test_views'];
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_nid_argument'];
/**
* {@inheritdoc}
*/
protected function setUp($import_test_views = TRUE) {
parent::setUp($import_test_views);
$this->installEntitySchema('node');
$this->installEntitySchema('user');
$this->installConfig(['node', 'field']);
ViewTestData::createTestViews(get_class($this), ['node_test_views']);
}
/**
* Test the nid argument.
*/
public function testNidArgument() {
$view = Views::getView('test_nid_argument');
$view->setDisplay();
$node1 = Node::create([
'type' => 'default',
'title' => $this->randomMachineName(),
]);
$node1->save();
$node2 = Node::create([
'type' => 'default',
'title' => $this->randomMachineName(),
]);
$node2->save();
$view->preview();
$this->assertEqual(count($view->result), 2, 'Found the expected number of results.');
// Set an the second node id as an argument.
$view->destroy();
$view->preview('default', [$node2->id()]);
// Verify that the title is overridden.
$this->assertEqual($view->getTitle(), $node2->getTitle());
// Verify that the argument filtering works.
$this->assertEqual(count($view->result), 1, 'Found the expected number of results.');
$this->assertEqual($node2->id(), (string) $view->style_plugin->getField(0, 'nid'), 'Found the correct nid.');
// Verify that setting a non-existing id as argument results in no nodes
// being shown.
$view->destroy();
$view->preview('default', [22]);
$this->assertEqual(count($view->result), 0, 'Found the expected number of results.');
}
}

View file

@ -29,7 +29,7 @@ class NodeIntegrationTest extends NodeTestBase {
$types = array();
$all_nids = array();
for ($i = 0; $i < 2; $i++) {
$type = $this->drupalCreateContentType();
$type = $this->drupalCreateContentType(['name' => '<em>' . $this->randomMachineName() . '</em>']);
$types[] = $type;
for ($j = 0; $j < 5; $j++) {
@ -49,6 +49,7 @@ class NodeIntegrationTest extends NodeTestBase {
foreach ($types as $type) {
$this->drupalGet("test-node-view/{$type->id()}");
$this->assertEscaped($type->label());
$this->assertNids(array_keys($nodes[$type->id()]));
}
}