diff options
Diffstat (limited to 'core/modules/node/src')
13 files changed, 59 insertions, 46 deletions
diff --git a/core/modules/node/src/Controller/NodeController.php b/core/modules/node/src/Controller/NodeController.php index 87c9586daee..d5a35f64285 100644 --- a/core/modules/node/src/Controller/NodeController.php +++ b/core/modules/node/src/Controller/NodeController.php @@ -196,10 +196,12 @@ class NodeController extends ControllerBase implements ContainerInjectionInterfa 'username' => $this->renderer->renderInIsolation($username), 'message' => ['#markup' => $revision->revision_log->value, '#allowed_tags' => Xss::getHtmlTagList()], ], + // @todo Fix this properly in https://www.drupal.org/project/drupal/issues/3227637. + '#cache' => [ + 'max-age' => 0, + ], ], ]; - // @todo Simplify once https://www.drupal.org/node/2334319 lands. - $this->renderer->addCacheableDependency($column['data'], $username); $row[] = $column; if ($is_current_revision) { diff --git a/core/modules/node/src/Form/NodeForm.php b/core/modules/node/src/Form/NodeForm.php index d5afa396568..5498c94c497 100644 --- a/core/modules/node/src/Form/NodeForm.php +++ b/core/modules/node/src/Form/NodeForm.php @@ -10,6 +10,7 @@ use Drupal\Core\Entity\EntityTypeBundleInfoInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\TempStore\PrivateTempStoreFactory; +use Drupal\Core\Utility\Error; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -124,7 +125,7 @@ class NodeForm extends ContentEntityForm { if ($this->operation == 'edit') { $form['#title'] = $this->t('<em>Edit @type</em> @title', [ - '@type' => node_get_type_label($node), + '@type' => $node->getBundleEntity()->label(), '@title' => $node->label(), ]); } @@ -163,7 +164,7 @@ class NodeForm extends ContentEntityForm { $form['meta']['author'] = [ '#type' => 'item', '#title' => $this->t('Author'), - '#markup' => $node->getOwner()?->getAccountName(), + '#markup' => $node->getOwner()?->getDisplayName(), '#wrapper_attributes' => ['class' => ['entity-meta__author']], ]; @@ -278,21 +279,22 @@ class NodeForm extends ContentEntityForm { public function save(array $form, FormStateInterface $form_state) { $node = $this->entity; $insert = $node->isNew(); - $node->save(); - $node_link = $node->toLink($this->t('View'))->toString(); - $context = ['@type' => $node->getType(), '%title' => $node->label(), 'link' => $node_link]; - $t_args = ['@type' => node_get_type_label($node), '%title' => $node->toLink()->toString()]; - - if ($insert) { - $this->logger('content')->info('@type: added %title.', $context); - $this->messenger()->addStatus($this->t('@type %title has been created.', $t_args)); - } - else { - $this->logger('content')->info('@type: updated %title.', $context); - $this->messenger()->addStatus($this->t('@type %title has been updated.', $t_args)); - } - if ($node->id()) { + try { + $node->save(); + $node_link = $node->toLink($this->t('View'))->toString(); + $context = ['@type' => $node->getType(), '%title' => $node->label(), 'link' => $node_link]; + $t_args = ['@type' => $node->getBundleEntity()->label(), '%title' => $node->access('view') ? $node->toLink()->toString() : $node->label()]; + + if ($insert) { + $this->logger('content')->info('@type: added %title.', $context); + $this->messenger()->addStatus($this->t('@type %title has been created.', $t_args)); + } + else { + $this->logger('content')->info('@type: updated %title.', $context); + $this->messenger()->addStatus($this->t('@type %title has been updated.', $t_args)); + } + $form_state->setValue('nid', $node->id()); $form_state->set('nid', $node->id()); if ($node->access('view')) { @@ -310,10 +312,15 @@ class NodeForm extends ContentEntityForm { $store = $this->tempStoreFactory->get('node_preview'); $store->delete($node->uuid()); } - else { + catch (\Exception $e) { // In the unlikely case something went wrong on save, the node will be - // rebuilt and node form redisplayed the same way as in preview. - $this->messenger()->addError($this->t('The post could not be saved.')); + // rebuilt and node form redisplayed. + $this->messenger()->addError($this->t('The content could not be saved. Contact the site administrator if the problem persists.')); + // It's likely that this exception is an EntityStorageException in which + // case we won't have the actual backtrace available. Attempt to get the + // previous exception if available to include the backtrace. + $e = $e->getPrevious() ?: $e; + \Drupal::logger('node')->error('%type saving node form: @message in %function (line %line of %file) @backtrace_string.', Error::decodeException($e)); $form_state->setRebuild(); } } diff --git a/core/modules/node/src/Form/NodeRevisionRevertForm.php b/core/modules/node/src/Form/NodeRevisionRevertForm.php index ffb58fb71fb..a1e04e2942d 100644 --- a/core/modules/node/src/Form/NodeRevisionRevertForm.php +++ b/core/modules/node/src/Form/NodeRevisionRevertForm.php @@ -136,7 +136,7 @@ class NodeRevisionRevertForm extends ConfirmFormBase { $this->logger('content')->info('@type: reverted %title revision %revision.', ['@type' => $this->revision->bundle(), '%title' => $this->revision->label(), '%revision' => $this->revision->getRevisionId()]); $this->messenger() ->addStatus($this->t('@type %title has been reverted to the revision from %revision-date.', [ - '@type' => node_get_type_label($this->revision), + '@type' => $this->revision->getBundleEntity()->label(), '%title' => $this->revision->label(), '%revision-date' => $this->dateFormatter->format($original_revision_timestamp), ])); diff --git a/core/modules/node/src/Hook/NodeHooks1.php b/core/modules/node/src/Hook/NodeHooks1.php index 8e25f2eb066..e103717fb61 100644 --- a/core/modules/node/src/Hook/NodeHooks1.php +++ b/core/modules/node/src/Hook/NodeHooks1.php @@ -92,7 +92,7 @@ class NodeHooks1 { case 'entity.entity_view_display.node.default': case 'entity.entity_view_display.node.view_mode': $type = $route_match->getParameter('node_type'); - return '<p>' . $this->t('Content items can be displayed using different view modes: Teaser, Full content, Print, RSS, etc. <em>Teaser</em> is a short format that is typically used in lists of multiple content items. <em>Full content</em> is typically used when the content is displayed on its own page.') . '</p>' . '<p>' . $this->t('Here, you can define which fields are shown and hidden when %type content is displayed in each view mode, and define how the fields are displayed in each view mode.', ['%type' => $type->label()]) . '</p>'; + return '<p>' . $this->t('Content items can be displayed using different view modes: Teaser, Full content, Print, RSS, etc. <em>Teaser</em> is a short format that is typically used in lists of multiple content items. <em>Full content</em> is typically used when the content is displayed on its own page.') . '</p><p>' . $this->t('Here, you can define which fields are shown and hidden when %type content is displayed in each view mode, and define how the fields are displayed in each view mode.', ['%type' => $type->label()]) . '</p>'; case 'entity.node.version_history': return '<p>' . $this->t('Revisions allow you to track differences between multiple versions of your content, and revert to older versions.') . '</p>'; @@ -219,7 +219,7 @@ class NodeHooks1 { $ranking = [ 'relevance' => [ 'title' => $this->t('Keyword relevance'), - // Average relevance values hover around 0.15 + // Average relevance values hover around 0.15. 'score' => 'i.relevance', ], 'sticky' => [ diff --git a/core/modules/node/src/Hook/NodeTokensHooks.php b/core/modules/node/src/Hook/NodeTokensHooks.php index 3d7f0b0adf4..a7a90347313 100644 --- a/core/modules/node/src/Hook/NodeTokensHooks.php +++ b/core/modules/node/src/Hook/NodeTokensHooks.php @@ -109,7 +109,7 @@ class NodeTokensHooks { break; case 'type-name': - $type_name = node_get_type_label($node); + $type_name = $node->getBundleEntity()->label(); $replacements[$original] = $type_name; break; diff --git a/core/modules/node/src/Hook/NodeViewsHooks.php b/core/modules/node/src/Hook/NodeViewsHooks.php index 477784c153d..8729f547c17 100644 --- a/core/modules/node/src/Hook/NodeViewsHooks.php +++ b/core/modules/node/src/Hook/NodeViewsHooks.php @@ -26,7 +26,7 @@ class NodeViewsHooks { if ($view->storage->get('base_table') == 'node') { foreach ($view->displayHandlers as $display) { if (!$display->isDefaulted('access') || !$display->isDefaulted('filters')) { - // Check for no access control + // Check for no access control. $access = $display->getOption('access'); if (empty($access['type']) || $access['type'] == 'none') { $anonymous_role = Role::load(RoleInterface::ANONYMOUS_ID); diff --git a/core/modules/node/src/NodeAccessControlHandlerInterface.php b/core/modules/node/src/NodeAccessControlHandlerInterface.php index 588391394ee..0d67cfb7bd6 100644 --- a/core/modules/node/src/NodeAccessControlHandlerInterface.php +++ b/core/modules/node/src/NodeAccessControlHandlerInterface.php @@ -30,6 +30,8 @@ interface NodeAccessControlHandlerInterface { /** * Creates the default node access grant entry on the grant storage. + * + * @see \Drupal\node\NodeGrantDatabaseStorageInterface::writeDefault() */ public function writeDefaultGrant(); diff --git a/core/modules/node/src/NodeGrantDatabaseStorage.php b/core/modules/node/src/NodeGrantDatabaseStorage.php index eea6cc10012..fbaab21a211 100644 --- a/core/modules/node/src/NodeGrantDatabaseStorage.php +++ b/core/modules/node/src/NodeGrantDatabaseStorage.php @@ -112,6 +112,13 @@ class NodeGrantDatabaseStorage implements NodeGrantDatabaseStorageInterface { if (count($grants) > 0) { $query->condition($grants); } + if ($query->execute()->fetchField()) { + $access_result = AccessResult::allowed(); + } + else { + $access_result = AccessResult::neutral(); + } + $access_result->addCacheContexts(['user.node_grants:' . $operation]); // Only the 'view' node grant can currently be cached; the others currently // don't have any cacheability metadata. Hopefully, we can add that in the @@ -119,20 +126,10 @@ class NodeGrantDatabaseStorage implements NodeGrantDatabaseStorageInterface { // cases. For now, this must remain marked as uncacheable, even when it is // theoretically cacheable, because we don't have the necessary metadata to // know it for a fact. - $set_cacheability = function (AccessResult $access_result) use ($operation) { - $access_result->addCacheContexts(['user.node_grants:' . $operation]); - if ($operation !== 'view') { - $access_result->setCacheMaxAge(0); - } - return $access_result; - }; - - if ($query->execute()->fetchField()) { - return $set_cacheability(AccessResult::allowed()); - } - else { - return $set_cacheability(AccessResult::neutral()); + if ($operation !== 'view') { + $access_result->setCacheMaxAge(0); } + return $access_result; } /** diff --git a/core/modules/node/src/NodeGrantDatabaseStorageInterface.php b/core/modules/node/src/NodeGrantDatabaseStorageInterface.php index cce74476563..d343a2f350b 100644 --- a/core/modules/node/src/NodeGrantDatabaseStorageInterface.php +++ b/core/modules/node/src/NodeGrantDatabaseStorageInterface.php @@ -42,8 +42,8 @@ interface NodeGrantDatabaseStorageInterface { * @param string $base_table * The base table of the query. * - * @return int - * Status of the access check. + * @return void + * No return value. */ public function alterQuery($query, array $tables, $operation, AccountInterface $account, $base_table); @@ -83,6 +83,12 @@ interface NodeGrantDatabaseStorageInterface { /** * Creates the default node access grant entry. + * + * The default node access grant is a special grant added to the node_access + * table when no modules implement hook_node_grants. It grants view access + * to any published node. + * + * @see self::access() */ public function writeDefault(); diff --git a/core/modules/node/src/NodeListBuilder.php b/core/modules/node/src/NodeListBuilder.php index 0fa80dee411..2b356eb2b34 100644 --- a/core/modules/node/src/NodeListBuilder.php +++ b/core/modules/node/src/NodeListBuilder.php @@ -95,7 +95,7 @@ class NodeListBuilder extends EntityListBuilder { '#title' => $entity->label(), '#url' => $entity->toUrl(), ]; - $row['type'] = node_get_type_label($entity); + $row['type'] = $entity->getBundleEntity()->label(); $row['author']['data'] = [ '#theme' => 'username', '#account' => $entity->getOwner(), diff --git a/core/modules/node/src/NodeTranslationHandler.php b/core/modules/node/src/NodeTranslationHandler.php index 6c802440f37..88a3680a572 100644 --- a/core/modules/node/src/NodeTranslationHandler.php +++ b/core/modules/node/src/NodeTranslationHandler.php @@ -50,8 +50,7 @@ class NodeTranslationHandler extends ContentTranslationHandler { * {@inheritdoc} */ protected function entityFormTitle(EntityInterface $entity) { - $type_name = node_get_type_label($entity); - return $this->t('<em>Edit @type</em> @title', ['@type' => $type_name, '@title' => $entity->label()]); + return $this->t('<em>Edit @type</em> @title', ['@type' => $entity->getBundleEntity()->label(), '@title' => $entity->label()]); } /** diff --git a/core/modules/node/src/Plugin/views/filter/Access.php b/core/modules/node/src/Plugin/views/filter/Access.php index 4934a2f2e63..4d579f687ce 100644 --- a/core/modules/node/src/Plugin/views/filter/Access.php +++ b/core/modules/node/src/Plugin/views/filter/Access.php @@ -36,7 +36,7 @@ class Access extends FilterPluginBase { */ public function query() { $account = $this->view->getUser(); - if (!$account->hasPermission('bypass node access')) { + if (!$account->hasPermission('bypass node access') && $this->moduleHandler->hasImplementations('node_grants')) { $table = $this->ensureMyTable(); $grants = $this->query->getConnection()->condition('OR'); foreach (node_access_grants('view', $account) as $realm => $gids) { diff --git a/core/modules/node/src/Plugin/views/wizard/Node.php b/core/modules/node/src/Plugin/views/wizard/Node.php index d66fa956f9a..bef4ddc8da5 100644 --- a/core/modules/node/src/Plugin/views/wizard/Node.php +++ b/core/modules/node/src/Plugin/views/wizard/Node.php @@ -92,7 +92,7 @@ class Node extends WizardPluginBase { * {@inheritdoc} */ public function getAvailableSorts() { - // You can't execute functions in properties, so override the method + // You can't execute functions in properties, so override the method. return [ 'node_field_data-title:ASC' => $this->t('Title'), ]; |