summaryrefslogtreecommitdiffstatshomepage
path: root/core/modules/node
diff options
context:
space:
mode:
Diffstat (limited to 'core/modules/node')
-rw-r--r--core/modules/node/config/optional/views.view.content.yml1
-rw-r--r--core/modules/node/config/optional/views.view.glossary.yml1
-rw-r--r--core/modules/node/config/schema/node.schema.yml4
-rw-r--r--core/modules/node/node.install127
-rw-r--r--core/modules/node/node.routing.yml1
-rw-r--r--core/modules/node/node.services.yml20
-rw-r--r--core/modules/node/src/Entity/Node.php2
-rw-r--r--core/modules/node/src/Entity/NodeType.php2
-rw-r--r--core/modules/node/src/Form/NodeForm.php (renamed from core/modules/node/src/NodeForm.php)4
-rw-r--r--core/modules/node/src/Form/NodeTypeForm.php (renamed from core/modules/node/src/NodeTypeForm.php)2
-rw-r--r--core/modules/node/src/Hook/NodeRequirements.php154
-rw-r--r--core/modules/node/src/PageCache/DenyNodePreview.php44
-rw-r--r--core/modules/node/src/Plugin/views/wizard/Node.php10
-rw-r--r--core/modules/node/src/Plugin/views/wizard/NodeRevision.php5
-rw-r--r--core/modules/node/tests/modules/node_no_default_author/node_no_default_author.info.yml5
-rw-r--r--core/modules/node/tests/modules/node_no_default_author/src/Hook/NodeNoDefaultAuthorHooks.php31
-rw-r--r--core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_access_join.yml10
-rw-r--r--core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_bulk_form.yml2
-rw-r--r--core/modules/node/tests/src/Functional/NodeEditFormTest.php10
-rw-r--r--core/modules/node/tests/src/Kernel/NodeRequirementsStatusFilterWarningTest.php3
-rw-r--r--core/modules/node/tests/src/Unit/PageCache/DenyNodePreviewTest.php92
21 files changed, 240 insertions, 290 deletions
diff --git a/core/modules/node/config/optional/views.view.content.yml b/core/modules/node/config/optional/views.view.content.yml
index d0bbb09cf5a0..09ba3dcc35ae 100644
--- a/core/modules/node/config/optional/views.view.content.yml
+++ b/core/modules/node/config/optional/views.view.content.yml
@@ -625,6 +625,7 @@ display:
empty_table: true
caption: ''
description: ''
+ class: ''
row:
type: fields
query:
diff --git a/core/modules/node/config/optional/views.view.glossary.yml b/core/modules/node/config/optional/views.view.glossary.yml
index 2698473d5271..868d51fb9e26 100644
--- a/core/modules/node/config/optional/views.view.glossary.yml
+++ b/core/modules/node/config/optional/views.view.glossary.yml
@@ -343,6 +343,7 @@ display:
summary: ''
order: asc
empty_table: false
+ class: ''
row:
type: fields
options:
diff --git a/core/modules/node/config/schema/node.schema.yml b/core/modules/node/config/schema/node.schema.yml
index 08fe92cc401e..8c81f68ae604 100644
--- a/core/modules/node/config/schema/node.schema.yml
+++ b/core/modules/node/config/schema/node.schema.yml
@@ -24,7 +24,7 @@ node.type.*:
label: 'Machine-readable name'
constraints:
# Node type machine names are specifically limited to 32 characters.
- # @see \Drupal\node\NodeTypeForm::form()
+ # @see \Drupal\node\Form\NodeTypeForm::form()
Length:
max: 32
description:
@@ -50,7 +50,7 @@ node.type.*:
constraints:
# These are the values of the DRUPAL_DISABLED, DRUPAL_OPTIONAL, and
# DRUPAL_REQUIRED constants.
- # @see \Drupal\node\NodeTypeForm::form()
+ # @see \Drupal\node\Form\NodeTypeForm::form()
Choice: [0, 1, 2]
display_submitted:
type: boolean
diff --git a/core/modules/node/node.install b/core/modules/node/node.install
index fb5c14c47675..4e232bdc2de9 100644
--- a/core/modules/node/node.install
+++ b/core/modules/node/node.install
@@ -5,137 +5,10 @@
* Install, update and uninstall functions for the node module.
*/
-use Drupal\Core\Link;
-use Drupal\Core\StringTranslation\PluralTranslatableMarkup;
-use Drupal\Core\Url;
use Drupal\Core\Database\Database;
use Drupal\user\RoleInterface;
/**
- * Implements hook_requirements().
- */
-function node_requirements($phase): array {
- $requirements = [];
- if ($phase === 'runtime') {
- // Only show rebuild button if there are either 0, or 2 or more, rows
- // in the {node_access} table, or if there are modules that
- // implement hook_node_grants().
- $grant_count = \Drupal::entityTypeManager()->getAccessControlHandler('node')->countGrants();
- $has_node_grants_implementations = \Drupal::moduleHandler()->hasImplementations('node_grants');
- if ($grant_count != 1 || $has_node_grants_implementations) {
- $value = \Drupal::translation()->formatPlural($grant_count, 'One permission in use', '@count permissions in use', ['@count' => $grant_count]);
- }
- else {
- $value = t('Disabled');
- }
-
- $requirements['node_access'] = [
- 'title' => t('Node Access Permissions'),
- 'value' => $value,
- 'description' => t('If the site is experiencing problems with permissions to content, you may have to rebuild the permissions cache. Rebuilding will remove all privileges to content and replace them with permissions based on the current modules and settings. Rebuilding may take some time if there is a lot of content or complex permission settings. After rebuilding has completed, content will automatically use the new permissions. <a href=":rebuild">Rebuild permissions</a>', [
- ':rebuild' => Url::fromRoute('node.configure_rebuild_confirm')->toString(),
- ]),
- ];
-
- // Report when the "Published status or admin user" has no impact on the
- // result of dependent views due to active node access modules.
- // @see https://www.drupal.org/node/3472976
- if ($has_node_grants_implementations && \Drupal::moduleHandler()->moduleExists('views')) {
- $node_status_filter_problematic_views = [];
- $active_view_ids = \Drupal::entityQuery('view')
- ->condition('status', TRUE)
- ->accessCheck(FALSE)
- ->execute();
-
- $views_storage = \Drupal::entityTypeManager()->getStorage('view');
- foreach ($views_storage->loadMultiple($active_view_ids) as $view) {
- foreach ($view->get('display') as $display_id => $display) {
- if (array_key_exists('filters', $display['display_options'])) {
- foreach ($display['display_options']['filters'] as $filter) {
- if (array_key_exists('plugin_id', $filter) && $filter['plugin_id'] === 'node_status') {
- $node_status_filter_problematic_views[$view->id()][$display_id] = [
- 'view_label' => $view->label(),
- 'display_name' => $display['display_title'] ?? $display_id,
- ];
- break;
- }
- }
- }
- }
- }
-
- if ($node_status_filter_problematic_views !== []) {
- $node_access_implementations = [];
- $module_data = \Drupal::service('extension.list.module')->getAllInstalledInfo();
- foreach (['node_grants', 'node_grants_alter'] as $hook) {
- \Drupal::moduleHandler()->invokeAllWith(
- $hook,
- static function (callable $hook, string $module) use (&$node_access_implementations, $module_data) {
- $node_access_implementations[$module] = $module_data[$module]['name'];
- }
- );
- }
- uasort($node_access_implementations, 'strnatcasecmp');
- $views_ui_enabled = \Drupal::moduleHandler()->moduleExists('views_ui');
- $node_status_filter_problematic_views_list = [];
- foreach ($node_status_filter_problematic_views as $view_id => $displays) {
- foreach ($displays as $display_id => $info) {
- $text = "{$info['view_label']} ({$info['display_name']})";
- if ($views_ui_enabled) {
- $url = Url::fromRoute('entity.view.edit_display_form', [
- 'view' => $view_id,
- 'display_id' => $display_id,
- ]);
- if ($url->access()) {
- $node_status_filter_problematic_views_list[] = Link::fromTextAndUrl($text, $url)->toString();
- }
- else {
- $node_status_filter_problematic_views_list[] = $text;
- }
- }
- else {
- $node_status_filter_problematic_views_list[] = $text;
- }
- }
- }
-
- $node_status_filter_problematic_views_count = count($node_status_filter_problematic_views_list);
- $node_status_filter_description_arguments = [
- '%modules' => implode(', ', $node_access_implementations),
- '%status_filter' => t('Published status or admin user'),
- ];
-
- if ($node_status_filter_problematic_views_count > 1) {
- $node_status_filter_problematic_views_list = [
- '#theme' => 'item_list',
- '#items' => $node_status_filter_problematic_views_list,
- ];
- $node_status_filter_description_arguments['@views'] = \Drupal::service('renderer')->renderInIsolation($node_status_filter_problematic_views_list);
- }
- else {
- $node_status_filter_description_arguments['%view'] = reset($node_status_filter_problematic_views_list);
- }
-
- $node_status_filter_description = new PluralTranslatableMarkup(
- $node_status_filter_problematic_views_count,
- 'The %view view uses the %status_filter filter but it has no effect because the following module(s) control access: %modules. Review and consider removing the filter.',
- 'The following views use the %status_filter filter but it has no effect because the following module(s) control access: %modules. Review and consider removing the filter from these views: @views',
- $node_status_filter_description_arguments,
- );
-
- $requirements['node_status_filter'] = [
- 'title' => t('Content status filter'),
- 'value' => t('Redundant filters detected'),
- 'description' => $node_status_filter_description,
- 'severity' => REQUIREMENT_WARNING,
- ];
- }
- }
- }
- return $requirements;
-}
-
-/**
* Implements hook_schema().
*/
function node_schema(): array {
diff --git a/core/modules/node/node.routing.yml b/core/modules/node/node.routing.yml
index 4ceb843af183..aa53d913cf7e 100644
--- a/core/modules/node/node.routing.yml
+++ b/core/modules/node/node.routing.yml
@@ -45,6 +45,7 @@ entity.node.preview:
requirements:
_node_preview_access: '{node_preview}'
options:
+ no_cache: TRUE
parameters:
node_preview:
type: 'node_preview'
diff --git a/core/modules/node/node.services.yml b/core/modules/node/node.services.yml
index e5daad354296..83eb19f7355d 100644
--- a/core/modules/node/node.services.yml
+++ b/core/modules/node/node.services.yml
@@ -1,3 +1,16 @@
+parameters:
+ node.moved_classes:
+ 'Drupal\node\NodeForm':
+ class: 'Drupal\node\Form\NodeForm'
+ deprecation_version: drupal:11.2.0
+ removed_version: drupal:12.0.0
+ change_record: https://www.drupal.org/node/3517871
+ 'Drupal\node\NodeTypeForm':
+ class: 'Drupal\node\Form\NodeTypeForm'
+ deprecation_version: drupal:11.2.0
+ removed_version: drupal:12.0.0
+ change_record: https://www.drupal.org/node/3517871
+
services:
_defaults:
autoconfigure: true
@@ -23,13 +36,6 @@ services:
tags:
- { name: paramconverter }
lazy: true
- node.page_cache_response_policy.deny_node_preview:
- class: Drupal\node\PageCache\DenyNodePreview
- arguments: ['@current_route_match']
- public: false
- tags:
- - { name: page_cache_response_policy }
- - { name: dynamic_page_cache_response_policy }
cache_context.user.node_grants:
class: Drupal\node\Cache\NodeAccessGrantsCacheContext
arguments: ['@current_user']
diff --git a/core/modules/node/src/Entity/Node.php b/core/modules/node/src/Entity/Node.php
index f4c519a43c8a..0f61a74f1c01 100644
--- a/core/modules/node/src/Entity/Node.php
+++ b/core/modules/node/src/Entity/Node.php
@@ -11,8 +11,8 @@ use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\node\Form\DeleteMultiple;
use Drupal\node\Form\NodeDeleteForm;
+use Drupal\node\Form\NodeForm;
use Drupal\node\NodeAccessControlHandler;
-use Drupal\node\NodeForm;
use Drupal\node\NodeInterface;
use Drupal\node\NodeListBuilder;
use Drupal\node\NodeStorage;
diff --git a/core/modules/node/src/Entity/NodeType.php b/core/modules/node/src/Entity/NodeType.php
index 35b911d7ffb7..48d295635f3d 100644
--- a/core/modules/node/src/Entity/NodeType.php
+++ b/core/modules/node/src/Entity/NodeType.php
@@ -9,7 +9,7 @@ use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\node\Form\NodeTypeDeleteConfirm;
use Drupal\node\NodeTypeAccessControlHandler;
-use Drupal\node\NodeTypeForm;
+use Drupal\node\Form\NodeTypeForm;
use Drupal\node\NodeTypeInterface;
use Drupal\node\NodeTypeListBuilder;
use Drupal\user\Entity\EntityPermissionsRouteProvider;
diff --git a/core/modules/node/src/NodeForm.php b/core/modules/node/src/Form/NodeForm.php
index ab81a4e3f928..d5afa396568c 100644
--- a/core/modules/node/src/NodeForm.php
+++ b/core/modules/node/src/Form/NodeForm.php
@@ -1,6 +1,6 @@
<?php
-namespace Drupal\node;
+namespace Drupal\node\Form;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Datetime\DateFormatterInterface;
@@ -163,7 +163,7 @@ class NodeForm extends ContentEntityForm {
$form['meta']['author'] = [
'#type' => 'item',
'#title' => $this->t('Author'),
- '#markup' => $node->getOwner()->getAccountName(),
+ '#markup' => $node->getOwner()?->getAccountName(),
'#wrapper_attributes' => ['class' => ['entity-meta__author']],
];
diff --git a/core/modules/node/src/NodeTypeForm.php b/core/modules/node/src/Form/NodeTypeForm.php
index 3328ade970da..93d510d4387e 100644
--- a/core/modules/node/src/NodeTypeForm.php
+++ b/core/modules/node/src/Form/NodeTypeForm.php
@@ -1,6 +1,6 @@
<?php
-namespace Drupal\node;
+namespace Drupal\node\Form;
use Drupal\Core\Entity\BundleEntityFormBase;
use Drupal\Core\Entity\EntityFieldManagerInterface;
diff --git a/core/modules/node/src/Hook/NodeRequirements.php b/core/modules/node/src/Hook/NodeRequirements.php
new file mode 100644
index 000000000000..aa8b39d5682f
--- /dev/null
+++ b/core/modules/node/src/Hook/NodeRequirements.php
@@ -0,0 +1,154 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\node\Hook;
+
+use Drupal\Core\Hook\Attribute\Hook;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Extension\ModuleExtensionList;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Link;
+use Drupal\Core\StringTranslation\PluralTranslatableMarkup;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\Core\StringTranslation\TranslationInterface;
+use Drupal\Core\Url;
+
+/**
+ * Requirements for the Node module.
+ */
+class NodeRequirements {
+
+ use StringTranslationTrait;
+
+ public function __construct(
+ protected readonly EntityTypeManagerInterface $entityTypeManager,
+ protected readonly ModuleHandlerInterface $moduleHandler,
+ protected readonly TranslationInterface $translation,
+ protected readonly ModuleExtensionList $moduleExtensionList,
+ ) {}
+
+ /**
+ * Implements hook_runtime_requirements().
+ */
+ #[Hook('runtime_requirements')]
+ public function runtime(): array {
+ $requirements = [];
+ // Only show rebuild button if there are either 0, or 2 or more, rows
+ // in the {node_access} table, or if there are modules that
+ // implement hook_node_grants().
+ $grant_count = $this->entityTypeManager->getAccessControlHandler('node')->countGrants();
+ $has_node_grants_implementations = $this->moduleHandler->hasImplementations('node_grants');
+ if ($grant_count != 1 || $has_node_grants_implementations) {
+ $value = $this->translation->formatPlural($grant_count, 'One permission in use', '@count permissions in use', ['@count' => $grant_count]);
+ }
+ else {
+ $value = $this->t('Disabled');
+ }
+
+ $requirements['node_access'] = [
+ 'title' => $this->t('Node Access Permissions'),
+ 'value' => $value,
+ 'description' => $this->t('If the site is experiencing problems with permissions to content, you may have to rebuild the permissions cache. Rebuilding will remove all privileges to content and replace them with permissions based on the current modules and settings. Rebuilding may take some time if there is a lot of content or complex permission settings. After rebuilding has completed, content will automatically use the new permissions. <a href=":rebuild">Rebuild permissions</a>', [
+ ':rebuild' => Url::fromRoute('node.configure_rebuild_confirm')->toString(),
+ ]),
+ ];
+
+ // Report when the "Published status or admin user" has no impact on the
+ // result of dependent views due to active node access modules.
+ // @see https://www.drupal.org/node/3472976
+ if ($has_node_grants_implementations && $this->moduleHandler->moduleExists('views')) {
+ $node_status_filter_problematic_views = [];
+ $query = $this->entityTypeManager->getStorage('view')->getQuery();
+ $query->condition('status', TRUE);
+ $query->accessCheck(FALSE);
+ $active_view_ids = $query->execute();
+
+ $views_storage = $this->entityTypeManager->getStorage('view');
+ foreach ($views_storage->loadMultiple($active_view_ids) as $view) {
+ foreach ($view->get('display') as $display_id => $display) {
+ if (array_key_exists('filters', $display['display_options'])) {
+ foreach ($display['display_options']['filters'] as $filter) {
+ if (array_key_exists('plugin_id', $filter) && $filter['plugin_id'] === 'node_status') {
+ $node_status_filter_problematic_views[$view->id()][$display_id] = [
+ 'view_label' => $view->label(),
+ 'display_name' => $display['display_title'] ?? $display_id,
+ ];
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if ($node_status_filter_problematic_views !== []) {
+ $node_access_implementations = [];
+ $module_data = $this->moduleExtensionList->getAllInstalledInfo();
+ foreach (['node_grants', 'node_grants_alter'] as $hook) {
+ $this->moduleHandler->invokeAllWith(
+ $hook,
+ static function (callable $hook, string $module) use (&$node_access_implementations, $module_data) {
+ $node_access_implementations[$module] = $module_data[$module]['name'];
+ }
+ );
+ }
+ uasort($node_access_implementations, 'strnatcasecmp');
+ $views_ui_enabled = $this->moduleHandler->moduleExists('views_ui');
+ $node_status_filter_problematic_views_list = [];
+ foreach ($node_status_filter_problematic_views as $view_id => $displays) {
+ foreach ($displays as $display_id => $info) {
+ $text = "{$info['view_label']} ({$info['display_name']})";
+ if ($views_ui_enabled) {
+ $url = Url::fromRoute('entity.view.edit_display_form', [
+ 'view' => $view_id,
+ 'display_id' => $display_id,
+ ]);
+ if ($url->access()) {
+ $node_status_filter_problematic_views_list[] = Link::fromTextAndUrl($text, $url)->toString();
+ }
+ else {
+ $node_status_filter_problematic_views_list[] = $text;
+ }
+ }
+ else {
+ $node_status_filter_problematic_views_list[] = $text;
+ }
+ }
+ }
+
+ $node_status_filter_problematic_views_count = count($node_status_filter_problematic_views_list);
+ $node_status_filter_description_arguments = [
+ '%modules' => implode(', ', $node_access_implementations),
+ '%status_filter' => $this->t('Published status or admin user'),
+ ];
+
+ if ($node_status_filter_problematic_views_count > 1) {
+ $node_status_filter_problematic_views_list = [
+ '#theme' => 'item_list',
+ '#items' => $node_status_filter_problematic_views_list,
+ ];
+ $node_status_filter_description_arguments['@views'] = \Drupal::service('renderer')->renderInIsolation($node_status_filter_problematic_views_list);
+ }
+ else {
+ $node_status_filter_description_arguments['%view'] = reset($node_status_filter_problematic_views_list);
+ }
+
+ $node_status_filter_description = new PluralTranslatableMarkup(
+ $node_status_filter_problematic_views_count,
+ 'The %view view uses the %status_filter filter but it has no effect because the following module(s) control access: %modules. Review and consider removing the filter.',
+ 'The following views use the %status_filter filter but it has no effect because the following module(s) control access: %modules. Review and consider removing the filter from these views: @views',
+ $node_status_filter_description_arguments,
+ );
+
+ $requirements['node_status_filter'] = [
+ 'title' => $this->t('Content status filter'),
+ 'value' => $this->t('Redundant filters detected'),
+ 'description' => $node_status_filter_description,
+ 'severity' => REQUIREMENT_WARNING,
+ ];
+ }
+ }
+ return $requirements;
+ }
+
+}
diff --git a/core/modules/node/src/PageCache/DenyNodePreview.php b/core/modules/node/src/PageCache/DenyNodePreview.php
deleted file mode 100644
index 0325f52b2017..000000000000
--- a/core/modules/node/src/PageCache/DenyNodePreview.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-
-namespace Drupal\node\PageCache;
-
-use Drupal\Core\PageCache\ResponsePolicyInterface;
-use Drupal\Core\Routing\RouteMatchInterface;
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpFoundation\Response;
-
-/**
- * Cache policy for node preview page.
- *
- * This policy rule denies caching of responses generated by the
- * entity.node.preview route.
- */
-class DenyNodePreview implements ResponsePolicyInterface {
-
- /**
- * The current route match.
- *
- * @var \Drupal\Core\Routing\RouteMatchInterface
- */
- protected $routeMatch;
-
- /**
- * Constructs a deny node preview page cache policy.
- *
- * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
- * The current route match.
- */
- public function __construct(RouteMatchInterface $route_match) {
- $this->routeMatch = $route_match;
- }
-
- /**
- * {@inheritdoc}
- */
- public function check(Response $response, Request $request) {
- if ($this->routeMatch->getRouteName() === 'entity.node.preview') {
- return static::DENY;
- }
- }
-
-}
diff --git a/core/modules/node/src/Plugin/views/wizard/Node.php b/core/modules/node/src/Plugin/views/wizard/Node.php
index 84a21c3f7f2e..d66fa956f9aa 100644
--- a/core/modules/node/src/Plugin/views/wizard/Node.php
+++ b/core/modules/node/src/Plugin/views/wizard/Node.php
@@ -89,11 +89,7 @@ class Node extends WizardPluginBase {
}
/**
- * Overrides Drupal\views\Plugin\views\wizard\WizardPluginBase::getAvailableSorts().
- *
- * @return array
- * An array whose keys are the available sort options and whose
- * corresponding values are human readable labels.
+ * {@inheritdoc}
*/
public function getAvailableSorts() {
// You can't execute functions in properties, so override the method
@@ -238,9 +234,7 @@ class Node extends WizardPluginBase {
}
/**
- * Overrides Drupal\views\Plugin\views\wizard\WizardPluginBase::buildFilters().
- *
- * Add some options for filter by taxonomy terms.
+ * {@inheritdoc}
*/
protected function buildFilters(&$form, FormStateInterface $form_state) {
parent::buildFilters($form, $form_state);
diff --git a/core/modules/node/src/Plugin/views/wizard/NodeRevision.php b/core/modules/node/src/Plugin/views/wizard/NodeRevision.php
index c10389cc2392..96422504cf5e 100644
--- a/core/modules/node/src/Plugin/views/wizard/NodeRevision.php
+++ b/core/modules/node/src/Plugin/views/wizard/NodeRevision.php
@@ -29,11 +29,10 @@ class NodeRevision extends WizardPluginBase {
protected $createdColumn = 'changed';
/**
- * Overrides Drupal\views\Plugin\views\wizard\WizardPluginBase::rowStyleOptions().
- *
- * Node revisions do not support full posts or teasers, so remove them.
+ * {@inheritdoc}
*/
protected function rowStyleOptions() {
+ // Node revisions do not support full posts or teasers, so remove them.
$options = parent::rowStyleOptions();
unset($options['teasers']);
unset($options['full_posts']);
diff --git a/core/modules/node/tests/modules/node_no_default_author/node_no_default_author.info.yml b/core/modules/node/tests/modules/node_no_default_author/node_no_default_author.info.yml
new file mode 100644
index 000000000000..c4f56344370f
--- /dev/null
+++ b/core/modules/node/tests/modules/node_no_default_author/node_no_default_author.info.yml
@@ -0,0 +1,5 @@
+name: 'Node no default author'
+type: module
+description: 'Disables the default value callback for the uid field on node.'
+package: Testing
+version: VERSION
diff --git a/core/modules/node/tests/modules/node_no_default_author/src/Hook/NodeNoDefaultAuthorHooks.php b/core/modules/node/tests/modules/node_no_default_author/src/Hook/NodeNoDefaultAuthorHooks.php
new file mode 100644
index 000000000000..700e82236adc
--- /dev/null
+++ b/core/modules/node/tests/modules/node_no_default_author/src/Hook/NodeNoDefaultAuthorHooks.php
@@ -0,0 +1,31 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\node_no_default_author\Hook;
+
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Hook\Attribute\Hook;
+
+/**
+ * Hook implementations for node_no_default_author.
+ */
+class NodeNoDefaultAuthorHooks {
+
+ /**
+ * Implements hook_entity_base_field_info_alter().
+ */
+ #[Hook('entity_base_field_info_alter')]
+ public function entityBaseFieldInfoAlter(&$fields, EntityTypeInterface $entity_type): void {
+ if ($entity_type->id() === 'node') {
+ $fields['uid']->setDefaultValueCallback(static::class . '::noDefaultAuthor');
+ }
+ }
+
+ /**
+ * An empty callback to set for the default value callback of uid.
+ */
+ public static function noDefaultAuthor(): void {
+ }
+
+}
diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_access_join.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_access_join.yml
index 766f656fc2bf..65ca46658711 100644
--- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_access_join.yml
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_access_join.yml
@@ -68,6 +68,16 @@ display:
quantity: 9
style:
type: table
+ options:
+ grouping: { }
+ class: ''
+ row_class: ''
+ default_row_class: true
+ override: true
+ sticky: false
+ caption: ''
+ summary: ''
+ description: ''
row:
type: fields
fields:
diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_bulk_form.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_bulk_form.yml
index d7a3fa080fed..107165a27fb6 100644
--- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_bulk_form.yml
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_bulk_form.yml
@@ -19,6 +19,8 @@ display:
display_options:
style:
type: table
+ options:
+ class: ''
row:
type: fields
fields:
diff --git a/core/modules/node/tests/src/Functional/NodeEditFormTest.php b/core/modules/node/tests/src/Functional/NodeEditFormTest.php
index bc8cfa927e43..dc47998c9093 100644
--- a/core/modules/node/tests/src/Functional/NodeEditFormTest.php
+++ b/core/modules/node/tests/src/Functional/NodeEditFormTest.php
@@ -258,6 +258,16 @@ class NodeEditFormTest extends NodeTestBase {
}
/**
+ * Tests the node form when the author is NULL.
+ */
+ public function testNodeFormNullAuthor(): void {
+ \Drupal::service('module_installer')->install(['node_no_default_author']);
+ $this->drupalLogin($this->adminUser);
+ $this->drupalGet('node/add/page');
+ $this->assertSession()->statusCodeEquals(200);
+ }
+
+ /**
* Checks that the "authored by" works correctly with various values.
*
* @param \Drupal\node\NodeInterface $node
diff --git a/core/modules/node/tests/src/Kernel/NodeRequirementsStatusFilterWarningTest.php b/core/modules/node/tests/src/Kernel/NodeRequirementsStatusFilterWarningTest.php
index 6ddb8c8c987d..60ce5c7cdb04 100644
--- a/core/modules/node/tests/src/Kernel/NodeRequirementsStatusFilterWarningTest.php
+++ b/core/modules/node/tests/src/Kernel/NodeRequirementsStatusFilterWarningTest.php
@@ -197,8 +197,7 @@ class NodeRequirementsStatusFilterWarningTest extends KernelTestBase {
* The requirements raised by the Node module.
*/
private function getRequirements(): array {
- $this->container->get('module_handler')->loadInclude('node', 'install');
- return node_requirements('runtime');
+ return $this->container->get('module_handler')->invoke('node', 'runtime_requirements');
}
/**
diff --git a/core/modules/node/tests/src/Unit/PageCache/DenyNodePreviewTest.php b/core/modules/node/tests/src/Unit/PageCache/DenyNodePreviewTest.php
deleted file mode 100644
index 1baf081ed000..000000000000
--- a/core/modules/node/tests/src/Unit/PageCache/DenyNodePreviewTest.php
+++ /dev/null
@@ -1,92 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\Tests\node\Unit\PageCache;
-
-use Drupal\Core\PageCache\ResponsePolicyInterface;
-use Drupal\node\PageCache\DenyNodePreview;
-use Drupal\Tests\UnitTestCase;
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpFoundation\Response;
-
-/**
- * @coversDefaultClass \Drupal\node\PageCache\DenyNodePreview
- * @group node
- */
-class DenyNodePreviewTest extends UnitTestCase {
-
- /**
- * The response policy under test.
- *
- * @var \Drupal\node\PageCache\DenyNodePreview
- */
- protected $policy;
-
- /**
- * A request object.
- *
- * @var \Symfony\Component\HttpFoundation\Request
- */
- protected $request;
-
- /**
- * A response object.
- *
- * @var \Symfony\Component\HttpFoundation\Response
- */
- protected $response;
-
- /**
- * The current route match.
- *
- * @var \Drupal\Core\Routing\RouteMatch|\PHPUnit\Framework\MockObject\MockObject
- */
- protected $routeMatch;
-
- /**
- * {@inheritdoc}
- */
- protected function setUp(): void {
- parent::setUp();
-
- $this->routeMatch = $this->createMock('Drupal\Core\Routing\RouteMatchInterface');
- $this->policy = new DenyNodePreview($this->routeMatch);
- $this->response = new Response();
- $this->request = new Request();
- }
-
- /**
- * Asserts that caching is denied on the node preview route.
- *
- * @dataProvider providerPrivateImageStyleDownloadPolicy
- * @covers ::check
- */
- public function testPrivateImageStyleDownloadPolicy($expected_result, $route_name): void {
- $this->routeMatch->expects($this->once())
- ->method('getRouteName')
- ->willReturn($route_name);
-
- $actual_result = $this->policy->check($this->response, $this->request);
- $this->assertSame($expected_result, $actual_result);
- }
-
- /**
- * Provides data and expected results for the test method.
- *
- * @return array
- * Data and expected results.
- */
- public static function providerPrivateImageStyleDownloadPolicy() {
- return [
- [ResponsePolicyInterface::DENY, 'entity.node.preview'],
- [NULL, 'some.other.route'],
- [NULL, NULL],
- [NULL, FALSE],
- [NULL, TRUE],
- [NULL, new \stdClass()],
- [NULL, [1, 2, 3]],
- ];
- }
-
-}