summaryrefslogtreecommitdiffstatshomepage
path: root/core/modules/node
diff options
context:
space:
mode:
Diffstat (limited to 'core/modules/node')
-rw-r--r--core/modules/node/node.module17
-rw-r--r--core/modules/node/src/Form/NodeForm.php43
-rw-r--r--core/modules/node/src/NodeGrantDatabaseStorage.php23
-rw-r--r--core/modules/node/src/NodeGrantDatabaseStorageInterface.php4
-rw-r--r--core/modules/node/tests/src/Functional/NodeCreationTest.php15
-rw-r--r--core/modules/node/tests/src/Functional/NodeEditFormTest.php7
-rw-r--r--core/modules/node/tests/src/FunctionalJavascript/CollapsedSummariesTest.php4
-rw-r--r--core/modules/node/tests/src/FunctionalJavascript/ContextualLinksTest.php4
-rw-r--r--core/modules/node/tests/src/FunctionalJavascript/NodeDeleteConfirmTest.php4
-rw-r--r--core/modules/node/tests/src/FunctionalJavascript/NodePreviewLinkTest.php4
-rw-r--r--core/modules/node/tests/src/FunctionalJavascript/SettingSummariesContentTypeTest.php4
11 files changed, 81 insertions, 48 deletions
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index f14d843faa1..6841f24b96b 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -36,8 +36,12 @@ use Drupal\node\NodeTypeInterface;
* @return array|false
* A renderable array containing a list of linked node titles fetched from
* $result, or FALSE if there are no rows in $result.
+ *
+ * @deprecated in drupal:11.3.0 and is removed from drupal:12.0.0. There is no replacement.
+ * @see https://www.drupal.org/node/3531959
*/
function node_title_list(StatementInterface $result, $title = NULL) {
+ @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.3.0 and is removed from drupal:12.0.0. There is no replacement. See https://www.drupal.org/node/3531959', E_USER_DEPRECATED);
$items = [];
$num_rows = FALSE;
$nids = [];
@@ -121,8 +125,12 @@ function node_get_type_label(NodeInterface $node) {
*
* @return string
* The node type description.
+ *
+ * @deprecated in drupal:11.3.0 and is removed from drupal:12.0.0. Use $node_type->getDescription() instead.
+ * @see https://www.drupal.org/node/3531945
*/
function node_type_get_description(NodeTypeInterface $node_type) {
+ @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.3.0 and is removed from drupal:12.0.0. Use $node_type->getDescription() instead. See https://www.drupal.org/node/3531945', E_USER_DEPRECATED);
return $node_type->getDescription();
}
@@ -325,10 +333,11 @@ function template_preprocess_node(&$variables): void {
// $variables['content'] is more flexible and consistent.
$submitted_configurable = $node->getFieldDefinition('created')->isDisplayConfigurable('view') || $node->getFieldDefinition('uid')->isDisplayConfigurable('view');
if (!$skip_custom_preprocessing || !$submitted_configurable) {
- $variables['date'] = \Drupal::service('renderer')->render($variables['elements']['created']);
- unset($variables['elements']['created']);
- $variables['author_name'] = \Drupal::service('renderer')->render($variables['elements']['uid']);
- unset($variables['elements']['uid']);
+ /** @var \Drupal\Core\Render\RendererInterface $renderer */
+ $renderer = \Drupal::service('renderer');
+ $variables['date'] = !empty($variables['elements']['created']) ? $renderer->render($variables['elements']['created']) : '';
+ $variables['author_name'] = !empty($variables['elements']['uid']) ? $renderer->render($variables['elements']['uid']) : '';
+ unset($variables['elements']['created'], $variables['elements']['uid']);
}
if (isset($variables['elements']['title']) && (!$skip_custom_preprocessing || !$node->getFieldDefinition('title')->isDisplayConfigurable('view'))) {
diff --git a/core/modules/node/src/Form/NodeForm.php b/core/modules/node/src/Form/NodeForm.php
index d739aa7de8f..295e9ab78ce 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;
/**
@@ -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->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));
- }
- 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_get_type_label($node), '%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/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 5e81e1d04d0..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);
diff --git a/core/modules/node/tests/src/Functional/NodeCreationTest.php b/core/modules/node/tests/src/Functional/NodeCreationTest.php
index 6930bb86f96..7e99e3ba2ec 100644
--- a/core/modules/node/tests/src/Functional/NodeCreationTest.php
+++ b/core/modules/node/tests/src/Functional/NodeCreationTest.php
@@ -311,6 +311,21 @@ class NodeCreationTest extends NodeTestBase {
}
/**
+ * Tests exception handling when saving a node through the form.
+ */
+ public function testNodeCreateExceptionHandling(): void {
+ $this->drupalGet('node/add/page');
+
+ $this->submitForm([
+ 'title[0][value]' => 'testing_transaction_exception',
+ 'body[0][value]' => $this->randomMachineName(16),
+ ], 'Save');
+
+ $this->assertSession()->pageTextNotContains('The website encountered an unexpected error.');
+ $this->assertSession()->pageTextContains('The content could not be saved. Contact the site administrator if the problem persists.');
+ }
+
+ /**
* Gets the watchdog IDs of the records with the rollback exception message.
*
* @return int[]
diff --git a/core/modules/node/tests/src/Functional/NodeEditFormTest.php b/core/modules/node/tests/src/Functional/NodeEditFormTest.php
index dc47998c909..f661ae18ebb 100644
--- a/core/modules/node/tests/src/Functional/NodeEditFormTest.php
+++ b/core/modules/node/tests/src/Functional/NodeEditFormTest.php
@@ -251,10 +251,15 @@ class NodeEditFormTest extends NodeTestBase {
$edit['body[0][value]'] = $this->randomMachineName(16);
$this->submitForm($edit, 'Save');
+ // Enable user_hooks_test to test the users display name is visible on the
+ // edit form.
+ \Drupal::service('module_installer')->install(['user_hooks_test']);
+ \Drupal::keyValue('user_hooks_test')->set('user_format_name_alter', TRUE);
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
- $this->drupalGet("node/" . $node->id() . "/edit");
+ $this->drupalGet($node->toUrl('edit-form'));
$this->assertSession()->pageTextContains('Published');
$this->assertSession()->pageTextContains($this->container->get('date.formatter')->format($node->getChangedTime(), 'short'));
+ $this->assertSession()->responseContains('<em>' . $this->adminUser->id() . '</em>');
}
/**
diff --git a/core/modules/node/tests/src/FunctionalJavascript/CollapsedSummariesTest.php b/core/modules/node/tests/src/FunctionalJavascript/CollapsedSummariesTest.php
index 84f4a376af9..6333930b886 100644
--- a/core/modules/node/tests/src/FunctionalJavascript/CollapsedSummariesTest.php
+++ b/core/modules/node/tests/src/FunctionalJavascript/CollapsedSummariesTest.php
@@ -5,12 +5,12 @@ declare(strict_types=1);
namespace Drupal\Tests\node\FunctionalJavascript;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
+use PHPUnit\Framework\Attributes\Group;
/**
* Tests that outlines of node meta values are displayed in summaries and tabs.
- *
- * @group node
*/
+#[Group('node')]
class CollapsedSummariesTest extends WebDriverTestBase {
/**
diff --git a/core/modules/node/tests/src/FunctionalJavascript/ContextualLinksTest.php b/core/modules/node/tests/src/FunctionalJavascript/ContextualLinksTest.php
index 4c499c01a86..876d9606776 100644
--- a/core/modules/node/tests/src/FunctionalJavascript/ContextualLinksTest.php
+++ b/core/modules/node/tests/src/FunctionalJavascript/ContextualLinksTest.php
@@ -7,12 +7,12 @@ namespace Drupal\Tests\node\FunctionalJavascript;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
use Drupal\node\Entity\Node;
use Drupal\Tests\contextual\FunctionalJavascript\ContextualLinkClickTrait;
+use PHPUnit\Framework\Attributes\Group;
/**
* Create a node with revisions and test contextual links.
- *
- * @group node
*/
+#[Group('node')]
class ContextualLinksTest extends WebDriverTestBase {
use ContextualLinkClickTrait;
diff --git a/core/modules/node/tests/src/FunctionalJavascript/NodeDeleteConfirmTest.php b/core/modules/node/tests/src/FunctionalJavascript/NodeDeleteConfirmTest.php
index 5eb912c577c..22a33d0c4b8 100644
--- a/core/modules/node/tests/src/FunctionalJavascript/NodeDeleteConfirmTest.php
+++ b/core/modules/node/tests/src/FunctionalJavascript/NodeDeleteConfirmTest.php
@@ -6,12 +6,12 @@ namespace Drupal\Tests\node\FunctionalJavascript;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
use Drupal\views\Views;
+use PHPUnit\Framework\Attributes\Group;
/**
* Tests JavaScript functionality specific to delete operations.
- *
- * @group node
*/
+#[Group('node')]
class NodeDeleteConfirmTest extends WebDriverTestBase {
/**
diff --git a/core/modules/node/tests/src/FunctionalJavascript/NodePreviewLinkTest.php b/core/modules/node/tests/src/FunctionalJavascript/NodePreviewLinkTest.php
index 33a8795a649..e1dbf426cec 100644
--- a/core/modules/node/tests/src/FunctionalJavascript/NodePreviewLinkTest.php
+++ b/core/modules/node/tests/src/FunctionalJavascript/NodePreviewLinkTest.php
@@ -6,12 +6,12 @@ namespace Drupal\Tests\node\FunctionalJavascript;
use Drupal\filter\Entity\FilterFormat;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
+use PHPUnit\Framework\Attributes\Group;
/**
* Tests the JavaScript prevention of navigation away from node previews.
- *
- * @group node
*/
+#[Group('node')]
class NodePreviewLinkTest extends WebDriverTestBase {
/**
diff --git a/core/modules/node/tests/src/FunctionalJavascript/SettingSummariesContentTypeTest.php b/core/modules/node/tests/src/FunctionalJavascript/SettingSummariesContentTypeTest.php
index 99ba0722d00..309c14c37b3 100644
--- a/core/modules/node/tests/src/FunctionalJavascript/SettingSummariesContentTypeTest.php
+++ b/core/modules/node/tests/src/FunctionalJavascript/SettingSummariesContentTypeTest.php
@@ -5,12 +5,12 @@ declare(strict_types=1);
namespace Drupal\Tests\node\FunctionalJavascript;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
+use PHPUnit\Framework\Attributes\Group;
/**
* Tests the JavaScript updating of summaries on content type form.
- *
- * @group node
*/
+#[Group('node')]
class SettingSummariesContentTypeTest extends WebDriverTestBase {
/**