update drupal
This commit is contained in:
@@ -8,7 +8,6 @@
|
||||
use Drupal\node\NodeInterface;
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Component\Utility\Xss;
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
|
||||
/**
|
||||
* @addtogroup hooks
|
||||
@@ -286,79 +285,6 @@ function hook_node_grants_alter(&$grants, \Drupal\Core\Session\AccountInterface
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls access to a node.
|
||||
*
|
||||
* Modules may implement this hook if they want to have a say in whether or not
|
||||
* a given user has access to perform a given operation on a node.
|
||||
*
|
||||
* The administrative account (user ID #1) always passes any access check, so
|
||||
* this hook is not called in that case. Users with the "bypass node access"
|
||||
* permission may always view and edit content through the administrative
|
||||
* interface.
|
||||
*
|
||||
* The access to a node can be influenced in several ways:
|
||||
* - To explicitly allow access, return an AccessResultInterface object with
|
||||
* isAllowed() returning TRUE. Other modules can override this access by
|
||||
* returning TRUE for isForbidden().
|
||||
* - To explicitly forbid access, return an AccessResultInterface object with
|
||||
* isForbidden() returning TRUE. Access will be forbidden even if your module
|
||||
* (or another module) also returns TRUE for isNeutral() or isAllowed().
|
||||
* - To neither allow nor explicitly forbid access, return an
|
||||
* AccessResultInterface object with isNeutral() returning TRUE.
|
||||
* - If your module does not return an AccessResultInterface object, neutral
|
||||
* access will be assumed.
|
||||
*
|
||||
* Also note that this function isn't called for node listings (e.g., RSS feeds,
|
||||
* the default home page at path 'node', a recent content block, etc.) See
|
||||
* @link node_access Node access rights @endlink for a full explanation.
|
||||
*
|
||||
* @param \Drupal\node\NodeInterface|string $node
|
||||
* Either a node entity or the machine name of the content type on which to
|
||||
* perform the access check.
|
||||
* @param string $op
|
||||
* The operation to be performed. Possible values:
|
||||
* - "create"
|
||||
* - "delete"
|
||||
* - "update"
|
||||
* - "view"
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The user object to perform the access check operation on.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessResultInterface
|
||||
* The access result.
|
||||
*
|
||||
* @ingroup node_access
|
||||
*/
|
||||
function hook_node_access(\Drupal\node\NodeInterface $node, $op, \Drupal\Core\Session\AccountInterface $account) {
|
||||
$type = $node->bundle();
|
||||
|
||||
switch ($op) {
|
||||
case 'create':
|
||||
return AccessResult::allowedIfHasPermission($account, 'create ' . $type . ' content');
|
||||
|
||||
case 'update':
|
||||
if ($account->hasPermission('edit any ' . $type . ' content')) {
|
||||
return AccessResult::allowed()->cachePerPermissions();
|
||||
}
|
||||
else {
|
||||
return AccessResult::allowedIf($account->hasPermission('edit own ' . $type . ' content') && ($account->id() == $node->getOwnerId()))->cachePerPermissions()->cachePerUser()->addCacheableDependency($node);
|
||||
}
|
||||
|
||||
case 'delete':
|
||||
if ($account->hasPermission('delete any ' . $type . ' content')) {
|
||||
return AccessResult::allowed()->cachePerPermissions();
|
||||
}
|
||||
else {
|
||||
return AccessResult::allowedIf($account->hasPermission('delete own ' . $type . ' content') && ($account->id() == $node->getOwnerId()))->cachePerPermissions()->cachePerUser()->addCacheableDependency($node);
|
||||
}
|
||||
|
||||
default:
|
||||
// No opinion.
|
||||
return AccessResult::neutral();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Act on a node being displayed as a search result.
|
||||
*
|
||||
|
||||
@@ -950,16 +950,16 @@ function node_form_system_themes_admin_form_submit($form, FormStateInterface $fo
|
||||
* @{
|
||||
* The node access system determines who can do what to which nodes.
|
||||
*
|
||||
* In determining access rights for a node, \Drupal\node\NodeAccessControlHandler
|
||||
* first checks whether the user has the "bypass node access" permission. Such
|
||||
* users have unrestricted access to all nodes. user 1 will always pass this
|
||||
* check.
|
||||
* In determining access rights for an existing node,
|
||||
* \Drupal\node\NodeAccessControlHandler first checks whether the user has the
|
||||
* "bypass node access" permission. Such users have unrestricted access to all
|
||||
* nodes. user 1 will always pass this check.
|
||||
*
|
||||
* Next, all implementations of hook_node_access() will be called. Each
|
||||
* implementation may explicitly allow, explicitly forbid, or ignore the access
|
||||
* request. If at least one module says to forbid the request, it will be
|
||||
* rejected. If no modules deny the request and at least one says to allow it,
|
||||
* the request will be permitted.
|
||||
* Next, all implementations of hook_ENTITY_TYPE_access() for node will
|
||||
* be called. Each implementation may explicitly allow, explicitly forbid, or
|
||||
* ignore the access request. If at least one module says to forbid the request,
|
||||
* it will be rejected. If no modules deny the request and at least one says to
|
||||
* allow it, the request will be permitted.
|
||||
*
|
||||
* If all modules ignore the access request, then the node_access table is used
|
||||
* to determine access. All node access modules are queried using
|
||||
@@ -972,40 +972,42 @@ function node_form_system_themes_admin_form_submit($form, FormStateInterface $fo
|
||||
*
|
||||
* In node listings (lists of nodes generated from a select query, such as the
|
||||
* default home page at path 'node', an RSS feed, a recent content block, etc.),
|
||||
* the process above is followed except that hook_node_access() is not called on
|
||||
* each node for performance reasons and for proper functioning of the pager
|
||||
* system. When adding a node listing to your module, be sure to use an entity
|
||||
* query, which will add a tag of "node_access". This will allow modules dealing
|
||||
* with node access to ensure only nodes to which the user has access are
|
||||
* retrieved, through the use of hook_query_TAG_alter(). See the
|
||||
* the process above is followed except that hook_ENTITY_TYPE_access() is not
|
||||
* called on each node for performance reasons and for proper functioning of
|
||||
* the pager system. When adding a node listing to your module, be sure to use
|
||||
* an entity query, which will add a tag of "node_access". This will allow
|
||||
* modules dealing with node access to ensure only nodes to which the user has
|
||||
* access are retrieved, through the use of hook_query_TAG_alter(). See the
|
||||
* @link entity_api Entity API topic @endlink for more information on entity
|
||||
* queries. Tagging a query with "node_access" does not check the
|
||||
* published/unpublished status of nodes, so the base query is responsible
|
||||
* for ensuring that unpublished nodes are not displayed to inappropriate users.
|
||||
*
|
||||
* Note: Even a single module returning an AccessResultInterface object from
|
||||
* hook_node_access() whose isForbidden() method equals TRUE will block access
|
||||
* to the node. Therefore, implementers should take care to not deny access
|
||||
* unless they really intend to. Unless a module wishes to actively forbid
|
||||
* access it should return an AccessResultInterface object whose isAllowed() nor
|
||||
* isForbidden() methods return TRUE, to allow other modules or the node_access
|
||||
* table to control access.
|
||||
* hook_ENTITY_TYPE_access() whose isForbidden() method equals TRUE will block
|
||||
* access to the node. Therefore, implementers should take care to not deny
|
||||
* access unless they really intend to. Unless a module wishes to actively
|
||||
* forbid access it should return an AccessResultInterface object whose
|
||||
* isAllowed() nor isForbidden() methods return TRUE, to allow other modules or
|
||||
* the node_access table to control access.
|
||||
*
|
||||
* Note also that access to create nodes is handled by
|
||||
* hook_ENTITY_TYPE_create_access().
|
||||
*
|
||||
* To see how to write a node access module of your own, see
|
||||
* node_access_example.module.
|
||||
*
|
||||
* @see \Drupal\node\NodeAccessControlHandler
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_node_access().
|
||||
* Implements hook_ENTITY_TYPE_access().
|
||||
*/
|
||||
function node_node_access(NodeInterface $node, $op, AccountInterface $account) {
|
||||
$type = $node->bundle();
|
||||
$access = AccessResult::neutral();
|
||||
|
||||
// Note create access is handled by hook_ENTITY_TYPE_create_access().
|
||||
switch ($op) {
|
||||
case 'create':
|
||||
$access = AccessResult::allowedIfHasPermission($account, 'create ' . $type . ' content');
|
||||
|
||||
case 'update':
|
||||
$access = AccessResult::allowedIfHasPermission($account, 'edit any ' . $type . ' content');
|
||||
if (!$access->isAllowed() && $account->hasPermission('edit own ' . $type . ' content')) {
|
||||
@@ -1019,6 +1021,9 @@ function node_node_access(NodeInterface $node, $op, AccountInterface $account) {
|
||||
$access = $access->orIf(AccessResult::allowedIf($account->id() == $node->getOwnerId()))->cachePerUser()->addCacheableDependency($node);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
$access = AccessResult::neutral();
|
||||
}
|
||||
|
||||
return $access;
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provide views data for node.module.
|
||||
*/
|
||||
|
||||
use Drupal\user\RoleInterface;
|
||||
use Drupal\views\ViewExecutable;
|
||||
use Drupal\user\Entity\Role;
|
||||
use Drupal\views\Analyzer;
|
||||
|
||||
/**
|
||||
* Implements hook_views_analyze().
|
||||
*/
|
||||
function node_views_analyze(ViewExecutable $view) {
|
||||
$ret = [];
|
||||
// Check for something other than the default display:
|
||||
if ($view->storage->get('base_table') == 'node') {
|
||||
foreach ($view->displayHandlers as $display) {
|
||||
if (!$display->isDefaulted('access') || !$display->isDefaulted('filters')) {
|
||||
// check for no access control
|
||||
$access = $display->getOption('access');
|
||||
if (empty($access['type']) || $access['type'] == 'none') {
|
||||
$anonymous_role = Role::load(RoleInterface::ANONYMOUS_ID);
|
||||
$anonymous_has_access = $anonymous_role && $anonymous_role->hasPermission('access content');
|
||||
$authenticated_role = Role::load(RoleInterface::AUTHENTICATED_ID);
|
||||
$authenticated_has_access = $authenticated_role && $authenticated_role->hasPermission('access content');
|
||||
if (!$anonymous_has_access || !$authenticated_has_access) {
|
||||
$ret[] = Analyzer::formatMessage(t('Some roles lack permission to access content, but display %display has no access control.', ['%display' => $display->display['display_title']]), 'warning');
|
||||
}
|
||||
$filters = $display->getOption('filters');
|
||||
foreach ($filters as $filter) {
|
||||
if ($filter['table'] == 'node' && ($filter['field'] == 'status' || $filter['field'] == 'status_extra')) {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
$ret[] = Analyzer::formatMessage(t('Display %display has no access control but does not contain a filter for published nodes.', ['%display' => $display->display['display_title']]), 'warning');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($view->displayHandlers as $display) {
|
||||
if ($display->getPluginId() == 'page') {
|
||||
if ($display->getOption('path') == 'node/%') {
|
||||
$ret[] = Analyzer::formatMessage(t('Display %display has set node/% as path. This will not produce what you want. If you want to have multiple versions of the node view, use Layout Builder.', ['%display' => $display->display['display_title']]), 'warning');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
@@ -5,9 +5,7 @@
|
||||
* Provide views runtime hooks for node.module.
|
||||
*/
|
||||
|
||||
use Drupal\user\RoleInterface;
|
||||
use Drupal\views\ViewExecutable;
|
||||
use Drupal\user\Entity\Role;
|
||||
|
||||
/**
|
||||
* Implements hook_views_query_substitutions().
|
||||
@@ -20,44 +18,3 @@ function node_views_query_substitutions(ViewExecutable $view) {
|
||||
'***BYPASS_NODE_ACCESS***' => intval($account->hasPermission('bypass node access')),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_views_analyze().
|
||||
*/
|
||||
function node_views_analyze(ViewExecutable $view) {
|
||||
$ret = [];
|
||||
// Check for something other than the default display:
|
||||
if ($view->storage->get('base_table') == 'node') {
|
||||
foreach ($view->displayHandlers as $display) {
|
||||
if (!$display->isDefaulted('access') || !$display->isDefaulted('filters')) {
|
||||
// check for no access control
|
||||
$access = $display->getOption('access');
|
||||
if (empty($access['type']) || $access['type'] == 'none') {
|
||||
$anonymous_role = Role::load(RoleInterface::ANONYMOUS_ID);
|
||||
$anonymous_has_access = $anonymous_role && $anonymous_role->hasPermission('access content');
|
||||
$authenticated_role = Role::load(RoleInterface::AUTHENTICATED_ID);
|
||||
$authenticated_has_access = $authenticated_role && $authenticated_role->hasPermission('access content');
|
||||
if (!$anonymous_has_access || !$authenticated_has_access) {
|
||||
$ret[] = Analyzer::formatMessage(t('Some roles lack permission to access content, but display %display has no access control.', ['%display' => $display->display['display_title']]), 'warning');
|
||||
}
|
||||
$filters = $display->getOption('filters');
|
||||
foreach ($filters as $filter) {
|
||||
if ($filter['table'] == 'node' && ($filter['field'] == 'status' || $filter['field'] == 'status_extra')) {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
$ret[] = Analyzer::formatMessage(t('Display %display has no access control but does not contain a filter for published nodes.', ['%display' => $display->display['display_title']]), 'warning');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($view->displayHandlers as $display) {
|
||||
if ($display->getPluginId() == 'page') {
|
||||
if ($display->getOption('path') == 'node/%') {
|
||||
$ret[] = Analyzer::formatMessage(t('Display %display has set node/% as path. This will not produce what you want. If you want to have multiple versions of the node view, use panels.', ['%display' => $display->display['display_title']]), 'warning');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
+9
-1
@@ -368,7 +368,15 @@ display:
|
||||
entity_type: node
|
||||
entity_field: revision_uid
|
||||
plugin_id: user_name
|
||||
sorts: { }
|
||||
sorts:
|
||||
vid:
|
||||
id: vid
|
||||
table: node_field_revision
|
||||
field: vid
|
||||
order: ASC
|
||||
plugin_id: field
|
||||
entity_type: node
|
||||
entity_field: vid
|
||||
header: { }
|
||||
footer: { }
|
||||
empty: { }
|
||||
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- node
|
||||
- user
|
||||
id: test_node_views_analyze
|
||||
label: test_node_views_analyze
|
||||
module: views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: node_field_data
|
||||
base_field: nid
|
||||
display:
|
||||
default:
|
||||
display_plugin: default
|
||||
id: default
|
||||
display_title: Master
|
||||
position: 0
|
||||
display_options:
|
||||
access:
|
||||
type: perm
|
||||
options:
|
||||
perm: 'access content'
|
||||
cache:
|
||||
type: tag
|
||||
options: { }
|
||||
query:
|
||||
type: views_query
|
||||
options:
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
replica: false
|
||||
query_comment: ''
|
||||
query_tags: { }
|
||||
exposed_form:
|
||||
type: basic
|
||||
options:
|
||||
submit_button: Apply
|
||||
reset_button: false
|
||||
reset_button_label: Reset
|
||||
exposed_sorts_label: 'Sort by'
|
||||
expose_sort_order: true
|
||||
sort_asc_label: Asc
|
||||
sort_desc_label: Desc
|
||||
pager:
|
||||
type: mini
|
||||
options:
|
||||
items_per_page: 10
|
||||
offset: 0
|
||||
id: 0
|
||||
total_pages: null
|
||||
expose:
|
||||
items_per_page: false
|
||||
items_per_page_label: 'Items per page'
|
||||
items_per_page_options: '5, 10, 25, 50'
|
||||
items_per_page_options_all: false
|
||||
items_per_page_options_all_label: '- All -'
|
||||
offset: false
|
||||
offset_label: Offset
|
||||
tags:
|
||||
previous: ‹‹
|
||||
next: ››
|
||||
style:
|
||||
type: default
|
||||
row:
|
||||
type: 'entity:node'
|
||||
options:
|
||||
view_mode: teaser
|
||||
fields:
|
||||
title:
|
||||
id: title
|
||||
table: node_field_data
|
||||
field: title
|
||||
entity_type: node
|
||||
entity_field: title
|
||||
label: ''
|
||||
alter:
|
||||
alter_text: false
|
||||
make_link: false
|
||||
absolute: false
|
||||
trim: false
|
||||
word_boundary: false
|
||||
ellipsis: false
|
||||
strip_tags: false
|
||||
html: false
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
settings:
|
||||
link_to_entity: true
|
||||
plugin_id: field
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
exclude: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: true
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_alter_empty: true
|
||||
click_sort_column: value
|
||||
type: string
|
||||
group_column: value
|
||||
group_columns: { }
|
||||
group_rows: true
|
||||
delta_limit: 0
|
||||
delta_offset: 0
|
||||
delta_reversed: false
|
||||
delta_first_last: false
|
||||
multi_type: separator
|
||||
separator: ', '
|
||||
field_api_classes: false
|
||||
filters:
|
||||
status:
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
plugin_id: boolean
|
||||
entity_type: node
|
||||
entity_field: status
|
||||
id: status
|
||||
expose:
|
||||
operator: ''
|
||||
operator_limit_selection: false
|
||||
operator_list: { }
|
||||
group: 1
|
||||
sorts:
|
||||
created:
|
||||
id: created
|
||||
table: node_field_data
|
||||
field: created
|
||||
order: DESC
|
||||
entity_type: node
|
||||
entity_field: created
|
||||
plugin_id: date
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
exposed: false
|
||||
expose:
|
||||
label: ''
|
||||
granularity: second
|
||||
title: test_node_views_analyze
|
||||
header: { }
|
||||
footer: { }
|
||||
empty: { }
|
||||
relationships: { }
|
||||
arguments: { }
|
||||
display_extenders: { }
|
||||
cache_metadata:
|
||||
max-age: -1
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url.query_args
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
tags: { }
|
||||
page_1:
|
||||
display_plugin: page
|
||||
id: page_1
|
||||
display_title: Page
|
||||
position: 1
|
||||
display_options:
|
||||
display_extenders: { }
|
||||
path: node/%
|
||||
cache_metadata:
|
||||
max-age: -1
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url.query_args
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
tags: { }
|
||||
@@ -82,7 +82,6 @@ class NodeAccessGrantsCacheContextTest extends NodeTestBase {
|
||||
if ($uid > 0) {
|
||||
$this->drupalLogin($this->userMapping[$uid]);
|
||||
}
|
||||
$this->pass('Asserting cache context for user ' . $uid . '.');
|
||||
$this->assertIdentical($context, $this->container->get('cache_context.user.node_grants')->getContext('view'));
|
||||
}
|
||||
$this->drupalLogout();
|
||||
|
||||
@@ -111,7 +111,7 @@ class NodeCreationTest extends NodeTestBase {
|
||||
$this->fail('Expected exception has not been thrown.');
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
$this->pass('Expected exception has been thrown.');
|
||||
// Expected exception; just continue testing.
|
||||
}
|
||||
|
||||
if (Database::getConnection()->supportsTransactions()) {
|
||||
@@ -294,7 +294,9 @@ class NodeCreationTest extends NodeTestBase {
|
||||
// PostgreSQL doesn't support bytea LIKE queries, so we need to unserialize
|
||||
// first to check for the rollback exception message.
|
||||
$matches = [];
|
||||
$query = Database::getConnection()->query("SELECT wid, variables FROM {watchdog}");
|
||||
$query = Database::getConnection()->select('watchdog', 'w')
|
||||
->fields('w', ['wid', 'variables'])
|
||||
->execute();
|
||||
foreach ($query as $row) {
|
||||
$variables = (array) unserialize($row->variables);
|
||||
if (isset($variables['@message']) && $variables['@message'] === 'Test exception for rollback.') {
|
||||
|
||||
@@ -197,8 +197,13 @@ class NodeRevisionsTest extends NodeTestBase {
|
||||
'%title' => $nodes[1]->label(),
|
||||
]), 'Revision deleted.');
|
||||
$connection = Database::getConnection();
|
||||
$this->assertTrue($connection->query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = :nid and vid = :vid', [':nid' => $node->id(), ':vid' => $nodes[1]->getRevisionId()])->fetchField() == 0, 'Revision not found.');
|
||||
$this->assertTrue($connection->query('SELECT COUNT(vid) FROM {node_field_revision} WHERE nid = :nid and vid = :vid', [':nid' => $node->id(), ':vid' => $nodes[1]->getRevisionId()])->fetchField() == 0, 'Field revision not found.');
|
||||
$nids = \Drupal::entityQuery('node')
|
||||
->accessCheck(FALSE)
|
||||
->allRevisions()
|
||||
->condition('nid', $node->id())
|
||||
->condition('vid', $nodes[1]->getRevisionId())
|
||||
->execute();
|
||||
$this->assertCount(0, $nids);
|
||||
|
||||
// Set the revision timestamp to an older date to make sure that the
|
||||
// confirmation message correctly displays the stored revision date.
|
||||
|
||||
@@ -55,7 +55,6 @@ class NodeRevisionsUiBypassAccessTest extends NodeTestBase {
|
||||
$this->drupalPlaceBlock('local_tasks_block');
|
||||
|
||||
$this->drupalLogin($this->editor);
|
||||
$node_storage = $this->container->get('entity_type.manager')->getStorage('node');
|
||||
|
||||
// Set page revision setting 'create new revision'. This will mean new
|
||||
// revisions are created by default when the node is edited.
|
||||
|
||||
@@ -371,7 +371,7 @@ class NodeTranslationUITest extends ContentTranslationUITestBase {
|
||||
$this->doTestTranslations('node/' . $node->id(), $values);
|
||||
|
||||
// Test that the node page has the correct alternate hreflang links.
|
||||
$this->doTestAlternateHreflangLinks($node->toUrl());
|
||||
$this->doTestAlternateHreflangLinks($node);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -393,24 +393,35 @@ class NodeTranslationUITest extends ContentTranslationUITestBase {
|
||||
/**
|
||||
* Tests that the given path provides the correct alternate hreflang links.
|
||||
*
|
||||
* @param \Drupal\Core\Url $url
|
||||
* The path to be tested.
|
||||
* @param \Drupal\node\Entity\Node $node
|
||||
* The node to be tested.
|
||||
*/
|
||||
protected function doTestAlternateHreflangLinks(Url $url) {
|
||||
protected function doTestAlternateHreflangLinks(Node $node) {
|
||||
$url = $node->toUrl();
|
||||
$languages = $this->container->get('language_manager')->getLanguages();
|
||||
$url->setAbsolute();
|
||||
$urls = [];
|
||||
$translations = [];
|
||||
foreach ($this->langcodes as $langcode) {
|
||||
$language_url = clone $url;
|
||||
$urls[$langcode] = $language_url->setOption('language', $languages[$langcode]);
|
||||
$translations[$langcode] = $node->getTranslation($langcode);
|
||||
}
|
||||
foreach ($this->langcodes as $langcode) {
|
||||
$this->drupalGet($urls[$langcode]);
|
||||
foreach ($urls as $alternate_langcode => $language_url) {
|
||||
// Retrieve desired link elements from the HTML head.
|
||||
$links = $this->xpath('head/link[@rel = "alternate" and @href = :href and @hreflang = :hreflang]',
|
||||
[':href' => $language_url->toString(), ':hreflang' => $alternate_langcode]);
|
||||
$this->assert(isset($links[0]), new FormattableMarkup('The %langcode node translation has the correct alternate hreflang link for %alternate_langcode: %link.', ['%langcode' => $langcode, '%alternate_langcode' => $alternate_langcode, '%link' => $url->toString()]));
|
||||
// Skip unpublished translations.
|
||||
if ($translations[$langcode]->isPublished()) {
|
||||
$this->drupalGet($urls[$langcode]);
|
||||
foreach ($urls as $alternate_langcode => $language_url) {
|
||||
// Retrieve desired link elements from the HTML head.
|
||||
$links = $this->xpath('head/link[@rel = "alternate" and @href = :href and @hreflang = :hreflang]',
|
||||
[':href' => $language_url->toString(), ':hreflang' => $alternate_langcode]);
|
||||
if ($translations[$alternate_langcode]->isPublished()) {
|
||||
$this->assert(isset($links[0]), new FormattableMarkup('The %langcode node translation has the correct alternate hreflang link for %alternate_langcode: %link.', ['%langcode' => $langcode, '%alternate_langcode' => $alternate_langcode, '%link' => $url->toString()]));
|
||||
}
|
||||
else {
|
||||
$this->assertFalse(isset($links[0]), new FormattableMarkup('The %langcode node translation has an hreflang link for unpublished %alternate_langcode translation: %link.', ['%langcode' => $langcode, '%alternate_langcode' => $alternate_langcode, '%link' => $url->toString()]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Drupal\Tests\node\Functional\Views;
|
||||
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\views\Views;
|
||||
|
||||
@@ -60,7 +59,6 @@ class BulkFormTest extends NodeTestBase {
|
||||
'promote' => FALSE,
|
||||
];
|
||||
$node = $this->drupalCreateNode($values);
|
||||
$this->pass(new FormattableMarkup('Node %title created with language %langcode.', ['%title' => $node->label(), '%langcode' => $node->language()->getId()]));
|
||||
$this->nodes[] = $node;
|
||||
}
|
||||
|
||||
@@ -71,7 +69,6 @@ class BulkFormTest extends NodeTestBase {
|
||||
if (!$node->hasTranslation($langcode)) {
|
||||
$title = $this->randomMachineName() . ' [' . $node->id() . ':' . $langcode . ']';
|
||||
$translation = $node->addTranslation($langcode, ['title' => $title, 'promote' => FALSE]);
|
||||
$this->pass(new FormattableMarkup('Translation %title created with language %langcode.', ['%title' => $translation->label(), '%langcode' => $translation->language()->getId()]));
|
||||
}
|
||||
}
|
||||
$node->save();
|
||||
@@ -82,7 +79,6 @@ class BulkFormTest extends NodeTestBase {
|
||||
$langcode = 'en';
|
||||
$title = $this->randomMachineName() . ' [' . $node->id() . ':' . $langcode . ']';
|
||||
$translation = $node->addTranslation($langcode, ['title' => $title]);
|
||||
$this->pass(new FormattableMarkup('Translation %title created with language %langcode.', ['%title' => $translation->label(), '%langcode' => $translation->language()->getId()]));
|
||||
$node->save();
|
||||
|
||||
// Check that all created translations are selected by the test view.
|
||||
|
||||
@@ -187,7 +187,7 @@ class FrontPageTest extends ViewTestBase {
|
||||
$this->drupalGet('node');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
// Check that the frontpage view was rendered.
|
||||
$this->assertPattern('/class=".+view-frontpage/', 'Frontpage view was rendered');
|
||||
$this->assertPattern('/class=".+view-frontpage/');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -304,7 +304,6 @@ class FrontPageTest extends ViewTestBase {
|
||||
'timezone',
|
||||
]);
|
||||
|
||||
$this->pass('First page');
|
||||
// First page.
|
||||
$first_page_result_cache_tags = [
|
||||
'config:views.view.frontpage',
|
||||
@@ -344,7 +343,6 @@ class FrontPageTest extends ViewTestBase {
|
||||
);
|
||||
|
||||
// Second page.
|
||||
$this->pass('Second page');
|
||||
$this->assertPageCacheContextsAndTags(Url::fromRoute('view.frontpage.page_1', [], ['query' => ['page' => 1]]), $cache_contexts, [
|
||||
// The cache tags for the listed nodes.
|
||||
'node:1',
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\node\Functional\Views;
|
||||
|
||||
/**
|
||||
* Tests node_views_analyze().
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeViewsAnalyzeTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['views_ui', 'node_test_views'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_node_views_analyze'];
|
||||
|
||||
/**
|
||||
* Tests the implementation of node_views_analyze().
|
||||
*/
|
||||
public function testNodeViewsAnalyze() {
|
||||
// Create user with permission to view analyze message on views_ui.
|
||||
$admin_user = $this->createUser(['administer views']);
|
||||
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Access to views analyze page.
|
||||
$this->drupalGet('admin/structure/views/nojs/analyze/test_node_views_analyze/page_1');
|
||||
|
||||
// Should return 200 with correct permission.
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
|
||||
$this->assertSession()->responseContains('has set node/% as path. This will not produce what you want. If you want to have multiple versions of the node view, use Layout Builder.');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -52,24 +52,24 @@ class MigrateNodeTest extends MigrateNodeTestBase {
|
||||
$node = Node::load(1);
|
||||
$this->assertIdentical('1', $node->id(), 'Node 1 loaded.');
|
||||
$this->assertIdentical('und', $node->langcode->value);
|
||||
$this->assertIdentical('test', $node->body->value);
|
||||
$this->assertIdentical('test', $node->body->summary);
|
||||
$this->assertIdentical('body test rev 3', $node->body->value);
|
||||
$this->assertIdentical('teaser test rev 3', $node->body->summary);
|
||||
$this->assertIdentical('filtered_html', $node->body->format);
|
||||
$this->assertIdentical('story', $node->getType(), 'Node has the correct bundle.');
|
||||
$this->assertIdentical('Test title', $node->getTitle(), 'Node has the correct title.');
|
||||
$this->assertIdentical('Test title rev 3', $node->getTitle(), 'Node has the correct title.');
|
||||
$this->assertIdentical('1390095702', $node->getCreatedTime(), 'Node has the correct created time.');
|
||||
$this->assertIdentical(FALSE, $node->isSticky());
|
||||
$this->assertIdentical('1', $node->getOwnerId());
|
||||
$this->assertIdentical('1390095702', $node->getRevisionCreationTime());
|
||||
$this->assertIdentical('1420861423', $node->getRevisionCreationTime());
|
||||
|
||||
/** @var \Drupal\node\NodeInterface $node_revision */
|
||||
$node_revision = \Drupal::entityTypeManager()->getStorage('node')->loadRevision(1);
|
||||
$this->assertIdentical('Test title', $node_revision->getTitle());
|
||||
$this->assertIdentical('1', $node_revision->getRevisionUser()->id(), 'Node revision has the correct user');
|
||||
$node_revision = \Drupal::entityTypeManager()->getStorage('node')->loadRevision(2001);
|
||||
$this->assertIdentical('Test title rev 3', $node_revision->getTitle());
|
||||
$this->assertIdentical('2', $node_revision->getRevisionUser()->id(), 'Node revision has the correct user');
|
||||
$this->assertSame('1', $node_revision->id(), 'Node 1 loaded.');
|
||||
$this->assertSame('1', $node_revision->getRevisionId(), 'Node 1 revision 1 loaded.');
|
||||
$this->assertSame('2001', $node_revision->getRevisionId(), 'Node 1 revision 2001 loaded.');
|
||||
// This is empty on the first revision.
|
||||
$this->assertIdentical(NULL, $node_revision->revision_log->value);
|
||||
$this->assertIdentical('modified rev 3', $node_revision->revision_log->value);
|
||||
$this->assertIdentical('This is a shared text field', $node->field_test->value);
|
||||
$this->assertIdentical('filtered_html', $node->field_test->format);
|
||||
$this->assertIdentical('10', $node->field_test_two->value);
|
||||
|
||||
@@ -30,7 +30,11 @@ class NodeAccessRecordsTest extends NodeAccessTestBase {
|
||||
|
||||
// Check to see if grants added by node_test_node_access_records made it in.
|
||||
$connection = Database::getConnection();
|
||||
$records = $connection->query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', [':nid' => $node1->id()])->fetchAll();
|
||||
$records = $connection->select('node_access', 'na')
|
||||
->fields('na', ['realm', 'gid'])
|
||||
->condition('nid', $node1->id())
|
||||
->execute()
|
||||
->fetchAll();
|
||||
$this->assertCount(1, $records, 'Returned the correct number of rows.');
|
||||
$this->assertEqual($records[0]->realm, 'test_article_realm', 'Grant with article_realm acquired for node without alteration.');
|
||||
$this->assertEqual($records[0]->gid, 1, 'Grant with gid = 1 acquired for node without alteration.');
|
||||
@@ -40,7 +44,11 @@ class NodeAccessRecordsTest extends NodeAccessTestBase {
|
||||
$this->assertNotEmpty(Node::load($node2->id()), 'Unpromoted basic page node created.');
|
||||
|
||||
// Check to see if grants added by node_test_node_access_records made it in.
|
||||
$records = $connection->query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', [':nid' => $node2->id()])->fetchAll();
|
||||
$records = $connection->select('node_access', 'na')
|
||||
->fields('na', ['realm', 'gid'])
|
||||
->condition('nid', $node2->id())
|
||||
->execute()
|
||||
->fetchAll();
|
||||
$this->assertCount(1, $records, 'Returned the correct number of rows.');
|
||||
$this->assertEqual($records[0]->realm, 'test_page_realm', 'Grant with page_realm acquired for node without alteration.');
|
||||
$this->assertEqual($records[0]->gid, 1, 'Grant with gid = 1 acquired for node without alteration.');
|
||||
@@ -50,7 +58,11 @@ class NodeAccessRecordsTest extends NodeAccessTestBase {
|
||||
$this->assertNotEmpty(Node::load($node3->id()), 'Unpromoted, unpublished basic page node created.');
|
||||
|
||||
// Check to see if grants added by node_test_node_access_records made it in.
|
||||
$records = $connection->query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', [':nid' => $node3->id()])->fetchAll();
|
||||
$records = $connection->select('node_access', 'na')
|
||||
->fields('na', ['realm', 'gid'])
|
||||
->condition('nid', $node3->id())
|
||||
->execute()
|
||||
->fetchAll();
|
||||
$this->assertCount(1, $records, 'Returned the correct number of rows.');
|
||||
$this->assertEqual($records[0]->realm, 'test_page_realm', 'Grant with page_realm acquired for node without alteration.');
|
||||
$this->assertEqual($records[0]->gid, 1, 'Grant with gid = 1 acquired for node without alteration.');
|
||||
@@ -61,7 +73,11 @@ class NodeAccessRecordsTest extends NodeAccessTestBase {
|
||||
|
||||
// Check to see if grant added by node_test_node_access_records was altered
|
||||
// by node_test_node_access_records_alter.
|
||||
$records = $connection->query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', [':nid' => $node4->id()])->fetchAll();
|
||||
$records = $connection->select('node_access', 'na')
|
||||
->fields('na', ['realm', 'gid'])
|
||||
->condition('nid', $node4->id())
|
||||
->execute()
|
||||
->fetchAll();
|
||||
$this->assertCount(1, $records, 'Returned the correct number of rows.');
|
||||
$this->assertEqual($records[0]->realm, 'test_alter_realm', 'Altered grant with alter_realm acquired for node.');
|
||||
$this->assertEqual($records[0]->gid, 2, 'Altered grant with gid = 2 acquired for node.');
|
||||
@@ -80,7 +96,11 @@ class NodeAccessRecordsTest extends NodeAccessTestBase {
|
||||
// Check that core does not grant access to an unpublished node when an
|
||||
// empty $grants array is returned.
|
||||
$node6 = $this->drupalCreateNode(['status' => 0, 'disable_node_access' => TRUE]);
|
||||
$records = $connection->query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', [':nid' => $node6->id()])->fetchAll();
|
||||
$records = $connection->select('node_access', 'na')
|
||||
->fields('na', ['realm', 'gid'])
|
||||
->condition('nid', $node6->id())
|
||||
->execute()
|
||||
->fetchAll();
|
||||
$this->assertCount(0, $records, 'Returned no records for unpublished node.');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user