updated core to 8.6.1 via composer

This commit is contained in:
2018-09-12 13:58:26 +02:00
parent a9a219f2ed
commit ea56b9fba3
4443 changed files with 112098 additions and 40708 deletions
@@ -4,8 +4,9 @@ namespace Drupal\node\ContextProvider;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Core\Plugin\Context\ContextProviderInterface;
use Drupal\Core\Plugin\Context\EntityContext;
use Drupal\Core\Plugin\Context\EntityContextDefinition;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\node\Entity\Node;
use Drupal\Core\StringTranslation\StringTranslationTrait;
@@ -39,7 +40,7 @@ class NodeRouteContext implements ContextProviderInterface {
*/
public function getRuntimeContexts(array $unqualified_context_ids) {
$result = [];
$context_definition = new ContextDefinition('entity:node', NULL, FALSE);
$context_definition = EntityContextDefinition::create('node')->setRequired(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')) {
@@ -65,7 +66,7 @@ class NodeRouteContext implements ContextProviderInterface {
* {@inheritdoc}
*/
public function getAvailableContexts() {
$context = new Context(new ContextDefinition('entity:node', $this->t('Node from URL')));
$context = EntityContext::fromEntityTypeId('node', $this->t('Node from URL'));
return ['node' => $context];
}
@@ -122,7 +122,7 @@ class NodeController extends ControllerBase implements ContainerInjectionInterfa
* The node revision ID.
*
* @return array
* An array suitable for drupal_render().
* An array suitable for \Drupal\Core\Render\RendererInterface::render().
*/
public function revisionShow($node_revision) {
$node = $this->entityManager()->getStorage('node')->loadRevision($node_revision);
@@ -154,7 +154,7 @@ class NodeController extends ControllerBase implements ContainerInjectionInterfa
* A node object.
*
* @return array
* An array as expected by drupal_render().
* An array as expected by \Drupal\Core\Render\RendererInterface::render().
*/
public function revisionOverview(NodeInterface $node) {
$account = $this->currentUser();
+3 -2
View File
@@ -33,7 +33,8 @@ use Drupal\user\UserInterface;
* "form" = {
* "default" = "Drupal\node\NodeForm",
* "delete" = "Drupal\node\Form\NodeDeleteForm",
* "edit" = "Drupal\node\NodeForm"
* "edit" = "Drupal\node\NodeForm",
* "delete-multiple-confirm" = "Drupal\node\Form\DeleteMultiple"
* },
* "route_provider" = {
* "html" = "Drupal\node\Entity\NodeRouteProvider",
@@ -71,6 +72,7 @@ use Drupal\user\UserInterface;
* links = {
* "canonical" = "/node/{node}",
* "delete-form" = "/node/{node}/delete",
* "delete-multiple-form" = "/admin/content/node/delete",
* "edit-form" = "/node/{node}/edit",
* "version-history" = "/node/{node}/revisions",
* "revision" = "/node/{node}/revisions/{node_revision}/view",
@@ -210,7 +212,6 @@ class Node extends EditorialContentEntityBase implements NodeInterface {
return $this->get('created')->value;
}
/**
* {@inheritdoc}
*/
+8 -1
View File
@@ -12,6 +12,13 @@ use Drupal\node\NodeTypeInterface;
* @ConfigEntityType(
* id = "node_type",
* label = @Translation("Content type"),
* label_collection = @Translation("Content types"),
* label_singular = @Translation("content type"),
* label_plural = @Translation("content types"),
* label_count = @PluralTranslation(
* singular = "@count content type",
* plural = "@count content types",
* ),
* handlers = {
* "access" = "Drupal\node\NodeTypeAccessControlHandler",
* "form" = {
@@ -179,7 +186,7 @@ class NodeType extends ConfigEntityBundleBase implements NodeTypeInterface {
if ($update && $this->getOriginalId() != $this->id()) {
$update_count = node_type_update_nodes($this->getOriginalId(), $this->id());
if ($update_count) {
drupal_set_message(\Drupal::translation()->formatPlural($update_count,
\Drupal::messenger()->addStatus(\Drupal::translation()->formatPlural($update_count,
'Changed the content type of 1 post from %old-type to %type.',
'Changed the content type of @count posts from %old-type to %type.',
[
+6 -171
View File
@@ -2,78 +2,15 @@
namespace Drupal\node\Form;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Form\ConfirmFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Entity\Form\DeleteMultipleForm as EntityDeleteMultipleForm;
use Drupal\Core\Url;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* Provides a node deletion confirmation form.
*
* @internal
*/
class DeleteMultiple extends ConfirmFormBase {
/**
* The array of nodes to delete.
*
* @var string[][]
*/
protected $nodeInfo = [];
/**
* The tempstore factory.
*
* @var \Drupal\Core\TempStore\PrivateTempStoreFactory
*/
protected $tempStoreFactory;
/**
* The node storage.
*
* @var \Drupal\Core\Entity\EntityStorageInterface
*/
protected $storage;
/**
* Constructs a DeleteMultiple form object.
*
* @param \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory
* The tempstore factory.
* @param \Drupal\Core\Entity\EntityManagerInterface $manager
* The entity manager.
*/
public function __construct(PrivateTempStoreFactory $temp_store_factory, EntityManagerInterface $manager) {
$this->tempStoreFactory = $temp_store_factory;
$this->storage = $manager->getStorage('node');
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('tempstore.private'),
$container->get('entity.manager')
);
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'node_multiple_delete_confirm';
}
/**
* {@inheritdoc}
*/
public function getQuestion() {
return $this->formatPlural(count($this->nodeInfo), 'Are you sure you want to delete this item?', 'Are you sure you want to delete these items?');
}
class DeleteMultiple extends EntityDeleteMultipleForm {
/**
* {@inheritdoc}
@@ -85,117 +22,15 @@ class DeleteMultiple extends ConfirmFormBase {
/**
* {@inheritdoc}
*/
public function getConfirmText() {
return t('Delete');
protected function getDeletedMessage($count) {
return $this->formatPlural($count, 'Deleted @count content item.', 'Deleted @count content items.');
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$this->nodeInfo = $this->tempStoreFactory->get('node_multiple_delete_confirm')->get(\Drupal::currentUser()->id());
if (empty($this->nodeInfo)) {
return new RedirectResponse($this->getCancelUrl()->setAbsolute()->toString());
}
/** @var \Drupal\node\NodeInterface[] $nodes */
$nodes = $this->storage->loadMultiple(array_keys($this->nodeInfo));
$items = [];
foreach ($this->nodeInfo as $id => $langcodes) {
foreach ($langcodes as $langcode) {
$node = $nodes[$id]->getTranslation($langcode);
$key = $id . ':' . $langcode;
$default_key = $id . ':' . $node->getUntranslated()->language()->getId();
// If we have a translated entity we build a nested list of translations
// that will be deleted.
$languages = $node->getTranslationLanguages();
if (count($languages) > 1 && $node->isDefaultTranslation()) {
$names = [];
foreach ($languages as $translation_langcode => $language) {
$names[] = $language->getName();
unset($items[$id . ':' . $translation_langcode]);
}
$items[$default_key] = [
'label' => [
'#markup' => $this->t('@label (Original translation) - <em>The following content translations will be deleted:</em>', ['@label' => $node->label()]),
],
'deleted_translations' => [
'#theme' => 'item_list',
'#items' => $names,
],
];
}
elseif (!isset($items[$default_key])) {
$items[$key] = $node->label();
}
}
}
$form['nodes'] = [
'#theme' => 'item_list',
'#items' => $items,
];
$form = parent::buildForm($form, $form_state);
return $form;
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
if ($form_state->getValue('confirm') && !empty($this->nodeInfo)) {
$total_count = 0;
$delete_nodes = [];
/** @var \Drupal\Core\Entity\ContentEntityInterface[][] $delete_translations */
$delete_translations = [];
/** @var \Drupal\node\NodeInterface[] $nodes */
$nodes = $this->storage->loadMultiple(array_keys($this->nodeInfo));
foreach ($this->nodeInfo as $id => $langcodes) {
foreach ($langcodes as $langcode) {
$node = $nodes[$id]->getTranslation($langcode);
if ($node->isDefaultTranslation()) {
$delete_nodes[$id] = $node;
unset($delete_translations[$id]);
$total_count += count($node->getTranslationLanguages());
}
elseif (!isset($delete_nodes[$id])) {
$delete_translations[$id][] = $node;
}
}
}
if ($delete_nodes) {
$this->storage->delete($delete_nodes);
$this->logger('content')->notice('Deleted @count posts.', ['@count' => count($delete_nodes)]);
}
if ($delete_translations) {
$count = 0;
foreach ($delete_translations as $id => $translations) {
$node = $nodes[$id]->getUntranslated();
foreach ($translations as $translation) {
$node->removeTranslation($translation->language()->getId());
}
$node->save();
$count += count($translations);
}
if ($count) {
$total_count += $count;
$this->logger('content')->notice('Deleted @count content translations.', ['@count' => $count]);
}
}
if ($total_count) {
drupal_set_message($this->formatPlural($total_count, 'Deleted 1 post.', 'Deleted @count posts.'));
}
$this->tempStoreFactory->get('node_multiple_delete_confirm')->delete(\Drupal::currentUser()->id());
}
$form_state->setRedirect('system.admin_content');
protected function getInaccessibleMessage($count) {
return $this->formatPlural($count, "@count content item has not been deleted because you do not have the necessary permissions.", "@count content items have not been deleted because you do not have the necessary permissions.");
}
}
@@ -107,7 +107,7 @@ class NodePreviewForm extends FormBase {
'#default_value' => $view_mode,
'#attributes' => [
'data-drupal-autosubmit' => TRUE,
]
],
];
$form['submit'] = [
@@ -118,7 +118,12 @@ class NodeRevisionDeleteForm extends ConfirmFormBase {
$this->logger('content')->notice('@type: deleted %title revision %revision.', ['@type' => $this->revision->bundle(), '%title' => $this->revision->label(), '%revision' => $this->revision->getRevisionId()]);
$node_type = $this->nodeTypeStorage->load($this->revision->bundle())->label();
drupal_set_message(t('Revision from %revision-date of @type %title has been deleted.', ['%revision-date' => format_date($this->revision->getRevisionCreationTime()), '@type' => $node_type, '%title' => $this->revision->label()]));
$this->messenger()
->addStatus($this->t('Revision from %revision-date of @type %title has been deleted.', [
'%revision-date' => format_date($this->revision->getRevisionCreationTime()),
'@type' => $node_type,
'%title' => $this->revision->label(),
]));
$form_state->setRedirect(
'entity.node.canonical',
['node' => $this->revision->id()]
@@ -128,12 +128,18 @@ class NodeRevisionRevertForm extends ConfirmFormBase {
$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->setRevisionUserId($this->currentUser()->id());
$this->revision->setRevisionCreationTime($this->time->getRequestTime());
$this->revision->setChangedTime($this->time->getRequestTime());
$this->revision->save();
$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)]));
$this->messenger()
->addStatus($this->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',
['node' => $this->revision->id()]
@@ -50,7 +50,6 @@ class NodeAccessControlHandler extends EntityAccessControlHandler implements Nod
);
}
/**
* {@inheritdoc}
*/
+11 -11
View File
@@ -4,7 +4,7 @@ namespace Drupal\node;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
@@ -35,8 +35,8 @@ class NodeForm extends ContentEntityForm {
/**
* Constructs a NodeForm object.
*
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager.
* @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
* The entity repository.
* @param \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory
* The factory for the temp store object.
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
@@ -46,8 +46,8 @@ class NodeForm extends ContentEntityForm {
* @param \Drupal\Core\Session\AccountInterface $current_user
* The current user.
*/
public function __construct(EntityManagerInterface $entity_manager, PrivateTempStoreFactory $temp_store_factory, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL, AccountInterface $current_user) {
parent::__construct($entity_manager, $entity_type_bundle_info, $time);
public function __construct(EntityRepositoryInterface $entity_repository, PrivateTempStoreFactory $temp_store_factory, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL, AccountInterface $current_user) {
parent::__construct($entity_repository, $entity_type_bundle_info, $time);
$this->tempStoreFactory = $temp_store_factory;
$this->currentUser = $current_user;
}
@@ -57,7 +57,7 @@ class NodeForm extends ContentEntityForm {
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity.manager'),
$container->get('entity.repository'),
$container->get('tempstore.private'),
$container->get('entity_type.bundle.info'),
$container->get('datetime.time'),
@@ -102,7 +102,7 @@ class NodeForm extends ContentEntityForm {
if ($this->operation == 'edit') {
$form['#title'] = $this->t('<em>Edit @type</em> @title', [
'@type' => node_get_type_label($node),
'@title' => $node->label()
'@title' => $node->label(),
]);
}
@@ -217,7 +217,7 @@ class NodeForm extends ContentEntityForm {
public function updateStatus($entity_type_id, NodeInterface $node, array $form, FormStateInterface $form_state) {
$element = $form_state->getTriggeringElement();
if (isset($element['#published_status'])) {
$node->setPublished($element['#published_status']);
$element['#published_status'] ? $node->setPublished() : $node->setUnpublished();
}
}
@@ -285,11 +285,11 @@ class NodeForm extends ContentEntityForm {
if ($insert) {
$this->logger('content')->notice('@type: added %title.', $context);
drupal_set_message(t('@type %title has been created.', $t_args));
$this->messenger()->addStatus($this->t('@type %title has been created.', $t_args));
}
else {
$this->logger('content')->notice('@type: updated %title.', $context);
drupal_set_message(t('@type %title has been updated.', $t_args));
$this->messenger()->addStatus($this->t('@type %title has been updated.', $t_args));
}
if ($node->id()) {
@@ -312,7 +312,7 @@ class NodeForm extends ContentEntityForm {
else {
// In the unlikely case something went wrong on save, the node will be
// rebuilt and node form redisplayed the same way as in preview.
drupal_set_message(t('The post could not be saved.'), 'error');
$this->messenger()->addError($this->t('The post could not be saved.'));
$form_state->setRebuild();
}
}
+5 -5
View File
@@ -19,7 +19,7 @@ class NodeStorage extends SqlContentEntityStorage implements NodeStorageInterfac
*/
public function revisionIds(NodeInterface $node) {
return $this->database->query(
'SELECT vid FROM {node_revision} WHERE nid=:nid ORDER BY vid',
'SELECT vid FROM {' . $this->getRevisionTable() . '} WHERE nid=:nid ORDER BY vid',
[':nid' => $node->id()]
)->fetchCol();
}
@@ -29,7 +29,7 @@ class NodeStorage extends SqlContentEntityStorage implements NodeStorageInterfac
*/
public function userRevisionIds(AccountInterface $account) {
return $this->database->query(
'SELECT vid FROM {node_field_revision} WHERE uid = :uid ORDER BY vid',
'SELECT vid FROM {' . $this->getRevisionDataTable() . '} WHERE uid = :uid ORDER BY vid',
[':uid' => $account->id()]
)->fetchCol();
}
@@ -38,14 +38,14 @@ class NodeStorage extends SqlContentEntityStorage implements NodeStorageInterfac
* {@inheritdoc}
*/
public function countDefaultLanguageRevisions(NodeInterface $node) {
return $this->database->query('SELECT COUNT(*) FROM {node_field_revision} WHERE nid = :nid AND default_langcode = 1', [':nid' => $node->id()])->fetchField();
return $this->database->query('SELECT COUNT(*) FROM {' . $this->getRevisionDataTable() . '} WHERE nid = :nid AND default_langcode = 1', [':nid' => $node->id()])->fetchField();
}
/**
* {@inheritdoc}
*/
public function updateType($old_type, $new_type) {
return $this->database->update('node')
return $this->database->update($this->getBaseTable())
->fields(['type' => $new_type])
->condition('type', $old_type)
->execute();
@@ -55,7 +55,7 @@ class NodeStorage extends SqlContentEntityStorage implements NodeStorageInterfac
* {@inheritdoc}
*/
public function clearRevisionsLanguage(LanguageInterface $language) {
return $this->database->update('node_revision')
return $this->database->update($this->getRevisionTable())
->fields(['langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED])
->condition('langcode', $language->getId())
->execute();
+6 -4
View File
@@ -17,10 +17,12 @@ class NodeStorageSchema extends SqlContentEntityStorageSchema {
protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $reset = FALSE) {
$schema = parent::getEntitySchema($entity_type, $reset);
$schema['node_field_data']['indexes'] += [
'node__frontpage' => ['promote', 'status', 'sticky', 'created'],
'node__title_type' => ['title', ['type', 4]],
];
if ($data_table = $this->storage->getDataTable()) {
$schema[$data_table]['indexes'] += [
'node__frontpage' => ['promote', 'status', 'sticky', 'created'],
'node__title_type' => ['title', ['type', 4]],
];
}
return $schema;
}
+3 -3
View File
@@ -124,7 +124,7 @@ class NodeTypeForm extends BundleEntityFormBase {
DRUPAL_REQUIRED => t('Required'),
],
];
$form['submission']['help'] = [
$form['submission']['help'] = [
'#type' => 'textarea',
'#title' => t('Explanation or submission guidelines'),
'#default_value' => $type->getHelp(),
@@ -225,11 +225,11 @@ class NodeTypeForm extends BundleEntityFormBase {
$t_args = ['%name' => $type->label()];
if ($status == SAVED_UPDATED) {
drupal_set_message(t('The content type %name has been updated.', $t_args));
$this->messenger()->addStatus($this->t('The content type %name has been updated.', $t_args));
}
elseif ($status == SAVED_NEW) {
node_add_body_field($type);
drupal_set_message(t('The content type %name has been added.', $t_args));
$this->messenger()->addStatus($this->t('The content type %name has been added.', $t_args));
$context = array_merge($t_args, ['link' => $type->link($this->t('View'), 'collection')]);
$this->logger('node')->notice('Added content type %name.', $context);
}
@@ -56,7 +56,7 @@ 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()
':link' => Url::fromRoute('node.type_add')->toString(),
]);
return $build;
}
+1 -1
View File
@@ -46,7 +46,7 @@ class NodeViewBuilder extends EntityViewBuilder {
'#title' => t('Language'),
'#markup' => $entity->language()->getName(),
'#prefix' => '<div id="field-language-display">',
'#suffix' => '</div>'
'#suffix' => '</div>',
];
}
}
+2 -2
View File
@@ -280,7 +280,7 @@ class NodeViewsData extends EntityViewsData {
// Define the base group of this table. Fields that don't have a group defined
// will go into this field by default.
$data['node_access']['table']['group'] = $this->t('Content access');
$data['node_access']['table']['group'] = $this->t('Content access');
// For other base tables, explain how we join.
$data['node_access']['table']['join'] = [
@@ -322,7 +322,7 @@ class NodeViewsData extends EntityViewsData {
'field' => 'sid',
'table' => 'search_index',
'extra' => "node_search_index.type = 'node_search' AND node_search_index.langcode = node_field_data.langcode",
]
],
];
$data['node_search_total']['table']['join'] = [
@@ -2,98 +2,33 @@
namespace Drupal\node\Plugin\Action;
use Drupal\Core\Action\ActionBase;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Action\Plugin\Action\DeleteAction;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Redirects to a node deletion form.
*
* @deprecated in Drupal 8.6.x, to be removed before Drupal 9.0.0.
* Use \Drupal\Core\Action\Plugin\Action\DeleteAction instead.
*
* @see \Drupal\Core\Action\Plugin\Action\DeleteAction
* @see https://www.drupal.org/node/2934349
*
* @Action(
* id = "node_delete_action",
* label = @Translation("Delete content"),
* type = "node",
* confirm_form_route_name = "node.multiple_delete_confirm"
* label = @Translation("Delete content")
* )
*/
class DeleteNode extends ActionBase implements ContainerFactoryPluginInterface {
/**
* The tempstore object.
*
* @var \Drupal\Core\TempStore\SharedTempStore
*/
protected $tempStore;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* Constructs a new DeleteNode object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin ID for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory
* The tempstore factory.
* @param \Drupal\Core\Session\AccountInterface $current_user
* Current user.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, PrivateTempStoreFactory $temp_store_factory, AccountInterface $current_user) {
$this->currentUser = $current_user;
$this->tempStore = $temp_store_factory->get('node_multiple_delete_confirm');
parent::__construct($configuration, $plugin_id, $plugin_definition);
}
class DeleteNode extends DeleteAction {
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('tempstore.private'),
$container->get('current_user')
);
}
/**
* {@inheritdoc}
*/
public function executeMultiple(array $entities) {
$info = [];
/** @var \Drupal\node\NodeInterface $node */
foreach ($entities as $node) {
$langcode = $node->language()->getId();
$info[$node->id()][$langcode] = $langcode;
}
$this->tempStore->set($this->currentUser->id(), $info);
}
/**
* {@inheritdoc}
*/
public function execute($object = NULL) {
$this->executeMultiple([$object]);
}
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
/** @var \Drupal\node\NodeInterface $object */
return $object->access('delete', $account, $return_as_object);
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, PrivateTempStoreFactory $temp_store_factory, AccountInterface $current_user) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager, $temp_store_factory, $current_user);
@trigger_error(__NAMESPACE__ . '\DeleteNode is deprecated in Drupal 8.6.x, will be removed before Drupal 9.0.0. Use \Drupal\Core\Action\Plugin\Action\DeleteAction instead. See https://www.drupal.org/node/2934349.', E_USER_DEPRECATED);
}
}
@@ -25,7 +25,7 @@ class UnpublishByKeywordNode extends ConfigurableActionBase {
foreach ($this->configuration['keywords'] as $keyword) {
$elements = node_view(clone $node);
if (strpos(\Drupal::service('renderer')->render($elements), $keyword) !== FALSE || strpos($node->label(), $keyword) !== FALSE) {
$node->setPublished(FALSE);
$node->setUnpublished();
$node->save();
break;
}
@@ -42,7 +42,7 @@ class NodeSelection extends DefaultSelection {
// In order to create a referenceable node, it needs to published.
/** @var \Drupal\node\NodeInterface $node */
$node->setPublished(TRUE);
$node->setPublished();
return $node;
}
@@ -13,6 +13,7 @@ use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Access\AccessibleInterface;
use Drupal\Core\Database\Query\Condition;
@@ -114,6 +115,13 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
*/
const ADVANCED_FORM = 'advanced-form';
/**
* The messenger.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
protected $messenger;
/**
* {@inheritdoc}
*/
@@ -128,6 +136,7 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
$container->get('config.factory')->get('search.settings'),
$container->get('language_manager'),
$container->get('renderer'),
$container->get('messenger'),
$container->get('current_user')
);
}
@@ -153,16 +162,19 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
* The language manager.
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* The messenger.
* @param \Drupal\Core\Session\AccountInterface $account
* The $account object to use for checking for access to advanced search.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, Connection $database, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, Config $search_settings, LanguageManagerInterface $language_manager, RendererInterface $renderer, AccountInterface $account = NULL) {
public function __construct(array $configuration, $plugin_id, $plugin_definition, Connection $database, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, Config $search_settings, LanguageManagerInterface $language_manager, RendererInterface $renderer, MessengerInterface $messenger, AccountInterface $account = NULL) {
$this->database = $database;
$this->entityManager = $entity_manager;
$this->moduleHandler = $module_handler;
$this->searchSettings = $search_settings;
$this->languageManager = $language_manager;
$this->renderer = $renderer;
$this->messenger = $messenger;
$this->account = $account;
parent::__construct($configuration, $plugin_id, $plugin_definition);
@@ -289,15 +301,15 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
$status = $query->getStatus();
if ($status & SearchQuery::EXPRESSIONS_IGNORED) {
drupal_set_message($this->t('Your search used too many AND/OR expressions. Only the first @count terms were included in this search.', ['@count' => $this->searchSettings->get('and_or_limit')]), 'warning');
$this->messenger->addWarning($this->t('Your search used too many AND/OR expressions. Only the first @count terms were included in this search.', ['@count' => $this->searchSettings->get('and_or_limit')]));
}
if ($status & SearchQuery::LOWER_CASE_OR) {
drupal_set_message($this->t('Search for either of the two terms with uppercase <strong>OR</strong>. For example, <strong>cats OR dogs</strong>.'), 'warning');
$this->messenger->addWarning($this->t('Search for either of the two terms with uppercase <strong>OR</strong>. For example, <strong>cats OR dogs</strong>.'));
}
if ($status & SearchQuery::NO_POSITIVE_KEYWORDS) {
drupal_set_message($this->formatPlural($this->searchSettings->get('index.minimum_word_size'), 'You must include at least one keyword to match in the content, and punctuation is ignored.', 'You must include at least one keyword to match in the content. Keywords must be at least @count characters, and punctuation is ignored.'), 'warning');
$this->messenger->addWarning($this->formatPlural($this->searchSettings->get('index.minimum_word_size'), 'You must include at least one keyword to match in the content, and punctuation is ignored.', 'You must include at least one keyword to match in the content. Keywords must be at least @count characters, and punctuation is ignored.'));
}
return $find;
@@ -475,7 +487,7 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
'#prefix' => '<h1>',
'#plain_text' => $node->label(),
'#suffix' => '</h1>',
'#weight' => -1000
'#weight' => -1000,
];
$text = $this->renderer->renderPlain($build);
@@ -781,7 +793,7 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
'#open' => TRUE,
];
$form['content_ranking']['info'] = [
'#markup' => '<p><em>' . $this->t('Influence is a numeric multiplier used in ordering search results. A higher number means the corresponding factor has more influence on search results; zero means the factor is ignored. Changing these numbers does not require the search index to be rebuilt. Changes take effect immediately.') . '</em></p>'
'#markup' => '<p><em>' . $this->t('Influence is a numeric multiplier used in ordering search results. A higher number means the corresponding factor has more influence on search results; zero means the factor is ignored. Changing these numbers does not require the search index to be rebuilt. Changes take effect immediately.') . '</em></p>',
];
// Prepare table.
$header = [$this->t('Factor'), $this->t('Influence')];
@@ -165,7 +165,7 @@ class D6NodeDeriver extends DeriverBase implements ContainerDeriverInterface {
$this->fieldPluginCache[$field_type] = $this->fieldPluginManager->createInstance($plugin_id, ['core' => 6], $migration);
}
$this->fieldPluginCache[$field_type]
->processFieldValues($migration, $field_name, $info);
->defineValueProcessPipeline($migration, $field_name, $info);
}
catch (PluginNotFoundException $ex) {
try {
@@ -0,0 +1,21 @@
<?php
namespace Drupal\node\Plugin\migrate;
use Drupal\migrate\Plugin\Migration;
use Drupal\migrate_drupal\Plugin\MigrationWithFollowUpInterface;
/**
* Migration plugin for the Drupal 6 node translations.
*/
class D6NodeTranslation extends Migration implements MigrationWithFollowUpInterface {
/**
* {@inheritdoc}
*/
public function generateFollowUpMigrations() {
$this->migrationPluginManager->clearCachedDefinitions();
return $this->migrationPluginManager->createInstances('d6_entity_reference_translation');
}
}
@@ -168,7 +168,7 @@ class D7NodeDeriver extends DeriverBase implements ContainerDeriverInterface {
$this->fieldPluginCache[$field_type] = $this->fieldPluginManager->createInstance($plugin_id, ['core' => 7], $migration);
}
$this->fieldPluginCache[$field_type]
->processFieldValues($migration, $field_name, $info);
->defineValueProcessPipeline($migration, $field_name, $info);
}
catch (PluginNotFoundException $ex) {
try {
@@ -0,0 +1,21 @@
<?php
namespace Drupal\node\Plugin\migrate;
use Drupal\migrate\Plugin\Migration;
use Drupal\migrate_drupal\Plugin\MigrationWithFollowUpInterface;
/**
* Migration plugin for the Drupal 7 node translations.
*/
class D7NodeTranslation extends Migration implements MigrationWithFollowUpInterface {
/**
* {@inheritdoc}
*/
public function generateFollowUpMigrations() {
$this->migrationPluginManager->clearCachedDefinitions();
return $this->migrationPluginManager->createInstances('d7_entity_reference_translation');
}
}
@@ -104,17 +104,39 @@ class Node extends FieldableEntity {
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
$nid = $row->getSourceProperty('nid');
$vid = $row->getSourceProperty('vid');
$type = $row->getSourceProperty('type');
// If this entity was translated using Entity Translation, we need to get
// its source language to get the field values in the right language.
// The translations will be migrated by the d7_node_entity_translation
// migration.
$entity_translatable = $this->isEntityTranslatable('node') && (int) $this->variableGet('language_content_type_' . $type, 0) === 4;
$language = $entity_translatable ? $this->getEntityTranslationSourceLanguage('node', $nid) : $row->getSourceProperty('language');
// Get Field API field values.
foreach (array_keys($this->getFields('node', $row->getSourceProperty('type'))) as $field) {
$nid = $row->getSourceProperty('nid');
$vid = $row->getSourceProperty('vid');
$row->setSourceProperty($field, $this->getFieldValues('node', $field, $nid, $vid));
foreach ($this->getFields('node', $type) as $field_name => $field) {
// Ensure we're using the right language if the entity and the field are
// translatable.
$field_language = $entity_translatable && $field['translatable'] ? $language : NULL;
$row->setSourceProperty($field_name, $this->getFieldValues('node', $field_name, $nid, $vid, $field_language));
}
// Make sure we always have a translation set.
if ($row->getSourceProperty('tnid') == 0) {
$row->setSourceProperty('tnid', $row->getSourceProperty('nid'));
}
// If the node title was replaced by a real field using the Drupal 7 Title
// module, use the field value instead of the node title.
if ($this->moduleExists('title')) {
$title_field = $row->getSourceProperty('title_field');
if (isset($title_field[0]['value'])) {
$row->setSourceProperty('title', $title_field[0]['value']);
}
}
return parent::prepareRow($row);
}
@@ -0,0 +1,125 @@
<?php
namespace Drupal\node\Plugin\migrate\source\d7;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\migrate\source\d7\FieldableEntity;
/**
* Provides Drupal 7 node entity translations source plugin.
*
* @MigrateSource(
* id = "d7_node_entity_translation",
* source_module = "entity_translation"
* )
*/
class NodeEntityTranslation extends FieldableEntity {
/**
* {@inheritdoc}
*/
public function query() {
$query = $this->select('entity_translation', 'et')
->fields('et', [
'entity_id',
'revision_id',
'language',
'source',
'uid',
'status',
'created',
'changed',
])
->fields('n', [
'title',
'type',
'promote',
'sticky',
])
->fields('nr', [
'log',
'timestamp',
])
->condition('et.entity_type', 'node')
->condition('et.source', '', '<>');
$query->addField('nr', 'uid', 'revision_uid');
$query->innerJoin('node', 'n', 'n.nid = et.entity_id');
$query->innerJoin('node_revision', 'nr', 'nr.vid = et.revision_id');
if (isset($this->configuration['node_type'])) {
$query->condition('n.type', $this->configuration['node_type']);
}
return $query;
}
/**
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
$nid = $row->getSourceProperty('entity_id');
$vid = $row->getSourceProperty('revision_id');
$type = $row->getSourceProperty('type');
$language = $row->getSourceProperty('language');
// Get Field API field values.
foreach ($this->getFields('node', $type) as $field_name => $field) {
// Ensure we're using the right language if the entity is translatable.
$field_language = $field['translatable'] ? $language : NULL;
$row->setSourceProperty($field_name, $this->getFieldValues('node', $field_name, $nid, $vid, $field_language));
}
// If the node title was replaced by a real field using the Drupal 7 Title
// module, use the field value instead of the node title.
if ($this->moduleExists('title')) {
$title_field = $row->getSourceProperty('title_field');
if (isset($title_field[0]['value'])) {
$row->setSourceProperty('title', $title_field[0]['value']);
}
}
return parent::prepareRow($row);
}
/**
* {@inheritdoc}
*/
public function fields() {
return [
'entity_id' => $this->t('Entity ID'),
'revision_id' => $this->t('Revision ID'),
'language' => $this->t('Node translation language'),
'source' => $this->t('Node translation source language'),
'uid' => $this->t('Node translation authored by (uid)'),
'status' => $this->t('Published'),
'created' => $this->t('Created timestamp'),
'changed' => $this->t('Modified timestamp'),
'title' => $this->t('Node title'),
'type' => $this->t('Node type'),
'promote' => $this->t('Promoted to front page'),
'sticky' => $this->t('Sticky at top of lists'),
'log' => $this->t('Revision log'),
'timestamp' => $this->t('The timestamp the latest revision of this node was created.'),
'revision_uid' => $this->t('Revision authored by (uid)'),
];
}
/**
* {@inheritdoc}
*/
public function getIds() {
return [
'entity_id' => [
'type' => 'integer',
'alias' => 'et',
],
'language' => [
'type' => 'string',
'alias' => 'et',
],
];
}
}
@@ -29,7 +29,7 @@ class Vid extends NumericArgument {
protected $nodeStorage;
/**
* Constructs a Drupal\Component\Plugin\PluginBase object.
* Constructs a \Drupal\node\Plugin\views\argument\Vid object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
@@ -16,7 +16,9 @@ use Drupal\views\Plugin\views\filter\FilterPluginBase;
class Access extends FilterPluginBase {
public function adminSummary() {}
protected function operatorForm(&$form, FormStateInterface $form_state) {}
public function canExpose() {
return FALSE;
}
@@ -37,7 +37,7 @@ class Node extends WizardPluginBase {
public function getAvailableSorts() {
// You can't execute functions in properties, so override the method
return [
'node_field_data-title:ASC' => $this->t('Title')
'node_field_data-title:ASC' => $this->t('Title'),
];
}
@@ -109,8 +109,8 @@ class NodeRevisionsTest extends NodeTestBase {
$node->untranslatable_string_field->value = $this->randomString();
$node->setNewRevision();
// Edit the 2nd revision with a different user.
if ($i == 1) {
// Edit the 1st and 2nd revision with a different user.
if ($i < 2) {
$editor = $this->drupalCreateUser();
$node->setRevisionUserId($editor->id());
}
@@ -174,11 +174,15 @@ class NodeRevisionsTest extends NodeTestBase {
$this->assertRaw(t('@type %title has been reverted to the revision from %revision-date.', [
'@type' => 'Basic page',
'%title' => $nodes[1]->label(),
'%revision-date' => format_date($nodes[1]->getRevisionCreationTime())
'%revision-date' => format_date($nodes[1]->getRevisionCreationTime()),
]), 'Revision reverted.');
$node_storage->resetCache([$node->id()]);
$reverted_node = $node_storage->load($node->id());
$this->assertTrue(($nodes[1]->body->value == $reverted_node->body->value), 'Node reverted correctly.');
// Confirm the revision author is the user performing the revert.
$this->assertTrue($reverted_node->getRevisionUserId() == $this->loggedInUser->id(), 'Node revision author is user performing revert.');
// And that its not the revision author.
$this->assertTrue($reverted_node->getRevisionUserId() != $nodes[1]->getRevisionUserId(), 'Node revision author is not original revision author.');
// Confirm that this is not the default version.
$node = node_revision_load($node->getRevisionId());
+1 -1
View File
@@ -105,7 +105,7 @@ abstract class NodeTestBase extends WebTestBase {
[
'@result' => $result ? 'true' : 'false',
'%op' => $operation,
'%langcode' => !empty($langcode) ? $langcode : 'empty'
'%langcode' => !empty($langcode) ? $langcode : 'empty',
]
);
}
+1 -1
View File
@@ -249,7 +249,7 @@ 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()
':link' => Url::fromRoute('node.type_add')->toString(),
]), 'Empty text when there are no content types in the system is correct.');
$bundle_info->clearCachedBundles();
@@ -4,7 +4,6 @@ namespace Drupal\node\Tests;
use Drupal\comment\Tests\CommentTestTrait;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Url;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
@@ -88,7 +87,7 @@ class PagePreviewTest extends NodeTestBase {
$field_config->save();
// Create a field.
$this->fieldName = Unicode::strtolower($this->randomMachineName());
$this->fieldName = mb_strtolower($this->randomMachineName());
$handler_settings = [
'target_bundles' => [
$this->vocabulary->id() => $this->vocabulary->id(),
@@ -134,7 +133,7 @@ class PagePreviewTest extends NodeTestBase {
'type' => 'text',
'settings' => [
'max_length' => 50,
]
],
]);
$field_storage->save();
FieldConfig::create([
@@ -184,6 +183,10 @@ class PagePreviewTest extends NodeTestBase {
$this->assertText($edit[$term_key], 'Term displayed.');
$this->assertLink(t('Back to content editing'));
// Check that we see the class of the node type on the body element.
$body_class_element = $this->xpath("//body[contains(@class, 'page-node-type-page')]");
$this->assertTrue(!empty($body_class_element), 'Node type body class found.');
// Get the UUID.
$url = parse_url($this->getUrl());
$paths = explode('/', $url['path']);