Drupal 8.0.0 beta 12. More info: https://www.drupal.org/node/2514176
This commit is contained in:
commit
9921556621
13277 changed files with 1459781 additions and 0 deletions
85
core/modules/node/src/Tests/Condition/NodeConditionTest.php
Normal file
85
core/modules/node/src/Tests/Condition/NodeConditionTest.php
Normal file
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\Condition\NodeConditionTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests\Condition;
|
||||
|
||||
use Drupal\system\Tests\Entity\EntityUnitTestBase;
|
||||
|
||||
/**
|
||||
* Tests that conditions, provided by the node module, are working properly.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeConditionTest extends EntityUnitTestBase {
|
||||
|
||||
public static $modules = array('node');
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create the node bundles required for testing.
|
||||
$type = entity_create('node_type', array('type' => 'page', 'name' => 'page'));
|
||||
$type->save();
|
||||
$type = entity_create('node_type', array('type' => 'article', 'name' => 'article'));
|
||||
$type->save();
|
||||
$type = entity_create('node_type', array('type' => 'test', 'name' => 'test'));
|
||||
$type->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests conditions.
|
||||
*/
|
||||
function testConditions() {
|
||||
$manager = $this->container->get('plugin.manager.condition', $this->container->get('container.namespaces'));
|
||||
$this->createUser();
|
||||
|
||||
// Get some nodes of various types to check against.
|
||||
$page = entity_create('node', array('type' => 'page', 'title' => $this->randomMachineName(), 'uid' => 1));
|
||||
$page->save();
|
||||
$article = entity_create('node', array('type' => 'article', 'title' => $this->randomMachineName(), 'uid' => 1));
|
||||
$article->save();
|
||||
$test = entity_create('node', array('type' => 'test', 'title' => $this->randomMachineName(), 'uid' => 1));
|
||||
$test->save();
|
||||
|
||||
// Grab the node type condition and configure it to check against node type
|
||||
// of 'article' and set the context to the page type node.
|
||||
$condition = $manager->createInstance('node_type')
|
||||
->setConfig('bundles', array('article' => 'article'))
|
||||
->setContextValue('node', $page);
|
||||
$this->assertFalse($condition->execute(), 'Page type nodes fail node type checks for articles.');
|
||||
// Check for the proper summary.
|
||||
$this->assertEqual('The node bundle is article', $condition->summary());
|
||||
|
||||
// Set the node type check to page.
|
||||
$condition->setConfig('bundles', array('page' => 'page'));
|
||||
$this->assertTrue($condition->execute(), 'Page type nodes pass node type checks for pages');
|
||||
// Check for the proper summary.
|
||||
$this->assertEqual('The node bundle is page', $condition->summary());
|
||||
|
||||
// Set the node type check to page or article.
|
||||
$condition->setConfig('bundles', array('page' => 'page', 'article' => 'article'));
|
||||
$this->assertTrue($condition->execute(), 'Page type nodes pass node type checks for pages or articles');
|
||||
// Check for the proper summary.
|
||||
$this->assertEqual('The node bundle is page or article', $condition->summary());
|
||||
|
||||
// Set the context to the article node.
|
||||
$condition->setContextValue('node', $article);
|
||||
$this->assertTrue($condition->execute(), 'Article type nodes pass node type checks for pages or articles');
|
||||
|
||||
// Set the context to the test node.
|
||||
$condition->setContextValue('node', $test);
|
||||
$this->assertFalse($condition->execute(), 'Test type nodes pass node type checks for pages or articles');
|
||||
|
||||
// Check a greater than 2 bundles summary scenario.
|
||||
$condition->setConfig('bundles', array('page' => 'page', 'article' => 'article', 'test' => 'test'));
|
||||
$this->assertEqual('The node bundle is page, article or test', $condition->summary());
|
||||
|
||||
// Test Constructor injection.
|
||||
$condition = $manager->createInstance('node_type', array('bundles' => array('article' => 'article'), 'context' => array('node' => $article)));
|
||||
$this->assertTrue($condition->execute(), 'Constructor injection of context and configuration working as anticipated.');
|
||||
}
|
||||
}
|
64
core/modules/node/src/Tests/Config/NodeImportChangeTest.php
Normal file
64
core/modules/node/src/Tests/Config/NodeImportChangeTest.php
Normal file
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\Config\NodeImportChangeTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests\Config;
|
||||
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\simpletest\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Change content types during config create method invocation.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeImportChangeTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node', 'field', 'text', 'system', 'node_test_config', 'user', 'entity_reference');
|
||||
|
||||
/**
|
||||
* Set the default field storage backend for fields created during tests.
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Set default storage backend.
|
||||
$this->installConfig(array('field', 'node_test_config'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests importing an updated content type.
|
||||
*/
|
||||
public function testImportChange() {
|
||||
$node_type_id = 'default';
|
||||
$node_type_config_name = "node.type.$node_type_id";
|
||||
|
||||
// Simulate config data to import:
|
||||
// - a modified version (modified label) of the node type config.
|
||||
$active = $this->container->get('config.storage');
|
||||
$staging = $this->container->get('config.storage.staging');
|
||||
$this->copyConfig($active, $staging);
|
||||
|
||||
$node_type = $active->read($node_type_config_name);
|
||||
$new_label = 'Test update import field';
|
||||
$node_type['name'] = $new_label;
|
||||
// Save as files in the staging directory.
|
||||
$staging->write($node_type_config_name, $node_type);
|
||||
|
||||
// Import the content of the staging directory.
|
||||
$this->configImporter()->import();
|
||||
|
||||
// Check that the updated config was correctly imported.
|
||||
$node_type = NodeType::load($node_type_id);
|
||||
$this->assertEqual($node_type->label(), $new_label, 'Node type name has been updated.');
|
||||
}
|
||||
|
||||
}
|
80
core/modules/node/src/Tests/Config/NodeImportCreateTest.php
Normal file
80
core/modules/node/src/Tests/Config/NodeImportCreateTest.php
Normal file
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\Config\NodeImportCreateTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests\Config;
|
||||
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\simpletest\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Create content types during config create method invocation.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeImportCreateTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node', 'field', 'text', 'system', 'user', 'entity_reference');
|
||||
|
||||
/**
|
||||
* Set the default field storage backend for fields created during tests.
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('user');
|
||||
|
||||
// Set default storage backend.
|
||||
$this->installConfig(array('field'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests creating a content type during default config import.
|
||||
*/
|
||||
public function testImportCreateDefault() {
|
||||
$node_type_id = 'default';
|
||||
|
||||
// Check that the content type does not exist yet.
|
||||
$this->assertFalse(NodeType::load($node_type_id));
|
||||
|
||||
// Enable node_test_config module and check that the content type
|
||||
// shipped in the module's default config is created.
|
||||
$this->container->get('module_installer')->install(array('node_test_config'));
|
||||
$node_type = NodeType::load($node_type_id);
|
||||
$this->assertTrue($node_type, 'The default content type was created.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests creating a content type during config import.
|
||||
*/
|
||||
public function testImportCreate() {
|
||||
$node_type_id = 'import';
|
||||
$node_type_config_name = "node.type.$node_type_id";
|
||||
|
||||
// Simulate config data to import.
|
||||
$active = $this->container->get('config.storage');
|
||||
$staging = $this->container->get('config.storage.staging');
|
||||
$this->copyConfig($active, $staging);
|
||||
// Manually add new node type.
|
||||
$src_dir = drupal_get_path('module', 'node_test_config') . '/staging';
|
||||
$target_dir = $this->configDirectories[CONFIG_STAGING_DIRECTORY];
|
||||
$this->assertTrue(file_unmanaged_copy("$src_dir/$node_type_config_name.yml", "$target_dir/$node_type_config_name.yml"));
|
||||
|
||||
// Import the content of the staging directory.
|
||||
$this->configImporter()->import();
|
||||
|
||||
// Check that the content type was created.
|
||||
$node_type = NodeType::load($node_type_id);
|
||||
$this->assertTrue($node_type, 'Import node type from staging was created.');
|
||||
$this->assertFalse(FieldConfig::loadByName('node', $node_type_id, 'body'));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\MultiStepNodeFormBasicOptionsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
|
||||
/**
|
||||
* Tests the persistence of basic options through multiple steps.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class MultiStepNodeFormBasicOptionsTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* The field name to create.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $fieldName;
|
||||
|
||||
/**
|
||||
* Tests changing the default values of basic options to ensure they persist.
|
||||
*/
|
||||
function testMultiStepNodeFormBasicOptions() {
|
||||
// Prepare a user to create the node.
|
||||
$web_user = $this->drupalCreateUser(array('administer nodes', 'create page content'));
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
// Create an unlimited cardinality field.
|
||||
$this->fieldName = Unicode::strtolower($this->randomMachineName());
|
||||
entity_create('field_storage_config', array(
|
||||
'field_name' => $this->fieldName,
|
||||
'entity_type' => 'node',
|
||||
'type' => 'text',
|
||||
'cardinality' => -1,
|
||||
))->save();
|
||||
|
||||
// Attach an instance of the field to the page content type.
|
||||
entity_create('field_config', array(
|
||||
'field_name' => $this->fieldName,
|
||||
'entity_type' => 'node',
|
||||
'bundle' => 'page',
|
||||
'label' => $this->randomMachineName() . '_label',
|
||||
))->save();
|
||||
entity_get_form_display('node', 'page', 'default')
|
||||
->setComponent($this->fieldName, array(
|
||||
'type' => 'text_textfield',
|
||||
))
|
||||
->save();
|
||||
|
||||
$edit = array(
|
||||
'title[0][value]' => 'a',
|
||||
'promote[value]' => FALSE,
|
||||
'sticky[value]' => 1,
|
||||
"{$this->fieldName}[0][value]" => $this->randomString(32),
|
||||
);
|
||||
$this->drupalPostForm('node/add/page', $edit, t('Add another item'));
|
||||
$this->assertNoFieldChecked('edit-promote-value', 'Promote stayed unchecked');
|
||||
$this->assertFieldChecked('edit-sticky-value', 'Sticky stayed checked');
|
||||
}
|
||||
|
||||
}
|
214
core/modules/node/src/Tests/NodeAccessBaseTableTest.php
Normal file
214
core/modules/node/src/Tests/NodeAccessBaseTableTest.php
Normal file
|
@ -0,0 +1,214 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeAccessBaseTableTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\node\Entity\NodeType;
|
||||
|
||||
/**
|
||||
* Tests behavior of the node access subsystem if the base table is not node.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeAccessBaseTableTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node_access_test', 'views');
|
||||
|
||||
/**
|
||||
* The installation profile to use with this test.
|
||||
*
|
||||
* This test class requires the "tags" taxonomy field.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $profile = 'standard';
|
||||
|
||||
/**
|
||||
* Nodes by user.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $nodesByUser;
|
||||
|
||||
/**
|
||||
* A public tid.
|
||||
*
|
||||
* @var \Drupal\Core\Database\StatementInterface
|
||||
*/
|
||||
protected $publicTid;
|
||||
|
||||
/**
|
||||
* A private tid.
|
||||
*
|
||||
* @var \Drupal\Core\Database\StatementInterface
|
||||
*/
|
||||
protected $privateTid;
|
||||
|
||||
/**
|
||||
* A web user.
|
||||
*/
|
||||
protected $webUser;
|
||||
|
||||
/**
|
||||
* The nids visible.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $nidsVisible;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
node_access_test_add_field(NodeType::load('article'));
|
||||
|
||||
node_access_rebuild();
|
||||
\Drupal::state()->set('node_access_test.private', TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the "private" node access functionality.
|
||||
*
|
||||
* - Create 2 users with "access content" and "create article" permissions.
|
||||
* - Each user creates one private and one not private article.
|
||||
*
|
||||
* - Test that each user can view the other user's non-private article.
|
||||
* - Test that each user cannot view the other user's private article.
|
||||
* - Test that each user finds only appropriate (non-private + own private)
|
||||
* in taxonomy listing.
|
||||
* - Create another user with 'view any private content'.
|
||||
* - Test that user 4 can view all content created above.
|
||||
* - Test that user 4 can view all content on taxonomy listing.
|
||||
*/
|
||||
function testNodeAccessBasic() {
|
||||
$num_simple_users = 2;
|
||||
$simple_users = array();
|
||||
|
||||
// Nodes keyed by uid and nid: $nodes[$uid][$nid] = $is_private;
|
||||
$this->nodesByUser = array();
|
||||
// Titles keyed by nid.
|
||||
$titles = [];
|
||||
// Array of nids marked private.
|
||||
$private_nodes = [];
|
||||
for ($i = 0; $i < $num_simple_users; $i++) {
|
||||
$simple_users[$i] = $this->drupalCreateUser(array('access content', 'create article content'));
|
||||
}
|
||||
foreach ($simple_users as $this->webUser) {
|
||||
$this->drupalLogin($this->webUser);
|
||||
foreach (array(0 => 'Public', 1 => 'Private') as $is_private => $type) {
|
||||
$edit = array(
|
||||
'title[0][value]' => t('@private_public Article created by @user', array('@private_public' => $type, '@user' => $this->webUser->getUsername())),
|
||||
);
|
||||
if ($is_private) {
|
||||
$edit['private[0][value]'] = TRUE;
|
||||
$edit['body[0][value]'] = 'private node';
|
||||
$edit['field_tags[target_id]'] = 'private';
|
||||
}
|
||||
else {
|
||||
$edit['body[0][value]'] = 'public node';
|
||||
$edit['field_tags[target_id]'] = 'public';
|
||||
}
|
||||
|
||||
$this->drupalPostForm('node/add/article', $edit, t('Save'));
|
||||
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
|
||||
$this->assertEqual($is_private, (int)$node->private->value, 'The private status of the node was properly set in the node_access_test table.');
|
||||
if ($is_private) {
|
||||
$private_nodes[] = $node->id();
|
||||
}
|
||||
$titles[$node->id()] = $edit['title[0][value]'];
|
||||
$this->nodesByUser[$this->webUser->id()][$node->id()] = $is_private;
|
||||
}
|
||||
}
|
||||
$this->publicTid = db_query('SELECT tid FROM {taxonomy_term_field_data} WHERE name = :name AND default_langcode = 1', array(':name' => 'public'))->fetchField();
|
||||
$this->privateTid = db_query('SELECT tid FROM {taxonomy_term_field_data} WHERE name = :name AND default_langcode = 1', array(':name' => 'private'))->fetchField();
|
||||
$this->assertTrue($this->publicTid, 'Public tid was found');
|
||||
$this->assertTrue($this->privateTid, 'Private tid was found');
|
||||
foreach ($simple_users as $this->webUser) {
|
||||
$this->drupalLogin($this->webUser);
|
||||
// Check own nodes to see that all are readable.
|
||||
foreach ($this->nodesByUser as $uid => $data) {
|
||||
foreach ($data as $nid => $is_private) {
|
||||
$this->drupalGet('node/' . $nid);
|
||||
if ($is_private) {
|
||||
$should_be_visible = $uid == $this->webUser->id();
|
||||
}
|
||||
else {
|
||||
$should_be_visible = TRUE;
|
||||
}
|
||||
$this->assertResponse($should_be_visible ? 200 : 403, strtr('A %private node by user %uid is %visible for user %current_uid.', array(
|
||||
'%private' => $is_private ? 'private' : 'public',
|
||||
'%uid' => $uid,
|
||||
'%visible' => $should_be_visible ? 'visible' : 'not visible',
|
||||
'%current_uid' => $this->webUser->id(),
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
// Check to see that the correct nodes are shown on taxonomy/private
|
||||
// and taxonomy/public.
|
||||
$this->assertTaxonomyPage(FALSE);
|
||||
}
|
||||
|
||||
// Now test that a user with 'node test view' permissions can view content.
|
||||
$access_user = $this->drupalCreateUser(array('access content', 'create article content', 'node test view', 'search content'));
|
||||
$this->drupalLogin($access_user);
|
||||
|
||||
foreach ($this->nodesByUser as $private_status) {
|
||||
foreach ($private_status as $nid => $is_private) {
|
||||
$this->drupalGet('node/' . $nid);
|
||||
$this->assertResponse(200);
|
||||
}
|
||||
}
|
||||
|
||||
// This user should be able to see all of the nodes on the relevant
|
||||
// taxonomy pages.
|
||||
$this->assertTaxonomyPage(TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks taxonomy/term listings to ensure only accessible nodes are listed.
|
||||
*
|
||||
* @param $is_admin
|
||||
* A boolean indicating whether the current user is an administrator. If
|
||||
* TRUE, all nodes should be listed. If FALSE, only public nodes and the
|
||||
* user's own private nodes should be listed.
|
||||
*/
|
||||
protected function assertTaxonomyPage($is_admin) {
|
||||
foreach (array($this->publicTid, $this->privateTid) as $tid_is_private => $tid) {
|
||||
$this->drupalGet("taxonomy/term/$tid");
|
||||
$this->nidsVisible = [];
|
||||
foreach ($this->xpath("//a[text()='Read more']") as $link) {
|
||||
// See also testTranslationRendering() in NodeTranslationUITest.
|
||||
$this->assertTrue(preg_match('|node/(\d+)$|', (string) $link['href'], $matches), 'Read more points to a node');
|
||||
$this->nidsVisible[$matches[1]] = TRUE;
|
||||
}
|
||||
foreach ($this->nodesByUser as $uid => $data) {
|
||||
foreach ($data as $nid => $is_private) {
|
||||
// Private nodes should be visible on the private term page,
|
||||
// public nodes should be visible on the public term page.
|
||||
$should_be_visible = $tid_is_private == $is_private;
|
||||
// Non-administrators can only see their own nodes on the private
|
||||
// term page.
|
||||
if (!$is_admin && $tid_is_private) {
|
||||
$should_be_visible = $should_be_visible && $uid == $this->webUser->id();
|
||||
}
|
||||
$this->assertIdentical(isset($this->nidsVisible[$nid]), $should_be_visible, strtr('A %private node by user %uid is %visible for user %current_uid on the %tid_is_private page.', array(
|
||||
'%private' => $is_private ? 'private' : 'public',
|
||||
'%uid' => $uid,
|
||||
'%visible' => isset($this->nidsVisible[$nid]) ? 'visible' : 'not visible',
|
||||
'%current_uid' => $this->webUser->id(),
|
||||
'%tid_is_private' => $tid_is_private ? 'private' : 'public',
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
115
core/modules/node/src/Tests/NodeAccessFieldTest.php
Normal file
115
core/modules/node/src/Tests/NodeAccessFieldTest.php
Normal file
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeAccessFieldTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
|
||||
/**
|
||||
* Tests the interaction of the node access system with fields.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeAccessFieldTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node_access_test', 'field_ui');
|
||||
|
||||
/**
|
||||
* A user with permission to bypass access content.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
/**
|
||||
* A user with permission to manage content types and fields.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $contentAdminUser;
|
||||
|
||||
/**
|
||||
* The name of the created field.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $fieldName;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
node_access_rebuild();
|
||||
|
||||
// Create some users.
|
||||
$this->adminUser = $this->drupalCreateUser(array('access content', 'bypass node access'));
|
||||
$this->contentAdminUser = $this->drupalCreateUser(array('access content', 'administer content types', 'administer node fields'));
|
||||
|
||||
// Add a custom field to the page content type.
|
||||
$this->fieldName = Unicode::strtolower($this->randomMachineName() . '_field_name');
|
||||
entity_create('field_storage_config', array(
|
||||
'field_name' => $this->fieldName,
|
||||
'entity_type' => 'node',
|
||||
'type' => 'text'
|
||||
))->save();
|
||||
entity_create('field_config', array(
|
||||
'field_name' => $this->fieldName,
|
||||
'entity_type' => 'node',
|
||||
'bundle' => 'page',
|
||||
))->save();
|
||||
entity_get_display('node', 'page', 'default')
|
||||
->setComponent($this->fieldName)
|
||||
->save();
|
||||
entity_get_form_display('node', 'page', 'default')
|
||||
->setComponent($this->fieldName)
|
||||
->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests administering fields when node access is restricted.
|
||||
*/
|
||||
function testNodeAccessAdministerField() {
|
||||
// Create a page node.
|
||||
$fieldData = array();
|
||||
$value = $fieldData[0]['value'] = $this->randomMachineName();
|
||||
$node = $this->drupalCreateNode(array($this->fieldName => $fieldData));
|
||||
|
||||
// Log in as the administrator and confirm that the field value is present.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$this->assertText($value, 'The saved field value is visible to an administrator.');
|
||||
|
||||
// Log in as the content admin and try to view the node.
|
||||
$this->drupalLogin($this->contentAdminUser);
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$this->assertText('Access denied', 'Access is denied for the content admin.');
|
||||
|
||||
// Modify the field default as the content admin.
|
||||
$edit = array();
|
||||
$default = 'Sometimes words have two meanings';
|
||||
$edit["default_value_input[{$this->fieldName}][0][value]"] = $default;
|
||||
$this->drupalPostForm(
|
||||
"admin/structure/types/manage/page/fields/node.page.{$this->fieldName}",
|
||||
$edit,
|
||||
t('Save settings')
|
||||
);
|
||||
|
||||
// Log in as the administrator.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Confirm that the existing node still has the correct field value.
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$this->assertText($value, 'The original field value is visible to an administrator.');
|
||||
|
||||
// Confirm that the new default value appears when creating a new node.
|
||||
$this->drupalGet('node/add/page');
|
||||
$this->assertRaw($default, 'The updated default value is displayed when creating a new node.');
|
||||
}
|
||||
}
|
143
core/modules/node/src/Tests/NodeAccessGrantsCacheContextTest.php
Normal file
143
core/modules/node/src/Tests/NodeAccessGrantsCacheContextTest.php
Normal file
|
@ -0,0 +1,143 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeAccessGrantsCacheContextTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Tests the node access grants cache context service.
|
||||
*
|
||||
* @group node
|
||||
* @group Cache
|
||||
*/
|
||||
class NodeAccessGrantsCacheContextTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node_access_test');
|
||||
|
||||
/**
|
||||
* User with permission to view content.
|
||||
*/
|
||||
protected $accessUser;
|
||||
|
||||
/**
|
||||
* User without permission to view content.
|
||||
*/
|
||||
protected $noAccessUser;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
node_access_rebuild();
|
||||
|
||||
// Create some content.
|
||||
$this->drupalCreateNode();
|
||||
$this->drupalCreateNode();
|
||||
$this->drupalCreateNode();
|
||||
$this->drupalCreateNode();
|
||||
|
||||
// Create user with simple node access permission. The 'node test view'
|
||||
// permission is implemented and granted by the node_access_test module.
|
||||
$this->accessUser = $this->drupalCreateUser(array('access content overview', 'access content', 'node test view'));
|
||||
$this->noAccessUser = $this->drupalCreateUser(array('access content overview', 'access content'));
|
||||
$this->noAccessUser2 = $this->drupalCreateUser(array('access content overview', 'access content'));
|
||||
|
||||
$this->userMapping = [
|
||||
1 => $this->rootUser,
|
||||
2 => $this->accessUser,
|
||||
3 => $this->noAccessUser,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that for each given user, the expected cache context is returned.
|
||||
*
|
||||
* @param array $expected
|
||||
* Expected values, keyed by user ID, expected cache contexts as values.
|
||||
*/
|
||||
protected function assertUserCacheContext(array $expected) {
|
||||
foreach ($expected as $uid => $context) {
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests NodeAccessGrantsCacheContext::getContext().
|
||||
*/
|
||||
public function testCacheContext() {
|
||||
$this->assertUserCacheContext([
|
||||
0 => 'view.all:0;node_access_test_author:0;node_access_all:0',
|
||||
1 => 'all',
|
||||
2 => 'view.all:0;node_access_test_author:2;node_access_test:8888,8889',
|
||||
3 => 'view.all:0;node_access_test_author:3',
|
||||
]);
|
||||
|
||||
// Grant view to all nodes (because nid = 0) for users in the
|
||||
// 'node_access_all' realm.
|
||||
$record = array(
|
||||
'nid' => 0,
|
||||
'gid' => 0,
|
||||
'realm' => 'node_access_all',
|
||||
'grant_view' => 1,
|
||||
'grant_update' => 0,
|
||||
'grant_delete' => 0,
|
||||
);
|
||||
db_insert('node_access')->fields($record)->execute();
|
||||
|
||||
// Put user accessUser (uid 0) in the realm.
|
||||
\Drupal::state()->set('node_access_test.no_access_uid', 0);
|
||||
drupal_static_reset('node_access_view_all_nodes');
|
||||
$this->assertUserCacheContext([
|
||||
0 => 'view.all',
|
||||
1 => 'all',
|
||||
2 => 'view.all:0;node_access_test_author:2;node_access_test:8888,8889',
|
||||
3 => 'view.all:0;node_access_test_author:3',
|
||||
]);
|
||||
|
||||
// Put user accessUser (uid 2) in the realm.
|
||||
\Drupal::state()->set('node_access_test.no_access_uid', $this->accessUser->id());
|
||||
drupal_static_reset('node_access_view_all_nodes');
|
||||
$this->assertUserCacheContext([
|
||||
0 => 'view.all:0;node_access_test_author:0',
|
||||
1 => 'all',
|
||||
2 => 'view.all',
|
||||
3 => 'view.all:0;node_access_test_author:3',
|
||||
]);
|
||||
|
||||
// Put user noAccessUser (uid 3) in the realm.
|
||||
\Drupal::state()->set('node_access_test.no_access_uid', $this->noAccessUser->id());
|
||||
drupal_static_reset('node_access_view_all_nodes');
|
||||
$this->assertUserCacheContext([
|
||||
0 => 'view.all:0;node_access_test_author:0',
|
||||
1 => 'all',
|
||||
2 => 'view.all:0;node_access_test_author:2;node_access_test:8888,8889',
|
||||
3 => 'view.all',
|
||||
]);
|
||||
|
||||
// Uninstall the node_access_test module
|
||||
$this->container->get('module_installer')->uninstall(['node_access_test']);
|
||||
drupal_static_reset('node_access_view_all_nodes');
|
||||
$this->assertUserCacheContext([
|
||||
0 => 'view.all',
|
||||
1 => 'all',
|
||||
2 => 'view.all',
|
||||
3 => 'view.all',
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
29
core/modules/node/src/Tests/NodeAccessGrantsTest.php
Normal file
29
core/modules/node/src/Tests/NodeAccessGrantsTest.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeAccessGrantsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Tests basic node_access functionality with hook_node_grants().
|
||||
*
|
||||
* This test just wraps the existing default permissions test while a module
|
||||
* that implements hook_node_grants() is enabled.
|
||||
*
|
||||
* @see \Drupal\node\NodeGrantDatabaseStorage
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeAccessGrantsTest extends NodeAccessTest {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node_access_test_empty');
|
||||
|
||||
}
|
|
@ -0,0 +1,351 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeAccessLanguageAwareCombinationTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* Tests node access functionality with multiple languages and two node access
|
||||
* modules.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeAccessLanguageAwareCombinationTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Enable language and two node access modules.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('language', 'node_access_test_language', 'node_access_test');
|
||||
|
||||
/**
|
||||
* A set of nodes to use in testing.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $nodes = array();
|
||||
|
||||
/**
|
||||
* A normal authenticated user.
|
||||
*
|
||||
* @var \Drupal\user\Entity\UserInterface.
|
||||
*/
|
||||
protected $webUser;
|
||||
|
||||
/**
|
||||
* User 1.
|
||||
*
|
||||
* @var \Drupal\user\Entity\UserInterface.
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
node_access_test_add_field(NodeType::load('page'));
|
||||
|
||||
// Create the 'private' field, which allows the node to be marked as private
|
||||
// (restricted access) in a given translation.
|
||||
$field_storage = entity_create('field_storage_config', array(
|
||||
'field_name' => 'field_private',
|
||||
'entity_type' => 'node',
|
||||
'type' => 'boolean',
|
||||
'cardinality' => 1,
|
||||
));
|
||||
$field_storage->save();
|
||||
|
||||
entity_create('field_config', array(
|
||||
'field_storage' => $field_storage,
|
||||
'bundle' => 'page',
|
||||
'widget' => array(
|
||||
'type' => 'options_buttons',
|
||||
),
|
||||
'settings' => array(
|
||||
'on_label' => 'Private',
|
||||
'off_label' => 'Not private',
|
||||
),
|
||||
))->save();
|
||||
|
||||
// After enabling a node access module, the access table has to be rebuild.
|
||||
node_access_rebuild();
|
||||
|
||||
// Add Hungarian and Catalan.
|
||||
ConfigurableLanguage::createFromLangcode('hu')->save();
|
||||
ConfigurableLanguage::createFromLangcode('ca')->save();
|
||||
|
||||
// Create a normal authenticated user.
|
||||
$this->webUser = $this->drupalCreateUser(array('access content'));
|
||||
|
||||
// Load the user 1 user for later use as an admin user with permission to
|
||||
// see everything.
|
||||
$this->adminUser = User::load(1);
|
||||
|
||||
// The node_access_test_language module allows individual translations of a
|
||||
// node to be marked private (not viewable by normal users), and the
|
||||
// node_access_test module allows whole nodes to be marked private. (In a
|
||||
// real-world implementation, hook_node_access_records_alter() might be
|
||||
// implemented by one or both modules to enforce that private nodes or
|
||||
// translations are always private, but we want to test the default,
|
||||
// additive behavior of node access).
|
||||
|
||||
// Create six Hungarian nodes with Catalan translations:
|
||||
// 1. One public with neither language marked as private.
|
||||
// 2. One private with neither language marked as private.
|
||||
// 3. One public with only the Hungarian translation private.
|
||||
// 4. One public with only the Catalan translation private.
|
||||
// 5. One public with both the Hungarian and Catalan translations private.
|
||||
// 6. One private with both the Hungarian and Catalan translations private.
|
||||
$this->nodes['public_both_public'] = $node = $this->drupalCreateNode(array(
|
||||
'body' => array(array()),
|
||||
'langcode' => 'hu',
|
||||
'field_private' => array(array('value' => 0)),
|
||||
'private' => FALSE,
|
||||
));
|
||||
$translation = $node->getTranslation('ca');
|
||||
$translation->field_private->value = 0;
|
||||
$node->save();
|
||||
|
||||
$this->nodes['private_both_public'] = $node = $this->drupalCreateNode(array(
|
||||
'body' => array(array()),
|
||||
'langcode' => 'hu',
|
||||
'field_private' => array(array('value' => 0)),
|
||||
'private' => TRUE,
|
||||
));
|
||||
$translation = $node->getTranslation('ca');
|
||||
$translation->field_private->value = 0;
|
||||
$node->save();
|
||||
|
||||
$this->nodes['public_hu_private'] = $node = $this->drupalCreateNode(array(
|
||||
'body' => array(array()),
|
||||
'langcode' => 'hu',
|
||||
'field_private' => array(array('value' => 1)),
|
||||
'private' => FALSE,
|
||||
));
|
||||
$translation = $node->getTranslation('ca');
|
||||
$translation->field_private->value = 0;
|
||||
$node->save();
|
||||
|
||||
$this->nodes['public_ca_private'] = $node = $this->drupalCreateNode(array(
|
||||
'body' => array(array()),
|
||||
'langcode' => 'hu',
|
||||
'field_private' => array(array('value' => 0)),
|
||||
'private' => FALSE,
|
||||
));
|
||||
$translation = $node->getTranslation('ca');
|
||||
$translation->field_private->value = 1;
|
||||
$node->save();
|
||||
|
||||
$this->nodes['public_both_private'] = $node = $this->drupalCreateNode(array(
|
||||
'body' => array(array()),
|
||||
'langcode' => 'hu',
|
||||
'field_private' => array(array('value' => 1)),
|
||||
'private' => FALSE,
|
||||
));
|
||||
$translation = $node->getTranslation('ca');
|
||||
$translation->field_private->value = 1;
|
||||
$node->save();
|
||||
|
||||
$this->nodes['private_both_private'] = $node = $this->drupalCreateNode(array(
|
||||
'body' => array(array()),
|
||||
'langcode' => 'hu',
|
||||
'field_private' => array(array('value' => 1)),
|
||||
'private' => TRUE,
|
||||
));
|
||||
$translation = $node->getTranslation('ca');
|
||||
$translation->field_private->value = 1;
|
||||
$node->save();
|
||||
|
||||
$this->nodes['public_no_language_private'] = $this->drupalCreateNode(array(
|
||||
'field_private' => array(array('value' => 1)),
|
||||
'private' => FALSE,
|
||||
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
||||
));
|
||||
$this->nodes['public_no_language_public'] = $this->drupalCreateNode(array(
|
||||
'field_private' => array(array('value' => 0)),
|
||||
'private' => FALSE,
|
||||
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
||||
));
|
||||
$this->nodes['private_no_language_private'] = $this->drupalCreateNode(array(
|
||||
'field_private' => array(array('value' => 1)),
|
||||
'private' => TRUE,
|
||||
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
||||
));
|
||||
$this->nodes['private_no_language_public'] = $this->drupalCreateNode(array(
|
||||
'field_private' => array(array('value' => 1)),
|
||||
'private' => TRUE,
|
||||
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests node access and node access queries with multiple node languages.
|
||||
*/
|
||||
function testNodeAccessLanguageAwareCombination() {
|
||||
|
||||
$expected_node_access = array('view' => TRUE, 'update' => FALSE, 'delete' => FALSE);
|
||||
$expected_node_access_no_access = array('view' => FALSE, 'update' => FALSE, 'delete' => FALSE);
|
||||
|
||||
// When the node and both translations are public, access should only be
|
||||
// denied when a translation that does not exist is requested.
|
||||
$this->assertNodeAccess($expected_node_access, $this->nodes['public_both_public'], $this->webUser);
|
||||
$this->assertNodeAccess($expected_node_access, $this->nodes['public_both_public'], $this->webUser, 'hu');
|
||||
$this->assertNodeAccess($expected_node_access, $this->nodes['public_both_public'], $this->webUser, 'ca');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_both_public'], $this->webUser, 'en');
|
||||
|
||||
// If the node is marked private but both existing translations are not,
|
||||
// access should still be granted, because the grants are additive.
|
||||
$this->assertNodeAccess($expected_node_access, $this->nodes['private_both_public'], $this->webUser);
|
||||
$this->assertNodeAccess($expected_node_access, $this->nodes['private_both_public'], $this->webUser, 'hu');
|
||||
$this->assertNodeAccess($expected_node_access, $this->nodes['private_both_public'], $this->webUser, 'ca');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_both_public'], $this->webUser, 'en');
|
||||
|
||||
// If the node is marked private, but a existing translation is public,
|
||||
// access should only be granted for the public translation. For a
|
||||
// translation that does not exist yet (English translation), the access is
|
||||
// denied. With the Hungarian translation marked as private, but the Catalan
|
||||
// translation public, the access is granted.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_hu_private'], $this->webUser);
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_hu_private'], $this->webUser, 'hu');
|
||||
$this->assertNodeAccess($expected_node_access, $this->nodes['public_hu_private'], $this->webUser, 'ca');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_hu_private'], $this->webUser, 'en');
|
||||
|
||||
// With the Catalan translation marked as private, but the node public,
|
||||
// access is granted for the existing Hungarian translation, but not for the
|
||||
// Catalan nor the English ones.
|
||||
$this->assertNodeAccess($expected_node_access, $this->nodes['public_ca_private'], $this->webUser);
|
||||
$this->assertNodeAccess($expected_node_access, $this->nodes['public_ca_private'], $this->webUser, 'hu');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_ca_private'], $this->webUser, 'ca');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_ca_private'], $this->webUser, 'en');
|
||||
|
||||
// With both translations marked as private, but the node public, access
|
||||
// should be denied in all cases.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_both_private'], $this->webUser);
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_both_private'], $this->webUser, 'hu');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_both_private'], $this->webUser, 'ca');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_both_private'], $this->webUser, 'en');
|
||||
|
||||
// If the node and both its existing translations are private, access should
|
||||
// be denied in all cases.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_both_private'], $this->webUser);
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_both_private'], $this->webUser, 'hu');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_both_private'], $this->webUser, 'ca');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_both_private'], $this->webUser, 'en');
|
||||
|
||||
// No access for all languages as the language aware node access module
|
||||
// denies access.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_no_language_private'], $this->webUser);
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_no_language_private'], $this->webUser, 'hu');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_no_language_private'], $this->webUser, 'ca');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_no_language_private'], $this->webUser, 'en');
|
||||
|
||||
// Access only for request with no language defined.
|
||||
$this->assertNodeAccess($expected_node_access, $this->nodes['public_no_language_public'], $this->webUser);
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_no_language_public'], $this->webUser, 'hu');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_no_language_public'], $this->webUser, 'ca');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['public_no_language_public'], $this->webUser, 'en');
|
||||
|
||||
// No access for all languages as both node access modules deny access.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_no_language_private'], $this->webUser);
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_no_language_private'], $this->webUser, 'hu');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_no_language_private'], $this->webUser, 'ca');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_no_language_private'], $this->webUser, 'en');
|
||||
|
||||
// No access for all languages as the non language aware node access module
|
||||
// denies access.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_no_language_public'], $this->webUser);
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_no_language_public'], $this->webUser, 'hu');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_no_language_public'], $this->webUser, 'ca');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['private_no_language_public'], $this->webUser, 'en');
|
||||
|
||||
|
||||
// Query the node table with the node access tag in several languages.
|
||||
|
||||
// Query with no language specified. The fallback (hu or und) will be used.
|
||||
$select = db_select('node', 'n')
|
||||
->fields('n', array('nid'))
|
||||
->addMetaData('account', $this->webUser)
|
||||
->addTag('node_access');
|
||||
$nids = $select->execute()->fetchAllAssoc('nid');
|
||||
|
||||
// Four nodes should be returned with public Hungarian translations or the
|
||||
// no language public node.
|
||||
$this->assertEqual(count($nids), 4, 'db_select() returns 4 nodes when no langcode is specified.');
|
||||
$this->assertTrue(array_key_exists($this->nodes['public_both_public']->id(), $nids), 'Returned node ID is full public node.');
|
||||
$this->assertTrue(array_key_exists($this->nodes['public_ca_private']->id(), $nids), 'Returned node ID is Hungarian public only node.');
|
||||
$this->assertTrue(array_key_exists($this->nodes['private_both_public']->id(), $nids), 'Returned node ID is both public non-language-aware private only node.');
|
||||
$this->assertTrue(array_key_exists($this->nodes['public_no_language_public']->id(), $nids), 'Returned node ID is no language public node.');
|
||||
|
||||
// Query with Hungarian (hu) specified.
|
||||
$select = db_select('node', 'n')
|
||||
->fields('n', array('nid'))
|
||||
->addMetaData('account', $this->webUser)
|
||||
->addMetaData('langcode', 'hu')
|
||||
->addTag('node_access');
|
||||
$nids = $select->execute()->fetchAllAssoc('nid');
|
||||
|
||||
// Three nodes should be returned (with public Hungarian translations).
|
||||
$this->assertEqual(count($nids), 3, 'db_select() returns 3 nodes.');
|
||||
$this->assertTrue(array_key_exists($this->nodes['public_both_public']->id(), $nids), 'Returned node ID is both public node.');
|
||||
$this->assertTrue(array_key_exists($this->nodes['public_ca_private']->id(), $nids), 'Returned node ID is Hungarian public only node.');
|
||||
$this->assertTrue(array_key_exists($this->nodes['private_both_public']->id(), $nids), 'Returned node ID is both public non-language-aware private only node.');
|
||||
|
||||
// Query with Catalan (ca) specified.
|
||||
$select = db_select('node', 'n')
|
||||
->fields('n', array('nid'))
|
||||
->addMetaData('account', $this->webUser)
|
||||
->addMetaData('langcode', 'ca')
|
||||
->addTag('node_access');
|
||||
$nids = $select->execute()->fetchAllAssoc('nid');
|
||||
|
||||
// Three nodes should be returned (with public Catalan translations).
|
||||
$this->assertEqual(count($nids), 3, 'db_select() returns 3 nodes.');
|
||||
$this->assertTrue(array_key_exists($this->nodes['public_both_public']->id(), $nids), 'Returned node ID is both public node.');
|
||||
$this->assertTrue(array_key_exists($this->nodes['public_hu_private']->id(), $nids), 'Returned node ID is Catalan public only node.');
|
||||
$this->assertTrue(array_key_exists($this->nodes['private_both_public']->id(), $nids), 'Returned node ID is both public non-language-aware private only node.');
|
||||
|
||||
// Query with German (de) specified.
|
||||
$select = db_select('node', 'n')
|
||||
->fields('n', array('nid'))
|
||||
->addMetaData('account', $this->webUser)
|
||||
->addMetaData('langcode', 'de')
|
||||
->addTag('node_access');
|
||||
$nids = $select->execute()->fetchAllAssoc('nid');
|
||||
|
||||
// There are no nodes with German translations, so no results are returned.
|
||||
$this->assertTrue(empty($nids), 'db_select() returns an empty result.');
|
||||
|
||||
// Query the nodes table as admin user (full access) with the node access
|
||||
// tag and no specific langcode.
|
||||
$select = db_select('node', 'n')
|
||||
->fields('n', array('nid'))
|
||||
->addMetaData('account', $this->adminUser)
|
||||
->addTag('node_access');
|
||||
$nids = $select->execute()->fetchAllAssoc('nid');
|
||||
|
||||
// All nodes are returned.
|
||||
$this->assertEqual(count($nids), 10, 'db_select() returns all nodes.');
|
||||
|
||||
// Query the nodes table as admin user (full access) with the node access
|
||||
// tag and langcode de.
|
||||
$select = db_select('node', 'n')
|
||||
->fields('n', array('nid'))
|
||||
->addMetaData('account', $this->adminUser)
|
||||
->addMetaData('langcode', 'de')
|
||||
->addTag('node_access');
|
||||
$nids = $select->execute()->fetchAllAssoc('nid');
|
||||
|
||||
// Even though there is no German translation, all nodes are returned
|
||||
// because node access filtering does not occur when the user is user 1.
|
||||
$this->assertEqual(count($nids), 10, 'db_select() returns all nodes.');
|
||||
}
|
||||
|
||||
}
|
293
core/modules/node/src/Tests/NodeAccessLanguageAwareTest.php
Normal file
293
core/modules/node/src/Tests/NodeAccessLanguageAwareTest.php
Normal file
|
@ -0,0 +1,293 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeAccessLanguageAwareTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* Tests node_access and db_select() with node_access tag functionality with
|
||||
* multiple languages with node_access_test_language which is language-aware.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeAccessLanguageAwareTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Enable language and a language-aware node access module.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('language', 'node_access_test_language');
|
||||
|
||||
/**
|
||||
* A set of nodes to use in testing.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $nodes = array();
|
||||
|
||||
/**
|
||||
* A user with permission to bypass access content.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
/**
|
||||
* A normal authenticated user.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $webUser;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create the 'private' field, which allows the node to be marked as private
|
||||
// (restricted access) in a given translation.
|
||||
$field_storage = entity_create('field_storage_config', array(
|
||||
'field_name' => 'field_private',
|
||||
'entity_type' => 'node',
|
||||
'type' => 'boolean',
|
||||
'cardinality' => 1,
|
||||
));
|
||||
$field_storage->save();
|
||||
|
||||
entity_create('field_config', array(
|
||||
'field_storage' => $field_storage,
|
||||
'bundle' => 'page',
|
||||
'widget' => array(
|
||||
'type' => 'options_buttons',
|
||||
),
|
||||
'settings' => array(
|
||||
'on_label' => 'Private',
|
||||
'off_label' => 'Not private',
|
||||
),
|
||||
))->save();
|
||||
|
||||
// After enabling a node access module, the access table has to be rebuild.
|
||||
node_access_rebuild();
|
||||
|
||||
// Create a normal authenticated user.
|
||||
$this->webUser = $this->drupalCreateUser(array('access content'));
|
||||
|
||||
// Load the user 1 user for later use as an admin user with permission to
|
||||
// see everything.
|
||||
$this->adminUser = User::load(1);
|
||||
|
||||
// Add Hungarian and Catalan.
|
||||
ConfigurableLanguage::createFromLangcode('hu')->save();
|
||||
ConfigurableLanguage::createFromLangcode('ca')->save();
|
||||
|
||||
// The node_access_test_language module allows individual translations of a
|
||||
// node to be marked private (not viewable by normal users).
|
||||
|
||||
// Create six nodes:
|
||||
// 1. Four Hungarian nodes with Catalan translations
|
||||
// - One with neither language marked as private.
|
||||
// - One with only the Hungarian translation private.
|
||||
// - One with only the Catalan translation private.
|
||||
// - One with both the Hungarian and Catalan translations private.
|
||||
// 2. Two nodes with no language specified.
|
||||
// - One public.
|
||||
// - One private.
|
||||
$this->nodes['both_public'] = $node = $this->drupalCreateNode(array(
|
||||
'body' => array(array()),
|
||||
'langcode' => 'hu',
|
||||
'field_private' => array(array('value' => 0)),
|
||||
));
|
||||
$translation = $node->getTranslation('ca');
|
||||
$translation->field_private->value = 0;
|
||||
$node->save();
|
||||
|
||||
$this->nodes['ca_private'] = $node = $this->drupalCreateNode(array(
|
||||
'body' => array(array()),
|
||||
'langcode' => 'hu',
|
||||
'field_private' => array(array('value' => 0)),
|
||||
));
|
||||
$translation = $node->getTranslation('ca');
|
||||
$translation->field_private->value = 1;
|
||||
$node->save();
|
||||
|
||||
$this->nodes['hu_private'] = $node = $this->drupalCreateNode(array(
|
||||
'body' => array(array()),
|
||||
'langcode' => 'hu',
|
||||
'field_private' => array(array('value' => 1)),
|
||||
));
|
||||
$translation = $node->getTranslation('ca');
|
||||
$translation->field_private->value = 0;
|
||||
$node->save();
|
||||
|
||||
$this->nodes['both_private'] = $node = $this->drupalCreateNode(array(
|
||||
'body' => array(array()),
|
||||
'langcode' => 'hu',
|
||||
'field_private' => array(array('value' => 1)),
|
||||
));
|
||||
$translation = $node->getTranslation('ca');
|
||||
$translation->field_private->value = 1;
|
||||
$node->save();
|
||||
|
||||
$this->nodes['no_language_public'] = $this->drupalCreateNode(array(
|
||||
'field_private' => array(array('value' => 0)),
|
||||
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
||||
));
|
||||
$this->nodes['no_language_private'] = $this->drupalCreateNode(array(
|
||||
'field_private' => array(array('value' => 1)),
|
||||
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests node access and node access queries with multiple node languages.
|
||||
*/
|
||||
function testNodeAccessLanguageAware() {
|
||||
// The node_access_test_language module only grants view access.
|
||||
$expected_node_access = array('view' => TRUE, 'update' => FALSE, 'delete' => FALSE);
|
||||
$expected_node_access_no_access = array('view' => FALSE, 'update' => FALSE, 'delete' => FALSE);
|
||||
|
||||
// When both Hungarian and Catalan are marked as public, access to the
|
||||
// Hungarian translation should be granted when no language is specified or
|
||||
// when the Hungarian translation is specified explicitly.
|
||||
$this->assertNodeAccess($expected_node_access, $this->nodes['both_public'], $this->webUser);
|
||||
$this->assertNodeAccess($expected_node_access, $this->nodes['both_public'], $this->webUser, 'hu');
|
||||
// Access to the Catalan translation should also be granted.
|
||||
$this->assertNodeAccess($expected_node_access, $this->nodes['both_public'], $this->webUser, 'ca');
|
||||
// There is no English translation, so a request to access the English
|
||||
// translation is denied.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['both_public'], $this->webUser, 'en');
|
||||
|
||||
// When Hungarian is marked as private, access to the Hungarian translation
|
||||
// should be denied when no language is specified or when the Hungarian
|
||||
// translation is specified explicitly.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['hu_private'], $this->webUser);
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['hu_private'], $this->webUser, 'hu');
|
||||
// Access to the Catalan translation should be granted.
|
||||
$this->assertNodeAccess($expected_node_access, $this->nodes['hu_private'], $this->webUser, 'ca');
|
||||
// There is no English translation, so a request to access the English
|
||||
// translation is denied.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['hu_private'], $this->webUser, 'en');
|
||||
|
||||
// When Catalan is marked as private, access to the Hungarian translation
|
||||
// should be granted when no language is specified or when the Hungarian
|
||||
// translation is specified explicitly.
|
||||
$this->assertNodeAccess($expected_node_access, $this->nodes['ca_private'], $this->webUser);
|
||||
$this->assertNodeAccess($expected_node_access, $this->nodes['ca_private'], $this->webUser, 'hu');
|
||||
// Access to the Catalan translation should be granted.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['ca_private'], $this->webUser, 'ca');
|
||||
// There is no English translation, so a request to access the English
|
||||
// translation is denied.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['ca_private'], $this->webUser, 'en');
|
||||
|
||||
// When both translations are marked as private, access should be denied
|
||||
// regardless of the language specified.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['both_private'], $this->webUser);
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['both_private'], $this->webUser, 'hu');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['both_private'], $this->webUser, 'ca');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['both_private'], $this->webUser, 'en');
|
||||
|
||||
// When no language is specified for a private node, access to every
|
||||
// language is denied.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['no_language_private'], $this->webUser);
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['no_language_private'], $this->webUser, 'hu');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['no_language_private'], $this->webUser, 'ca');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['no_language_private'], $this->webUser, 'en');
|
||||
|
||||
// When no language is specified for a public node, access should be granted
|
||||
// only for the existing language (not specified), so only the request with
|
||||
// no language will give access, as this request will be made with the
|
||||
// langcode of the node, which is "not specified".
|
||||
$this->assertNodeAccess($expected_node_access, $this->nodes['no_language_public'], $this->webUser);
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['no_language_public'], $this->webUser, 'hu');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['no_language_public'], $this->webUser, 'ca');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $this->nodes['no_language_public'], $this->webUser, 'en');
|
||||
|
||||
// Query the node table with the node access tag in several languages.
|
||||
|
||||
// Query with no language specified. The fallback (hu) will be used.
|
||||
$select = db_select('node', 'n')
|
||||
->fields('n', array('nid'))
|
||||
->addMetaData('account', $this->webUser)
|
||||
->addTag('node_access');
|
||||
$nids = $select->execute()->fetchAllAssoc('nid');
|
||||
|
||||
// Three nodes should be returned:
|
||||
// - Node with both translations public.
|
||||
// - Node with only the Catalan translation marked as private.
|
||||
// - No language node marked as public.
|
||||
$this->assertEqual(count($nids), 3, 'db_select() returns 3 nodes when no langcode is specified.');
|
||||
$this->assertTrue(array_key_exists($this->nodes['both_public']->id(), $nids), 'The node with both translations public is returned.');
|
||||
$this->assertTrue(array_key_exists($this->nodes['ca_private']->id(), $nids), 'The node with only the Catalan translation private is returned.');
|
||||
$this->assertTrue(array_key_exists($this->nodes['no_language_public']->id(), $nids), 'The node with no language is returned.');
|
||||
|
||||
// Query with Hungarian (hu) specified.
|
||||
$select = db_select('node', 'n')
|
||||
->fields('n', array('nid'))
|
||||
->addMetaData('account', $this->webUser)
|
||||
->addMetaData('langcode', 'hu')
|
||||
->addTag('node_access');
|
||||
$nids = $select->execute()->fetchAllAssoc('nid');
|
||||
|
||||
// Two nodes should be returned: the node with both translations public, and
|
||||
// the node with only the Catalan translation marked as private.
|
||||
$this->assertEqual(count($nids), 2, 'db_select() returns 2 nodes when the hu langcode is specified.');
|
||||
$this->assertTrue(array_key_exists($this->nodes['both_public']->id(), $nids), 'The node with both translations public is returned.');
|
||||
$this->assertTrue(array_key_exists($this->nodes['ca_private']->id(), $nids), 'The node with only the Catalan translation private is returned.');
|
||||
|
||||
// Query with Catalan (ca) specified.
|
||||
$select = db_select('node', 'n')
|
||||
->fields('n', array('nid'))
|
||||
->addMetaData('account', $this->webUser)
|
||||
->addMetaData('langcode', 'ca')
|
||||
->addTag('node_access');
|
||||
$nids = $select->execute()->fetchAllAssoc('nid');
|
||||
|
||||
// Two nodes should be returned: the node with both translations public, and
|
||||
// the node with only the Hungarian translation marked as private.
|
||||
$this->assertEqual(count($nids), 2, 'db_select() returns 2 nodes when the hu langcode is specified.');
|
||||
$this->assertTrue(array_key_exists($this->nodes['both_public']->id(), $nids), 'The node with both translations public is returned.');
|
||||
$this->assertTrue(array_key_exists($this->nodes['hu_private']->id(), $nids), 'The node with only the Hungarian translation private is returned.');
|
||||
|
||||
// Query with German (de) specified.
|
||||
$select = db_select('node', 'n')
|
||||
->fields('n', array('nid'))
|
||||
->addMetaData('account', $this->webUser)
|
||||
->addMetaData('langcode', 'de')
|
||||
->addTag('node_access');
|
||||
$nids = $select->execute()->fetchAllAssoc('nid');
|
||||
|
||||
// There are no nodes with German translations, so no results are returned.
|
||||
$this->assertTrue(empty($nids), 'db_select() returns an empty result when the de langcode is specified.');
|
||||
|
||||
// Query the nodes table as admin user (full access) with the node access
|
||||
// tag and no specific langcode.
|
||||
$select = db_select('node', 'n')
|
||||
->fields('n', array('nid'))
|
||||
->addMetaData('account', $this->adminUser)
|
||||
->addTag('node_access');
|
||||
$nids = $select->execute()->fetchAllAssoc('nid');
|
||||
|
||||
// All nodes are returned.
|
||||
$this->assertEqual(count($nids), 6, 'db_select() returns all nodes.');
|
||||
|
||||
// Query the nodes table as admin user (full access) with the node access
|
||||
// tag and langcode de.
|
||||
$select = db_select('node', 'n')
|
||||
->fields('n', array('nid'))
|
||||
->addMetaData('account', $this->adminUser)
|
||||
->addMetaData('langcode', 'de')
|
||||
->addTag('node_access');
|
||||
$nids = $select->execute()->fetchAllAssoc('nid');
|
||||
|
||||
// Even though there is no German translation, all nodes are returned
|
||||
// because node access filtering does not occur when the user is user 1.
|
||||
$this->assertEqual(count($nids), 6, 'db_select() returns all nodes.');
|
||||
}
|
||||
|
||||
}
|
301
core/modules/node/src/Tests/NodeAccessLanguageTest.php
Normal file
301
core/modules/node/src/Tests/NodeAccessLanguageTest.php
Normal file
|
@ -0,0 +1,301 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeAccessLanguageTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* Tests node_access and db_select() with node_access tag functionality with
|
||||
* multiple languages with a test node access module that is not language-aware.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeAccessLanguageTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('language', 'node_access_test');
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
node_access_test_add_field(NodeType::load('page'));
|
||||
|
||||
// After enabling a node access module, the access table has to be rebuild.
|
||||
node_access_rebuild();
|
||||
|
||||
// Enable the private node feature of the node_access_test module.
|
||||
\Drupal::state()->set('node_access_test.private', TRUE);
|
||||
|
||||
// Add Hungarian, Catalan and Croatian.
|
||||
ConfigurableLanguage::createFromLangcode('hu')->save();
|
||||
ConfigurableLanguage::createFromLangcode('ca')->save();
|
||||
ConfigurableLanguage::createFromLangcode('hr')->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests node access with multiple node languages and no private nodes.
|
||||
*/
|
||||
function testNodeAccess() {
|
||||
$web_user = $this->drupalCreateUser(array('access content'));
|
||||
|
||||
$expected_node_access = array('view' => TRUE, 'update' => FALSE, 'delete' => FALSE);
|
||||
$expected_node_access_no_access = array('view' => FALSE, 'update' => FALSE, 'delete' => FALSE);
|
||||
|
||||
// Creating a public node with langcode Hungarian, will be saved as the
|
||||
// fallback in node access table.
|
||||
$node_public_hu = $this->drupalCreateNode(array('body' => array(array()), 'langcode' => 'hu', 'private' => FALSE));
|
||||
$this->assertTrue($node_public_hu->language()->getId() == 'hu', 'Node created as Hungarian.');
|
||||
|
||||
// Tests the default access is provided for the public Hungarian node.
|
||||
$this->assertNodeAccess($expected_node_access, $node_public_hu, $web_user);
|
||||
|
||||
// Tests that Hungarian provided specifically results in the same.
|
||||
$this->assertNodeAccess($expected_node_access, $node_public_hu, $web_user, 'hu');
|
||||
|
||||
// There is no specific Catalan version of this node and Croatian is not
|
||||
// even set up on the system in this scenario, so the user will not get
|
||||
// access to these nodes.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_public_hu, $web_user, 'ca');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_public_hu, $web_user, 'hr');
|
||||
|
||||
// Creating a public node with no special langcode, like when no language
|
||||
// module enabled.
|
||||
$node_public_no_language = $this->drupalCreateNode(array(
|
||||
'private' => FALSE,
|
||||
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
||||
));
|
||||
$this->assertTrue($node_public_no_language->language()->getId() == LanguageInterface::LANGCODE_NOT_SPECIFIED, 'Node created with not specified language.');
|
||||
|
||||
// Tests that access is granted if requested with no language.
|
||||
$this->assertNodeAccess($expected_node_access, $node_public_no_language, $web_user);
|
||||
|
||||
// Tests that access is not granted if requested with Hungarian language.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_public_no_language, $web_user, 'hu');
|
||||
|
||||
// There is no specific Catalan version of this node and Croatian is not
|
||||
// even set up on the system in this scenario, so the user will not get
|
||||
// access to these nodes.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_public_no_language, $web_user, 'ca');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_public_no_language, $web_user, 'hr');
|
||||
|
||||
// Reset the node access cache and turn on our test node access code.
|
||||
\Drupal::entityManager()->getAccessControlHandler('node')->resetCache();
|
||||
\Drupal::state()->set('node_access_test_secret_catalan', 1);
|
||||
$node_public_ca = $this->drupalCreateNode(array('body' => array(array()), 'langcode' => 'ca', 'private' => FALSE));
|
||||
$this->assertTrue($node_public_ca->language()->getId() == 'ca', 'Node created as Catalan.');
|
||||
|
||||
// Tests that access is granted if requested with no language.
|
||||
$this->assertNodeAccess($expected_node_access, $node_public_no_language, $web_user);
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_public_ca, $web_user);
|
||||
|
||||
// Tests that Hungarian is still not accessible.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_public_no_language, $web_user, 'hu');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_public_ca, $web_user, 'hu');
|
||||
|
||||
// Tests that Hungarian node is still accessible.
|
||||
$this->assertNodeAccess($expected_node_access, $node_public_hu, $web_user, 'hu');
|
||||
|
||||
// Tests that Catalan is still not accessible.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_public_no_language, $web_user, 'ca');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_public_ca, $web_user, 'ca');
|
||||
|
||||
// Make Catalan accessible.
|
||||
\Drupal::state()->set('node_access_test_secret_catalan', 0);
|
||||
|
||||
// Tests that Catalan is accessible on a node with a Catalan version as the
|
||||
// static cache has not been reset.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_public_ca, $web_user, 'ca');
|
||||
|
||||
\Drupal::entityManager()->getAccessControlHandler('node')->resetCache();
|
||||
|
||||
// Tests that access is granted if requested with no language.
|
||||
$this->assertNodeAccess($expected_node_access, $node_public_no_language, $web_user);
|
||||
$this->assertNodeAccess($expected_node_access, $node_public_ca, $web_user);
|
||||
|
||||
// Tests that Hungarian is still not accessible.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_public_no_language, $web_user, 'hu');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_public_ca, $web_user, 'hu');
|
||||
|
||||
// Tests that Hungarian node is still accessible.
|
||||
$this->assertNodeAccess($expected_node_access, $node_public_hu, $web_user, 'hu');
|
||||
|
||||
// Tests that Catalan is still not accessible on a node without a language.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_public_no_language, $web_user, 'ca');
|
||||
|
||||
// Tests that Catalan is accessible on a node with a Catalan version.
|
||||
$this->assertNodeAccess($expected_node_access, $node_public_ca, $web_user, 'ca');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests node access with multiple node languages and private nodes.
|
||||
*/
|
||||
function testNodeAccessPrivate() {
|
||||
$web_user = $this->drupalCreateUser(array('access content'));
|
||||
$expected_node_access = array('view' => TRUE, 'update' => FALSE, 'delete' => FALSE);
|
||||
$expected_node_access_no_access = array('view' => FALSE, 'update' => FALSE, 'delete' => FALSE);
|
||||
|
||||
// Creating a private node with langcode Hungarian, will be saved as the
|
||||
// fallback in node access table.
|
||||
$node_private_hu = $this->drupalCreateNode(array('body' => array(array()), 'langcode' => 'hu', 'private' => TRUE));
|
||||
$this->assertTrue($node_private_hu->language()->getId() == 'hu', 'Node created as Hungarian.');
|
||||
|
||||
// Tests the default access is not provided for the private Hungarian node.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_private_hu, $web_user);
|
||||
|
||||
// Tests that Hungarian provided specifically results in the same.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_private_hu, $web_user, 'hu');
|
||||
|
||||
// There is no specific Catalan version of this node and Croatian is not
|
||||
// even set up on the system in this scenario, so the user will not get
|
||||
// access to these nodes.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_private_hu, $web_user, 'ca');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_private_hu, $web_user, 'hr');
|
||||
|
||||
// Creating a private node with no special langcode, like when no language
|
||||
// module enabled.
|
||||
$node_private_no_language = $this->drupalCreateNode(array(
|
||||
'private' => TRUE,
|
||||
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
||||
));
|
||||
$this->assertTrue($node_private_no_language->language()->getId() == LanguageInterface::LANGCODE_NOT_SPECIFIED, 'Node created with not specified language.');
|
||||
|
||||
// Tests that access is not granted if requested with no language.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_private_no_language, $web_user);
|
||||
|
||||
// Tests that access is not granted if requested with Hungarian language.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_private_no_language, $web_user, 'hu');
|
||||
|
||||
// There is no specific Catalan version of this node and Croatian is not
|
||||
// even set up on the system in this scenario, so the user will not get
|
||||
// access to these nodes.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_private_no_language, $web_user, 'ca');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_private_no_language, $web_user, 'hr');
|
||||
|
||||
// Reset the node access cache and turn on our test node access code.
|
||||
\Drupal::entityManager()->getAccessControlHandler('node')->resetCache();
|
||||
\Drupal::state()->set('node_access_test_secret_catalan', 1);
|
||||
|
||||
// Tests that access is not granted if requested with no language.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_private_no_language, $web_user);
|
||||
|
||||
// Tests that Hungarian is still not accessible.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_private_no_language, $web_user, 'hu');
|
||||
|
||||
// Tests that Catalan is still not accessible.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_private_no_language, $web_user, 'ca');
|
||||
|
||||
// Creating a private node with langcode Catalan to test that the
|
||||
// node_access_test_secret_catalan flag works.
|
||||
$private_ca_user = $this->drupalCreateUser(array('access content', 'node test view'));
|
||||
$node_private_ca = $this->drupalCreateNode(array('body' => array(array()), 'langcode' => 'ca', 'private' => TRUE));
|
||||
$this->assertTrue($node_private_ca->language()->getId() == 'ca', 'Node created as Catalan.');
|
||||
|
||||
// Tests that Catalan is still not accessible to either user.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_private_ca, $web_user, 'ca');
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_private_ca, $private_ca_user, 'ca');
|
||||
|
||||
\Drupal::entityManager()->getAccessControlHandler('node')->resetCache();
|
||||
\Drupal::state()->set('node_access_test_secret_catalan', 0);
|
||||
|
||||
// Tests that Catalan is still not accessible for a user with no access to
|
||||
// private nodes.
|
||||
$this->assertNodeAccess($expected_node_access_no_access, $node_private_ca, $web_user, 'ca');
|
||||
|
||||
// Tests that Catalan is accessible by a user with the permission to see
|
||||
// private nodes.
|
||||
$this->assertNodeAccess($expected_node_access, $node_private_ca, $private_ca_user, 'ca');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests db_select() with a 'node_access' tag and langcode metadata.
|
||||
*/
|
||||
function testNodeAccessQueryTag() {
|
||||
// Create a normal authenticated user.
|
||||
$web_user = $this->drupalCreateUser(array('access content'));
|
||||
|
||||
// Load the user 1 user for later use as an admin user with permission to
|
||||
// see everything.
|
||||
$admin_user = User::load(1);
|
||||
|
||||
// Creating a private node with langcode Hungarian, will be saved as
|
||||
// the fallback in node access table.
|
||||
$node_private = $this->drupalCreateNode(array('body' => array(array()), 'langcode' => 'hu', 'private' => TRUE));
|
||||
$this->assertTrue($node_private->language()->getId() == 'hu', 'Node created as Hungarian.');
|
||||
|
||||
// Creating a public node with langcode Hungarian, will be saved as
|
||||
// the fallback in node access table.
|
||||
$node_public = $this->drupalCreateNode(array('body' => array(array()), 'langcode' => 'hu', 'private' => FALSE));
|
||||
$this->assertTrue($node_public->language()->getId() == 'hu', 'Node created as Hungarian.');
|
||||
|
||||
// Creating a public node with no special langcode, like when no language
|
||||
// module enabled.
|
||||
$node_no_language = $this->drupalCreateNode(array(
|
||||
'private' => FALSE,
|
||||
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
||||
));
|
||||
$this->assertTrue($node_no_language->language()->getId() == LanguageInterface::LANGCODE_NOT_SPECIFIED, 'Node created with not specified language.');
|
||||
|
||||
// Query the nodes table as the web user with the node access tag and no
|
||||
// specific langcode.
|
||||
$select = db_select('node', 'n')
|
||||
->fields('n', array('nid'))
|
||||
->addMetaData('account', $web_user)
|
||||
->addTag('node_access');
|
||||
$nids = $select->execute()->fetchAllAssoc('nid');
|
||||
|
||||
// The public node and no language node should be returned. Because no
|
||||
// langcode is given it will use the fallback node.
|
||||
$this->assertEqual(count($nids), 2, 'db_select() returns 2 node');
|
||||
$this->assertTrue(array_key_exists($node_public->id(), $nids), 'Returned node ID is public node.');
|
||||
$this->assertTrue(array_key_exists($node_no_language->id(), $nids), 'Returned node ID is no language node.');
|
||||
|
||||
// Query the nodes table as the web user with the node access tag and
|
||||
// langcode de.
|
||||
$select = db_select('node', 'n')
|
||||
->fields('n', array('nid'))
|
||||
->addMetaData('account', $web_user)
|
||||
->addMetaData('langcode', 'de')
|
||||
->addTag('node_access');
|
||||
$nids = $select->execute()->fetchAllAssoc('nid');
|
||||
|
||||
// Because no nodes are created in German, no nodes are returned.
|
||||
$this->assertTrue(empty($nids), 'db_select() returns an empty result.');
|
||||
|
||||
// Query the nodes table as admin user (full access) with the node access
|
||||
// tag and no specific langcode.
|
||||
$select = db_select('node', 'n')
|
||||
->fields('n', array('nid'))
|
||||
->addMetaData('account', $admin_user)
|
||||
->addTag('node_access');
|
||||
$nids = $select->execute()->fetchAllAssoc('nid');
|
||||
|
||||
// All nodes are returned.
|
||||
$this->assertEqual(count($nids), 3, 'db_select() returns all three nodes.');
|
||||
|
||||
// Query the nodes table as admin user (full access) with the node access
|
||||
// tag and langcode de.
|
||||
$select = db_select('node', 'n')
|
||||
->fields('n', array('nid'))
|
||||
->addMetaData('account', $admin_user)
|
||||
->addMetaData('langcode', 'de')
|
||||
->addTag('node_access');
|
||||
$nids = $select->execute()->fetchAllAssoc('nid');
|
||||
|
||||
// All nodes are returned because node access tag is not invoked when the
|
||||
// user is user 1.
|
||||
$this->assertEqual(count($nids), 3, 'db_select() returns all three nodes.');
|
||||
}
|
||||
|
||||
}
|
103
core/modules/node/src/Tests/NodeAccessPagerTest.php
Normal file
103
core/modules/node/src/Tests/NodeAccessPagerTest.php
Normal file
|
@ -0,0 +1,103 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeAccessPagerTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\comment\CommentInterface;
|
||||
use Drupal\comment\Tests\CommentTestTrait;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests access controlled node views have the right amount of comment pages.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeAccessPagerTest extends WebTestBase {
|
||||
|
||||
use CommentTestTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node_access_test', 'comment', 'forum');
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
node_access_rebuild();
|
||||
$this->drupalCreateContentType(array('type' => 'page', 'name' => t('Basic page')));
|
||||
$this->addDefaultCommentField('node', 'page');
|
||||
$this->webUser = $this->drupalCreateUser(array('access content', 'access comments', 'node test view'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the comment pager for nodes with multiple grants per realm.
|
||||
*/
|
||||
public function testCommentPager() {
|
||||
// Create a node.
|
||||
$node = $this->drupalCreateNode();
|
||||
|
||||
// Create 60 comments.
|
||||
for ($i = 0; $i < 60; $i++) {
|
||||
$comment = entity_create('comment', array(
|
||||
'entity_id' => $node->id(),
|
||||
'entity_type' => 'node',
|
||||
'field_name' => 'comment',
|
||||
'subject' => $this->randomMachineName(),
|
||||
'comment_body' => array(
|
||||
array('value' => $this->randomMachineName()),
|
||||
),
|
||||
'status' => CommentInterface::PUBLISHED,
|
||||
));
|
||||
$comment->save();
|
||||
}
|
||||
|
||||
$this->drupalLogin($this->webUser);
|
||||
|
||||
// View the node page. With the default 50 comments per page there should
|
||||
// be two pages (0, 1) but no third (2) page.
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$this->assertText($node->label());
|
||||
$this->assertText(t('Comments'));
|
||||
$this->assertRaw('page=1');
|
||||
$this->assertNoRaw('page=2');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the forum node pager for nodes with multiple grants per realm.
|
||||
*/
|
||||
public function testForumPager() {
|
||||
// Look up the forums vocabulary ID.
|
||||
$vid = $this->config('forum.settings')->get('vocabulary');
|
||||
$this->assertTrue($vid, 'Forum navigation vocabulary ID is set.');
|
||||
|
||||
// Look up the general discussion term.
|
||||
$tree = \Drupal::entityManager()->getStorage('taxonomy_term')->loadTree($vid, 0, 1);
|
||||
$tid = reset($tree)->tid;
|
||||
$this->assertTrue($tid, 'General discussion term is found in the forum vocabulary.');
|
||||
|
||||
// Create 30 nodes.
|
||||
for ($i = 0; $i < 30; $i++) {
|
||||
$this->drupalCreateNode(array(
|
||||
'nid' => NULL,
|
||||
'type' => 'forum',
|
||||
'taxonomy_forums' => array(
|
||||
array('target_id' => $tid),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
// View the general discussion forum page. With the default 25 nodes per
|
||||
// page there should be two pages for 30 nodes, no more.
|
||||
$this->drupalLogin($this->webUser);
|
||||
$this->drupalGet('forum/' . $tid);
|
||||
$this->assertRaw('page=1');
|
||||
$this->assertNoRaw('page=2');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeAccessRebuildNodeGrantsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Ensures that node access rebuild functions work correctly even
|
||||
* when other modules implements hook_node_grants().
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeAccessRebuildNodeGrantsTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* A user to test the rebuild nodes feature.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $webUser;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$admin_user = $this->drupalCreateUser(array('administer site configuration', 'access administration pages', 'access site reports', 'bypass node access'));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
$this->webUser = $this->drupalCreateUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests rebuilding the node access permissions table with content.
|
||||
*/
|
||||
public function testNodeAccessRebuildNodeGrants() {
|
||||
\Drupal::service('module_installer')->install(['node_access_test']);
|
||||
$this->resetAll();
|
||||
|
||||
$node = $this->drupalCreateNode(array(
|
||||
'uid' => $this->webUser->id(),
|
||||
));
|
||||
|
||||
// Default realm access and node records are present.
|
||||
$this->assertTrue(\Drupal::service('node.grant_storage')->access($node, 'view', 'en', $this->webUser), 'The expected node access records are present');
|
||||
$this->assertEqual(1, \Drupal::service('node.grant_storage')->checkAll($this->webUser), 'There is an all realm access record');
|
||||
$this->assertTrue(\Drupal::state()->get('node.node_access_needs_rebuild'), 'Node access permissions need to be rebuilt');
|
||||
|
||||
// Rebuild permissions.
|
||||
$this->drupalGet('admin/reports/status/rebuild');
|
||||
$this->drupalPostForm(NULL, array(), t('Rebuild permissions'));
|
||||
$this->assertText(t('The content access permissions have been rebuilt.'));
|
||||
|
||||
// Test if the rebuild has been successful.
|
||||
$this->assertNull(\Drupal::state()->get('node.node_access_needs_rebuild'), 'Node access permissions have been rebuilt');
|
||||
$this->assertTrue(\Drupal::service('node.grant_storage')->access($node, 'view', 'en', $this->webUser), 'The expected node access records are present');
|
||||
$this->assertFalse(\Drupal::service('node.grant_storage')->checkAll($this->webUser), 'There is no all realm access record');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests rebuilding the node access permissions table with no content.
|
||||
*/
|
||||
public function testNodeAccessRebuildNoAccessModules() {
|
||||
// Default realm access is present.
|
||||
$this->assertEqual(1, \Drupal::service('node.grant_storage')->count(), 'There is an all realm access record');
|
||||
|
||||
// No need to rebuild permissions.
|
||||
$this->assertFalse(\Drupal::state()->get('node.node_access_needs_rebuild'), 'Node access permissions need to be rebuilt');
|
||||
|
||||
// Rebuild permissions.
|
||||
$this->drupalGet('admin/reports/status');
|
||||
$this->clickLink(t('Rebuild permissions'));
|
||||
$this->drupalPostForm(NULL, array(), t('Rebuild permissions'));
|
||||
$this->assertText(t('Content permissions have been rebuilt.'));
|
||||
$this->assertNull(\Drupal::state()->get('node.node_access_needs_rebuild'), 'Node access permissions have been rebuilt');
|
||||
|
||||
// Default realm access is still present.
|
||||
$this->assertEqual(1, \Drupal::service('node.grant_storage')->count(), 'There is an all realm access record');
|
||||
}
|
||||
|
||||
}
|
40
core/modules/node/src/Tests/NodeAccessRebuildTest.php
Normal file
40
core/modules/node/src/Tests/NodeAccessRebuildTest.php
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeAccessRebuildTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Ensures that node access rebuild functions work correctly.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeAccessRebuildTest extends NodeTestBase {
|
||||
/**
|
||||
* A normal authenticated user.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $webUser;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$web_user = $this->drupalCreateUser(array('administer site configuration', 'access administration pages', 'access site reports'));
|
||||
$this->drupalLogin($web_user);
|
||||
$this->webUser = $web_user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests rebuilding the node access permissions table.
|
||||
*/
|
||||
function testNodeAccessRebuild() {
|
||||
$this->drupalGet('admin/reports/status');
|
||||
$this->clickLink(t('Rebuild permissions'));
|
||||
$this->drupalPostForm(NULL, array(), t('Rebuild permissions'));
|
||||
$this->assertText(t('Content permissions have been rebuilt.'));
|
||||
}
|
||||
}
|
88
core/modules/node/src/Tests/NodeAccessRecordsTest.php
Normal file
88
core/modules/node/src/Tests/NodeAccessRecordsTest.php
Normal file
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeAccessRecordsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\node\Entity\Node;
|
||||
|
||||
/**
|
||||
* Tests hook_node_access_records when acquiring grants.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeAccessRecordsTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Enable a module that implements node access API hooks and alter hook.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node_test');
|
||||
|
||||
/**
|
||||
* Creates a node and tests the creation of node access rules.
|
||||
*/
|
||||
function testNodeAccessRecords() {
|
||||
// Create an article node.
|
||||
$node1 = $this->drupalCreateNode(array('type' => 'article'));
|
||||
$this->assertTrue(Node::load($node1->id()), 'Article node created.');
|
||||
|
||||
// Check to see if grants added by node_test_node_access_records made it in.
|
||||
$records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node1->id()))->fetchAll();
|
||||
$this->assertEqual(count($records), 1, '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.');
|
||||
|
||||
// Create an unpromoted "Basic page" node.
|
||||
$node2 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 0));
|
||||
$this->assertTrue(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 = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node2->id()))->fetchAll();
|
||||
$this->assertEqual(count($records), 1, '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.');
|
||||
|
||||
// Create an unpromoted, unpublished "Basic page" node.
|
||||
$node3 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 0, 'status' => 0));
|
||||
$this->assertTrue(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 = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node3->id()))->fetchAll();
|
||||
$this->assertEqual(count($records), 1, '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.');
|
||||
|
||||
// Create a promoted "Basic page" node.
|
||||
$node4 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 1));
|
||||
$this->assertTrue(Node::load($node4->id()), 'Promoted basic page node created.');
|
||||
|
||||
// Check to see if grant added by node_test_node_access_records was altered
|
||||
// by node_test_node_access_records_alter.
|
||||
$records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node4->id()))->fetchAll();
|
||||
$this->assertEqual(count($records), 1, '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.');
|
||||
|
||||
// Check to see if we can alter grants with hook_node_grants_alter().
|
||||
$operations = array('view', 'update', 'delete');
|
||||
// Create a user that is allowed to access content.
|
||||
$web_user = $this->drupalCreateUser(array('access content'));
|
||||
foreach ($operations as $op) {
|
||||
$grants = node_test_node_grants($web_user, $op);
|
||||
$altered_grants = $grants;
|
||||
\Drupal::moduleHandler()->alter('node_grants', $altered_grants, $web_user, $op);
|
||||
$this->assertNotEqual($grants, $altered_grants, format_string('Altered the %op grant for a user.', array('%op' => $op)));
|
||||
}
|
||||
|
||||
// Check that core does not grant access to an unpublished node when an
|
||||
// empty $grants array is returned.
|
||||
$node6 = $this->drupalCreateNode(array('status' => 0, 'disable_node_access' => TRUE));
|
||||
$records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node6->id()))->fetchAll();
|
||||
$this->assertEqual(count($records), 0, 'Returned no records for unpublished node.');
|
||||
}
|
||||
}
|
77
core/modules/node/src/Tests/NodeAccessTest.php
Normal file
77
core/modules/node/src/Tests/NodeAccessTest.php
Normal file
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeAccessTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\user\RoleInterface;
|
||||
|
||||
/**
|
||||
* Tests basic node_access functionality.
|
||||
*
|
||||
* Note that hook_node_access_records() is covered in another test class.
|
||||
*
|
||||
* @group node
|
||||
* @todo Cover hook_node_access in a separate test class.
|
||||
*/
|
||||
class NodeAccessTest extends NodeTestBase {
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
// Clear permissions for authenticated users.
|
||||
$this->config('user.role.' . RoleInterface::AUTHENTICATED_ID)->set('permissions', array())->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs basic tests for node_access function.
|
||||
*/
|
||||
function testNodeAccess() {
|
||||
// Ensures user without 'access content' permission can do nothing.
|
||||
$web_user1 = $this->drupalCreateUser(array('create page content', 'edit any page content', 'delete any page content'));
|
||||
$node1 = $this->drupalCreateNode(array('type' => 'page'));
|
||||
$this->assertNodeCreateAccess($node1->bundle(), FALSE, $web_user1);
|
||||
$this->assertNodeAccess(array('view' => FALSE, 'update' => FALSE, 'delete' => FALSE), $node1, $web_user1);
|
||||
|
||||
// Ensures user with 'bypass node access' permission can do everything.
|
||||
$web_user2 = $this->drupalCreateUser(array('bypass node access'));
|
||||
$node2 = $this->drupalCreateNode(array('type' => 'page'));
|
||||
$this->assertNodeCreateAccess($node2->bundle(), TRUE, $web_user2);
|
||||
$this->assertNodeAccess(array('view' => TRUE, 'update' => TRUE, 'delete' => TRUE), $node2, $web_user2);
|
||||
|
||||
// User cannot 'view own unpublished content'.
|
||||
$web_user3 = $this->drupalCreateUser(array('access content'));
|
||||
$node3 = $this->drupalCreateNode(array('status' => 0, 'uid' => $web_user3->id()));
|
||||
$this->assertNodeAccess(array('view' => FALSE), $node3, $web_user3);
|
||||
|
||||
// User cannot create content without permission.
|
||||
$this->assertNodeCreateAccess($node3->bundle(), FALSE, $web_user3);
|
||||
|
||||
// User can 'view own unpublished content', but another user cannot.
|
||||
$web_user4 = $this->drupalCreateUser(array('access content', 'view own unpublished content'));
|
||||
$web_user5 = $this->drupalCreateUser(array('access content', 'view own unpublished content'));
|
||||
$node4 = $this->drupalCreateNode(array('status' => 0, 'uid' => $web_user4->id()));
|
||||
$this->assertNodeAccess(array('view' => TRUE, 'update' => FALSE), $node4, $web_user4);
|
||||
$this->assertNodeAccess(array('view' => FALSE), $node4, $web_user5);
|
||||
|
||||
// Tests the default access provided for a published node.
|
||||
$node5 = $this->drupalCreateNode();
|
||||
$this->assertNodeAccess(array('view' => TRUE, 'update' => FALSE, 'delete' => FALSE), $node5, $web_user3);
|
||||
|
||||
// Tests the "edit any BUNDLE" and "delete any BUNDLE" permissions.
|
||||
$web_user6 = $this->drupalCreateUser(array('access content', 'edit any page content', 'delete any page content'));
|
||||
$node6 = $this->drupalCreateNode(array('type' => 'page'));
|
||||
$this->assertNodeAccess(array('view' => TRUE, 'update' => TRUE, 'delete' => TRUE), $node6, $web_user6);
|
||||
|
||||
// Tests the "edit own BUNDLE" and "delete own BUNDLE" permission.
|
||||
$web_user7 = $this->drupalCreateUser(array('access content', 'edit own page content', 'delete own page content'));
|
||||
// User should not be able to edit or delete nodes they do not own.
|
||||
$this->assertNodeAccess(array('view' => TRUE, 'update' => FALSE, 'delete' => FALSE), $node6, $web_user7);
|
||||
|
||||
// User should be able to edit or delete nodes they own.
|
||||
$node7 = $this->drupalCreateNode(array('type' => 'page', 'uid' => $web_user7->id()));
|
||||
$this->assertNodeAccess(array('view' => TRUE, 'update' => TRUE, 'delete' => TRUE), $node7, $web_user7);
|
||||
}
|
||||
|
||||
}
|
198
core/modules/node/src/Tests/NodeAdminTest.php
Normal file
198
core/modules/node/src/Tests/NodeAdminTest.php
Normal file
|
@ -0,0 +1,198 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeAdminTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\user\RoleInterface;
|
||||
|
||||
/**
|
||||
* Tests node administration page functionality.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeAdminTest extends NodeTestBase {
|
||||
/**
|
||||
* A user with permission to bypass access content.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
/**
|
||||
* A user with the 'access content overview' permission.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $baseUser1;
|
||||
|
||||
/**
|
||||
* A normal user with permission to view own unpublished content.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $baseUser2;
|
||||
|
||||
/**
|
||||
* A normal user with permission to bypass node access content.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $baseUser3;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('views');
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Remove the "view own unpublished content" permission which is set
|
||||
// by default for authenticated users so we can test this permission
|
||||
// correctly.
|
||||
user_role_revoke_permissions(RoleInterface::AUTHENTICATED_ID, array('view own unpublished content'));
|
||||
|
||||
$this->adminUser = $this->drupalCreateUser(array('access administration pages', 'access content overview', 'administer nodes', 'bypass node access'));
|
||||
$this->baseUser1 = $this->drupalCreateUser(['access content overview']);
|
||||
$this->baseUser2 = $this->drupalCreateUser(['access content overview', 'view own unpublished content']);
|
||||
$this->baseUser3 = $this->drupalCreateUser(['access content overview', 'bypass node access']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the table sorting works on the content admin pages.
|
||||
*/
|
||||
function testContentAdminSort() {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
$changed = REQUEST_TIME;
|
||||
foreach (array('dd', 'aa', 'DD', 'bb', 'cc', 'CC', 'AA', 'BB') as $prefix) {
|
||||
$changed += 1000;
|
||||
$node = $this->drupalCreateNode(array('title' => $prefix . $this->randomMachineName(6)));
|
||||
db_update('node_field_data')
|
||||
->fields(array('changed' => $changed))
|
||||
->condition('nid', $node->id())
|
||||
->execute();
|
||||
}
|
||||
|
||||
// Test that the default sort by node.changed DESC actually fires properly.
|
||||
$nodes_query = db_select('node_field_data', 'n')
|
||||
->fields('n', array('title'))
|
||||
->orderBy('changed', 'DESC')
|
||||
->execute()
|
||||
->fetchCol();
|
||||
|
||||
$this->drupalGet('admin/content');
|
||||
foreach ($nodes_query as $delta => $string) {
|
||||
$elements = $this->xpath('//table[contains(@class, :class)]/tbody/tr[' . ($delta + 1) . ']/td[2]/a[normalize-space(text())=:label]', array(':class' => 'views-table', ':label' => $string));
|
||||
$this->assertTrue(!empty($elements), 'The node was found in the correct order.');
|
||||
}
|
||||
|
||||
// Compare the rendered HTML node list to a query for the nodes ordered by
|
||||
// title to account for possible database-dependent sort order.
|
||||
$nodes_query = db_select('node_field_data', 'n')
|
||||
->fields('n', array('title'))
|
||||
->orderBy('title')
|
||||
->execute()
|
||||
->fetchCol();
|
||||
|
||||
$this->drupalGet('admin/content', array('query' => array('sort' => 'asc', 'order' => 'title')));
|
||||
foreach ($nodes_query as $delta => $string) {
|
||||
$elements = $this->xpath('//table[contains(@class, :class)]/tbody/tr[' . ($delta + 1) . ']/td[2]/a[normalize-space(text())=:label]', array(':class' => 'views-table', ':label' => $string));
|
||||
$this->assertTrue(!empty($elements), 'The node was found in the correct order.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests content overview with different user permissions.
|
||||
*
|
||||
* Taxonomy filters are tested separately.
|
||||
*
|
||||
* @see TaxonomyNodeFilterTestCase
|
||||
*/
|
||||
function testContentAdminPages() {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
$nodes['published_page'] = $this->drupalCreateNode(array('type' => 'page'));
|
||||
$nodes['published_article'] = $this->drupalCreateNode(array('type' => 'article'));
|
||||
$nodes['unpublished_page_1'] = $this->drupalCreateNode(array('type' => 'page', 'uid' => $this->baseUser1->id(), 'status' => 0));
|
||||
$nodes['unpublished_page_2'] = $this->drupalCreateNode(array('type' => 'page', 'uid' => $this->baseUser2->id(), 'status' => 0));
|
||||
|
||||
// Verify view, edit, and delete links for any content.
|
||||
$this->drupalGet('admin/content');
|
||||
$this->assertResponse(200);
|
||||
foreach ($nodes as $node) {
|
||||
$this->assertLinkByHref('node/' . $node->id());
|
||||
$this->assertLinkByHref('node/' . $node->id() . '/edit');
|
||||
$this->assertLinkByHref('node/' . $node->id() . '/delete');
|
||||
}
|
||||
|
||||
// Verify filtering by publishing status.
|
||||
$this->drupalGet('admin/content', array('query' => array('status' => TRUE)));
|
||||
|
||||
$this->assertLinkByHref('node/' . $nodes['published_page']->id() . '/edit');
|
||||
$this->assertLinkByHref('node/' . $nodes['published_article']->id() . '/edit');
|
||||
$this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->id() . '/edit');
|
||||
|
||||
// Verify filtering by status and content type.
|
||||
$this->drupalGet('admin/content', array('query' => array('status' => TRUE, 'type' => 'page')));
|
||||
|
||||
$this->assertLinkByHref('node/' . $nodes['published_page']->id() . '/edit');
|
||||
$this->assertNoLinkByHref('node/' . $nodes['published_article']->id() . '/edit');
|
||||
|
||||
// Verify no operation links are displayed for regular users.
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->baseUser1);
|
||||
$this->drupalGet('admin/content');
|
||||
$this->assertResponse(200);
|
||||
$this->assertLinkByHref('node/' . $nodes['published_page']->id());
|
||||
$this->assertLinkByHref('node/' . $nodes['published_article']->id());
|
||||
$this->assertNoLinkByHref('node/' . $nodes['published_page']->id() . '/edit');
|
||||
$this->assertNoLinkByHref('node/' . $nodes['published_page']->id() . '/delete');
|
||||
$this->assertNoLinkByHref('node/' . $nodes['published_article']->id() . '/edit');
|
||||
$this->assertNoLinkByHref('node/' . $nodes['published_article']->id() . '/delete');
|
||||
|
||||
// Verify no unpublished content is displayed without permission.
|
||||
$this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->id());
|
||||
$this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->id() . '/edit');
|
||||
$this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->id() . '/delete');
|
||||
|
||||
// Verify no tableselect.
|
||||
$this->assertNoFieldByName('nodes[' . $nodes['published_page']->id() . ']', '', 'No tableselect found.');
|
||||
|
||||
// Verify unpublished content is displayed with permission.
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->baseUser2);
|
||||
$this->drupalGet('admin/content');
|
||||
$this->assertResponse(200);
|
||||
$this->assertLinkByHref('node/' . $nodes['unpublished_page_2']->id());
|
||||
// Verify no operation links are displayed.
|
||||
$this->assertNoLinkByHref('node/' . $nodes['unpublished_page_2']->id() . '/edit');
|
||||
$this->assertNoLinkByHref('node/' . $nodes['unpublished_page_2']->id() . '/delete');
|
||||
|
||||
// Verify user cannot see unpublished content of other users.
|
||||
$this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->id());
|
||||
$this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->id() . '/edit');
|
||||
$this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->id() . '/delete');
|
||||
|
||||
// Verify no tableselect.
|
||||
$this->assertNoFieldByName('nodes[' . $nodes['unpublished_page_2']->id() . ']', '', 'No tableselect found.');
|
||||
|
||||
// Verify node access can be bypassed.
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->baseUser3);
|
||||
$this->drupalGet('admin/content');
|
||||
$this->assertResponse(200);
|
||||
foreach ($nodes as $node) {
|
||||
$this->assertLinkByHref('node/' . $node->id());
|
||||
$this->assertLinkByHref('node/' . $node->id() . '/edit');
|
||||
$this->assertLinkByHref('node/' . $node->id() . '/delete');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
161
core/modules/node/src/Tests/NodeBlockFunctionalTest.php
Normal file
161
core/modules/node/src/Tests/NodeBlockFunctionalTest.php
Normal file
|
@ -0,0 +1,161 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeBlockFunctionalTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\block\Entity\Block;
|
||||
use Drupal\user\RoleInterface;
|
||||
|
||||
/**
|
||||
* Tests node block functionality.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeBlockFunctionalTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* An administrative user for testing.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
/**
|
||||
* An unprivileged user for testing.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $webUser;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('block', 'views');
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create users and test node.
|
||||
$this->adminUser = $this->drupalCreateUser(array('administer content types', 'administer nodes', 'administer blocks', 'access content overview'));
|
||||
$this->webUser = $this->drupalCreateUser(array('access content', 'create article content'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the recent comments block.
|
||||
*/
|
||||
public function testRecentNodeBlock() {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Disallow anonymous users to view content.
|
||||
user_role_change_permissions(RoleInterface::ANONYMOUS_ID, array(
|
||||
'access content' => FALSE,
|
||||
));
|
||||
|
||||
// Enable the recent content block with two items.
|
||||
$block = $this->drupalPlaceBlock('views_block:content_recent-block_1', array('id' => 'test_block', 'items_per_page' => 2));
|
||||
|
||||
// Test that block is not visible without nodes.
|
||||
$this->drupalGet('');
|
||||
$this->assertText(t('No content available.'), 'Block with "No content available." found.');
|
||||
|
||||
// Add some test nodes.
|
||||
$default_settings = array('uid' => $this->webUser->id(), 'type' => 'article');
|
||||
$node1 = $this->drupalCreateNode($default_settings);
|
||||
$node2 = $this->drupalCreateNode($default_settings);
|
||||
$node3 = $this->drupalCreateNode($default_settings);
|
||||
|
||||
// Change the changed time for node so that we can test ordering.
|
||||
db_update('node_field_data')
|
||||
->fields(array(
|
||||
'changed' => $node1->getChangedTime() + 100,
|
||||
))
|
||||
->condition('nid', $node2->id())
|
||||
->execute();
|
||||
db_update('node_field_data')
|
||||
->fields(array(
|
||||
'changed' => $node1->getChangedTime() + 200,
|
||||
))
|
||||
->condition('nid', $node3->id())
|
||||
->execute();
|
||||
|
||||
// Test that a user without the 'access content' permission cannot
|
||||
// see the block.
|
||||
$this->drupalLogout();
|
||||
$this->drupalGet('');
|
||||
$this->assertNoText($block->label(), 'Block was not found.');
|
||||
|
||||
// Test that only the 2 latest nodes are shown.
|
||||
$this->drupalLogin($this->webUser);
|
||||
$this->assertNoText($node1->label(), 'Node not found in block.');
|
||||
$this->assertText($node2->label(), 'Node found in block.');
|
||||
$this->assertText($node3->label(), 'Node found in block.');
|
||||
|
||||
// Check to make sure nodes are in the right order.
|
||||
$this->assertTrue($this->xpath('//div[@id="block-test-block"]//table/tbody/tr[position() = 1]/td/a[text() = "' . $node3->label() . '"]'), 'Nodes were ordered correctly in block.');
|
||||
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Verify that the More link is shown and leads to the admin content page.
|
||||
$this->drupalGet('');
|
||||
$this->clickLink('More');
|
||||
$this->assertResponse('200');
|
||||
$this->assertUrl('admin/content');
|
||||
|
||||
// Set the number of recent nodes to show to 10.
|
||||
$block->getPlugin()->setConfigurationValue('items_per_page', 10);
|
||||
$block->save();
|
||||
|
||||
// Post an additional node.
|
||||
$node4 = $this->drupalCreateNode($default_settings);
|
||||
|
||||
// Test that all four nodes are shown.
|
||||
$this->drupalGet('');
|
||||
$this->assertText($node1->label(), 'Node found in block.');
|
||||
$this->assertText($node2->label(), 'Node found in block.');
|
||||
$this->assertText($node3->label(), 'Node found in block.');
|
||||
$this->assertText($node4->label(), 'Node found in block.');
|
||||
|
||||
// Enable the "Powered by Drupal" block only on article nodes.
|
||||
$edit = [
|
||||
'id' => strtolower($this->randomMachineName()),
|
||||
'region' => 'sidebar_first',
|
||||
'visibility[node_type][bundles][article]' => 'article',
|
||||
];
|
||||
$theme = \Drupal::service('theme_handler')->getDefault();
|
||||
$this->drupalPostForm("admin/structure/block/add/system_powered_by_block/$theme", $edit, t('Save block'));
|
||||
|
||||
$block = Block::load($edit['id']);
|
||||
$visibility = $block->getVisibility();
|
||||
$this->assertTrue(isset($visibility['node_type']['bundles']['article']), 'Visibility settings were saved to configuration');
|
||||
|
||||
// Create a page node.
|
||||
$node5 = $this->drupalCreateNode(array('uid' => $this->adminUser->id(), 'type' => 'page'));
|
||||
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->webUser);
|
||||
|
||||
// Verify visibility rules.
|
||||
$this->drupalGet('');
|
||||
$label = $block->label();
|
||||
$this->assertNoText($label, 'Block was not displayed on the front page.');
|
||||
$this->drupalGet('node/add/article');
|
||||
$this->assertText($label, 'Block was displayed on the node/add/article page.');
|
||||
$this->drupalGet('node/' . $node1->id());
|
||||
$this->assertText($label, 'Block was displayed on the node/N when node is of type article.');
|
||||
$this->drupalGet('node/' . $node5->id());
|
||||
$this->assertNoText($label, 'Block was not displayed on nodes of type page.');
|
||||
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$this->assertText($label, 'Block was displayed on the admin/structure/block page.');
|
||||
$this->assertLinkByHref($block->url());
|
||||
}
|
||||
|
||||
}
|
63
core/modules/node/src/Tests/NodeBodyFieldStorageTest.php
Normal file
63
core/modules/node/src/Tests/NodeBodyFieldStorageTest.php
Normal file
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeBodyFieldStorageTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\Core\Field\Entity\BaseFieldOverride;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\simpletest\KernelTestBase;
|
||||
use Drupal\system\Tests\Entity\EntityUnitTestBase;
|
||||
|
||||
/**
|
||||
* Tests node body field storage.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeBodyFieldStorageTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('user', 'system', 'field', 'node', 'text', 'filter', 'entity_reference');
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installSchema('system', 'sequences');
|
||||
$this->installSchema('system', array('router'));
|
||||
// Necessary for module uninstall.
|
||||
$this->installSchema('user', 'users_data');
|
||||
$this->installEntitySchema('user');
|
||||
$this->installEntitySchema('node');
|
||||
$this->installConfig(array('field', 'node'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests node body field storage persistence even if there are no instances.
|
||||
*/
|
||||
public function testFieldOverrides() {
|
||||
$field_storage = FieldStorageConfig::loadByName('node', 'body');
|
||||
$this->assertTrue($field_storage, 'Node body field storage exists.');
|
||||
$type = NodeType::create(['name' => 'Ponies', 'type' => 'ponies']);
|
||||
$type->save();
|
||||
node_add_body_field($type);
|
||||
$field_storage = FieldStorageConfig::loadByName('node', 'body');
|
||||
$this->assertTrue(count($field_storage->getBundles()) == 1, 'Node body field storage is being used on the new node type.');
|
||||
$field = FieldConfig::loadByName('node', 'ponies', 'body');
|
||||
$field->delete();
|
||||
$field_storage = FieldStorageConfig::loadByName('node', 'body');
|
||||
$this->assertTrue(count($field_storage->getBundles()) == 0, 'Node body field storage exists after deleting the only instance of a field.');
|
||||
\Drupal::service('module_installer')->uninstall(array('node'));
|
||||
$field_storage = FieldStorageConfig::loadByName('node', 'body');
|
||||
$this->assertFalse($field_storage, 'Node body field storage does not exist after uninstalling the Node module.');
|
||||
}
|
||||
|
||||
}
|
68
core/modules/node/src/Tests/NodeCacheTagsTest.php
Normal file
68
core/modules/node/src/Tests/NodeCacheTagsTest.php
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeCacheTagsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\system\Tests\Entity\EntityWithUriCacheTagsTestBase;
|
||||
use Drupal\user\Entity\Role;
|
||||
|
||||
/**
|
||||
* Tests the Node entity's cache tags.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeCacheTagsTest extends EntityWithUriCacheTagsTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = array('node');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
// Create a "Camelids" node type.
|
||||
entity_create('node_type', array(
|
||||
'name' => 'Camelids',
|
||||
'type' => 'camelids',
|
||||
))->save();
|
||||
|
||||
// Create a "Llama" node.
|
||||
$node = entity_create('node', array('type' => 'camelids'));
|
||||
$node->setTitle('Llama')
|
||||
->setPublished(TRUE)
|
||||
->save();
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getAdditionalCacheContextsForEntity(EntityInterface $entity) {
|
||||
return ['timezone'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Each node must have an author.
|
||||
*/
|
||||
protected function getAdditionalCacheTagsForEntity(EntityInterface $node) {
|
||||
return array('user:' . $node->getOwnerId(), 'user_view');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getAdditionalCacheContextsForEntityListing() {
|
||||
return ['user.node_grants:view'];
|
||||
}
|
||||
|
||||
}
|
224
core/modules/node/src/Tests/NodeCreationTest.php
Normal file
224
core/modules/node/src/Tests/NodeCreationTest.php
Normal file
|
@ -0,0 +1,224 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeCreationTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
|
||||
/**
|
||||
* Create a node and test saving it.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeCreationTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* Enable dummy module that implements hook_ENTITY_TYPE_insert() for
|
||||
* exceptions (function node_test_exception_node_insert() ).
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node_test_exception', 'dblog', 'test_page_test');
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$web_user = $this->drupalCreateUser(array('create page content', 'edit own page content'));
|
||||
$this->drupalLogin($web_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a "Basic page" node and verifies its consistency in the database.
|
||||
*/
|
||||
function testNodeCreation() {
|
||||
$node_type_storage = \Drupal::entityManager()->getStorage('node_type');
|
||||
|
||||
// Test /node/add page with only one content type.
|
||||
$node_type_storage->load('article')->delete();
|
||||
$this->drupalGet('node/add');
|
||||
$this->assertResponse(200);
|
||||
$this->assertUrl('node/add/page');
|
||||
// Create a node.
|
||||
$edit = array();
|
||||
$edit['title[0][value]'] = $this->randomMachineName(8);
|
||||
$edit['body[0][value]'] = $this->randomMachineName(16);
|
||||
$this->drupalPostForm('node/add/page', $edit, t('Save'));
|
||||
|
||||
// Check that the Basic page has been created.
|
||||
$this->assertRaw(t('!post %title has been created.', array('!post' => 'Basic page', '%title' => $edit['title[0][value]'])), 'Basic page created.');
|
||||
|
||||
// Check that the node exists in the database.
|
||||
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
|
||||
$this->assertTrue($node, 'Node found in database.');
|
||||
|
||||
// Verify that pages do not show submitted information by default.
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$this->assertNoText($node->getOwner()->getUsername());
|
||||
$this->assertNoText(format_date($node->getCreatedTime()));
|
||||
|
||||
// Change the node type setting to show submitted by information.
|
||||
/** @var \Drupal\node\NodeTypeInterface $node_type */
|
||||
$node_type = $node_type_storage->load('page');
|
||||
$node_type->setDisplaySubmitted(TRUE);
|
||||
$node_type->save();
|
||||
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$this->assertText($node->getOwner()->getUsername());
|
||||
$this->assertText(format_date($node->getCreatedTime()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that a transaction rolls back the failed creation.
|
||||
*/
|
||||
function testFailedPageCreation() {
|
||||
// Create a node.
|
||||
$edit = array(
|
||||
'uid' => $this->loggedInUser->id(),
|
||||
'name' => $this->loggedInUser->name,
|
||||
'type' => 'page',
|
||||
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
||||
'title' => 'testing_transaction_exception',
|
||||
);
|
||||
|
||||
try {
|
||||
// An exception is generated by node_test_exception_node_insert() if the
|
||||
// title is 'testing_transaction_exception'.
|
||||
entity_create('node', $edit)->save();
|
||||
$this->fail(t('Expected exception has not been thrown.'));
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
$this->pass(t('Expected exception has been thrown.'));
|
||||
}
|
||||
|
||||
if (Database::getConnection()->supportsTransactions()) {
|
||||
// Check that the node does not exist in the database.
|
||||
$node = $this->drupalGetNodeByTitle($edit['title']);
|
||||
$this->assertFalse($node, 'Transactions supported, and node not found in database.');
|
||||
}
|
||||
else {
|
||||
// Check that the node exists in the database.
|
||||
$node = $this->drupalGetNodeByTitle($edit['title']);
|
||||
$this->assertTrue($node, 'Transactions not supported, and node found in database.');
|
||||
|
||||
// Check that the failed rollback was logged.
|
||||
$records = static::getWatchdogIdsForFailedExplicitRollback();
|
||||
$this->assertTrue(count($records) > 0, 'Transactions not supported, and rollback error logged to watchdog.');
|
||||
}
|
||||
|
||||
// Check that the rollback error was logged.
|
||||
$records = static::getWatchdogIdsForTestExceptionRollback();
|
||||
$this->assertTrue(count($records) > 0, 'Rollback explanatory error logged to watchdog.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an unpublished node and confirms correct redirect behavior.
|
||||
*/
|
||||
function testUnpublishedNodeCreation() {
|
||||
// Set the front page to the test page.
|
||||
$this->config('system.site')->set('page.front', '/test-page')->save();
|
||||
|
||||
// Set "Basic page" content type to be unpublished by default.
|
||||
$fields = \Drupal::entityManager()->getFieldDefinitions('node', 'page');
|
||||
$fields['status']->getConfig('page')
|
||||
->setDefaultValue(FALSE)
|
||||
->save();
|
||||
|
||||
// Create a node.
|
||||
$edit = array();
|
||||
$edit['title[0][value]'] = $this->randomMachineName(8);
|
||||
$edit['body[0][value]'] = $this->randomMachineName(16);
|
||||
$this->drupalPostForm('node/add/page', $edit, t('Save'));
|
||||
|
||||
// Check that the user was redirected to the home page.
|
||||
$this->assertUrl('');
|
||||
$this->assertText(t('Test page text'));
|
||||
|
||||
// Confirm that the node was created.
|
||||
$this->assertRaw(t('!post %title has been created.', array('!post' => 'Basic page', '%title' => $edit['title[0][value]'])));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the author autocompletion textfield.
|
||||
*/
|
||||
public function testAuthorAutocomplete() {
|
||||
$admin_user = $this->drupalCreateUser(array('administer nodes', 'create page content'));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
$this->drupalGet('node/add/page');
|
||||
|
||||
$result = $this->xpath('//input[@id="edit-uid-0-value" and contains(@data-autocomplete-path, "user/autocomplete")]');
|
||||
$this->assertEqual(count($result), 0, 'No autocompletion without access user profiles.');
|
||||
|
||||
$admin_user = $this->drupalCreateUser(array('administer nodes', 'create page content', 'access user profiles'));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
$this->drupalGet('node/add/page');
|
||||
|
||||
$result = $this->xpath('//input[@id="edit-uid-0-target-id" and contains(@data-autocomplete-path, "/entity_reference_autocomplete/user/default")]');
|
||||
$this->assertEqual(count($result), 1, 'Ensure that the user does have access to the autocompletion');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check node/add when no node types exist.
|
||||
*/
|
||||
function testNodeAddWithoutContentTypes () {
|
||||
$this->drupalGet('node/add');
|
||||
$this->assertResponse(200);
|
||||
$this->assertNoLinkByHref('/admin/structure/types/add');
|
||||
|
||||
// Test /node/add page without content types.
|
||||
foreach (\Drupal::entityManager()->getStorage('node_type')->loadMultiple() as $entity ) {
|
||||
$entity->delete();
|
||||
}
|
||||
|
||||
$this->drupalGet('node/add');
|
||||
$this->assertResponse(403);
|
||||
|
||||
$admin_content_types = $this->drupalCreateUser(array('administer content types'));
|
||||
$this->drupalLogin($admin_content_types);
|
||||
|
||||
$this->drupalGet('node/add');
|
||||
|
||||
$this->assertLinkByHref('/admin/structure/types/add');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the watchdog IDs of the records with the rollback exception message.
|
||||
*
|
||||
* @return int[]
|
||||
* Array containing the IDs of the log records with the rollback exception
|
||||
* message.
|
||||
*/
|
||||
protected static function getWatchdogIdsForTestExceptionRollback() {
|
||||
// PostgreSQL doesn't support bytea LIKE queries, so we need to unserialize
|
||||
// first to check for the rollback exception message.
|
||||
$matches = array();
|
||||
$query = db_query("SELECT wid, variables FROM {watchdog}");
|
||||
foreach ($query as $row) {
|
||||
$variables = (array) unserialize($row->variables);
|
||||
if (isset($variables['!message']) && $variables['!message'] === 'Test exception for rollback.') {
|
||||
$matches[] = $row->wid;
|
||||
}
|
||||
}
|
||||
return $matches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the log records with the explicit rollback failed exception message.
|
||||
*
|
||||
* @return \Drupal\Core\Database\StatementInterface
|
||||
* A prepared statement object (already executed), which contains the log
|
||||
* records with the explicit rollback failed exception message.
|
||||
*/
|
||||
protected static function getWatchdogIdsForFailedExplicitRollback() {
|
||||
return db_query("SELECT wid FROM {watchdog} WHERE message LIKE 'Explicit rollback failed%'")->fetchAll();
|
||||
}
|
||||
|
||||
}
|
51
core/modules/node/src/Tests/NodeEntityViewModeAlterTest.php
Normal file
51
core/modules/node/src/Tests/NodeEntityViewModeAlterTest.php
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeEntityViewModeAlterTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Tests changing view modes for nodes.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeEntityViewModeAlterTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Enable dummy module that implements hook_ENTITY_TYPE_view() for nodes.
|
||||
*/
|
||||
public static $modules = array('node_test');
|
||||
|
||||
/**
|
||||
* Create a "Basic page" node and verify its consistency in the database.
|
||||
*/
|
||||
function testNodeViewModeChange() {
|
||||
$web_user = $this->drupalCreateUser(array('create page content', 'edit own page content'));
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
// Create a node.
|
||||
$edit = array();
|
||||
$edit['title[0][value]'] = $this->randomMachineName(8);
|
||||
$edit['body[0][value]'] = t('Data that should appear only in the body for the node.');
|
||||
$edit['body[0][summary]'] = t('Extra data that should appear only in the teaser for the node.');
|
||||
$this->drupalPostForm('node/add/page', $edit, t('Save'));
|
||||
|
||||
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
|
||||
|
||||
// Set the flag to alter the view mode and view the node.
|
||||
\Drupal::state()->set('node_test_change_view_mode', 'teaser');
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
|
||||
// Check that teaser mode is viewed.
|
||||
$this->assertText('Extra data that should appear only in the teaser for the node.', 'Teaser text present');
|
||||
// Make sure body text is not present.
|
||||
$this->assertNoText('Data that should appear only in the body for the node.', 'Body text not present');
|
||||
|
||||
// Test that the correct build mode has been set.
|
||||
$build = $this->drupalBuildEntityView($node);
|
||||
$this->assertEqual($build['#view_mode'], 'teaser', 'The view mode has correctly been set to teaser.');
|
||||
}
|
||||
}
|
153
core/modules/node/src/Tests/NodeFieldAccessTest.php
Normal file
153
core/modules/node/src/Tests/NodeFieldAccessTest.php
Normal file
|
@ -0,0 +1,153 @@
|
|||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeFieldAccessTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\system\Tests\Entity\EntityUnitTestBase;
|
||||
|
||||
/**
|
||||
* Tests node field level access.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeFieldAccessTest extends EntityUnitTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node');
|
||||
|
||||
/**
|
||||
* Fields that only users with administer nodes permissions can change.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $administrativeFields = array(
|
||||
'status',
|
||||
'promote',
|
||||
'sticky',
|
||||
'created',
|
||||
'uid',
|
||||
);
|
||||
|
||||
/**
|
||||
* These fields are automatically managed and can not be changed by any user.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $readOnlyFields = array('changed', 'revision_uid', 'revision_timestamp');
|
||||
|
||||
/**
|
||||
* Test permissions on nodes status field.
|
||||
*/
|
||||
function testAccessToAdministrativeFields() {
|
||||
|
||||
// Create the page node type with revisions disabled.
|
||||
$page = NodeType::create([
|
||||
'type' => 'page',
|
||||
'new_revision' => FALSE,
|
||||
]);
|
||||
$page->save();
|
||||
|
||||
// Create the article node type with revisions disabled.
|
||||
$article = NodeType::create([
|
||||
'type' => 'article',
|
||||
'new_revision' => TRUE,
|
||||
]);
|
||||
$article->save();
|
||||
|
||||
// An administrator user. No user exists yet, ensure that the first user
|
||||
// does not have UID 1.
|
||||
$content_admin_user = $this->createUser(array('uid' => 2), array('administer nodes'));
|
||||
|
||||
// Two different editor users.
|
||||
$page_creator_user = $this->createUser(array(), array('create page content', 'edit own page content', 'delete own page content'));
|
||||
$page_manager_user = $this->createUser(array(), array('create page content', 'edit any page content', 'delete any page content'));
|
||||
|
||||
// An unprivileged user.
|
||||
$page_unrelated_user = $this->createUser(array(), array('access content'));
|
||||
|
||||
// List of all users
|
||||
$test_users = array(
|
||||
$content_admin_user,
|
||||
$page_creator_user,
|
||||
$page_manager_user,
|
||||
$page_unrelated_user,
|
||||
);
|
||||
|
||||
// Create three "Basic pages". One is owned by our test-user
|
||||
// "page_creator", one by "page_manager", and one by someone else.
|
||||
$node1 = Node::create(array(
|
||||
'title' => $this->randomMachineName(8),
|
||||
'uid' => $page_creator_user->id(),
|
||||
'type' => 'page',
|
||||
));
|
||||
$node2 = Node::create(array(
|
||||
'title' => $this->randomMachineName(8),
|
||||
'uid' => $page_manager_user->id(),
|
||||
'type' => 'article',
|
||||
));
|
||||
$node3 = Node::create(array(
|
||||
'title' => $this->randomMachineName(8),
|
||||
'type' => 'page',
|
||||
));
|
||||
|
||||
foreach ($this->administrativeFields as $field) {
|
||||
|
||||
// Checks on view operations.
|
||||
foreach ($test_users as $account) {
|
||||
$may_view = $node1->{$field}->access('view', $account);
|
||||
$this->assertTrue($may_view, SafeMarkup::format('Any user may view the field @name.', array('@name' => $field)));
|
||||
}
|
||||
|
||||
// Checks on edit operations.
|
||||
$may_update = $node1->{$field}->access('edit', $page_creator_user);
|
||||
$this->assertFalse($may_update, SafeMarkup::format('Users with permission "edit own page content" is not allowed to the field @name.', array('@name' => $field)));
|
||||
$may_update = $node2->{$field}->access('edit', $page_creator_user);
|
||||
$this->assertFalse($may_update, SafeMarkup::format('Users with permission "edit own page content" is not allowed to the field @name.', array('@name' => $field)));
|
||||
$may_update = $node2->{$field}->access('edit', $page_manager_user);
|
||||
$this->assertFalse($may_update, SafeMarkup::format('Users with permission "edit any page content" is not allowed to the field @name.', array('@name' => $field)));
|
||||
$may_update = $node1->{$field}->access('edit', $page_manager_user);
|
||||
$this->assertFalse($may_update, SafeMarkup::format('Users with permission "edit any page content" is not allowed to the field @name.', array('@name' => $field)));
|
||||
$may_update = $node2->{$field}->access('edit', $page_unrelated_user);
|
||||
$this->assertFalse($may_update, SafeMarkup::format('Users not having permission "edit any page content" is not allowed to the field @name.', array('@name' => $field)));
|
||||
$may_update = $node1->{$field}->access('edit', $content_admin_user) && $node3->status->access('edit', $content_admin_user);
|
||||
$this->assertTrue($may_update, SafeMarkup::format('Users with permission "administer nodes" may edit @name fields on all nodes.', array('@name' => $field)));
|
||||
}
|
||||
|
||||
foreach ($this->readOnlyFields as $field) {
|
||||
// Check view operation.
|
||||
foreach ($test_users as $account) {
|
||||
$may_view = $node1->{$field}->access('view', $account);
|
||||
$this->assertTrue($may_view, SafeMarkup::format('Any user may view the field @name.', array('@name' => $field)));
|
||||
}
|
||||
|
||||
// Check edit operation.
|
||||
foreach ($test_users as $account) {
|
||||
$may_view = $node1->{$field}->access('edit', $account);
|
||||
$this->assertFalse($may_view, SafeMarkup::format('No user is not allowed to edit the field @name.', array('@name' => $field)));
|
||||
}
|
||||
}
|
||||
|
||||
// Check the revision_log field on node 1 which has revisions disabled.
|
||||
$may_update = $node1->revision_log->access('edit', $content_admin_user);
|
||||
$this->assertTrue($may_update, 'A user with permission "administer nodes" can edit the revision_log field when revisions are disabled.');
|
||||
$may_update = $node1->revision_log->access('edit', $page_creator_user);
|
||||
$this->assertFalse($may_update, 'A user without permission "administer nodes" can not edit the revision_log field when revisions are disabled.');
|
||||
|
||||
// Check the revision_log field on node 2 which has revisions enabled.
|
||||
$may_update = $node2->revision_log->access('edit', $content_admin_user);
|
||||
$this->assertTrue($may_update, 'A user with permission "administer nodes" can edit the revision_log field when revisions are enabled.');
|
||||
$may_update = $node2->revision_log->access('edit', $page_creator_user);
|
||||
$this->assertTrue($may_update, 'A user without permission "administer nodes" can edit the revision_log field when revisions are enabled.');
|
||||
}
|
||||
|
||||
}
|
134
core/modules/node/src/Tests/NodeFieldMultilingualTest.php
Normal file
134
core/modules/node/src/Tests/NodeFieldMultilingualTest.php
Normal file
|
@ -0,0 +1,134 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeFieldMultilingualTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrl;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
|
||||
/**
|
||||
* Tests multilingual support for fields.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeFieldMultilingualTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node', 'language');
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create Basic page node type.
|
||||
$this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
|
||||
|
||||
// Setup users.
|
||||
$admin_user = $this->drupalCreateUser(array('administer languages', 'administer content types', 'access administration pages', 'create page content', 'edit own page content'));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Add a new language.
|
||||
ConfigurableLanguage::createFromLangcode('it')->save();
|
||||
|
||||
// Enable URL language detection and selection.
|
||||
$edit = array('language_interface[enabled][language-url]' => '1');
|
||||
$this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings'));
|
||||
|
||||
// Set "Basic page" content type to use multilingual support.
|
||||
$edit = array(
|
||||
'language_configuration[language_alterable]' => TRUE,
|
||||
);
|
||||
$this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type'));
|
||||
$this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Basic page')), 'Basic page content type has been updated.');
|
||||
|
||||
// Make node body translatable.
|
||||
$field_storage = FieldStorageConfig::loadByName('node', 'body');
|
||||
$field_storage->setTranslatable(TRUE);
|
||||
$field_storage->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether field languages are correctly set through the node form.
|
||||
*/
|
||||
function testMultilingualNodeForm() {
|
||||
// Create "Basic page" content.
|
||||
$langcode = language_get_default_langcode('node', 'page');
|
||||
$title_key = 'title[0][value]';
|
||||
$title_value = $this->randomMachineName(8);
|
||||
$body_key = 'body[0][value]';
|
||||
$body_value = $this->randomMachineName(16);
|
||||
|
||||
// Create node to edit.
|
||||
$edit = array();
|
||||
$edit[$title_key] = $title_value;
|
||||
$edit[$body_key] = $body_value;
|
||||
$this->drupalPostForm('node/add/page', $edit, t('Save'));
|
||||
|
||||
// Check that the node exists in the database.
|
||||
$node = $this->drupalGetNodeByTitle($edit[$title_key]);
|
||||
$this->assertTrue($node, 'Node found in database.');
|
||||
$this->assertTrue($node->language()->getId() == $langcode && $node->body->value == $body_value, 'Field language correctly set.');
|
||||
|
||||
// Change node language.
|
||||
$langcode = 'it';
|
||||
$this->drupalGet("node/{$node->id()}/edit");
|
||||
$edit = array(
|
||||
$title_key => $this->randomMachineName(8),
|
||||
'langcode[0][value]' => $langcode,
|
||||
);
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
$node = $this->drupalGetNodeByTitle($edit[$title_key], TRUE);
|
||||
$this->assertTrue($node, 'Node found in database.');
|
||||
$this->assertTrue($node->language()->getId() == $langcode && $node->body->value == $body_value, 'Field language correctly changed.');
|
||||
|
||||
// Enable content language URL detection.
|
||||
$this->container->get('language_negotiator')->saveConfiguration(LanguageInterface::TYPE_CONTENT, array(LanguageNegotiationUrl::METHOD_ID => 0));
|
||||
|
||||
// Test multilingual field language fallback logic.
|
||||
$this->drupalGet("it/node/{$node->id()}");
|
||||
$this->assertRaw($body_value, 'Body correctly displayed using Italian as requested language');
|
||||
|
||||
$this->drupalGet("node/{$node->id()}");
|
||||
$this->assertRaw($body_value, 'Body correctly displayed using English as requested language');
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests multilingual field display settings.
|
||||
*/
|
||||
function testMultilingualDisplaySettings() {
|
||||
// Create "Basic page" content.
|
||||
$title_key = 'title[0][value]';
|
||||
$title_value = $this->randomMachineName(8);
|
||||
$body_key = 'body[0][value]';
|
||||
$body_value = $this->randomMachineName(16);
|
||||
|
||||
// Create node to edit.
|
||||
$edit = array();
|
||||
$edit[$title_key] = $title_value;
|
||||
$edit[$body_key] = $body_value;
|
||||
$this->drupalPostForm('node/add/page', $edit, t('Save'));
|
||||
|
||||
// Check that the node exists in the database.
|
||||
$node = $this->drupalGetNodeByTitle($edit[$title_key]);
|
||||
$this->assertTrue($node, 'Node found in database.');
|
||||
|
||||
// Check if node body is showed.
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$body = $this->xpath('//article[contains(concat(" ", normalize-space(@class), " "), :node-class)]//div[contains(concat(" ", normalize-space(@class), " "), :content-class)]/descendant::p', array(
|
||||
':node-class' => ' node ',
|
||||
':content-class' => 'node__content',
|
||||
));
|
||||
$this->assertEqual(current($body), $node->body->value, 'Node body found.');
|
||||
}
|
||||
|
||||
}
|
68
core/modules/node/src/Tests/NodeFieldOverridesTest.php
Normal file
68
core/modules/node/src/Tests/NodeFieldOverridesTest.php
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeFieldOverridesTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\Core\Field\Entity\BaseFieldOverride;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\system\Tests\Entity\EntityUnitTestBase;
|
||||
|
||||
/**
|
||||
* Tests node field overrides.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeFieldOverridesTest extends EntityUnitTestBase {
|
||||
|
||||
/**
|
||||
* Current logged in user.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('user', 'system', 'field', 'node');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installConfig(array('user'));
|
||||
$this->user = $this->createUser();
|
||||
\Drupal::service('current_user')->setAccount($this->user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that field overrides work as expected.
|
||||
*/
|
||||
public function testFieldOverrides() {
|
||||
if (!NodeType::load('ponies')) {
|
||||
NodeType::create(['name' => 'Ponies', 'type' => 'ponies'])->save();
|
||||
}
|
||||
$override = BaseFieldOverride::loadByName('node', 'ponies', 'uid');
|
||||
if ($override) {
|
||||
$override->delete();
|
||||
}
|
||||
$uid_field = \Drupal::entityManager()->getBaseFieldDefinitions('node')['uid'];
|
||||
$config = $uid_field->getConfig('ponies');
|
||||
$config->save();
|
||||
$this->assertEqual($config->get('default_value_callback'), 'Drupal\node\Entity\Node::getCurrentUserId');
|
||||
/** @var \Drupal\node\NodeInterface $node */
|
||||
$node = Node::create(['type' => 'ponies']);
|
||||
$owner = $node->getOwner();
|
||||
$this->assertTrue($owner instanceof \Drupal\user\UserInterface);
|
||||
$this->assertEqual($owner->id(), $this->user->id());
|
||||
}
|
||||
|
||||
}
|
175
core/modules/node/src/Tests/NodeFormButtonsTest.php
Normal file
175
core/modules/node/src/Tests/NodeFormButtonsTest.php
Normal file
|
@ -0,0 +1,175 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeFormButtonsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Tests all the different buttons on the node form.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeFormButtonsTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* A normal logged in user.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $webUser;
|
||||
|
||||
/**
|
||||
* A user with permission to bypass access content.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create a user that has no access to change the state of the node.
|
||||
$this->webUser = $this->drupalCreateUser(array('create article content', 'edit own article content'));
|
||||
// Create a user that has access to change the state of the node.
|
||||
$this->adminUser = $this->drupalCreateUser(array('administer nodes', 'bypass node access'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the right buttons are displayed for saving nodes.
|
||||
*/
|
||||
function testNodeFormButtons() {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
// Login as administrative user.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Verify the buttons on a node add form.
|
||||
$this->drupalGet('node/add/article');
|
||||
$this->assertButtons(array(t('Save and publish'), t('Save as unpublished')));
|
||||
|
||||
// Save the node and assert it's published after clicking
|
||||
// 'Save and publish'.
|
||||
$edit = array('title[0][value]' => $this->randomString());
|
||||
$this->drupalPostForm('node/add/article', $edit, t('Save and publish'));
|
||||
|
||||
// Get the node.
|
||||
$node_1 = $node_storage->load(1);
|
||||
$this->assertTrue($node_1->isPublished(), 'Node is published');
|
||||
|
||||
// Verify the buttons on a node edit form.
|
||||
$this->drupalGet('node/' . $node_1->id() . '/edit');
|
||||
$this->assertButtons(array(t('Save and keep published'), t('Save and unpublish')));
|
||||
|
||||
// Save the node and verify it's still published after clicking
|
||||
// 'Save and keep published'.
|
||||
$this->drupalPostForm(NULL, $edit, t('Save and keep published'));
|
||||
$node_storage->resetCache(array(1));
|
||||
$node_1 = $node_storage->load(1);
|
||||
$this->assertTrue($node_1->isPublished(), 'Node is published');
|
||||
|
||||
// Save the node and verify it's unpublished after clicking
|
||||
// 'Save and unpublish'.
|
||||
$this->drupalPostForm('node/' . $node_1->id() . '/edit', $edit, t('Save and unpublish'));
|
||||
$node_storage->resetCache(array(1));
|
||||
$node_1 = $node_storage->load(1);
|
||||
$this->assertFalse($node_1->isPublished(), 'Node is unpublished');
|
||||
|
||||
// Verify the buttons on an unpublished node edit screen.
|
||||
$this->drupalGet('node/' . $node_1->id() . '/edit');
|
||||
$this->assertButtons(array(t('Save and keep unpublished'), t('Save and publish')));
|
||||
|
||||
// Create a node as a normal user.
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->webUser);
|
||||
|
||||
// Verify the buttons for a normal user.
|
||||
$this->drupalGet('node/add/article');
|
||||
$this->assertButtons(array(t('Save')), FALSE);
|
||||
|
||||
// Create the node.
|
||||
$edit = array('title[0][value]' => $this->randomString());
|
||||
$this->drupalPostForm('node/add/article', $edit, t('Save'));
|
||||
$node_2 = $node_storage->load(2);
|
||||
$this->assertTrue($node_2->isPublished(), 'Node is published');
|
||||
|
||||
// Login as an administrator and unpublish the node that just
|
||||
// was created by the normal user.
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalPostForm('node/' . $node_2->id() . '/edit', array(), t('Save and unpublish'));
|
||||
$node_storage->resetCache(array(2));
|
||||
$node_2 = $node_storage->load(2);
|
||||
$this->assertFalse($node_2->isPublished(), 'Node is unpublished');
|
||||
|
||||
// Login again as the normal user, save the node and verify
|
||||
// it's still unpublished.
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->webUser);
|
||||
$this->drupalPostForm('node/' . $node_2->id() . '/edit', array(), t('Save'));
|
||||
$node_storage->resetCache(array(2));
|
||||
$node_2 = $node_storage->load(2);
|
||||
$this->assertFalse($node_2->isPublished(), 'Node is still unpublished');
|
||||
$this->drupalLogout();
|
||||
|
||||
// Set article content type default to unpublished. This will change the
|
||||
// the initial order of buttons and/or status of the node when creating
|
||||
// a node.
|
||||
$fields = \Drupal::entityManager()->getFieldDefinitions('node', 'article');
|
||||
$fields['status']->getConfig('article')
|
||||
->setDefaultValue(FALSE)
|
||||
->save();
|
||||
|
||||
// Verify the buttons on a node add form for an administrator.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalGet('node/add/article');
|
||||
$this->assertButtons(array(t('Save as unpublished'), t('Save and publish')));
|
||||
|
||||
// Verify the node is unpublished by default for a normal user.
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->webUser);
|
||||
$edit = array('title[0][value]' => $this->randomString());
|
||||
$this->drupalPostForm('node/add/article', $edit, t('Save'));
|
||||
$node_3 = $node_storage->load(3);
|
||||
$this->assertFalse($node_3->isPublished(), 'Node is unpublished');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert method to verify the buttons in the dropdown element.
|
||||
*
|
||||
* @param array $buttons
|
||||
* A collection of buttons to assert for on the page.
|
||||
* @param bool $dropbutton
|
||||
* Whether to check if the buttons are in a dropbutton widget or not.
|
||||
*/
|
||||
public function assertButtons($buttons, $dropbutton = TRUE) {
|
||||
|
||||
// Try to find a Save button.
|
||||
$save_button = $this->xpath('//input[@type="submit"][@value="Save"]');
|
||||
|
||||
// Verify that the number of buttons passed as parameters is
|
||||
// available in the dropbutton widget.
|
||||
if ($dropbutton) {
|
||||
$i = 0;
|
||||
$count = count($buttons);
|
||||
|
||||
// Assert there is no save button.
|
||||
$this->assertTrue(empty($save_button));
|
||||
|
||||
// Dropbutton elements.
|
||||
$elements = $this->xpath('//div[@class="dropbutton-wrapper"]//input[@type="submit"]');
|
||||
$this->assertEqual($count, count($elements));
|
||||
foreach ($elements as $element) {
|
||||
$value = isset($element['value']) ? (string) $element['value'] : '';
|
||||
$this->assertEqual($buttons[$i], $value);
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Assert there is a save button.
|
||||
$this->assertTrue(!empty($save_button));
|
||||
$this->assertNoRaw('dropbutton-wrapper');
|
||||
}
|
||||
}
|
||||
}
|
81
core/modules/node/src/Tests/NodeHelpTest.php
Normal file
81
core/modules/node/src/Tests/NodeHelpTest.php
Normal file
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeHelpTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests help functionality for nodes.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeHelpTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array.
|
||||
*/
|
||||
public static $modules = array('block', 'node', 'help');
|
||||
|
||||
/**
|
||||
* The name of the test node type to create.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $testType;
|
||||
|
||||
/**
|
||||
* The test 'node help' text to be checked.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $testText;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create user.
|
||||
$admin_user = $this->drupalCreateUser(array(
|
||||
'administer content types',
|
||||
'administer nodes',
|
||||
'bypass node access',
|
||||
));
|
||||
|
||||
$this->drupalLogin($admin_user);
|
||||
$this->drupalPlaceBlock('help_block');
|
||||
|
||||
$this->testType = 'type';
|
||||
$this->testText = t('Help text to find on node forms.');
|
||||
|
||||
// Create content type.
|
||||
$this->drupalCreateContentType(array(
|
||||
'type' => $this->testType,
|
||||
'help' => $this->testText,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that help text appears on node add/edit forms.
|
||||
*/
|
||||
public function testNodeShowHelpText() {
|
||||
// Check the node add form.
|
||||
$this->drupalGet('node/add/' . $this->testType);
|
||||
$this->assertResponse(200);
|
||||
$this->assertText($this->testText);
|
||||
|
||||
// Create node and check the node edit form.
|
||||
$node = $this->drupalCreateNode(array('type' => $this->testType));
|
||||
$this->drupalGet('node/' . $node->id() . '/edit');
|
||||
$this->assertResponse(200);
|
||||
$this->assertText($this->testText);
|
||||
}
|
||||
}
|
47
core/modules/node/src/Tests/NodeLinksTest.php
Normal file
47
core/modules/node/src/Tests/NodeLinksTest.php
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeLinksTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Tests the output of node links (read more, add new comment, etc).
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeLinksTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('views');
|
||||
|
||||
/**
|
||||
* Tests that the links can be hidden in the view display settings.
|
||||
*/
|
||||
public function testHideLinks() {
|
||||
$node = $this->drupalCreateNode(array(
|
||||
'type' => 'article',
|
||||
'promote' => NODE_PROMOTED,
|
||||
));
|
||||
|
||||
// Links are displayed by default.
|
||||
$this->drupalGet('node');
|
||||
$this->assertText($node->getTitle());
|
||||
$this->assertLink('Read more');
|
||||
|
||||
// Hide links.
|
||||
entity_get_display('node', 'article', 'teaser')
|
||||
->removeComponent('links')
|
||||
->save();
|
||||
|
||||
$this->drupalGet('node');
|
||||
$this->assertText($node->getTitle());
|
||||
$this->assertNoLink('Read more');
|
||||
}
|
||||
|
||||
}
|
45
core/modules/node/src/Tests/NodeListBuilderTest.php
Normal file
45
core/modules/node/src/Tests/NodeListBuilderTest.php
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeListBuilderTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\simpletest\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests the admin listing fallback when views is not enabled.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeListBuilderTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['node', 'user'];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installEntitySchema('node');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests that the correct cache contexts are set.
|
||||
*/
|
||||
public function testCacheContexts() {
|
||||
/** @var \Drupal\Core\Entity\EntityListBuilderInterface $list_builder */
|
||||
$list_builder = $this->container->get('entity.manager')->getListBuilder('node');
|
||||
|
||||
$build = $list_builder->render();
|
||||
$this->container->get('renderer')->renderRoot($build);
|
||||
|
||||
$this->assertEqual(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'url.query_args.pagers:0', 'user.node_grants:view'], $build['#cache']['contexts']);
|
||||
}
|
||||
|
||||
}
|
66
core/modules/node/src/Tests/NodeLoadMultipleTest.php
Normal file
66
core/modules/node/src/Tests/NodeLoadMultipleTest.php
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeLoadMultipleTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\node\Entity\Node;
|
||||
|
||||
/**
|
||||
* Tests the loading of multiple nodes.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeLoadMultipleTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Enable Views to test the frontpage against Node::loadMultiple() results.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('views');
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$web_user = $this->drupalCreateUser(array('create article content', 'create page content'));
|
||||
$this->drupalLogin($web_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates four nodes and ensures that they are loaded correctly.
|
||||
*/
|
||||
function testNodeMultipleLoad() {
|
||||
$node1 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
|
||||
$node2 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
|
||||
$node3 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 0));
|
||||
$node4 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 0));
|
||||
|
||||
// Confirm that promoted nodes appear in the default node listing.
|
||||
$this->drupalGet('node');
|
||||
$this->assertText($node1->label(), 'Node title appears on the default listing.');
|
||||
$this->assertText($node2->label(), 'Node title appears on the default listing.');
|
||||
$this->assertNoText($node3->label(), 'Node title does not appear in the default listing.');
|
||||
$this->assertNoText($node4->label(), 'Node title does not appear in the default listing.');
|
||||
|
||||
// Load nodes with only a condition. Nodes 3 and 4 will be loaded.
|
||||
$nodes = entity_load_multiple_by_properties('node', array('promote' => 0));
|
||||
$this->assertEqual($node3->label(), $nodes[$node3->id()]->label(), 'Node was loaded.');
|
||||
$this->assertEqual($node4->label(), $nodes[$node4->id()]->label(), 'Node was loaded.');
|
||||
$count = count($nodes);
|
||||
$this->assertTrue($count == 2, format_string('@count nodes loaded.', array('@count' => $count)));
|
||||
|
||||
// Load nodes by nid. Nodes 1, 2 and 4 will be loaded.
|
||||
$nodes = Node::loadMultiple(array(1, 2, 4));
|
||||
$count = count($nodes);
|
||||
$this->assertTrue(count($nodes) == 3, format_string('@count nodes loaded', array('@count' => $count)));
|
||||
$this->assertTrue(isset($nodes[$node1->id()]), 'Node is correctly keyed in the array');
|
||||
$this->assertTrue(isset($nodes[$node2->id()]), 'Node is correctly keyed in the array');
|
||||
$this->assertTrue(isset($nodes[$node4->id()]), 'Node is correctly keyed in the array');
|
||||
foreach ($nodes as $node) {
|
||||
$this->assertTrue(is_object($node), 'Node is an object');
|
||||
}
|
||||
}
|
||||
}
|
62
core/modules/node/src/Tests/NodePostSettingsTest.php
Normal file
62
core/modules/node/src/Tests/NodePostSettingsTest.php
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodePostSettingsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Tests that the post information (submitted by Username on date) text displays
|
||||
* appropriately.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodePostSettingsTest extends NodeTestBase {
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$web_user = $this->drupalCreateUser(array('create page content', 'administer content types', 'access user profiles'));
|
||||
$this->drupalLogin($web_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirms "Basic page" content type and post information is on a new node.
|
||||
*/
|
||||
function testPagePostInfo() {
|
||||
|
||||
// Set "Basic page" content type to display post information.
|
||||
$edit = array();
|
||||
$edit['display_submitted'] = TRUE;
|
||||
$this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type'));
|
||||
|
||||
// Create a node.
|
||||
$edit = array();
|
||||
$edit['title[0][value]'] = $this->randomMachineName(8);
|
||||
$edit['body[0][value]'] = $this->randomMachineName(16);
|
||||
$this->drupalPostForm('node/add/page', $edit, t('Save'));
|
||||
|
||||
// Check that the post information is displayed.
|
||||
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
|
||||
$elements = $this->xpath('//div[contains(@class, :class)]', array(':class' => 'node__submitted'));
|
||||
$this->assertEqual(count($elements), 1, 'Post information is displayed.');
|
||||
$node->delete();
|
||||
|
||||
// Set "Basic page" content type to display post information.
|
||||
$edit = array();
|
||||
$edit['display_submitted'] = FALSE;
|
||||
$this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type'));
|
||||
|
||||
// Create a node.
|
||||
$edit = array();
|
||||
$edit['title[0][value]'] = $this->randomMachineName(8);
|
||||
$edit['body[0][value]'] = $this->randomMachineName(16);
|
||||
$this->drupalPostForm('node/add/page', $edit, t('Save'));
|
||||
|
||||
// Check that the post information is displayed.
|
||||
$elements = $this->xpath('//div[contains(@class, :class)]', array(':class' => 'node__submitted'));
|
||||
$this->assertEqual(count($elements), 0, 'Post information is not displayed.');
|
||||
}
|
||||
}
|
183
core/modules/node/src/Tests/NodeQueryAlterTest.php
Normal file
183
core/modules/node/src/Tests/NodeQueryAlterTest.php
Normal file
|
@ -0,0 +1,183 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeQueryAlterTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Tests that node access queries are properly altered by the node module.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeQueryAlterTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node_access_test');
|
||||
|
||||
/**
|
||||
* User with permission to view content.
|
||||
*/
|
||||
protected $accessUser;
|
||||
|
||||
/**
|
||||
* User without permission to view content.
|
||||
*/
|
||||
protected $noAccessUser;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
node_access_rebuild();
|
||||
|
||||
// Create some content.
|
||||
$this->drupalCreateNode();
|
||||
$this->drupalCreateNode();
|
||||
$this->drupalCreateNode();
|
||||
$this->drupalCreateNode();
|
||||
|
||||
// Create user with simple node access permission. The 'node test view'
|
||||
// permission is implemented and granted by the node_access_test module.
|
||||
$this->accessUser = $this->drupalCreateUser(array('access content overview', 'access content', 'node test view'));
|
||||
$this->noAccessUser = $this->drupalCreateUser(array('access content overview', 'access content'));
|
||||
$this->noAccessUser2 = $this->drupalCreateUser(array('access content overview', 'access content'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests 'node_access' query alter, for user with access.
|
||||
*
|
||||
* Verifies that a non-standard table alias can be used, and that a user with
|
||||
* node access can view the nodes.
|
||||
*/
|
||||
function testNodeQueryAlterLowLevelWithAccess() {
|
||||
// User with access should be able to view 4 nodes.
|
||||
try {
|
||||
$query = db_select('node', 'mytab')
|
||||
->fields('mytab');
|
||||
$query->addTag('node_access');
|
||||
$query->addMetaData('op', 'view');
|
||||
$query->addMetaData('account', $this->accessUser);
|
||||
|
||||
$result = $query->execute()->fetchAll();
|
||||
$this->assertEqual(count($result), 4, 'User with access can see correct nodes');
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
$this->fail(t('Altered query is malformed'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests 'node_access' query alter, for user without access.
|
||||
*
|
||||
* Verifies that a non-standard table alias can be used, and that a user
|
||||
* without node access cannot view the nodes.
|
||||
*/
|
||||
function testNodeQueryAlterLowLevelNoAccess() {
|
||||
// User without access should be able to view 0 nodes.
|
||||
try {
|
||||
$query = db_select('node', 'mytab')
|
||||
->fields('mytab');
|
||||
$query->addTag('node_access');
|
||||
$query->addMetaData('op', 'view');
|
||||
$query->addMetaData('account', $this->noAccessUser);
|
||||
|
||||
$result = $query->execute()->fetchAll();
|
||||
$this->assertEqual(count($result), 0, 'User with no access cannot see nodes');
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
$this->fail(t('Altered query is malformed'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests 'node_access' query alter, for edit access.
|
||||
*
|
||||
* Verifies that a non-standard table alias can be used, and that a user with
|
||||
* view-only node access cannot edit the nodes.
|
||||
*/
|
||||
function testNodeQueryAlterLowLevelEditAccess() {
|
||||
// User with view-only access should not be able to edit nodes.
|
||||
try {
|
||||
$query = db_select('node', 'mytab')
|
||||
->fields('mytab');
|
||||
$query->addTag('node_access');
|
||||
$query->addMetaData('op', 'update');
|
||||
$query->addMetaData('account', $this->accessUser);
|
||||
|
||||
$result = $query->execute()->fetchAll();
|
||||
$this->assertEqual(count($result), 0, 'User with view-only access cannot edit nodes');
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
$this->fail($e->getMessage());
|
||||
$this->fail((string) $query);
|
||||
$this->fail(t('Altered query is malformed'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests 'node_access' query alter override.
|
||||
*
|
||||
* Verifies that node_access_view_all_nodes() is called from
|
||||
* node_query_node_access_alter(). We do this by checking that a user who
|
||||
* normally would not have view privileges is able to view the nodes when we
|
||||
* add a record to {node_access} paired with a corresponding privilege in
|
||||
* hook_node_grants().
|
||||
*/
|
||||
function testNodeQueryAlterOverride() {
|
||||
$record = array(
|
||||
'nid' => 0,
|
||||
'gid' => 0,
|
||||
'realm' => 'node_access_all',
|
||||
'grant_view' => 1,
|
||||
'grant_update' => 0,
|
||||
'grant_delete' => 0,
|
||||
);
|
||||
db_insert('node_access')->fields($record)->execute();
|
||||
|
||||
// Test that the noAccessUser still doesn't have the 'view'
|
||||
// privilege after adding the node_access record.
|
||||
drupal_static_reset('node_access_view_all_nodes');
|
||||
try {
|
||||
$query = db_select('node', 'mytab')
|
||||
->fields('mytab');
|
||||
$query->addTag('node_access');
|
||||
$query->addMetaData('op', 'view');
|
||||
$query->addMetaData('account', $this->noAccessUser);
|
||||
|
||||
$result = $query->execute()->fetchAll();
|
||||
$this->assertEqual(count($result), 0, 'User view privileges are not overridden');
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
$this->fail(t('Altered query is malformed'));
|
||||
}
|
||||
|
||||
// Have node_test_node_grants return a node_access_all privilege,
|
||||
// to grant the noAccessUser 'view' access. To verify that
|
||||
// node_access_view_all_nodes is properly checking the specified
|
||||
// $account instead of the current user, we will log in as
|
||||
// noAccessUser2.
|
||||
$this->drupalLogin($this->noAccessUser2);
|
||||
\Drupal::state()->set('node_access_test.no_access_uid', $this->noAccessUser->id());
|
||||
drupal_static_reset('node_access_view_all_nodes');
|
||||
try {
|
||||
$query = db_select('node', 'mytab')
|
||||
->fields('mytab');
|
||||
$query->addTag('node_access');
|
||||
$query->addMetaData('op', 'view');
|
||||
$query->addMetaData('account', $this->noAccessUser);
|
||||
|
||||
$result = $query->execute()->fetchAll();
|
||||
$this->assertEqual(count($result), 4, 'User view privileges are overridden');
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
$this->fail(t('Altered query is malformed'));
|
||||
}
|
||||
\Drupal::state()->delete('node_access_test.no_access_uid');
|
||||
}
|
||||
}
|
68
core/modules/node/src/Tests/NodeRSSContentTest.php
Normal file
68
core/modules/node/src/Tests/NodeRSSContentTest.php
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeRSSContentTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Ensures that data added to nodes by other modules appears in RSS feeds.
|
||||
*
|
||||
* Create a node, enable the node_test module to ensure that extra data is
|
||||
* added to the node's renderable array, then verify that the data appears on
|
||||
* the site-wide RSS feed at rss.xml.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeRSSContentTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Enable a module that implements hook_node_view().
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node_test', 'views');
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Use bypass node access permission here, because the test class uses
|
||||
// hook_grants_alter() to deny access to everyone on node_access
|
||||
// queries.
|
||||
$user = $this->drupalCreateUser(array('bypass node access', 'access content', 'create article content'));
|
||||
$this->drupalLogin($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that a new node includes the custom data when added to an RSS feed.
|
||||
*/
|
||||
function testNodeRSSContent() {
|
||||
// Create a node.
|
||||
$node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
|
||||
|
||||
$this->drupalGet('rss.xml');
|
||||
|
||||
// Check that content added in 'rss' view mode appear in RSS feed.
|
||||
$rss_only_content = t('Extra data that should appear only in the RSS feed for node !nid.', array('!nid' => $node->id()));
|
||||
$this->assertText($rss_only_content, 'Node content designated for RSS appear in RSS feed.');
|
||||
|
||||
// Check that content added in view modes other than 'rss' doesn't
|
||||
// appear in RSS feed.
|
||||
$non_rss_content = t('Extra data that should appear everywhere except the RSS feed for node !nid.', array('!nid' => $node->id()));
|
||||
$this->assertNoText($non_rss_content, 'Node content not designed for RSS does not appear in RSS feed.');
|
||||
|
||||
// Check that extra RSS elements and namespaces are added to RSS feed.
|
||||
$test_element = '<testElement>' . t('Value of testElement RSS element for node !nid.', array('!nid' => $node->id())) . '</testElement>';
|
||||
$test_ns = 'xmlns:drupaltest="http://example.com/test-namespace"';
|
||||
$this->assertRaw($test_element, 'Extra RSS elements appear in RSS feed.');
|
||||
$this->assertRaw($test_ns, 'Extra namespaces appear in RSS feed.');
|
||||
|
||||
// Check that content added in 'rss' view mode doesn't appear when
|
||||
// viewing node.
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$this->assertNoText($rss_only_content, 'Node content designed for RSS does not appear when viewing node.');
|
||||
}
|
||||
|
||||
}
|
173
core/modules/node/src/Tests/NodeRevisionPermissionsTest.php
Normal file
173
core/modules/node/src/Tests/NodeRevisionPermissionsTest.php
Normal file
|
@ -0,0 +1,173 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeRevisionPermissionsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Tests user permissions for node revisions.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeRevisionPermissionsTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* The node revisions.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $nodeRevisions = [];
|
||||
|
||||
/**
|
||||
* The accounts.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $accounts = array();
|
||||
|
||||
// Map revision permission names to node revision access ops.
|
||||
protected $map = array(
|
||||
'view' => 'view all revisions',
|
||||
'update' => 'revert all revisions',
|
||||
'delete' => 'delete all revisions',
|
||||
);
|
||||
|
||||
// Map revision permission names to node type revision access ops.
|
||||
protected $typeMap = array(
|
||||
'view' => 'view page revisions',
|
||||
'update' => 'revert page revisions',
|
||||
'delete' => 'delete page revisions',
|
||||
);
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$types = array('page', 'article');
|
||||
|
||||
foreach ($types as $type) {
|
||||
// Create a node with several revisions.
|
||||
$nodes[$type] = $this->drupalCreateNode(array('type' => $type));
|
||||
$this->nodeRevisions[$type][] = $nodes[$type];
|
||||
|
||||
for ($i = 0; $i < 3; $i++) {
|
||||
// Create a revision for the same nid and settings with a random log.
|
||||
$revision = clone $nodes[$type];
|
||||
$revision->setNewRevision();
|
||||
$revision->revision_log = $this->randomMachineName(32);
|
||||
$revision->save();
|
||||
$this->nodeRevisions[$type][] = $revision;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests general revision access permissions.
|
||||
*/
|
||||
function testNodeRevisionAccessAnyType() {
|
||||
// Create three users, one with each revision permission.
|
||||
foreach ($this->map as $op => $permission) {
|
||||
// Create the user.
|
||||
$account = $this->drupalCreateUser(
|
||||
array(
|
||||
'access content',
|
||||
'edit any page content',
|
||||
'delete any page content',
|
||||
$permission,
|
||||
)
|
||||
);
|
||||
$account->op = $op;
|
||||
$this->accounts[] = $account;
|
||||
}
|
||||
|
||||
// Create an admin account (returns TRUE for all revision permissions).
|
||||
$admin_account = $this->drupalCreateUser(array('access content', 'administer nodes'));
|
||||
$admin_account->is_admin = TRUE;
|
||||
$this->accounts['admin'] = $admin_account;
|
||||
$accounts['admin'] = $admin_account;
|
||||
|
||||
// Create a normal account (returns FALSE for all revision permissions).
|
||||
$normal_account = $this->drupalCreateUser();
|
||||
$normal_account->op = FALSE;
|
||||
$this->accounts[] = $normal_account;
|
||||
$accounts[] = $normal_account;
|
||||
$revision = $this->nodeRevisions['page'][1];
|
||||
|
||||
$parameters = array(
|
||||
'op' => array_keys($this->map),
|
||||
'account' => $this->accounts,
|
||||
);
|
||||
|
||||
$permutations = $this->generatePermutations($parameters);
|
||||
|
||||
$node_revision_access = \Drupal::service('access_check.node.revision');
|
||||
foreach ($permutations as $case) {
|
||||
// Skip this test if there are no revisions for the node.
|
||||
if (!($revision->isDefaultRevision() && (db_query('SELECT COUNT(vid) FROM {node_field_revision} WHERE nid = :nid', array(':nid' => $revision->id()))->fetchField() == 1 || $case['op'] == 'update' || $case['op'] == 'delete'))) {
|
||||
if (!empty($case['account']->is_admin) || $case['account']->hasPermission($this->map[$case['op']])) {
|
||||
$this->assertTrue($node_revision_access->checkAccess($revision, $case['account'], $case['op']), "{$this->map[$case['op']]} granted.");
|
||||
}
|
||||
else {
|
||||
$this->assertFalse($node_revision_access->checkAccess($revision, $case['account'], $case['op']), "{$this->map[$case['op']]} not granted.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test that access is FALSE for a node administrator with an invalid $node
|
||||
// or $op parameters.
|
||||
$admin_account = $accounts['admin'];
|
||||
$this->assertFalse($node_revision_access->checkAccess($revision, $admin_account, 'invalid-op'), 'NodeRevisionAccessCheck() returns FALSE with an invalid op.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests revision access permissions for a specific content type.
|
||||
*/
|
||||
function testNodeRevisionAccessPerType() {
|
||||
// Create three users, one with each revision permission.
|
||||
foreach ($this->typeMap as $op => $permission) {
|
||||
// Create the user.
|
||||
$account = $this->drupalCreateUser(
|
||||
array(
|
||||
'access content',
|
||||
'edit any page content',
|
||||
'delete any page content',
|
||||
$permission,
|
||||
)
|
||||
);
|
||||
$account->op = $op;
|
||||
$accounts[] = $account;
|
||||
}
|
||||
|
||||
$parameters = array(
|
||||
'op' => array_keys($this->typeMap),
|
||||
'account' => $accounts,
|
||||
);
|
||||
|
||||
// Test that the accounts have access to the corresponding page revision
|
||||
// permissions.
|
||||
$revision = $this->nodeRevisions['page'][1];
|
||||
|
||||
$permutations = $this->generatePermutations($parameters);
|
||||
$node_revision_access = \Drupal::service('access_check.node.revision');
|
||||
foreach ($permutations as $case) {
|
||||
// Skip this test if there are no revisions for the node.
|
||||
if (!($revision->isDefaultRevision() && (db_query('SELECT COUNT(vid) FROM {node_field_revision} WHERE nid = :nid', array(':nid' => $revision->id()))->fetchField() == 1 || $case['op'] == 'update' || $case['op'] == 'delete'))) {
|
||||
if (!empty($case['account']->is_admin) || $case['account']->hasPermission($this->typeMap[$case['op']], $case['account'])) {
|
||||
$this->assertTrue($node_revision_access->checkAccess($revision, $case['account'], $case['op']), "{$this->typeMap[$case['op']]} granted.");
|
||||
}
|
||||
else {
|
||||
$this->assertFalse($node_revision_access->checkAccess($revision, $case['account'], $case['op']), "{$this->typeMap[$case['op']]} not granted.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test that the accounts have no access to the article revisions.
|
||||
$revision = $this->nodeRevisions['article'][1];
|
||||
|
||||
foreach ($permutations as $case) {
|
||||
$this->assertFalse($node_revision_access->checkAccess($revision, $case['account'], $case['op']), "{$this->typeMap[$case['op']]} did not grant revision permission for articles.");
|
||||
}
|
||||
}
|
||||
}
|
154
core/modules/node/src/Tests/NodeRevisionsAllTest.php
Normal file
154
core/modules/node/src/Tests/NodeRevisionsAllTest.php
Normal file
|
@ -0,0 +1,154 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeRevisionsAllTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Create a node with revisions and test viewing, saving, reverting, and
|
||||
* deleting revisions for user with access to all.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeRevisionsAllTest extends NodeTestBase {
|
||||
protected $nodes;
|
||||
protected $revisionLogs;
|
||||
protected $profile = "standard";
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
// Create and log in user.
|
||||
$web_user = $this->drupalCreateUser(
|
||||
array(
|
||||
'view page revisions',
|
||||
'revert page revisions',
|
||||
'delete page revisions',
|
||||
'edit any page content',
|
||||
'delete any page content'
|
||||
)
|
||||
);
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
// Create an initial node.
|
||||
$node = $this->drupalCreateNode();
|
||||
|
||||
$settings = get_object_vars($node);
|
||||
$settings['revision'] = 1;
|
||||
|
||||
$nodes = array();
|
||||
$logs = array();
|
||||
|
||||
// Get the original node.
|
||||
$nodes[] = clone $node;
|
||||
|
||||
// Create three revisions.
|
||||
$revision_count = 3;
|
||||
for ($i = 0; $i < $revision_count; $i++) {
|
||||
$logs[] = $node->revision_log = $this->randomMachineName(32);
|
||||
|
||||
// Create revision with a random title and body and update variables.
|
||||
$node->title = $this->randomMachineName();
|
||||
$node->body = array(
|
||||
'value' => $this->randomMachineName(32),
|
||||
'format' => filter_default_format(),
|
||||
);
|
||||
$node->setNewRevision();
|
||||
$node->save();
|
||||
|
||||
$node_storage->resetCache(array($node->id()));
|
||||
$node = $node_storage->load($node->id()); // Make sure we get revision information.
|
||||
$nodes[] = clone $node;
|
||||
}
|
||||
|
||||
$this->nodes = $nodes;
|
||||
$this->revisionLogs = $logs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks node revision operations.
|
||||
*/
|
||||
function testRevisions() {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
$nodes = $this->nodes;
|
||||
$logs = $this->revisionLogs;
|
||||
|
||||
// Get last node for simple checks.
|
||||
$node = $nodes[3];
|
||||
|
||||
// Create and login user.
|
||||
$content_admin = $this->drupalCreateUser(
|
||||
array(
|
||||
'view all revisions',
|
||||
'revert all revisions',
|
||||
'delete all revisions',
|
||||
'edit any page content',
|
||||
'delete any page content'
|
||||
)
|
||||
);
|
||||
$this->drupalLogin($content_admin);
|
||||
|
||||
// Confirm the correct revision text appears on "view revisions" page.
|
||||
$this->drupalGet("node/" . $node->id() . "/revisions/" . $node->getRevisionId() . "/view");
|
||||
$this->assertText($node->body->value, 'Correct text displays for version.');
|
||||
|
||||
// Confirm the correct revision log message appears on the "revisions
|
||||
// overview" page.
|
||||
$this->drupalGet("node/" . $node->id() . "/revisions");
|
||||
foreach ($logs as $revision_log) {
|
||||
$this->assertText($revision_log, 'Revision log message found.');
|
||||
}
|
||||
|
||||
// Confirm that this is the current revision.
|
||||
$this->assertTrue($node->isDefaultRevision(), 'Third node revision is the current one.');
|
||||
|
||||
// Confirm that revisions revert properly.
|
||||
$this->drupalPostForm("node/" . $node->id() . "/revisions/" . $nodes[1]->getRevisionId() . "/revert", array(), t('Revert'));
|
||||
$this->assertRaw(t('@type %title has been reverted to the revision from %revision-date.',
|
||||
array(
|
||||
'@type' => 'Basic page',
|
||||
'%title' => $nodes[1]->getTitle(),
|
||||
'%revision-date' => format_date($nodes[1]->getRevisionCreationTime())
|
||||
)),
|
||||
'Revision reverted.');
|
||||
$node_storage->resetCache(array($node->id()));
|
||||
$reverted_node = $node_storage->load($node->id());
|
||||
$this->assertTrue(($nodes[1]->body->value == $reverted_node->body->value), 'Node reverted correctly.');
|
||||
|
||||
// Confirm that this is not the current version.
|
||||
$node = node_revision_load($node->getRevisionId());
|
||||
$this->assertFalse($node->isDefaultRevision(), 'Third node revision is not the current one.');
|
||||
|
||||
// Confirm revisions delete properly.
|
||||
$this->drupalPostForm("node/" . $node->id() . "/revisions/" . $nodes[1]->getRevisionId() . "/delete", array(), t('Delete'));
|
||||
$this->assertRaw(t('Revision from %revision-date of @type %title has been deleted.',
|
||||
array(
|
||||
'%revision-date' => format_date($nodes[1]->getRevisionCreationTime()),
|
||||
'@type' => 'Basic page',
|
||||
'%title' => $nodes[1]->getTitle(),
|
||||
)),
|
||||
'Revision deleted.');
|
||||
$this->assertTrue(db_query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = :nid and vid = :vid',
|
||||
array(':nid' => $node->id(), ':vid' => $nodes[1]->getRevisionId()))->fetchField() == 0,
|
||||
'Revision not found.');
|
||||
|
||||
// Set the revision timestamp to an older date to make sure that the
|
||||
// confirmation message correctly displays the stored revision date.
|
||||
$old_revision_date = REQUEST_TIME - 86400;
|
||||
db_update('node_revision')
|
||||
->condition('vid', $nodes[2]->getRevisionId())
|
||||
->fields(array(
|
||||
'revision_timestamp' => $old_revision_date,
|
||||
))
|
||||
->execute();
|
||||
$this->drupalPostForm("node/" . $node->id() . "/revisions/" . $nodes[2]->getRevisionId() . "/revert", array(), t('Revert'));
|
||||
$this->assertRaw(t('@type %title has been reverted to the revision from %revision-date.', array(
|
||||
'@type' => 'Basic page',
|
||||
'%title' => $nodes[2]->getTitle(),
|
||||
'%revision-date' => format_date($old_revision_date),
|
||||
)));
|
||||
}
|
||||
}
|
277
core/modules/node/src/Tests/NodeRevisionsTest.php
Normal file
277
core/modules/node/src/Tests/NodeRevisionsTest.php
Normal file
|
@ -0,0 +1,277 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeRevisionsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\node\NodeInterface;
|
||||
|
||||
/**
|
||||
* Create a node with revisions and test viewing, saving, reverting, and
|
||||
* deleting revisions for users with access for this content type.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeRevisionsTest extends NodeTestBase {
|
||||
protected $nodes;
|
||||
protected $revisionLogs;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = array('node', 'datetime', 'language', 'content_translation');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
ConfigurableLanguage::createFromLangcode('it')->save();
|
||||
|
||||
/** @var \Drupal\content_translation\ContentTranslationManagerInterface $manager */
|
||||
$manager = \Drupal::service('content_translation.manager');
|
||||
$manager->setEnabled('node', 'article', TRUE);
|
||||
|
||||
// Create and log in user.
|
||||
$web_user = $this->drupalCreateUser(
|
||||
array(
|
||||
'view page revisions',
|
||||
'revert page revisions',
|
||||
'delete page revisions',
|
||||
'edit any page content',
|
||||
'delete any page content',
|
||||
'translate any entity',
|
||||
)
|
||||
);
|
||||
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
// Create initial node.
|
||||
$node = $this->drupalCreateNode();
|
||||
$settings = get_object_vars($node);
|
||||
$settings['revision'] = 1;
|
||||
$settings['isDefaultRevision'] = TRUE;
|
||||
|
||||
$nodes = array();
|
||||
$logs = array();
|
||||
|
||||
// Get original node.
|
||||
$nodes[] = clone $node;
|
||||
|
||||
// Create three revisions.
|
||||
$revision_count = 3;
|
||||
for ($i = 0; $i < $revision_count; $i++) {
|
||||
$logs[] = $node->revision_log = $this->randomMachineName(32);
|
||||
|
||||
// Create revision with a random title and body and update variables.
|
||||
$node->title = $this->randomMachineName();
|
||||
$node->body = array(
|
||||
'value' => $this->randomMachineName(32),
|
||||
'format' => filter_default_format(),
|
||||
);
|
||||
$node->setNewRevision();
|
||||
$node->save();
|
||||
|
||||
$node = Node::load($node->id()); // Make sure we get revision information.
|
||||
$nodes[] = clone $node;
|
||||
}
|
||||
|
||||
$this->nodes = $nodes;
|
||||
$this->revisionLogs = $logs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks node revision related operations.
|
||||
*/
|
||||
function testRevisions() {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
$nodes = $this->nodes;
|
||||
$logs = $this->revisionLogs;
|
||||
|
||||
// Get last node for simple checks.
|
||||
$node = $nodes[3];
|
||||
|
||||
// Confirm the correct revision text appears on "view revisions" page.
|
||||
$this->drupalGet("node/" . $node->id() . "/revisions/" . $node->getRevisionId() . "/view");
|
||||
$this->assertText($node->body->value, 'Correct text displays for version.');
|
||||
|
||||
// Confirm the correct log message appears on "revisions overview" page.
|
||||
$this->drupalGet("node/" . $node->id() . "/revisions");
|
||||
foreach ($logs as $revision_log) {
|
||||
$this->assertText($revision_log, 'Revision log message found.');
|
||||
}
|
||||
|
||||
// Confirm that this is the default revision.
|
||||
$this->assertTrue($node->isDefaultRevision(), 'Third node revision is the default one.');
|
||||
|
||||
// Confirm that revisions revert properly.
|
||||
$this->drupalPostForm("node/" . $node->id() . "/revisions/" . $nodes[1]->getRevisionid() . "/revert", array(), t('Revert'));
|
||||
$this->assertRaw(t('@type %title has been reverted to the revision from %revision-date.',
|
||||
array('@type' => 'Basic page', '%title' => $nodes[1]->label(),
|
||||
'%revision-date' => format_date($nodes[1]->getRevisionCreationTime()))), 'Revision reverted.');
|
||||
$node_storage->resetCache(array($node->id()));
|
||||
$reverted_node = $node_storage->load($node->id());
|
||||
$this->assertTrue(($nodes[1]->body->value == $reverted_node->body->value), 'Node reverted correctly.');
|
||||
|
||||
// Confirm that this is not the default version.
|
||||
$node = node_revision_load($node->getRevisionId());
|
||||
$this->assertFalse($node->isDefaultRevision(), 'Third node revision is not the default one.');
|
||||
|
||||
// Confirm revisions delete properly.
|
||||
$this->drupalPostForm("node/" . $node->id() . "/revisions/" . $nodes[1]->getRevisionId() . "/delete", array(), t('Delete'));
|
||||
$this->assertRaw(t('Revision from %revision-date of @type %title has been deleted.',
|
||||
array('%revision-date' => format_date($nodes[1]->getRevisionCreationTime()),
|
||||
'@type' => 'Basic page', '%title' => $nodes[1]->label())), 'Revision deleted.');
|
||||
$this->assertTrue(db_query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = :nid and vid = :vid', array(':nid' => $node->id(), ':vid' => $nodes[1]->getRevisionId()))->fetchField() == 0, 'Revision not found.');
|
||||
|
||||
// Set the revision timestamp to an older date to make sure that the
|
||||
// confirmation message correctly displays the stored revision date.
|
||||
$old_revision_date = REQUEST_TIME - 86400;
|
||||
db_update('node_revision')
|
||||
->condition('vid', $nodes[2]->getRevisionId())
|
||||
->fields(array(
|
||||
'revision_timestamp' => $old_revision_date,
|
||||
))
|
||||
->execute();
|
||||
$this->drupalPostForm("node/" . $node->id() . "/revisions/" . $nodes[2]->getRevisionId() . "/revert", array(), t('Revert'));
|
||||
$this->assertRaw(t('@type %title has been reverted to the revision from %revision-date.', array(
|
||||
'@type' => 'Basic page',
|
||||
'%title' => $nodes[2]->label(),
|
||||
'%revision-date' => format_date($old_revision_date),
|
||||
)));
|
||||
|
||||
// Make a new revision and set it to not be default.
|
||||
// This will create a new revision that is not "front facing".
|
||||
$new_node_revision = clone $node;
|
||||
$new_body = $this->randomMachineName();
|
||||
$new_node_revision->body->value = $new_body;
|
||||
// Save this as a non-default revision.
|
||||
$new_node_revision->setNewRevision();
|
||||
$new_node_revision->isDefaultRevision = FALSE;
|
||||
$new_node_revision->save();
|
||||
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$this->assertNoText($new_body, 'Revision body text is not present on default version of node.');
|
||||
|
||||
// Verify that the new body text is present on the revision.
|
||||
$this->drupalGet("node/" . $node->id() . "/revisions/" . $new_node_revision->getRevisionId() . "/view");
|
||||
$this->assertText($new_body, 'Revision body text is present when loading specific revision.');
|
||||
|
||||
// Verify that the non-default revision vid is greater than the default
|
||||
// revision vid.
|
||||
$default_revision = db_select('node', 'n')
|
||||
->fields('n', array('vid'))
|
||||
->condition('nid', $node->id())
|
||||
->execute()
|
||||
->fetchCol();
|
||||
$default_revision_vid = $default_revision[0];
|
||||
$this->assertTrue($new_node_revision->getRevisionId() > $default_revision_vid, 'Revision vid is greater than default revision vid.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that revisions are correctly saved without log messages.
|
||||
*/
|
||||
function testNodeRevisionWithoutLogMessage() {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
// Create a node with an initial log message.
|
||||
$revision_log = $this->randomMachineName(10);
|
||||
$node = $this->drupalCreateNode(array('revision_log' => $revision_log));
|
||||
|
||||
// Save over the same revision and explicitly provide an empty log message
|
||||
// (for example, to mimic the case of a node form submitted with no text in
|
||||
// the "log message" field), and check that the original log message is
|
||||
// preserved.
|
||||
$new_title = $this->randomMachineName(10) . 'testNodeRevisionWithoutLogMessage1';
|
||||
|
||||
$node = clone $node;
|
||||
$node->title = $new_title;
|
||||
$node->revision_log = '';
|
||||
$node->setNewRevision(FALSE);
|
||||
|
||||
$node->save();
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$this->assertText($new_title, 'New node title appears on the page.');
|
||||
$node_storage->resetCache(array($node->id()));
|
||||
$node_revision = $node_storage->load($node->id());
|
||||
$this->assertEqual($node_revision->revision_log->value, $revision_log, 'After an existing node revision is re-saved without a log message, the original log message is preserved.');
|
||||
|
||||
// Create another node with an initial revision log message.
|
||||
$node = $this->drupalCreateNode(array('revision_log' => $revision_log));
|
||||
|
||||
// Save a new node revision without providing a log message, and check that
|
||||
// this revision has an empty log message.
|
||||
$new_title = $this->randomMachineName(10) . 'testNodeRevisionWithoutLogMessage2';
|
||||
|
||||
$node = clone $node;
|
||||
$node->title = $new_title;
|
||||
$node->setNewRevision();
|
||||
$node->revision_log = NULL;
|
||||
|
||||
$node->save();
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$this->assertText($new_title, 'New node title appears on the page.');
|
||||
$node_storage->resetCache(array($node->id()));
|
||||
$node_revision = $node_storage->load($node->id());
|
||||
$this->assertTrue(empty($node_revision->revision_log->value), 'After a new node revision is saved with an empty log message, the log message for the node is empty.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the revision translations are correctly reverted.
|
||||
*/
|
||||
public function testRevisionTranslationRevert() {
|
||||
// Create a node and a few revisions.
|
||||
$node = $this->drupalCreateNode(['langcode' => 'en']);
|
||||
$this->createRevisions($node, 2);
|
||||
|
||||
// Translate the node and create a few translation revisions.
|
||||
$translation = $node->addTranslation('it');
|
||||
$this->createRevisions($translation, 3);
|
||||
$revert_id = $node->getRevisionId();
|
||||
$translated_title = $translation->label();
|
||||
|
||||
// Create a new revision for the default translation in-between a series of
|
||||
// translation revisions.
|
||||
$this->createRevisions($node, 1);
|
||||
$default_translation_title = $node->label();
|
||||
|
||||
// And create a few more translation revisions.
|
||||
$this->createRevisions($translation, 2);
|
||||
$translation_revision_id = $translation->getRevisionId();
|
||||
|
||||
// Now revert the a translation revision preceding the last default
|
||||
// translation revision, and check that the desired value was reverted but
|
||||
// the default translation value was preserved.
|
||||
$this->drupalPostForm("node/" . $node->id() . "/revisions/" . $revert_id . "/revert", [], t('Revert'));
|
||||
/** @var \Drupal\node\NodeStorage $node_storage */
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
$node_storage->resetCache();
|
||||
/** @var \Drupal\node\NodeInterface $node */
|
||||
$node = $node_storage->load($node->id());
|
||||
$this->assertTrue($node->getRevisionId() > $translation_revision_id);
|
||||
$this->assertEqual($node->label(), $default_translation_title);
|
||||
$this->assertEqual($node->getTranslation('it')->label(), $translated_title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a series of revisions for the specified node.
|
||||
*
|
||||
* @param \Drupal\node\NodeInterface $node
|
||||
* The node object.
|
||||
* @param $count
|
||||
* The number of revisions to be created.
|
||||
*/
|
||||
protected function createRevisions(NodeInterface $node, $count) {
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$node->title = $this->randomString();
|
||||
$node->setNewRevision(TRUE);
|
||||
$node->save();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
78
core/modules/node/src/Tests/NodeRevisionsUiTest.php
Normal file
78
core/modules/node/src/Tests/NodeRevisionsUiTest.php
Normal file
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeRevisionsUiTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\node\Entity\NodeType;
|
||||
|
||||
/**
|
||||
* Tests the UI for controlling node revision behavior.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeRevisionsUiTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create and log in user.
|
||||
$web_user = $this->drupalCreateUser(
|
||||
array(
|
||||
'administer nodes',
|
||||
'edit any page content'
|
||||
)
|
||||
);
|
||||
|
||||
$this->drupalLogin($web_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that unchecking 'Create new revision' works when editing a node.
|
||||
*/
|
||||
function testNodeFormSaveWithoutRevision() {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
|
||||
// Set page revision setting 'create new revision'. This will mean new
|
||||
// revisions are created by default when the node is edited.
|
||||
$type = NodeType::load('page');
|
||||
$type->setNewRevision(TRUE);
|
||||
$type->save();
|
||||
|
||||
// Create the node.
|
||||
$node = $this->drupalCreateNode();
|
||||
|
||||
// Verify the checkbox is checked on the node edit form.
|
||||
$this->drupalGet('node/' . $node->id() . '/edit');
|
||||
$this->assertFieldChecked('edit-revision', "'Create new revision' checkbox is checked");
|
||||
|
||||
// Uncheck the create new revision checkbox and save the node.
|
||||
$edit = array('revision' => FALSE);
|
||||
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save and keep published'));
|
||||
|
||||
// Load the node again and check the revision is the same as before.
|
||||
$node_storage->resetCache(array($node->id()));
|
||||
$node_revision = $node_storage->load($node->id(), TRUE);
|
||||
$this->assertEqual($node_revision->getRevisionId(), $node->getRevisionId(), "After an existing node is saved with 'Create new revision' unchecked, a new revision is not created.");
|
||||
|
||||
// Verify the checkbox is checked on the node edit form.
|
||||
$this->drupalGet('node/' . $node->id() . '/edit');
|
||||
$this->assertFieldChecked('edit-revision', "'Create new revision' checkbox is checked");
|
||||
|
||||
// Submit the form without changing the checkbox.
|
||||
$edit = array();
|
||||
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save and keep published'));
|
||||
|
||||
// Load the node again and check the revision is different from before.
|
||||
$node_storage->resetCache(array($node->id()));
|
||||
$node_revision = $node_storage->load($node->id());
|
||||
$this->assertNotEqual($node_revision->getRevisionId(), $node->getRevisionId(), "After an existing node is saved with 'Create new revision' checked, a new revision is created.");
|
||||
|
||||
}
|
||||
}
|
186
core/modules/node/src/Tests/NodeSaveTest.php
Normal file
186
core/modules/node/src/Tests/NodeSaveTest.php
Normal file
|
@ -0,0 +1,186 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeSaveTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\node\Entity\Node;
|
||||
|
||||
/**
|
||||
* Tests $node->save() for saving content.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeSaveTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* A normal logged in user.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $webUser;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node_test');
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create a user that is allowed to post; we'll use this to test the submission.
|
||||
$web_user = $this->drupalCreateUser(array('create article content'));
|
||||
$this->drupalLogin($web_user);
|
||||
$this->webUser = $web_user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether custom node IDs are saved properly during an import operation.
|
||||
*
|
||||
* Workflow:
|
||||
* - first create a piece of content
|
||||
* - save the content
|
||||
* - check if node exists
|
||||
*/
|
||||
function testImport() {
|
||||
// Node ID must be a number that is not in the database.
|
||||
$nids = \Drupal::entityManager()->getStorage('node')->getQuery()
|
||||
->sort('nid', 'DESC')
|
||||
->range(0, 1)
|
||||
->execute();
|
||||
$max_nid = reset($nids);
|
||||
$test_nid = $max_nid + mt_rand(1000, 1000000);
|
||||
$title = $this->randomMachineName(8);
|
||||
$node = array(
|
||||
'title' => $title,
|
||||
'body' => array(array('value' => $this->randomMachineName(32))),
|
||||
'uid' => $this->webUser->id(),
|
||||
'type' => 'article',
|
||||
'nid' => $test_nid,
|
||||
);
|
||||
/** @var \Drupal\node\NodeInterface $node */
|
||||
$node = entity_create('node', $node);
|
||||
$node->enforceIsNew();
|
||||
|
||||
$this->assertEqual($node->getOwnerId(), $this->webUser->id());
|
||||
|
||||
$node->save();
|
||||
// Test the import.
|
||||
$node_by_nid = Node::load($test_nid);
|
||||
$this->assertTrue($node_by_nid, 'Node load by node ID.');
|
||||
|
||||
$node_by_title = $this->drupalGetNodeByTitle($title);
|
||||
$this->assertTrue($node_by_title, 'Node load by node title.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies accuracy of the "created" and "changed" timestamp functionality.
|
||||
*/
|
||||
function testTimestamps() {
|
||||
// Use the default timestamps.
|
||||
$edit = array(
|
||||
'uid' => $this->webUser->id(),
|
||||
'type' => 'article',
|
||||
'title' => $this->randomMachineName(8),
|
||||
);
|
||||
|
||||
entity_create('node', $edit)->save();
|
||||
$node = $this->drupalGetNodeByTitle($edit['title']);
|
||||
$this->assertEqual($node->getCreatedTime(), REQUEST_TIME, 'Creating a node sets default "created" timestamp.');
|
||||
$this->assertEqual($node->getChangedTime(), REQUEST_TIME, 'Creating a node sets default "changed" timestamp.');
|
||||
|
||||
// Store the timestamps.
|
||||
$created = $node->getCreatedTime();
|
||||
|
||||
$node->save();
|
||||
$node = $this->drupalGetNodeByTitle($edit['title'], TRUE);
|
||||
$this->assertEqual($node->getCreatedTime(), $created, 'Updating a node preserves "created" timestamp.');
|
||||
|
||||
// Programmatically set the timestamps using hook_ENTITY_TYPE_presave().
|
||||
$node->title = 'testing_node_presave';
|
||||
|
||||
$node->save();
|
||||
$node = $this->drupalGetNodeByTitle('testing_node_presave', TRUE);
|
||||
$this->assertEqual($node->getCreatedTime(), 280299600, 'Saving a node uses "created" timestamp set in presave hook.');
|
||||
$this->assertEqual($node->getChangedTime(), 979534800, 'Saving a node uses "changed" timestamp set in presave hook.');
|
||||
|
||||
// Programmatically set the timestamps on the node.
|
||||
$edit = array(
|
||||
'uid' => $this->webUser->id(),
|
||||
'type' => 'article',
|
||||
'title' => $this->randomMachineName(8),
|
||||
'created' => 280299600, // Sun, 19 Nov 1978 05:00:00 GMT
|
||||
'changed' => 979534800, // Drupal 1.0 release.
|
||||
);
|
||||
|
||||
entity_create('node', $edit)->save();
|
||||
$node = $this->drupalGetNodeByTitle($edit['title']);
|
||||
$this->assertEqual($node->getCreatedTime(), 280299600, 'Creating a node programmatically uses programmatically set "created" timestamp.');
|
||||
$this->assertEqual($node->getChangedTime(), 979534800, 'Creating a node programmatically uses programmatically set "changed" timestamp.');
|
||||
|
||||
// Update the timestamps.
|
||||
$node->setCreatedTime(979534800);
|
||||
$node->changed = 280299600;
|
||||
|
||||
$node->save();
|
||||
$node = $this->drupalGetNodeByTitle($edit['title'], TRUE);
|
||||
$this->assertEqual($node->getCreatedTime(), 979534800, 'Updating a node uses user-set "created" timestamp.');
|
||||
// Allowing setting changed timestamps is required, see
|
||||
// Drupal\content_translation\ContentTranslationMetadataWrapper::setChangedTime($timestamp)
|
||||
// for example.
|
||||
$this->assertEqual($node->getChangedTime(), 280299600, 'Updating a node uses user-set "changed" timestamp.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests node presave and static node load cache.
|
||||
*
|
||||
* This test determines changes in hook_ENTITY_TYPE_presave() and verifies
|
||||
* that the static node load cache is cleared upon save.
|
||||
*/
|
||||
function testDeterminingChanges() {
|
||||
// Initial creation.
|
||||
$node = entity_create('node', array(
|
||||
'uid' => $this->webUser->id(),
|
||||
'type' => 'article',
|
||||
'title' => 'test_changes',
|
||||
));
|
||||
$node->save();
|
||||
|
||||
// Update the node without applying changes.
|
||||
$node->save();
|
||||
$this->assertEqual($node->label(), 'test_changes', 'No changes have been determined.');
|
||||
|
||||
// Apply changes.
|
||||
$node->title = 'updated';
|
||||
$node->save();
|
||||
|
||||
// The hook implementations node_test_node_presave() and
|
||||
// node_test_node_update() determine changes and change the title.
|
||||
$this->assertEqual($node->label(), 'updated_presave_update', 'Changes have been determined.');
|
||||
|
||||
// Test the static node load cache to be cleared.
|
||||
$node = Node::load($node->id());
|
||||
$this->assertEqual($node->label(), 'updated_presave', 'Static cache has been cleared.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests saving a node on node insert.
|
||||
*
|
||||
* This test ensures that a node has been fully saved when
|
||||
* hook_ENTITY_TYPE_insert() is invoked, so that the node can be saved again
|
||||
* in a hook implementation without errors.
|
||||
*
|
||||
* @see node_test_node_insert()
|
||||
*/
|
||||
function testNodeSaveOnInsert() {
|
||||
// node_test_node_insert() triggers a save on insert if the title equals
|
||||
// 'new'.
|
||||
$node = $this->drupalCreateNode(array('title' => 'new'));
|
||||
$this->assertEqual($node->getTitle(), 'Node ' . $node->id(), 'Node saved on node insert.');
|
||||
}
|
||||
}
|
42
core/modules/node/src/Tests/NodeSyndicateBlockTest.php
Normal file
42
core/modules/node/src/Tests/NodeSyndicateBlockTest.php
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeSyndicateBlockTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Tests if the syndicate block is available.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeSyndicateBlockTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('block');
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create a user and log in.
|
||||
$admin_user = $this->drupalCreateUser(array('administer blocks'));
|
||||
$this->drupalLogin($admin_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the "Syndicate" block is shown when enabled.
|
||||
*/
|
||||
public function testSyndicateBlock() {
|
||||
// Place the "Syndicate" block and confirm that it is rendered.
|
||||
$this->drupalPlaceBlock('node_syndicate_block', array('id' => 'test_syndicate_block'));
|
||||
$this->drupalGet('');
|
||||
$this->assertFieldByXPath('//div[@id="block-test-syndicate-block"]/*', NULL, 'Syndicate block found.');
|
||||
}
|
||||
|
||||
}
|
43
core/modules/node/src/Tests/NodeTemplateSuggestionsTest.php
Normal file
43
core/modules/node/src/Tests/NodeTemplateSuggestionsTest.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeTemplateSuggestionsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Tests node template suggestions.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeTemplateSuggestionsTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Tests if template_preprocess_node() generates the correct suggestions.
|
||||
*/
|
||||
function testNodeThemeHookSuggestions() {
|
||||
// Create node to be rendered.
|
||||
$node = $this->drupalCreateNode();
|
||||
$view_mode = 'full';
|
||||
|
||||
// Simulate theming of the node.
|
||||
$build = \Drupal::entityManager()->getViewBuilder('node')->view($node, $view_mode);
|
||||
|
||||
$variables['elements'] = $build;
|
||||
$suggestions = \Drupal::moduleHandler()->invokeAll('theme_suggestions_node', array($variables));
|
||||
|
||||
$this->assertEqual($suggestions, array('node__full', 'node__page', 'node__page__full', 'node__' . $node->id(), 'node__' . $node->id() . '__full'), 'Found expected node suggestions.');
|
||||
|
||||
// Change the view mode.
|
||||
$view_mode = 'node.my_custom_view_mode';
|
||||
$build = \Drupal::entityManager()->getViewBuilder('node')->view($node, $view_mode);
|
||||
|
||||
$variables['elements'] = $build;
|
||||
$suggestions = \Drupal::moduleHandler()->invokeAll('theme_suggestions_node', array($variables));
|
||||
|
||||
$this->assertEqual($suggestions, array('node__node_my_custom_view_mode', 'node__page', 'node__page__node_my_custom_view_mode', 'node__' . $node->id(), 'node__' . $node->id() . '__node_my_custom_view_mode'), 'Found expected node suggestions.');
|
||||
}
|
||||
|
||||
}
|
120
core/modules/node/src/Tests/NodeTestBase.php
Normal file
120
core/modules/node/src/Tests/NodeTestBase.php
Normal file
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeTestBase.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Sets up page and article content types.
|
||||
*/
|
||||
abstract class NodeTestBase extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node', 'datetime');
|
||||
|
||||
/**
|
||||
* The node access control handler.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityAccessControlHandlerInterface
|
||||
*/
|
||||
protected $accessHandler;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create Basic page and Article node types.
|
||||
if ($this->profile != 'standard') {
|
||||
$this->drupalCreateContentType(array(
|
||||
'type' => 'page',
|
||||
'name' => 'Basic page',
|
||||
'display_submitted' => FALSE,
|
||||
));
|
||||
$this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
|
||||
}
|
||||
$this->accessHandler = \Drupal::entityManager()->getAccessControlHandler('node');
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that node access correctly grants or denies access.
|
||||
*
|
||||
* @param array $ops
|
||||
* An associative array of the expected node access grants for the node
|
||||
* and account, with each key as the name of an operation (e.g. 'view',
|
||||
* 'delete') and each value a Boolean indicating whether access to that
|
||||
* operation should be granted.
|
||||
* @param \Drupal\node\Entity\Node $node
|
||||
* The node object to check.
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The user account for which to check access.
|
||||
* @param string|null $langcode
|
||||
* (optional) The language code indicating which translation of the node
|
||||
* to check. If NULL, the untranslated (fallback) access is checked.
|
||||
*/
|
||||
function assertNodeAccess(array $ops, $node, AccountInterface $account, $langcode = NULL) {
|
||||
foreach ($ops as $op => $result) {
|
||||
if (empty($langcode)) {
|
||||
$langcode = $node->prepareLangcode();
|
||||
}
|
||||
$this->assertEqual($result, $this->accessHandler->access($node, $op, $langcode, $account), $this->nodeAccessAssertMessage($op, $result, $langcode));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that node create access correctly grants or denies access.
|
||||
*
|
||||
* @param string $bundle
|
||||
* The node bundle to check access to.
|
||||
* @param bool $result
|
||||
* Whether access should be granted or not.
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The user account for which to check access.
|
||||
* @param string|null $langcode
|
||||
* (optional) The language code indicating which translation of the node
|
||||
* to check. If NULL, the untranslated (fallback) access is checked.
|
||||
*/
|
||||
function assertNodeCreateAccess($bundle, $result, AccountInterface $account, $langcode = NULL) {
|
||||
$this->assertEqual($result, $this->accessHandler->createAccess($bundle, $account, array(
|
||||
'langcode' => $langcode,
|
||||
)), $this->nodeAccessAssertMessage('create', $result, $langcode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an assert message to display which node access was tested.
|
||||
*
|
||||
* @param string $operation
|
||||
* The operation to check access for.
|
||||
* @param bool $result
|
||||
* Whether access should be granted or not.
|
||||
* @param string|null $langcode
|
||||
* (optional) The language code indicating which translation of the node
|
||||
* to check. If NULL, the untranslated (fallback) access is checked.
|
||||
*
|
||||
* @return string
|
||||
* An assert message string which contains information in plain English
|
||||
* about the node access permission test that was performed.
|
||||
*/
|
||||
function nodeAccessAssertMessage($operation, $result, $langcode = NULL) {
|
||||
return format_string(
|
||||
'Node access returns @result with operation %op, language code %langcode.',
|
||||
array(
|
||||
'@result' => $result ? 'true' : 'false',
|
||||
'%op' => $operation,
|
||||
'%langcode' => !empty($langcode) ? $langcode : 'empty'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
89
core/modules/node/src/Tests/NodeTitleTest.php
Normal file
89
core/modules/node/src/Tests/NodeTitleTest.php
Normal file
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeTitleTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\comment\Tests\CommentTestTrait;
|
||||
|
||||
/**
|
||||
* Tests node title.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeTitleTest extends NodeTestBase {
|
||||
|
||||
use CommentTestTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('comment', 'views', 'block');
|
||||
|
||||
/**
|
||||
* A user with permission to bypass access content.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->drupalPlaceBlock('system_breadcrumb_block');
|
||||
|
||||
$this->adminUser = $this->drupalCreateUser(array('administer nodes', 'create article content', 'create page content', 'post comments'));
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->addDefaultCommentField('node', 'page');
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates one node and tests if the node title has the correct value.
|
||||
*/
|
||||
function testNodeTitle() {
|
||||
// Create "Basic page" content with title.
|
||||
// Add the node to the frontpage so we can test if teaser links are
|
||||
// clickable.
|
||||
$settings = array(
|
||||
'title' => $this->randomMachineName(8),
|
||||
'promote' => 1,
|
||||
);
|
||||
$node = $this->drupalCreateNode($settings);
|
||||
|
||||
// Test <title> tag.
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$xpath = '//title';
|
||||
$this->assertEqual(current($this->xpath($xpath)), $node->label() .' | Drupal', 'Page title is equal to node title.', 'Node');
|
||||
|
||||
// Test breadcrumb in comment preview.
|
||||
$this->drupalGet('comment/reply/node/' . $node->id() . '/comment');
|
||||
$xpath = '//nav[@class="breadcrumb"]/ol/li[last()]/a';
|
||||
$this->assertEqual(current($this->xpath($xpath)), $node->label(), 'Node breadcrumb is equal to node title.', 'Node');
|
||||
|
||||
// Test node title in comment preview.
|
||||
$this->assertEqual(current($this->xpath('//article[contains(concat(" ", normalize-space(@class), " "), :node-class)]/h2/a/span', array(':node-class' => ' node--type-' . $node->bundle() . ' '))), $node->label(), 'Node preview title is equal to node title.', 'Node');
|
||||
|
||||
// Test node title is clickable on teaser list (/node).
|
||||
$this->drupalGet('node');
|
||||
$this->clickLink($node->label());
|
||||
|
||||
// Test edge case where node title is set to 0.
|
||||
$settings = array(
|
||||
'title' => 0,
|
||||
);
|
||||
$node = $this->drupalCreateNode($settings);
|
||||
// Test that 0 appears as <title>.
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$this->assertTitle(0 . ' | Drupal', 'Page title is equal to 0.', 'Node');
|
||||
// Test that 0 appears in the template <h1>.
|
||||
$xpath = '//h1';
|
||||
$this->assertEqual(current($this->xpath($xpath)), 0, 'Node title is displayed as 0.', 'Node');
|
||||
}
|
||||
}
|
44
core/modules/node/src/Tests/NodeTitleXSSTest.php
Normal file
44
core/modules/node/src/Tests/NodeTitleXSSTest.php
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeTitleXSSTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Create a node with dangerous tags in its title and test that they are
|
||||
* escaped.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeTitleXSSTest extends NodeTestBase {
|
||||
/**
|
||||
* Tests XSS functionality with a node entity.
|
||||
*/
|
||||
function testNodeTitleXSS() {
|
||||
// Prepare a user to do the stuff.
|
||||
$web_user = $this->drupalCreateUser(array('create page content', 'edit any page content'));
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
$xss = '<script>alert("xss")</script>';
|
||||
$title = $xss . $this->randomMachineName();
|
||||
$edit = array();
|
||||
$edit['title[0][value]'] = $title;
|
||||
|
||||
$this->drupalPostForm('node/add/page', $edit, t('Preview'));
|
||||
$this->assertNoRaw($xss, 'Harmful tags are escaped when previewing a node.');
|
||||
|
||||
$settings = array('title' => $title);
|
||||
$node = $this->drupalCreateNode($settings);
|
||||
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
// assertTitle() decodes HTML-entities inside the <title> element.
|
||||
$this->assertTitle($title . ' | Drupal', 'Title is displayed when viewing a node.');
|
||||
$this->assertNoRaw($xss, 'Harmful tags are escaped when viewing a node.');
|
||||
|
||||
$this->drupalGet('node/' . $node->id() . '/edit');
|
||||
$this->assertNoRaw($xss, 'Harmful tags are escaped when editing a node.');
|
||||
}
|
||||
}
|
129
core/modules/node/src/Tests/NodeTokenReplaceTest.php
Normal file
129
core/modules/node/src/Tests/NodeTokenReplaceTest.php
Normal file
|
@ -0,0 +1,129 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeTokenReplaceTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\system\Tests\System\TokenReplaceUnitTestBase;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
|
||||
/**
|
||||
* Generates text using placeholders for dummy content to check node token
|
||||
* replacement.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeTokenReplaceTest extends TokenReplaceUnitTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node', 'filter');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installConfig(array('filter', 'node'));
|
||||
|
||||
$node_type = entity_create('node_type', array('type' => 'article', 'name' => 'Article'));
|
||||
$node_type->save();
|
||||
node_add_body_field($node_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a node, then tests the tokens generated from it.
|
||||
*/
|
||||
function testNodeTokenReplacement() {
|
||||
$url_options = array(
|
||||
'absolute' => TRUE,
|
||||
'language' => $this->interfaceLanguage,
|
||||
);
|
||||
|
||||
// Create a user and a node.
|
||||
$account = $this->createUser();
|
||||
/* @var $node \Drupal\node\NodeInterface */
|
||||
$node = entity_create('node', array(
|
||||
'type' => 'article',
|
||||
'tnid' => 0,
|
||||
'uid' => $account->id(),
|
||||
'title' => '<blink>Blinking Text</blink>',
|
||||
'body' => array(array('value' => $this->randomMachineName(32), 'summary' => $this->randomMachineName(16), 'format' => 'plain_text')),
|
||||
));
|
||||
$node->save();
|
||||
|
||||
// Generate and test sanitized tokens.
|
||||
$tests = array();
|
||||
$tests['[node:nid]'] = $node->id();
|
||||
$tests['[node:vid]'] = $node->getRevisionId();
|
||||
$tests['[node:type]'] = 'article';
|
||||
$tests['[node:type-name]'] = 'Article';
|
||||
$tests['[node:title]'] = SafeMarkup::checkPlain($node->getTitle());
|
||||
$tests['[node:body]'] = $node->body->processed;
|
||||
$tests['[node:summary]'] = $node->body->summary_processed;
|
||||
$tests['[node:langcode]'] = SafeMarkup::checkPlain($node->language()->getId());
|
||||
$tests['[node:url]'] = $node->url('canonical', $url_options);
|
||||
$tests['[node:edit-url]'] = $node->url('edit-form', $url_options);
|
||||
$tests['[node:author]'] = SafeMarkup::checkPlain($account->getUsername());
|
||||
$tests['[node:author:uid]'] = $node->getOwnerId();
|
||||
$tests['[node:author:name]'] = SafeMarkup::checkPlain($account->getUsername());
|
||||
$tests['[node:created:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($node->getCreatedTime(), array('langcode' => $this->interfaceLanguage->getId()));
|
||||
$tests['[node:changed:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($node->getChangedTime(), array('langcode' => $this->interfaceLanguage->getId()));
|
||||
|
||||
// Test to make sure that we generated something for each token.
|
||||
$this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated.');
|
||||
|
||||
foreach ($tests as $input => $expected) {
|
||||
$output = $this->tokenService->replace($input, array('node' => $node), array('langcode' => $this->interfaceLanguage->getId()));
|
||||
$this->assertEqual($output, $expected, format_string('Sanitized node token %token replaced.', array('%token' => $input)));
|
||||
}
|
||||
|
||||
// Generate and test unsanitized tokens.
|
||||
$tests['[node:title]'] = $node->getTitle();
|
||||
$tests['[node:body]'] = $node->body->value;
|
||||
$tests['[node:summary]'] = $node->body->summary;
|
||||
$tests['[node:langcode]'] = $node->language()->getId();
|
||||
$tests['[node:author:name]'] = $account->getUsername();
|
||||
|
||||
foreach ($tests as $input => $expected) {
|
||||
$output = $this->tokenService->replace($input, array('node' => $node), array('langcode' => $this->interfaceLanguage->getId(), 'sanitize' => FALSE));
|
||||
$this->assertEqual($output, $expected, format_string('Unsanitized node token %token replaced.', array('%token' => $input)));
|
||||
}
|
||||
|
||||
// Repeat for a node without a summary.
|
||||
$node = entity_create('node', array(
|
||||
'type' => 'article',
|
||||
'uid' => $account->id(),
|
||||
'title' => '<blink>Blinking Text</blink>',
|
||||
'body' => array(array('value' => $this->randomMachineName(32), 'format' => 'plain_text')),
|
||||
));
|
||||
$node->save();
|
||||
|
||||
// Generate and test sanitized token - use full body as expected value.
|
||||
$tests = array();
|
||||
$tests['[node:summary]'] = $node->body->processed;
|
||||
|
||||
// Test to make sure that we generated something for each token.
|
||||
$this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated for node without a summary.');
|
||||
|
||||
foreach ($tests as $input => $expected) {
|
||||
$output = $this->tokenService->replace($input, array('node' => $node), array('language' => $this->interfaceLanguage));
|
||||
$this->assertEqual($output, $expected, format_string('Sanitized node token %token replaced for node without a summary.', array('%token' => $input)));
|
||||
}
|
||||
|
||||
// Generate and test unsanitized tokens.
|
||||
$tests['[node:summary]'] = $node->body->value;
|
||||
|
||||
foreach ($tests as $input => $expected) {
|
||||
$output = $this->tokenService->replace($input, array('node' => $node), array('language' => $this->interfaceLanguage, 'sanitize' => FALSE));
|
||||
$this->assertEqual($output, $expected, format_string('Unsanitized node token %token replaced for node without a summary.', array('%token' => $input)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
401
core/modules/node/src/Tests/NodeTranslationUITest.php
Normal file
401
core/modules/node/src/Tests/NodeTranslationUITest.php
Normal file
|
@ -0,0 +1,401 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeTranslationUITest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\content_translation\Tests\ContentTranslationUITestBase;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\node\Entity\Node;
|
||||
|
||||
/**
|
||||
* Tests the Node Translation UI.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeTranslationUITest extends ContentTranslationUITestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('block', 'language', 'content_translation', 'node', 'datetime', 'field_ui', 'help');
|
||||
|
||||
/**
|
||||
* The profile to install as a basis for testing.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $profile = 'standard';
|
||||
|
||||
protected function setUp() {
|
||||
$this->entityTypeId = 'node';
|
||||
$this->bundle = 'article';
|
||||
parent::setUp();
|
||||
|
||||
// Ensure the help message is shown even with prefixed paths.
|
||||
$this->drupalPlaceBlock('help_block', array('region' => 'content'));
|
||||
|
||||
// Display the language selector.
|
||||
$this->drupalLogin($this->administrator);
|
||||
$edit = array('language_configuration[language_alterable]' => TRUE);
|
||||
$this->drupalPostForm('admin/structure/types/manage/article', $edit, t('Save content type'));
|
||||
$this->drupalLogin($this->translator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the basic translation UI.
|
||||
*/
|
||||
function testTranslationUI() {
|
||||
parent::testTranslationUI();
|
||||
$this->doUninstallTest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides \Drupal\content_translation\Tests\ContentTranslationUITestBase::getTranslatorPermission().
|
||||
*/
|
||||
protected function getTranslatorPermissions() {
|
||||
return array_merge(parent::getTranslatorPermissions(), array('administer nodes', "edit any $this->bundle content"));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getEditorPermissions() {
|
||||
return array('administer nodes', 'create article content');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getAdministratorPermissions() {
|
||||
return array_merge(parent::getAdministratorPermissions(), array('access administration pages', 'administer content types', 'administer node fields', 'access content overview', 'bypass node access', 'administer languages', 'administer themes', 'view the administration theme'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides \Drupal\content_translation\Tests\ContentTranslationUITestBase::getNewEntityValues().
|
||||
*/
|
||||
protected function getNewEntityValues($langcode) {
|
||||
return array('title' => array(array('value' => $this->randomMachineName()))) + parent::getNewEntityValues($langcode);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getFormSubmitAction(EntityInterface $entity, $langcode) {
|
||||
if ($entity->getTranslation($langcode)->isPublished()) {
|
||||
return t('Save and keep published') . $this->getFormSubmitSuffix($entity, $langcode);
|
||||
}
|
||||
else {
|
||||
return t('Save and keep unpublished') . $this->getFormSubmitSuffix($entity, $langcode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides \Drupal\content_translation\Tests\ContentTranslationUITestBase::assertPublishedStatus().
|
||||
*/
|
||||
protected function doTestPublishedStatus() {
|
||||
$entity = entity_load($this->entityTypeId, $this->entityId, TRUE);
|
||||
$languages = $this->container->get('language_manager')->getLanguages();
|
||||
|
||||
$actions = array(
|
||||
t('Save and keep published'),
|
||||
t('Save and unpublish'),
|
||||
);
|
||||
|
||||
foreach ($actions as $index => $action) {
|
||||
// (Un)publish the node translations and check that the translation
|
||||
// statuses are (un)published accordingly.
|
||||
foreach ($this->langcodes as $langcode) {
|
||||
$options = array('language' => $languages[$langcode]);
|
||||
$url = $entity->urlInfo('edit-form', $options);
|
||||
$this->drupalPostForm($url, array(), $action . $this->getFormSubmitSuffix($entity, $langcode), $options);
|
||||
}
|
||||
$entity = entity_load($this->entityTypeId, $this->entityId, TRUE);
|
||||
foreach ($this->langcodes as $langcode) {
|
||||
// The node is created as unpublished thus we switch to the published
|
||||
// status first.
|
||||
$status = !$index;
|
||||
$translation = $entity->getTranslation($langcode);
|
||||
$this->assertEqual($status, $this->manager->getTranslationMetadata($translation)->isPublished(), 'The translation has been correctly unpublished.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides \Drupal\content_translation\Tests\ContentTranslationUITestBase::assertAuthoringInfo().
|
||||
*/
|
||||
protected function doTestAuthoringInfo() {
|
||||
$entity = entity_load($this->entityTypeId, $this->entityId, TRUE);
|
||||
$languages = $this->container->get('language_manager')->getLanguages();
|
||||
$values = array();
|
||||
|
||||
// Post different base field information for each translation.
|
||||
foreach ($this->langcodes as $langcode) {
|
||||
$user = $this->drupalCreateUser();
|
||||
$values[$langcode] = array(
|
||||
'uid' => $user->id(),
|
||||
'created' => REQUEST_TIME - mt_rand(0, 1000),
|
||||
'sticky' => (bool) mt_rand(0, 1),
|
||||
'promote' => (bool) mt_rand(0, 1),
|
||||
);
|
||||
$edit = array(
|
||||
'uid[0][target_id]' => $user->getUsername(),
|
||||
'created[0][value][date]' => format_date($values[$langcode]['created'], 'custom', 'Y-m-d'),
|
||||
'created[0][value][time]' => format_date($values[$langcode]['created'], 'custom', 'H:i:s'),
|
||||
'sticky[value]' => $values[$langcode]['sticky'],
|
||||
'promote[value]' => $values[$langcode]['promote'],
|
||||
);
|
||||
$options = array('language' => $languages[$langcode]);
|
||||
$url = $entity->urlInfo('edit-form', $options);
|
||||
$this->drupalPostForm($url, $edit, $this->getFormSubmitAction($entity, $langcode), $options);
|
||||
}
|
||||
|
||||
$entity = entity_load($this->entityTypeId, $this->entityId, TRUE);
|
||||
foreach ($this->langcodes as $langcode) {
|
||||
$translation = $entity->getTranslation($langcode);
|
||||
$metadata = $this->manager->getTranslationMetadata($translation);
|
||||
$this->assertEqual($metadata->getAuthor()->id(), $values[$langcode]['uid'], 'Translation author correctly stored.');
|
||||
$this->assertEqual($metadata->getCreatedTime(), $values[$langcode]['created'], 'Translation date correctly stored.');
|
||||
$this->assertEqual($translation->isSticky(), $values[$langcode]['sticky'], 'Sticky of Translation correctly stored.');
|
||||
$this->assertEqual($translation->isPromoted(), $values[$langcode]['promote'], 'Promoted of Translation correctly stored.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that translation page inherits admin status of edit page.
|
||||
*/
|
||||
function testTranslationLinkTheme() {
|
||||
$this->drupalLogin($this->administrator);
|
||||
$article = $this->drupalCreateNode(array('type' => 'article', 'langcode' => $this->langcodes[0]));
|
||||
|
||||
// Set up Seven as the admin theme and use it for node editing.
|
||||
$this->container->get('theme_handler')->install(array('seven'));
|
||||
$edit = array();
|
||||
$edit['admin_theme'] = 'seven';
|
||||
$edit['use_admin_theme'] = TRUE;
|
||||
$this->drupalPostForm('admin/appearance', $edit, t('Save configuration'));
|
||||
$this->drupalGet('node/' . $article->id() . '/translations');
|
||||
$this->assertRaw('core/themes/seven/css/base/elements.css', 'Translation uses admin theme if edit is admin.');
|
||||
|
||||
// Turn off admin theme for editing, assert inheritance to translations.
|
||||
$edit['use_admin_theme'] = FALSE;
|
||||
$this->drupalPostForm('admin/appearance', $edit, t('Save configuration'));
|
||||
$this->drupalGet('node/' . $article->id() . '/translations');
|
||||
$this->assertNoRaw('core/themes/seven/css/base/elements.css', 'Translation uses frontend theme if edit is frontend.');
|
||||
|
||||
// Assert presence of translation page itself (vs. DisabledBundle below).
|
||||
$this->assertResponse(200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that no metadata is stored for a disabled bundle.
|
||||
*/
|
||||
public function testDisabledBundle() {
|
||||
// Create a bundle that does not have translation enabled.
|
||||
$disabledBundle = $this->randomMachineName();
|
||||
$this->drupalCreateContentType(array('type' => $disabledBundle, 'name' => $disabledBundle));
|
||||
|
||||
// Create a node for each bundle.
|
||||
$node = $this->drupalCreateNode(array(
|
||||
'type' => $this->bundle,
|
||||
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
||||
));
|
||||
|
||||
// Make sure that nothing was inserted into the {content_translation} table.
|
||||
$rows = db_query('SELECT nid, count(nid) AS count FROM {node_field_data} WHERE type <> :type GROUP BY nid HAVING count(nid) >= 2', array(':type' => $this->bundle))->fetchAll();
|
||||
$this->assertEqual(0, count($rows));
|
||||
|
||||
// Ensure the translation tab is not accessible.
|
||||
$this->drupalGet('node/' . $node->id() . '/translations');
|
||||
$this->assertResponse(403);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that translations are rendered properly.
|
||||
*/
|
||||
function testTranslationRendering() {
|
||||
$default_langcode = $this->langcodes[0];
|
||||
$values[$default_langcode] = $this->getNewEntityValues($default_langcode);
|
||||
$this->entityId = $this->createEntity($values[$default_langcode], $default_langcode);
|
||||
$node = \Drupal::entityManager()->getStorage($this->entityTypeId)->load($this->entityId);
|
||||
$node->setPromoted(TRUE);
|
||||
|
||||
// Create translations.
|
||||
foreach (array_diff($this->langcodes, array($default_langcode)) as $langcode) {
|
||||
$values[$langcode] = $this->getNewEntityValues($langcode);
|
||||
$translation = $node->addTranslation($langcode, $values[$langcode]);
|
||||
// Publish and promote the translation to frontpage.
|
||||
$translation->setPromoted(TRUE);
|
||||
$translation->setPublished(TRUE);
|
||||
}
|
||||
$node->save();
|
||||
|
||||
// Test that the frontpage view displays the correct translations.
|
||||
\Drupal::service('module_installer')->install(array('views'), TRUE);
|
||||
$this->rebuildContainer();
|
||||
$this->doTestTranslations('node', $values);
|
||||
|
||||
// Enable the translation language renderer.
|
||||
$view = \Drupal::entityManager()->getStorage('view')->load('frontpage');
|
||||
$display = &$view->getDisplay('default');
|
||||
$display['display_options']['rendering_language'] = '***LANGUAGE_entity_translation***';
|
||||
$view->save();
|
||||
|
||||
// Need to check from the beginning, including the base_path, in the url
|
||||
// since the pattern for the default language might be a substring of
|
||||
// the strings for other languages.
|
||||
$base_path = base_path();
|
||||
|
||||
// Check the frontpage for 'Read more' links to each translation.
|
||||
// See also assertTaxonomyPage() in NodeAccessBaseTableTest.
|
||||
$node_href = 'node/' . $node->id();
|
||||
foreach ($this->langcodes as $langcode) {
|
||||
$this->drupalGet('node', array('language' => \Drupal::languageManager()->getLanguage($langcode)));
|
||||
$num_match_found = 0;
|
||||
if ($langcode == 'en') {
|
||||
// Site default language does not have langcode prefix in the URL.
|
||||
$expected_href = $base_path . $node_href;
|
||||
}
|
||||
else {
|
||||
$expected_href = $base_path . $langcode . '/' . $node_href;
|
||||
}
|
||||
$pattern = '|^' . $expected_href . '$|';
|
||||
foreach ($this->xpath("//a[text()='Read more']") as $link) {
|
||||
if (preg_match($pattern, (string) $link['href'], $matches) == TRUE) {
|
||||
$num_match_found++;
|
||||
}
|
||||
}
|
||||
$this->assertTrue($num_match_found == 1, 'There is 1 Read more link, ' . $expected_href . ', for the ' . $langcode . ' translation of a node on the frontpage. (Found ' . $num_match_found . '.)');
|
||||
}
|
||||
|
||||
// Check the frontpage for 'Add new comment' links that include the
|
||||
// language.
|
||||
$comment_form_href = 'node/' . $node->id() . '#comment-form';
|
||||
foreach ($this->langcodes as $langcode) {
|
||||
$this->drupalGet('node', array('language' => \Drupal::languageManager()->getLanguage($langcode)));
|
||||
$num_match_found = 0;
|
||||
if ($langcode == 'en') {
|
||||
// Site default language does not have langcode prefix in the URL.
|
||||
$expected_href = $base_path . $comment_form_href;
|
||||
}
|
||||
else {
|
||||
$expected_href = $base_path . $langcode . '/' . $comment_form_href;
|
||||
}
|
||||
$pattern = '|^' . $expected_href . '$|';
|
||||
foreach ($this->xpath("//a[text()='Add new comment']") as $link) {
|
||||
if (preg_match($pattern, (string) $link['href'], $matches) == TRUE) {
|
||||
$num_match_found++;
|
||||
}
|
||||
}
|
||||
$this->assertTrue($num_match_found == 1, 'There is 1 Add new comment link, ' . $expected_href . ', for the ' . $langcode . ' translation of a node on the frontpage. (Found ' . $num_match_found . '.)');
|
||||
}
|
||||
|
||||
// Test that the node page displays the correct translations.
|
||||
$this->doTestTranslations('node/' . $node->id(), $values);
|
||||
|
||||
// Test that the node page has the correct alternate hreflang links.
|
||||
$this->doTestAlternateHreflangLinks($node->urlInfo());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the given path displays the correct translation values.
|
||||
*
|
||||
* @param string $path
|
||||
* The path to be tested.
|
||||
* @param array $values
|
||||
* The translation values to be found.
|
||||
*/
|
||||
protected function doTestTranslations($path, array $values) {
|
||||
$languages = $this->container->get('language_manager')->getLanguages();
|
||||
foreach ($this->langcodes as $langcode) {
|
||||
$this->drupalGet($path, array('language' => $languages[$langcode]));
|
||||
$this->assertText($values[$langcode]['title'][0]['value'], format_string('The %langcode node translation is correctly displayed.', array('%langcode' => $langcode)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the given path provides the correct alternate hreflang links.
|
||||
*
|
||||
* @param \Drupal\Core\Url $url
|
||||
* The path to be tested.
|
||||
*/
|
||||
protected function doTestAlternateHreflangLinks(Url $url) {
|
||||
$languages = $this->container->get('language_manager')->getLanguages();
|
||||
$url->setAbsolute();
|
||||
$urls = [];
|
||||
foreach ($this->langcodes as $langcode) {
|
||||
$language_url = clone $url;
|
||||
$urls[$langcode] = $language_url->setOption('language', $languages[$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]',
|
||||
array(':href' => $language_url->toString(), ':hreflang' => $alternate_langcode));
|
||||
$this->assert(isset($links[0]), format_string('The %langcode node translation has the correct alternate hreflang link for %alternate_langcode: %link.', array('%langcode' => $langcode, '%alternate_langcode' => $alternate_langcode, '%link' => $url->toString())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getFormSubmitSuffix(EntityInterface $entity, $langcode) {
|
||||
if (!$entity->isNew() && $entity->isTranslatable()) {
|
||||
$translations = $entity->getTranslationLanguages();
|
||||
if ((count($translations) > 1 || !isset($translations[$langcode])) && ($field = $entity->getFieldDefinition('status'))) {
|
||||
return ' ' . ($field->isTranslatable() ? t('(this translation)') : t('(all translations)'));
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests uninstalling content_translation.
|
||||
*/
|
||||
protected function doUninstallTest() {
|
||||
// Delete all the nodes so there is no data.
|
||||
$nodes = Node::loadMultiple();
|
||||
foreach ($nodes as $node) {
|
||||
$node->delete();
|
||||
}
|
||||
$language_count = count(\Drupal::configFactory()->listAll('language.content_settings.'));
|
||||
\Drupal::service('module_installer')->uninstall(['content_translation']);
|
||||
$this->rebuildContainer();
|
||||
$this->assertEqual($language_count, count(\Drupal::configFactory()->listAll('language.content_settings.')), 'Languages have been fixed rather than deleted during content_translation uninstall.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function doTestTranslationEdit() {
|
||||
$entity = entity_load($this->entityTypeId, $this->entityId, TRUE);
|
||||
$languages = $this->container->get('language_manager')->getLanguages();
|
||||
$type_name = node_get_type_label($entity);
|
||||
|
||||
foreach ($this->langcodes as $langcode) {
|
||||
// We only want to test the title for non-english translations.
|
||||
if ($langcode != 'en') {
|
||||
$options = array('language' => $languages[$langcode]);
|
||||
$url = $entity->urlInfo('edit-form', $options);
|
||||
$this->drupalGet($url);
|
||||
|
||||
$title = t('<em>Edit @type</em> @title [%language translation]', array(
|
||||
'@type' => $type_name,
|
||||
'@title' => $entity->getTranslation($langcode)->label(),
|
||||
'%language' => $languages[$langcode]->getName(),
|
||||
));
|
||||
$this->assertRaw($title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
130
core/modules/node/src/Tests/NodeTypeInitialLanguageTest.php
Normal file
130
core/modules/node/src/Tests/NodeTypeInitialLanguageTest.php
Normal file
|
@ -0,0 +1,130 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeTypeInitialLanguageTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
|
||||
/**
|
||||
* Tests node type initial language settings.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeTypeInitialLanguageTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('language', 'field_ui');
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types', 'administer node fields', 'administer node form display', 'administer node display', 'administer languages'));
|
||||
$this->drupalLogin($web_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the node type initial language defaults, and modifies them.
|
||||
*
|
||||
* The default initial language must be the site's default, and the language
|
||||
* locked option must be on.
|
||||
*/
|
||||
function testNodeTypeInitialLanguageDefaults() {
|
||||
$this->drupalGet('admin/structure/types/manage/article');
|
||||
$this->assertOptionSelected('edit-language-configuration-langcode', LanguageInterface::LANGCODE_SITE_DEFAULT, 'The default initial language is the site default.');
|
||||
$this->assertNoFieldChecked('edit-language-configuration-language-alterable', 'Language selector is hidden by default.');
|
||||
|
||||
// Tests if the language field cannot be rearranged on the manage fields tab.
|
||||
$this->drupalGet('admin/structure/types/manage/article/fields');
|
||||
$language_field = $this->xpath('//*[@id="field-overview"]/*[@id="language"]');
|
||||
$this->assert(empty($language_field), 'Language field is not visible on manage fields tab.');
|
||||
|
||||
$this->drupalGet('node/add/article');
|
||||
$this->assertNoField('langcode', 'Language is not selectable on node add/edit page by default.');
|
||||
|
||||
// Adds a new language and set it as default.
|
||||
$edit = array(
|
||||
'predefined_langcode' => 'hu',
|
||||
);
|
||||
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
|
||||
$edit = array(
|
||||
'site_default_language' => 'hu',
|
||||
);
|
||||
$this->drupalPostForm('admin/config/regional/language', $edit, t('Save configuration'));
|
||||
|
||||
// Tests the initial language after changing the site default language.
|
||||
// First unhide the language selector.
|
||||
$edit = array(
|
||||
'language_configuration[language_alterable]' => TRUE,
|
||||
);
|
||||
$this->drupalPostForm('admin/structure/types/manage/article', $edit, t('Save content type'));
|
||||
$this->drupalGet('node/add/article');
|
||||
$this->assertField('langcode[0][value]', 'Language is selectable on node add/edit page when language not hidden.');
|
||||
$this->assertOptionSelected('edit-langcode-0-value', 'hu', 'The initial language is the site default on the node add page after the site default language is changed.');
|
||||
|
||||
// Tests if the language field can be rearranged on the manage form display
|
||||
// tab.
|
||||
$this->drupalGet('admin/structure/types/manage/article/form-display');
|
||||
$language_field = $this->xpath('//*[@id="langcode"]');
|
||||
$this->assert(!empty($language_field), 'Language field is visible on manage form display tab.');
|
||||
|
||||
// Tests if the language field can be rearranged on the manage display tab.
|
||||
$this->drupalGet('admin/structure/types/manage/article/display');
|
||||
$language_display = $this->xpath('//*[@id="langcode"]');
|
||||
$this->assert(!empty($language_display), 'Language field is visible on manage display tab.');
|
||||
// Tests if the language field is hidden by default.
|
||||
$this->assertOptionSelected('edit-fields-langcode-type', 'hidden', 'Language is hidden by default on manage display tab.');
|
||||
|
||||
// Changes the initial language settings.
|
||||
$edit = array(
|
||||
'language_configuration[langcode]' => 'en',
|
||||
);
|
||||
$this->drupalPostForm('admin/structure/types/manage/article', $edit, t('Save content type'));
|
||||
$this->drupalGet('node/add/article');
|
||||
$this->assertOptionSelected('edit-langcode-0-value', 'en', 'The initial language is the defined language.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests language field visibility features.
|
||||
*/
|
||||
function testLanguageFieldVisibility() {
|
||||
// Creates a node to test Language field visibility feature.
|
||||
$edit = array(
|
||||
'title[0][value]' => $this->randomMachineName(8),
|
||||
'body[0][value]' => $this->randomMachineName(16),
|
||||
);
|
||||
$this->drupalPostForm('node/add/article', $edit, t('Save'));
|
||||
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
|
||||
$this->assertTrue($node, 'Node found in database.');
|
||||
|
||||
// Loads node page and check if Language field is hidden by default.
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$language_field = $this->xpath('//div[@id=:id]/div', array(
|
||||
':id' => 'field-language-display',
|
||||
));
|
||||
$this->assertTrue(empty($language_field), 'Language field value is not shown by default on node page.');
|
||||
|
||||
// Configures Language field formatter and check if it is saved.
|
||||
$edit = array(
|
||||
'fields[langcode][type]' => 'language',
|
||||
);
|
||||
$this->drupalPostForm('admin/structure/types/manage/article/display', $edit, t('Save'));
|
||||
$this->drupalGet('admin/structure/types/manage/article/display');
|
||||
$this->assertOptionSelected('edit-fields-langcode-type', 'language', 'Language field has been set to visible.');
|
||||
|
||||
// Loads node page and check if Language field is shown.
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$language_field = $this->xpath('//div[@id=:id]/div', array(
|
||||
':id' => 'field-language-display',
|
||||
));
|
||||
$this->assertFalse(empty($language_field), 'Language field value is shown on node page.');
|
||||
}
|
||||
|
||||
}
|
145
core/modules/node/src/Tests/NodeTypeRenameConfigImportTest.php
Normal file
145
core/modules/node/src/Tests/NodeTypeRenameConfigImportTest.php
Normal file
|
@ -0,0 +1,145 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeTypeRenameConfigImportTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityStorage;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
|
||||
/**
|
||||
* Tests importing renamed node type via configuration synchronization.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeTypeRenameConfigImportTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node', 'text', 'config');
|
||||
|
||||
/**
|
||||
* A normal logged in user.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $webUser;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->webUser = $this->drupalCreateUser(array('synchronize configuration'));
|
||||
$this->drupalLogin($this->webUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests configuration renaming.
|
||||
*/
|
||||
public function testConfigurationRename() {
|
||||
$content_type = $this->drupalCreateContentType(array(
|
||||
'type' => Unicode::strtolower($this->randomMachineName(16)),
|
||||
'name' => $this->randomMachineName(),
|
||||
));
|
||||
$staged_type = $content_type->id();
|
||||
|
||||
// Check the default status value for a node of this type.
|
||||
$node = entity_create('node', array('type' => $staged_type));
|
||||
$this->assertTrue($node->status->value, 'Node status defaults to TRUE.');
|
||||
|
||||
// Override a core base field.
|
||||
$fields = \Drupal::entityManager()->getFieldDefinitions($content_type->getEntityType()->getBundleOf(), $content_type->id());
|
||||
$fields['status']->getConfig($content_type->id())->setDefaultValue(FALSE)->save();
|
||||
|
||||
$active = $this->container->get('config.storage');
|
||||
$staging = $this->container->get('config.storage.staging');
|
||||
|
||||
$config_name = $content_type->getEntityType()->getConfigPrefix() . '.' . $content_type->id();
|
||||
// Emulate a staging operation.
|
||||
$this->copyConfig($active, $staging);
|
||||
|
||||
// Change the machine name of the content type.
|
||||
$content_type->set('type', Unicode::strtolower($this->randomMachineName(8)));
|
||||
$content_type->save();
|
||||
$active_type = $content_type->id();
|
||||
|
||||
// Ensure the base field override has been renamed and the value is correct.
|
||||
$node = entity_create('node', array('type' => $active_type));
|
||||
$this->assertFalse($node->status->value, 'Node status defaults to FALSE.');
|
||||
|
||||
$renamed_config_name = $content_type->getEntityType()->getConfigPrefix() . '.' . $content_type->id();
|
||||
$this->assertTrue($active->exists($renamed_config_name), 'The content type has the new name in the active store.');
|
||||
$this->assertFalse($active->exists($config_name), "The content type's old name does not exist active store.");
|
||||
|
||||
$this->configImporter()->reset();
|
||||
$this->assertEqual(0, count($this->configImporter()->getUnprocessedConfiguration('create')), 'There are no configuration items to create.');
|
||||
$this->assertEqual(0, count($this->configImporter()->getUnprocessedConfiguration('delete')), 'There are no configuration items to delete.');
|
||||
$this->assertEqual(0, count($this->configImporter()->getUnprocessedConfiguration('update')), 'There are no configuration items to update.');
|
||||
|
||||
// We expect that changing the machine name of the content type will
|
||||
// rename five configuration entities: the node type, the body field
|
||||
// instance, two entity form displays, and the entity view display.
|
||||
// @see \Drupal\node\Entity\NodeType::postSave()
|
||||
$expected = array(
|
||||
'node.type.' . $active_type . '::node.type.' . $staged_type,
|
||||
'core.base_field_override.node.' . $active_type . '.status::core.base_field_override.node.' . $staged_type . '.status',
|
||||
'core.entity_form_display.node.' . $active_type . '.default::core.entity_form_display.node.' . $staged_type . '.default',
|
||||
'core.entity_view_display.node.' . $active_type . '.default::core.entity_view_display.node.' . $staged_type . '.default',
|
||||
'core.entity_view_display.node.' . $active_type . '.teaser::core.entity_view_display.node.' . $staged_type . '.teaser',
|
||||
'field.field.node.' . $active_type . '.body::field.field.node.' . $staged_type . '.body',
|
||||
);
|
||||
$renames = $this->configImporter()->getUnprocessedConfiguration('rename');
|
||||
$this->assertIdentical($expected, $renames);
|
||||
|
||||
$this->drupalGet('admin/config/development/configuration');
|
||||
foreach ($expected as $rename) {
|
||||
$names = $this->configImporter()->getStorageComparer()->extractRenameNames($rename);
|
||||
$this->assertText(SafeMarkup::format('!source_name to !target_name', array('!source_name' => $names['old_name'], '!target_name' => $names['new_name'])));
|
||||
// Test that the diff link is present for each renamed item.
|
||||
$href = \Drupal::urlGenerator()->getPathFromRoute('config.diff', array('source_name' => $names['old_name'], 'target_name' => $names['new_name']));
|
||||
$this->assertLinkByHref($href);
|
||||
$hrefs[$rename] = $href;
|
||||
}
|
||||
|
||||
// Ensure that the diff works for each renamed item.
|
||||
foreach ($hrefs as $rename => $href) {
|
||||
$this->drupalGet($href);
|
||||
$names = $this->configImporter()->getStorageComparer()->extractRenameNames($rename);
|
||||
$config_entity_type = \Drupal::service('config.manager')->getEntityTypeIdByName($names['old_name']);
|
||||
$entity_type = \Drupal::entityManager()->getDefinition($config_entity_type);
|
||||
$old_id = ConfigEntityStorage::getIDFromConfigName($names['old_name'], $entity_type->getConfigPrefix());
|
||||
$new_id = ConfigEntityStorage::getIDFromConfigName($names['new_name'], $entity_type->getConfigPrefix());
|
||||
|
||||
// Because table columns can be on multiple lines, need to assert a regex
|
||||
// pattern rather than normal text.
|
||||
$id_key = $entity_type->getKey('id');
|
||||
$text = "$id_key: $old_id";
|
||||
$this->assertTextPattern('/\-\s+' . preg_quote($text, '/') . '/', "'-$text' found.");
|
||||
$text = "$id_key: $new_id";
|
||||
$this->assertTextPattern('/\+\s+' . preg_quote($text, '/') . '/', "'+$text' found.");
|
||||
}
|
||||
|
||||
// Run the import.
|
||||
$this->drupalPostForm('admin/config/development/configuration', array(), t('Import all'));
|
||||
$this->assertText(t('There are no configuration changes to import.'));
|
||||
|
||||
$this->assertFalse(NodeType::load($active_type), 'The content no longer exists with the old name.');
|
||||
$content_type = NodeType::load($staged_type);
|
||||
$this->assertIdentical($staged_type, $content_type->id());
|
||||
|
||||
// Ensure the base field override has been renamed and the value is correct.
|
||||
$node = entity_create('node', array('type' => $staged_type));
|
||||
$this->assertFALSE($node->status->value, 'Node status defaults to FALSE.');
|
||||
}
|
||||
|
||||
}
|
227
core/modules/node/src/Tests/NodeTypeTest.php
Normal file
227
core/modules/node/src/Tests/NodeTypeTest.php
Normal file
|
@ -0,0 +1,227 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeTypeTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\Core\Url;
|
||||
|
||||
/**
|
||||
* Ensures that node type functions work correctly.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeTypeTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['field_ui'];
|
||||
|
||||
/**
|
||||
* Ensures that node type functions (node_type_get_*) work correctly.
|
||||
*
|
||||
* Load available node types and validate the returned data.
|
||||
*/
|
||||
function testNodeTypeGetFunctions() {
|
||||
$node_types = NodeType::loadMultiple();
|
||||
$node_names = node_type_get_names();
|
||||
|
||||
$this->assertTrue(isset($node_types['article']), 'Node type article is available.');
|
||||
$this->assertTrue(isset($node_types['page']), 'Node type basic page is available.');
|
||||
|
||||
$this->assertEqual($node_types['article']->label(), $node_names['article'], 'Correct node type base has been returned.');
|
||||
|
||||
$article = NodeType::load('article');
|
||||
$this->assertEqual($node_types['article'], $article, 'Correct node type has been returned.');
|
||||
$this->assertEqual($node_types['article']->label(), $article->label(), 'Correct node type name has been returned.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests creating a content type programmatically and via a form.
|
||||
*/
|
||||
function testNodeTypeCreation() {
|
||||
// Create a content type programmatically.
|
||||
$type = $this->drupalCreateContentType();
|
||||
|
||||
$type_exists = (bool) NodeType::load($type->id());
|
||||
$this->assertTrue($type_exists, 'The new content type has been created in the database.');
|
||||
|
||||
// Login a test user.
|
||||
$web_user = $this->drupalCreateUser(array('create ' . $type->label() . ' content'));
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
$this->drupalGet('node/add/' . $type->id());
|
||||
$this->assertResponse(200, 'The new content type can be accessed at node/add.');
|
||||
|
||||
// Create a content type via the user interface.
|
||||
$web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types'));
|
||||
$this->drupalLogin($web_user);
|
||||
$edit = array(
|
||||
'name' => 'foo',
|
||||
'title_label' => 'title for foo',
|
||||
'type' => 'foo',
|
||||
);
|
||||
$this->drupalPostForm('admin/structure/types/add', $edit, t('Save and manage fields'));
|
||||
$type_exists = (bool) NodeType::load('foo');
|
||||
$this->assertTrue($type_exists, 'The new content type has been created in the database.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests editing a node type using the UI.
|
||||
*/
|
||||
function testNodeTypeEditing() {
|
||||
$web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types', 'administer node fields'));
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
$field = FieldConfig::loadByName('node', 'page', 'body');
|
||||
$this->assertEqual($field->getLabel(), 'Body', 'Body field was found.');
|
||||
|
||||
// Verify that title and body fields are displayed.
|
||||
$this->drupalGet('node/add/page');
|
||||
$this->assertRaw('Title', 'Title field was found.');
|
||||
$this->assertRaw('Body', 'Body field was found.');
|
||||
|
||||
// Rename the title field.
|
||||
$edit = array(
|
||||
'title_label' => 'Foo',
|
||||
);
|
||||
$this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type'));
|
||||
|
||||
$this->drupalGet('node/add/page');
|
||||
$this->assertRaw('Foo', 'New title label was displayed.');
|
||||
$this->assertNoRaw('Title', 'Old title label was not displayed.');
|
||||
|
||||
// Change the name, machine name and description.
|
||||
$edit = array(
|
||||
'name' => 'Bar',
|
||||
'type' => 'bar',
|
||||
'description' => 'Lorem ipsum.',
|
||||
);
|
||||
$this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type'));
|
||||
|
||||
$this->drupalGet('node/add');
|
||||
$this->assertRaw('Bar', 'New name was displayed.');
|
||||
$this->assertRaw('Lorem ipsum', 'New description was displayed.');
|
||||
$this->clickLink('Bar');
|
||||
$this->assertUrl(\Drupal::url('node.add', ['node_type' => 'bar'], ['absolute' => TRUE]), [], 'New machine name was used in URL.');
|
||||
$this->assertRaw('Foo', 'Title field was found.');
|
||||
$this->assertRaw('Body', 'Body field was found.');
|
||||
|
||||
// Remove the body field.
|
||||
$this->drupalPostForm('admin/structure/types/manage/bar/fields/node.bar.body/delete', array(), t('Delete'));
|
||||
// Resave the settings for this type.
|
||||
$this->drupalPostForm('admin/structure/types/manage/bar', array(), t('Save content type'));
|
||||
// Check that the body field doesn't exist.
|
||||
$this->drupalGet('node/add/bar');
|
||||
$this->assertNoRaw('Body', 'Body field was not found.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests deleting a content type that still has content.
|
||||
*/
|
||||
function testNodeTypeDeletion() {
|
||||
// Create a content type programmatically.
|
||||
$type = $this->drupalCreateContentType();
|
||||
|
||||
// Log in a test user.
|
||||
$web_user = $this->drupalCreateUser(array(
|
||||
'bypass node access',
|
||||
'administer content types',
|
||||
));
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
// Add a new node of this type.
|
||||
$node = $this->drupalCreateNode(array('type' => $type->id()));
|
||||
// Attempt to delete the content type, which should not be allowed.
|
||||
$this->drupalGet('admin/structure/types/manage/' . $type->label() . '/delete');
|
||||
$this->assertRaw(
|
||||
t('%type is used by 1 piece of content on your site. You can not remove this content type until you have removed all of the %type content.', array('%type' => $type->label())),
|
||||
'The content type will not be deleted until all nodes of that type are removed.'
|
||||
);
|
||||
$this->assertNoText(t('This action cannot be undone.'), 'The node type deletion confirmation form is not available.');
|
||||
|
||||
// Delete the node.
|
||||
$node->delete();
|
||||
// Attempt to delete the content type, which should now be allowed.
|
||||
$this->drupalGet('admin/structure/types/manage/' . $type->label() . '/delete');
|
||||
$this->assertRaw(
|
||||
t('Are you sure you want to delete the content type %type?', array('%type' => $type->label())),
|
||||
'The content type is available for deletion.'
|
||||
);
|
||||
$this->assertText(t('This action cannot be undone.'), 'The node type deletion confirmation form is available.');
|
||||
|
||||
// Test that a locked node type could not be deleted.
|
||||
$this->container->get('module_installer')->install(array('node_test_config'));
|
||||
// Lock the default node type.
|
||||
$locked = \Drupal::state()->get('node.type.locked');
|
||||
$locked['default'] = 'default';
|
||||
\Drupal::state()->set('node.type.locked', $locked);
|
||||
// Call to flush all caches after installing the forum module in the same
|
||||
// way installing a module through the UI does.
|
||||
$this->resetAll();
|
||||
$this->drupalGet('admin/structure/types/manage/default');
|
||||
$this->assertNoLink(t('Delete'));
|
||||
$this->drupalGet('admin/structure/types/manage/default/delete');
|
||||
$this->assertResponse(403);
|
||||
$this->container->get('module_installer')->uninstall(array('node_test_config'));
|
||||
$this->container = \Drupal::getContainer();
|
||||
unset($locked['default']);
|
||||
\Drupal::state()->set('node.type.locked', $locked);
|
||||
$this->drupalGet('admin/structure/types/manage/default');
|
||||
$this->clickLink(t('Delete'));
|
||||
$this->assertResponse(200);
|
||||
$this->drupalPostForm(NULL, array(), t('Delete'));
|
||||
$this->assertFalse((bool) NodeType::load('default'), 'Node type with machine default deleted.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests Field UI integration for content types.
|
||||
*/
|
||||
public function testNodeTypeFieldUiPermissions() {
|
||||
// Create an admin user who can only manage node fields.
|
||||
$admin_user_1 = $this->drupalCreateUser(array('administer content types', 'administer node fields'));
|
||||
$this->drupalLogin($admin_user_1);
|
||||
|
||||
// Test that the user only sees the actions available to him.
|
||||
$this->drupalGet('admin/structure/types');
|
||||
$this->assertLinkByHref('admin/structure/types/manage/article/fields');
|
||||
$this->assertNoLinkByHref('admin/structure/types/manage/article/display');
|
||||
|
||||
// Create another admin user who can manage node fields display.
|
||||
$admin_user_2 = $this->drupalCreateUser(array('administer content types', 'administer node display'));
|
||||
$this->drupalLogin($admin_user_2);
|
||||
|
||||
// Test that the user only sees the actions available to him.
|
||||
$this->drupalGet('admin/structure/types');
|
||||
$this->assertNoLinkByHref('admin/structure/types/manage/article/fields');
|
||||
$this->assertLinkByHref('admin/structure/types/manage/article/display');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for when there are no content types defined.
|
||||
*/
|
||||
public function testNodeTypeNoContentType() {
|
||||
$web_user = $this->drupalCreateUser(['administer content types']);
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
// Delete 'article' bundle.
|
||||
$this->drupalPostForm('admin/structure/types/manage/article/delete', [], t('Delete'));
|
||||
// Delete 'page' bundle.
|
||||
$this->drupalPostForm('admin/structure/types/manage/page/delete', [], t('Delete'));
|
||||
|
||||
// Navigate to content type administration screen
|
||||
$this->drupalGet('admin/structure/types');
|
||||
$this->assertRaw(t('No content types available. <a href="@link">Add content type</a>.', [
|
||||
'@link' => Url::fromRoute('node.type_add')->toString()
|
||||
]), 'Empty text when there are no content types in the system is correct.');
|
||||
}
|
||||
|
||||
}
|
69
core/modules/node/src/Tests/NodeValidationTest.php
Normal file
69
core/modules/node/src/Tests/NodeValidationTest.php
Normal file
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeValidationTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\system\Tests\Entity\EntityUnitTestBase;
|
||||
|
||||
/**
|
||||
* Tests node validation constraints.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeValidationTest extends EntityUnitTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node');
|
||||
|
||||
/**
|
||||
* Set the default field storage backend for fields created during tests.
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create a node type for testing.
|
||||
$type = entity_create('node_type', array('type' => 'page', 'name' => 'page'));
|
||||
$type->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the node validation constraints.
|
||||
*/
|
||||
public function testValidation() {
|
||||
$this->createUser();
|
||||
$node = entity_create('node', array('type' => 'page', 'title' => 'test', 'uid' => 1));
|
||||
$violations = $node->validate();
|
||||
$this->assertEqual(count($violations), 0, 'No violations when validating a default node.');
|
||||
|
||||
$node->set('title', $this->randomString(256));
|
||||
$violations = $node->validate();
|
||||
$this->assertEqual(count($violations), 1, 'Violation found when title is too long.');
|
||||
$this->assertEqual($violations[0]->getPropertyPath(), 'title.0.value');
|
||||
$this->assertEqual($violations[0]->getMessage(), '<em class="placeholder">Title</em>: may not be longer than 255 characters.');
|
||||
|
||||
$node->set('title', NULL);
|
||||
$violations = $node->validate();
|
||||
$this->assertEqual(count($violations), 1, 'Violation found when title is not set.');
|
||||
$this->assertEqual($violations[0]->getPropertyPath(), 'title');
|
||||
$this->assertEqual($violations[0]->getMessage(), 'This value should not be null.');
|
||||
|
||||
// Make the title valid again.
|
||||
$node->set('title', $this->randomString());
|
||||
// Save the node so that it gets an ID and a changed date.
|
||||
$node->save();
|
||||
// Set the changed date to something in the far past.
|
||||
$node->set('changed', 433918800);
|
||||
$violations = $node->validate();
|
||||
$this->assertEqual(count($violations), 1, 'Violation found when changed date is before the last changed date.');
|
||||
$this->assertEqual($violations[0]->getPropertyPath(), '');
|
||||
$this->assertEqual($violations[0]->getMessage(), 'The content has either been modified by another user, or you have already submitted modifications. As a result, your changes cannot be saved.');
|
||||
}
|
||||
}
|
45
core/modules/node/src/Tests/NodeViewLanguageTest.php
Normal file
45
core/modules/node/src/Tests/NodeViewLanguageTest.php
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeViewLanguageTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
|
||||
/**
|
||||
* Tests the node language extra field display.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeViewLanguageTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node', 'datetime', 'language');
|
||||
|
||||
/**
|
||||
* Tests the language extra field display.
|
||||
*/
|
||||
public function testViewLanguage() {
|
||||
// Add Spanish language.
|
||||
ConfigurableLanguage::createFromLangcode('es')->save();
|
||||
|
||||
// Set language field visible.
|
||||
entity_get_display('node', 'page', 'full')
|
||||
->setComponent('langcode')
|
||||
->save();
|
||||
|
||||
// Create a node in Spanish.
|
||||
$node = $this->drupalCreateNode(array('langcode' => 'es'));
|
||||
|
||||
$this->drupalGet($node->urlInfo());
|
||||
$this->assertText('Spanish','The language field is displayed properly.');
|
||||
}
|
||||
|
||||
}
|
48
core/modules/node/src/Tests/NodeViewTest.php
Normal file
48
core/modules/node/src/Tests/NodeViewTest.php
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\NodeViewTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Tests the node/{node} page.
|
||||
*
|
||||
* @group node
|
||||
* @see \Drupal\node\Controller\NodeController
|
||||
*/
|
||||
class NodeViewTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Tests the html head links.
|
||||
*/
|
||||
public function testHtmlHeadLinks() {
|
||||
$node = $this->drupalCreateNode();
|
||||
|
||||
$this->drupalGet($node->urlInfo());
|
||||
|
||||
$result = $this->xpath('//link[@rel = "version-history"]');
|
||||
$this->assertEqual($result[0]['href'], $node->url('version-history'));
|
||||
|
||||
$result = $this->xpath('//link[@rel = "edit-form"]');
|
||||
$this->assertEqual($result[0]['href'], $node->url('edit-form'));
|
||||
|
||||
$result = $this->xpath('//link[@rel = "canonical"]');
|
||||
$this->assertEqual($result[0]['href'], $node->url());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that we store and retrieve multi-byte UTF-8 characters correctly.
|
||||
*/
|
||||
public function testMultiByteUtf8() {
|
||||
$title = '🐝';
|
||||
$this->assertTrue(mb_strlen($title, 'utf-8') < strlen($title), 'Title has multi-byte characters.');
|
||||
$node = $this->drupalCreateNode(array('title' => $title));
|
||||
$this->drupalGet($node->urlInfo());
|
||||
$result = $this->xpath('//span[contains(@class, "field-name-title")]');
|
||||
$this->assertEqual((string) $result[0], $title, 'The passed title was returned.');
|
||||
}
|
||||
|
||||
}
|
139
core/modules/node/src/Tests/PageEditTest.php
Normal file
139
core/modules/node/src/Tests/PageEditTest.php
Normal file
|
@ -0,0 +1,139 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\PageEditTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Create a node and test node edit functionality.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class PageEditTest extends NodeTestBase {
|
||||
protected $webUser;
|
||||
protected $adminUser;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->webUser = $this->drupalCreateUser(array('edit own page content', 'create page content'));
|
||||
$this->adminUser = $this->drupalCreateUser(array('bypass node access', 'administer nodes'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks node edit functionality.
|
||||
*/
|
||||
function testPageEdit() {
|
||||
$this->drupalLogin($this->webUser);
|
||||
|
||||
$title_key = 'title[0][value]';
|
||||
$body_key = 'body[0][value]';
|
||||
// Create node to edit.
|
||||
$edit = array();
|
||||
$edit[$title_key] = $this->randomMachineName(8);
|
||||
$edit[$body_key] = $this->randomMachineName(16);
|
||||
$this->drupalPostForm('node/add/page', $edit, t('Save'));
|
||||
|
||||
// Check that the node exists in the database.
|
||||
$node = $this->drupalGetNodeByTitle($edit[$title_key]);
|
||||
$this->assertTrue($node, 'Node found in database.');
|
||||
|
||||
// Check that "edit" link points to correct page.
|
||||
$this->clickLink(t('Edit'));
|
||||
$this->assertUrl($node->url('edit-form', ['absolute' => TRUE]));
|
||||
|
||||
// Check that the title and body fields are displayed with the correct values.
|
||||
$active = '<span class="visually-hidden">' . t('(active tab)') . '</span>';
|
||||
$link_text = t('!local-task-title!active', array('!local-task-title' => t('Edit'), '!active' => $active));
|
||||
$this->assertText(strip_tags($link_text), 0, 'Edit tab found and marked active.');
|
||||
$this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
|
||||
$this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
|
||||
|
||||
// Edit the content of the node.
|
||||
$edit = array();
|
||||
$edit[$title_key] = $this->randomMachineName(8);
|
||||
$edit[$body_key] = $this->randomMachineName(16);
|
||||
// Stay on the current page, without reloading.
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
|
||||
// Check that the title and body fields are displayed with the updated values.
|
||||
$this->assertText($edit[$title_key], 'Title displayed.');
|
||||
$this->assertText($edit[$body_key], 'Body displayed.');
|
||||
|
||||
// Login as a second administrator user.
|
||||
$second_web_user = $this->drupalCreateUser(array('administer nodes', 'edit any page content'));
|
||||
$this->drupalLogin($second_web_user);
|
||||
// Edit the same node, creating a new revision.
|
||||
$this->drupalGet("node/" . $node->id() . "/edit");
|
||||
$edit = array();
|
||||
$edit['title[0][value]'] = $this->randomMachineName(8);
|
||||
$edit[$body_key] = $this->randomMachineName(16);
|
||||
$edit['revision'] = TRUE;
|
||||
$this->drupalPostForm(NULL, $edit, t('Save and keep published'));
|
||||
|
||||
// Ensure that the node revision has been created.
|
||||
$revised_node = $this->drupalGetNodeByTitle($edit['title[0][value]'], TRUE);
|
||||
$this->assertNotIdentical($node->getRevisionId(), $revised_node->getRevisionId(), 'A new revision has been created.');
|
||||
// Ensure that the node author is preserved when it was not changed in the
|
||||
// edit form.
|
||||
$this->assertIdentical($node->getOwnerId(), $revised_node->getOwnerId(), 'The node author has been preserved.');
|
||||
// Ensure that the revision authors are different since the revisions were
|
||||
// made by different users.
|
||||
$first_node_version = node_revision_load($node->getRevisionId());
|
||||
$second_node_version = node_revision_load($revised_node->getRevisionId());
|
||||
$this->assertNotIdentical($first_node_version->getRevisionAuthor()->id(), $second_node_version->getRevisionAuthor()->id(), 'Each revision has a distinct user.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests changing a node's "authored by" field.
|
||||
*/
|
||||
function testPageAuthoredBy() {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Create node to edit.
|
||||
$body_key = 'body[0][value]';
|
||||
$edit = array();
|
||||
$edit['title[0][value]'] = $this->randomMachineName(8);
|
||||
$edit[$body_key] = $this->randomMachineName(16);
|
||||
$this->drupalPostForm('node/add/page', $edit, t('Save and publish'));
|
||||
|
||||
// Check that the node was authored by the currently logged in user.
|
||||
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
|
||||
$this->assertIdentical($node->getOwnerId(), $this->adminUser->id(), 'Node authored by admin user.');
|
||||
|
||||
// Try to change the 'authored by' field to an invalid user name.
|
||||
$edit = array(
|
||||
'uid[0][target_id]' => 'invalid-name',
|
||||
);
|
||||
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save and keep published'));
|
||||
$this->assertRaw(t('There are no entities matching "%name".', array('%name' => 'invalid-name')));
|
||||
|
||||
// Change the authored by field to the anonymous user (uid 0).
|
||||
$edit['uid[0][target_id]'] = 'Anonymous (0)';
|
||||
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save and keep published'));
|
||||
$node_storage->resetCache(array($node->id()));
|
||||
$node = $node_storage->load($node->id());
|
||||
$uid = $node->getOwnerId();
|
||||
// Most SQL database drivers stringify fetches but entities are not
|
||||
// necessarily stored in a SQL database. At the same time, NULL/FALSE/""
|
||||
// won't do.
|
||||
$this->assertTrue($uid === 0 || $uid === '0', 'Node authored by anonymous user.');
|
||||
|
||||
// Change the authored by field to another user's name (that is not
|
||||
// logged in).
|
||||
$edit['uid[0][target_id]'] = $this->webUser->getUsername();
|
||||
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save and keep published'));
|
||||
$node_storage->resetCache(array($node->id()));
|
||||
$node = $node_storage->load($node->id());
|
||||
$this->assertIdentical($node->getOwnerId(), $this->webUser->id(), 'Node authored by normal user.');
|
||||
|
||||
// Check that normal users cannot change the authored by information.
|
||||
$this->drupalLogin($this->webUser);
|
||||
$this->drupalGet('node/' . $node->id() . '/edit');
|
||||
$this->assertNoFieldByName('uid[0][target_id]');
|
||||
}
|
||||
}
|
274
core/modules/node/src/Tests/PagePreviewTest.php
Normal file
274
core/modules/node/src/Tests/PagePreviewTest.php
Normal file
|
@ -0,0 +1,274 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\PagePreviewTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
|
||||
/**
|
||||
* Tests the node entity preview functionality.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class PagePreviewTest extends NodeTestBase {
|
||||
|
||||
use EntityReferenceTestTrait;
|
||||
|
||||
/**
|
||||
* Enable the node and taxonomy modules to test both on the preview.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node', 'taxonomy');
|
||||
|
||||
/**
|
||||
* The name of the created field.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $fieldName;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$web_user = $this->drupalCreateUser(array('edit own page content', 'create page content'));
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
// Add a vocabulary so we can test different view modes.
|
||||
$vocabulary = entity_create('taxonomy_vocabulary', array(
|
||||
'name' => $this->randomMachineName(),
|
||||
'description' => $this->randomMachineName(),
|
||||
'vid' => $this->randomMachineName(),
|
||||
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
||||
'help' => '',
|
||||
));
|
||||
$vocabulary->save();
|
||||
|
||||
$this->vocabulary = $vocabulary;
|
||||
|
||||
// Add a term to the vocabulary.
|
||||
$term = entity_create('taxonomy_term', array(
|
||||
'name' => $this->randomMachineName(),
|
||||
'description' => $this->randomMachineName(),
|
||||
'vid' => $this->vocabulary->id(),
|
||||
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
||||
));
|
||||
$term->save();
|
||||
|
||||
$this->term = $term;
|
||||
|
||||
// Create a field.
|
||||
$this->fieldName = Unicode::strtolower($this->randomMachineName());
|
||||
$handler_settings = array(
|
||||
'target_bundles' => array(
|
||||
$this->vocabulary->id() => $this->vocabulary->id(),
|
||||
),
|
||||
'auto_create' => TRUE,
|
||||
);
|
||||
$this->createEntityReferenceField('node', 'page', $this->fieldName, 'Tags', 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
|
||||
|
||||
entity_get_form_display('node', 'page', 'default')
|
||||
->setComponent($this->fieldName, array(
|
||||
'type' => 'entity_reference_autocomplete_tags',
|
||||
))
|
||||
->save();
|
||||
|
||||
// Show on default display and teaser.
|
||||
entity_get_display('node', 'page', 'default')
|
||||
->setComponent($this->fieldName, array(
|
||||
'type' => 'entity_reference_label',
|
||||
))
|
||||
->save();
|
||||
entity_get_display('node', 'page', 'teaser')
|
||||
->setComponent($this->fieldName, array(
|
||||
'type' => 'entity_reference_label',
|
||||
))
|
||||
->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the node preview functionality.
|
||||
*/
|
||||
function testPagePreview() {
|
||||
$title_key = 'title[0][value]';
|
||||
$body_key = 'body[0][value]';
|
||||
$term_key = $this->fieldName . '[target_id]';
|
||||
|
||||
// Fill in node creation form and preview node.
|
||||
$edit = array();
|
||||
$edit[$title_key] = $this->randomMachineName(8);
|
||||
$edit[$body_key] = $this->randomMachineName(16);
|
||||
$edit[$term_key] = $this->term->getName();
|
||||
$this->drupalPostForm('node/add/page', $edit, t('Preview'));
|
||||
|
||||
// Check that the preview is displaying the title, body and term.
|
||||
$this->assertTitle(t('@title | Drupal', array('@title' => $edit[$title_key])), 'Basic page title is preview.');
|
||||
$this->assertText($edit[$title_key], 'Title displayed.');
|
||||
$this->assertText($edit[$body_key], 'Body displayed.');
|
||||
$this->assertText($edit[$term_key], 'Term displayed.');
|
||||
$this->assertLink(t('Back to content editing'));
|
||||
|
||||
// Get the UUID.
|
||||
$url = parse_url($this->getUrl());
|
||||
$paths = explode('/', $url['path']);
|
||||
$view_mode = array_pop($paths);
|
||||
$uuid = array_pop($paths);
|
||||
|
||||
// Switch view mode. We'll remove the body from the teaser view mode.
|
||||
entity_get_display('node', 'page', 'teaser')
|
||||
->removeComponent('body')
|
||||
->save();
|
||||
|
||||
$view_mode_edit = array('view_mode' => 'teaser');
|
||||
$this->drupalPostForm('node/preview/' . $uuid . '/default', $view_mode_edit, t('Switch'));
|
||||
$this->assertRaw('view-mode-teaser', 'View mode teaser class found.');
|
||||
$this->assertNoText($edit[$body_key], 'Body not displayed.');
|
||||
|
||||
// Check that the title, body and term fields are displayed with the
|
||||
// values after going back to the content edit page.
|
||||
$this->clickLink(t('Back to content editing'));
|
||||
$this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
|
||||
$this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
|
||||
$this->assertFieldByName($term_key, $edit[$term_key] . ' (' . $this->term->id() . ')', 'Term field displayed.');
|
||||
|
||||
// Assert the content is kept when reloading the page.
|
||||
$this->drupalGet('node/add/page', array('query' => array('uuid' => $uuid)));
|
||||
$this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
|
||||
$this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
|
||||
$this->assertFieldByName($term_key, $edit[$term_key] . ' (' . $this->term->id() . ')', 'Term field displayed.');
|
||||
|
||||
// Save the node.
|
||||
$this->drupalPostForm('node/add/page', $edit, t('Save'));
|
||||
$node = $this->drupalGetNodeByTitle($edit[$title_key]);
|
||||
|
||||
// Check the term was displayed on the saved node.
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$this->assertText($edit[$term_key], 'Term displayed.');
|
||||
|
||||
// Check the term appears again on the edit form.
|
||||
$this->drupalGet('node/' . $node->id() . '/edit');
|
||||
$this->assertFieldByName($term_key, $edit[$term_key] . ' (' . $this->term->id() . ')', 'Term field displayed.');
|
||||
|
||||
// Check with two new terms on the edit form, additionally to the existing
|
||||
// one.
|
||||
$edit = array();
|
||||
$newterm1 = $this->randomMachineName(8);
|
||||
$newterm2 = $this->randomMachineName(8);
|
||||
$edit[$term_key] = $this->term->getName() . ', ' . $newterm1 . ', ' . $newterm2;
|
||||
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Preview'));
|
||||
$this->assertRaw('>' . $newterm1 . '<', 'First new term displayed.');
|
||||
$this->assertRaw('>' . $newterm2 . '<', 'Second new term displayed.');
|
||||
// The first term should be displayed as link, the others not.
|
||||
$this->assertLink($this->term->getName());
|
||||
$this->assertNoLink($newterm1);
|
||||
$this->assertNoLink($newterm2);
|
||||
|
||||
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save'));
|
||||
|
||||
// Check with one more new term, keeping old terms, removing the existing
|
||||
// one.
|
||||
$edit = array();
|
||||
$newterm3 = $this->randomMachineName(8);
|
||||
$edit[$term_key] = $newterm1 . ', ' . $newterm3 . ', ' . $newterm2;
|
||||
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Preview'));
|
||||
$this->assertRaw('>' . $newterm1 . '<', 'First existing term displayed.');
|
||||
$this->assertRaw('>' . $newterm2 . '<', 'Second existing term displayed.');
|
||||
$this->assertRaw('>' . $newterm3 . '<', 'Third new term displayed.');
|
||||
$this->assertNoText($this->term->getName());
|
||||
$this->assertLink($newterm1);
|
||||
$this->assertLink($newterm2);
|
||||
$this->assertNoLink($newterm3);
|
||||
|
||||
// Check that editing an existing node after it has been previewed and not
|
||||
// saved doesn't remember the previous changes.
|
||||
$edit = array(
|
||||
$title_key => $this->randomMachineName(8),
|
||||
);
|
||||
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Preview'));
|
||||
$this->assertText($edit[$title_key], 'New title displayed.');
|
||||
$this->clickLink(t('Back to content editing'));
|
||||
$this->assertFieldByName($title_key, $edit[$title_key], 'New title value displayed.');
|
||||
// Navigate away from the node without saving.
|
||||
$this->drupalGet('<front>');
|
||||
// Go back to the edit form, the title should have its initial value.
|
||||
$this->drupalGet('node/' . $node->id() . '/edit');
|
||||
$this->assertFieldByName($title_key, $node->label(), 'Correct title value displayed.');
|
||||
|
||||
// Check with required preview.
|
||||
$node_type = NodeType::load('page');
|
||||
$node_type->setPreviewMode(DRUPAL_REQUIRED);
|
||||
$node_type->save();
|
||||
$this->drupalGet('node/add/page');
|
||||
$this->assertNoRaw('edit-submit');
|
||||
$this->drupalPostForm('node/add/page', array($title_key => 'Preview'), t('Preview'));
|
||||
$this->clickLink(t('Back to content editing'));
|
||||
$this->assertRaw('edit-submit');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the node preview functionality, when using revisions.
|
||||
*/
|
||||
function testPagePreviewWithRevisions() {
|
||||
$title_key = 'title[0][value]';
|
||||
$body_key = 'body[0][value]';
|
||||
$term_key = $this->fieldName . '[target_id]';
|
||||
// Force revision on "Basic page" content.
|
||||
$node_type = NodeType::load('page');
|
||||
$node_type->setNewRevision(TRUE);
|
||||
$node_type->save();
|
||||
|
||||
// Fill in node creation form and preview node.
|
||||
$edit = array();
|
||||
$edit[$title_key] = $this->randomMachineName(8);
|
||||
$edit[$body_key] = $this->randomMachineName(16);
|
||||
$edit[$term_key] = $this->term->id();
|
||||
$edit['revision_log[0][value]'] = $this->randomString(32);
|
||||
$this->drupalPostForm('node/add/page', $edit, t('Preview'));
|
||||
|
||||
// Check that the preview is displaying the title, body and term.
|
||||
$this->assertTitle(t('@title | Drupal', array('@title' => $edit[$title_key])), 'Basic page title is preview.');
|
||||
$this->assertText($edit[$title_key], 'Title displayed.');
|
||||
$this->assertText($edit[$body_key], 'Body displayed.');
|
||||
$this->assertText($edit[$term_key], 'Term displayed.');
|
||||
|
||||
// Check that the title and body fields are displayed with the correct
|
||||
// values after going back to the content edit page.
|
||||
$this->clickLink(t('Back to content editing')); $this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
|
||||
$this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
|
||||
$this->assertFieldByName($term_key, $edit[$term_key], 'Term field displayed.');
|
||||
|
||||
// Check that the revision log field has the correct value.
|
||||
$this->assertFieldByName('revision_log[0][value]', $edit['revision_log[0][value]'], 'Revision log field displayed.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the node preview accessible for simultaneous node editing.
|
||||
*/
|
||||
public function testSimultaneousPreview() {
|
||||
$title_key = 'title[0][value]';
|
||||
$node = $this->drupalCreateNode(array());
|
||||
|
||||
$edit = array($title_key => 'New page title');
|
||||
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Preview'));
|
||||
$this->assertText($edit[$title_key]);
|
||||
|
||||
$user2 = $this->drupalCreateUser(array('edit any page content'));
|
||||
$this->drupalLogin($user2);
|
||||
$this->drupalGet('node/' . $node->id() . '/edit');
|
||||
$this->assertFieldByName($title_key, $node->label(), 'No title leaked from previous user.');
|
||||
|
||||
$edit2 = array($title_key => 'Another page title');
|
||||
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit2, t('Preview'));
|
||||
$this->assertUrl(\Drupal::url('entity.node.preview', ['node_preview' => $node->uuid(), 'view_mode_id' => 'default'], ['absolute' => TRUE]));
|
||||
$this->assertText($edit2[$title_key]);
|
||||
}
|
||||
|
||||
}
|
46
core/modules/node/src/Tests/PageViewTest.php
Normal file
46
core/modules/node/src/Tests/PageViewTest.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\PageViewTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\node\Entity\Node;
|
||||
|
||||
/**
|
||||
* Create a node and test edit permissions.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class PageViewTest extends NodeTestBase {
|
||||
/**
|
||||
* Tests an anonymous and unpermissioned user attempting to edit the node.
|
||||
*/
|
||||
function testPageView() {
|
||||
// Create a node to view.
|
||||
$node = $this->drupalCreateNode();
|
||||
$this->assertTrue(Node::load($node->id()), 'Node created.');
|
||||
|
||||
// Try to edit with anonymous user.
|
||||
$this->drupalGet("node/" . $node->id() . "/edit");
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Create a user without permission to edit node.
|
||||
$web_user = $this->drupalCreateUser(array('access content'));
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
// Attempt to access edit page.
|
||||
$this->drupalGet("node/" . $node->id() . "/edit");
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Create user with permission to edit node.
|
||||
$web_user = $this->drupalCreateUser(array('bypass node access'));
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
// Attempt to access edit page.
|
||||
$this->drupalGet("node/" . $node->id() . "/edit");
|
||||
$this->assertResponse(200);
|
||||
}
|
||||
}
|
59
core/modules/node/src/Tests/SummaryLengthTest.php
Normal file
59
core/modules/node/src/Tests/SummaryLengthTest.php
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\SummaryLengthTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\node\Entity\Node;
|
||||
|
||||
/**
|
||||
* Tests summary length.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class SummaryLengthTest extends NodeTestBase {
|
||||
/**
|
||||
* Tests the node summary length functionality.
|
||||
*/
|
||||
public function testSummaryLength() {
|
||||
/** @var \Drupal\Core\Render\RendererInterface $renderer */
|
||||
$renderer = $this->container->get('renderer');
|
||||
|
||||
// Create a node to view.
|
||||
$settings = array(
|
||||
'body' => array(array('value' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam vitae arcu at leo cursus laoreet. Curabitur dui tortor, adipiscing malesuada tempor in, bibendum ac diam. Cras non tellus a libero pellentesque condimentum. What is a Drupalism? Suspendisse ac lacus libero. Ut non est vel nisl faucibus interdum nec sed leo. Pellentesque sem risus, vulputate eu semper eget, auctor in libero. Ut fermentum est vitae metus convallis scelerisque. Phasellus pellentesque rhoncus tellus, eu dignissim purus posuere id. Quisque eu fringilla ligula. Morbi ullamcorper, lorem et mattis egestas, tortor neque pretium velit, eget eleifend odio turpis eu purus. Donec vitae metus quis leo pretium tincidunt a pulvinar sem. Morbi adipiscing laoreet mauris vel placerat. Nullam elementum, nisl sit amet scelerisque malesuada, dolor nunc hendrerit quam, eu ultrices erat est in orci. Curabitur feugiat egestas nisl sed accumsan.')),
|
||||
'promote' => 1,
|
||||
);
|
||||
$node = $this->drupalCreateNode($settings);
|
||||
$this->assertTrue(Node::load($node->id()), 'Node created.');
|
||||
|
||||
// Render the node as a teaser.
|
||||
$content = $this->drupalBuildEntityView($node, 'teaser');
|
||||
$this->assertTrue(strlen($content['body'][0]['#markup']) < 600, 'Teaser is less than 600 characters long.');
|
||||
$this->setRawContent($renderer->renderRoot($content));
|
||||
// The string 'What is a Drupalism?' is between the 200th and 600th
|
||||
// characters of the node body, so it should be included if the summary is
|
||||
// 600 characters long.
|
||||
$expected = 'What is a Drupalism?';
|
||||
$this->assertRaw($expected);
|
||||
|
||||
// Change the teaser length for "Basic page" content type.
|
||||
$display = entity_get_display('node', $node->getType(), 'teaser');
|
||||
$display_options = $display->getComponent('body');
|
||||
$display_options['settings']['trim_length'] = 200;
|
||||
$display->setComponent('body', $display_options)
|
||||
->save();
|
||||
|
||||
// Render the node as a teaser again and check that the summary is now only
|
||||
// 200 characters in length and so does not include 'What is a Drupalism?'.
|
||||
$content = $this->drupalBuildEntityView($node, 'teaser');
|
||||
$this->assertTrue(strlen($content['body'][0]['#markup']) < 200, 'Teaser is less than 200 characters long.');
|
||||
$this->setRawContent($renderer->renderRoot($content));
|
||||
$this->assertText($node->label());
|
||||
$this->assertNoRaw($expected);
|
||||
}
|
||||
|
||||
}
|
177
core/modules/node/src/Tests/Views/BulkFormAccessTest.php
Normal file
177
core/modules/node/src/Tests/Views/BulkFormAccessTest.php
Normal file
|
@ -0,0 +1,177 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\Views\BulkFormAccessTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests\Views;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
|
||||
/**
|
||||
* Tests if entity access is respected on a node bulk operations form.
|
||||
*
|
||||
* @group node
|
||||
* @see \Drupal\node\Plugin\views\field\BulkForm
|
||||
* @see \Drupal\node\Tests\NodeTestBase
|
||||
* @see \Drupal\node\Tests\NodeAccessBaseTableTest
|
||||
* @see \Drupal\node\Tests\Views\BulkFormTest
|
||||
*/
|
||||
class BulkFormAccessTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node_test_views', 'node_access_test');
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = array('test_node_bulk_form');
|
||||
|
||||
/**
|
||||
* The node access control handler.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityAccessControlHandlerInterface
|
||||
*/
|
||||
protected $accessHandler;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create Article node type.
|
||||
$this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
|
||||
|
||||
$this->accessHandler = \Drupal::entityManager()->getAccessControlHandler('node');
|
||||
|
||||
node_access_test_add_field(NodeType::load('article'));
|
||||
|
||||
// After enabling a node access module, the access table has to be rebuild.
|
||||
node_access_rebuild();
|
||||
|
||||
// Enable the private node feature of the node_access_test module.
|
||||
\Drupal::state()->set('node_access_test.private', TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if nodes that may not be edited, can not be edited in bulk.
|
||||
*/
|
||||
public function testNodeEditAccess() {
|
||||
// Create an account who will be the author of a private node.
|
||||
$author = $this->drupalCreateUser();
|
||||
// Create a private node (author may view, edit and delete, others may not).
|
||||
$node = $this->drupalCreateNode(array(
|
||||
'type' => 'article',
|
||||
'private' => array(array(
|
||||
'value' => TRUE,
|
||||
)),
|
||||
'uid' => $author->id(),
|
||||
));
|
||||
// Create an account that may view the private node, but not edit it.
|
||||
$account = $this->drupalCreateUser(array('node test view'));
|
||||
$this->drupalLogin($account);
|
||||
|
||||
// Ensure the node is published.
|
||||
$this->assertTrue($node->isPublished(), 'Node is initially published.');
|
||||
|
||||
// Ensure that the node can not be edited.
|
||||
$this->assertEqual(FALSE, $this->accessHandler->access($node, 'update', $node->prepareLangcode(), $account), 'The node may not be edited.');
|
||||
|
||||
// Test editing the node using the bulk form.
|
||||
$edit = array(
|
||||
'node_bulk_form[0]' => TRUE,
|
||||
'action' => 'node_unpublish_action',
|
||||
);
|
||||
$this->drupalPostForm('test-node-bulk-form', $edit, t('Apply'));
|
||||
$this->assertRaw(SafeMarkup::format('No access to execute %action on the @entity_type_label %entity_label.', [
|
||||
'%action' => 'Unpublish content',
|
||||
'@entity_type_label' => 'Content',
|
||||
'%entity_label' => $node->label(),
|
||||
]));
|
||||
|
||||
// Re-load the node and check the status.
|
||||
$node = Node::load($node->id());
|
||||
$this->assertTrue($node->isPublished(), 'The node is still published.');
|
||||
|
||||
// Create an account that may view the private node, but can update the
|
||||
// status.
|
||||
$account = $this->drupalCreateUser(array('administer nodes', 'node test view'));
|
||||
$this->drupalLogin($account);
|
||||
|
||||
// Ensure the node is published.
|
||||
$this->assertTrue($node->isPublished(), 'Node is initially published.');
|
||||
|
||||
// Ensure that the private node can not be edited.
|
||||
$this->assertEqual(FALSE, $node->access('update', $account), 'The node may not be edited.');
|
||||
$this->assertEqual(TRUE, $node->status->access('edit', $account), 'The node status can be edited.');
|
||||
|
||||
// Test editing the node using the bulk form.
|
||||
$edit = array(
|
||||
'node_bulk_form[0]' => TRUE,
|
||||
'action' => 'node_unpublish_action',
|
||||
);
|
||||
$this->drupalPostForm('test-node-bulk-form', $edit, t('Apply'));
|
||||
// Re-load the node and check the status.
|
||||
$node = Node::load($node->id());
|
||||
$this->assertTrue($node->isPublished(), 'The node is still published.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if nodes that may not be deleted, can not be deleted in bulk.
|
||||
*/
|
||||
public function testNodeDeleteAccess() {
|
||||
// Create an account who will be the author of a private node.
|
||||
$author = $this->drupalCreateUser();
|
||||
// Create a private node (author may view, edit and delete, others may not).
|
||||
$private_node = $this->drupalCreateNode(array(
|
||||
'type' => 'article',
|
||||
'private' => array(array(
|
||||
'value' => TRUE,
|
||||
)),
|
||||
'uid' => $author->id(),
|
||||
));
|
||||
// Create an account that may view the private node, but not delete it.
|
||||
$account = $this->drupalCreateUser(array('access content', 'administer nodes', 'delete own article content', 'node test view'));
|
||||
// Create a node that may be deleted too, to ensure the delete confirmation
|
||||
// page is shown later. In node_access_test.module, nodes may only be
|
||||
// deleted by the author.
|
||||
$own_node = $this->drupalCreateNode(array(
|
||||
'type' => 'article',
|
||||
'private' => array(array(
|
||||
'value' => TRUE,
|
||||
)),
|
||||
'uid' => $account->id(),
|
||||
));
|
||||
$this->drupalLogin($account);
|
||||
|
||||
// Ensure that the private node can not be deleted.
|
||||
$this->assertEqual(FALSE, $this->accessHandler->access($private_node, 'delete', $private_node->prepareLangcode(), $account), 'The private node may not be deleted.');
|
||||
// Ensure that the public node may be deleted.
|
||||
$this->assertEqual(TRUE, $this->accessHandler->access($own_node, 'delete', $own_node->prepareLangcode(), $account), 'The own node may be deleted.');
|
||||
|
||||
// Try to delete the node using the bulk form.
|
||||
$edit = array(
|
||||
'node_bulk_form[0]' => TRUE,
|
||||
'node_bulk_form[1]' => TRUE,
|
||||
'action' => 'node_delete_action',
|
||||
);
|
||||
$this->drupalPostForm('test-node-bulk-form', $edit, t('Apply'));
|
||||
$this->drupalPostForm(NULL, array(), t('Delete'));
|
||||
// Ensure the private node still exists.
|
||||
$private_node = Node::load($private_node->id());
|
||||
$this->assertNotNull($private_node, 'The private node has not been deleted.');
|
||||
// Ensure the own node is deleted.
|
||||
$own_node = Node::load($own_node->id());
|
||||
$this->assertNull($own_node, 'The own node is deleted.');
|
||||
}
|
||||
}
|
280
core/modules/node/src/Tests/Views/BulkFormTest.php
Normal file
280
core/modules/node/src/Tests/Views/BulkFormTest.php
Normal file
|
@ -0,0 +1,280 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\Views\BulkFormTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests\Views;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests a node bulk form.
|
||||
*
|
||||
* @group node
|
||||
* @see \Drupal\node\Plugin\views\field\BulkForm
|
||||
*/
|
||||
class BulkFormTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Modules to be enabled.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node_test_views', 'language');
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = array('test_node_bulk_form');
|
||||
|
||||
/**
|
||||
* The test nodes.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface[]
|
||||
*/
|
||||
protected $nodes;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
ConfigurableLanguage::createFromLangcode('fr')->save();
|
||||
ConfigurableLanguage::createFromLangcode('it')->save();
|
||||
|
||||
// Create some test nodes.
|
||||
$this->nodes = [];
|
||||
$langcodes = ['en', 'fr', 'it'];
|
||||
for ($i = 1; $i <= 5; $i++) {
|
||||
$langcode = $langcodes[($i - 1) % 3];
|
||||
$values = [
|
||||
'title' => $this->randomMachineName() . ' [' . $i . ':' . $langcode . ']',
|
||||
'langcode' => $langcode,
|
||||
'promote' => FALSE,
|
||||
];
|
||||
$node = $this->drupalCreateNode($values);
|
||||
$this->pass(SafeMarkup::format('Node %title created with language %langcode.', ['%title' => $node->label(), '%langcode' => $node->language()->getId()]));
|
||||
$this->nodes[] = $node;
|
||||
}
|
||||
|
||||
// Create translations for all languages for some nodes.
|
||||
for ($i = 0; $i < 2; $i++) {
|
||||
$node = $this->nodes[$i];
|
||||
foreach ($langcodes as $langcode) {
|
||||
if (!$node->hasTranslation($langcode)) {
|
||||
$title = $this->randomMachineName() . ' [' . $node->id() . ':' . $langcode . ']';
|
||||
$translation = $node->addTranslation($langcode, ['title' => $title, 'promote' => FALSE]);
|
||||
$this->pass(SafeMarkup::format('Translation %title created with language %langcode.', ['%title' => $translation->label(), '%langcode' => $translation->language()->getId()]));
|
||||
}
|
||||
}
|
||||
$node->save();
|
||||
}
|
||||
|
||||
// Create a node with only one translation.
|
||||
$node = $this->nodes[2];
|
||||
$langcode = 'en';
|
||||
$title = $this->randomMachineName() . ' [' . $node->id() . ':' . $langcode . ']';
|
||||
$translation = $node->addTranslation($langcode, ['title' => $title]);
|
||||
$this->pass(SafeMarkup::format('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.
|
||||
$view = Views::getView('test_node_bulk_form');
|
||||
$view->execute();
|
||||
$this->assertEqual(count($view->result), 10, 'All created translations are selected.');
|
||||
|
||||
// Check the operations are accessible to the logged in user.
|
||||
$this->drupalLogin($this->drupalCreateUser(array('administer nodes', 'access content overview', 'bypass node access')));
|
||||
$this->drupalGet('test-node-bulk-form');
|
||||
$elements = $this->xpath('//select[@id="edit-action"]//option');
|
||||
$this->assertIdentical(count($elements), 8, 'All node operations are found.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the node bulk form.
|
||||
*/
|
||||
public function testBulkForm() {
|
||||
// Unpublish a node using the bulk form.
|
||||
$node = reset($this->nodes);
|
||||
$this->assertTrue($node->isPublished(), 'Node is initially published');
|
||||
$this->assertTrue($node->getTranslation('fr')->isPublished(), 'Node translation is published');
|
||||
$this->assertTrue($node->getTranslation('it')->isPublished(), 'Node translation is published');
|
||||
$edit = array(
|
||||
'node_bulk_form[0]' => TRUE,
|
||||
'action' => 'node_unpublish_action',
|
||||
);
|
||||
$this->drupalPostForm(NULL, $edit, t('Apply'));
|
||||
$node = $this->loadNode($node->id());
|
||||
$this->assertFalse($node->isPublished(), 'Node has been unpublished');
|
||||
$this->assertTrue($node->getTranslation('fr')->isPublished(), 'Node translation has not been unpublished');
|
||||
$this->assertTrue($node->getTranslation('it')->isPublished(), 'Node translation has not been unpublished');
|
||||
|
||||
// Publish action.
|
||||
$edit = array(
|
||||
'node_bulk_form[0]' => TRUE,
|
||||
'action' => 'node_publish_action',
|
||||
);
|
||||
$this->drupalPostForm(NULL, $edit, t('Apply'));
|
||||
$node = $this->loadNode($node->id());
|
||||
$this->assertTrue($node->isPublished(), 'Node has been published again');
|
||||
|
||||
// Make sticky action.
|
||||
$this->assertFalse($node->isSticky(), 'Node is not sticky');
|
||||
$this->assertFalse($node->getTranslation('fr')->isSticky(), 'Node translation is not sticky');
|
||||
$this->assertFalse($node->getTranslation('it')->isSticky(), 'Node translation is not sticky');
|
||||
$edit = array(
|
||||
'node_bulk_form[0]' => TRUE,
|
||||
'action' => 'node_make_sticky_action',
|
||||
);
|
||||
$this->drupalPostForm(NULL, $edit, t('Apply'));
|
||||
$node = $this->loadNode($node->id());
|
||||
$this->assertTrue($node->isPublished(), 'Node has been made sticky');
|
||||
$this->assertFalse($node->getTranslation('fr')->isSticky(), 'Node translation has not been made sticky');
|
||||
$this->assertFalse($node->getTranslation('it')->isSticky(), 'Node translation has not been made sticky');
|
||||
|
||||
// Make unsticky action.
|
||||
$edit = array(
|
||||
'node_bulk_form[0]' => TRUE,
|
||||
'action' => 'node_make_unsticky_action',
|
||||
);
|
||||
$this->drupalPostForm(NULL, $edit, t('Apply'));
|
||||
$node = $this->loadNode($node->id());
|
||||
$this->assertFalse($node->isSticky(), 'Node is not sticky anymore');
|
||||
|
||||
// Promote to front page.
|
||||
$this->assertFalse($node->isPromoted(), 'Node is not promoted to the front page');
|
||||
$this->assertFalse($node->getTranslation('fr')->isPromoted(), 'Node translation is not promoted to the front page');
|
||||
$this->assertFalse($node->getTranslation('it')->isPromoted(), 'Node translation is not promoted to the front page');
|
||||
$edit = array(
|
||||
'node_bulk_form[0]' => TRUE,
|
||||
'action' => 'node_promote_action',
|
||||
);
|
||||
$this->drupalPostForm(NULL, $edit, t('Apply'));
|
||||
$node = $this->loadNode($node->id());
|
||||
$this->assertTrue($node->isPromoted(), 'Node has been promoted to the front page');
|
||||
$this->assertFalse($node->getTranslation('fr')->isPromoted(), 'Node translation has not been promoted to the front page');
|
||||
$this->assertFalse($node->getTranslation('it')->isPromoted(), 'Node translation has not been promoted to the front page');
|
||||
|
||||
// Demote from front page.
|
||||
$edit = array(
|
||||
'node_bulk_form[0]' => TRUE,
|
||||
'action' => 'node_unpromote_action',
|
||||
);
|
||||
$this->drupalPostForm(NULL, $edit, t('Apply'));
|
||||
$node = $this->loadNode($node->id());
|
||||
$this->assertFalse($node->isPromoted(), 'Node has been demoted');
|
||||
|
||||
// Select a bunch of translated and untranslated nodes and check that
|
||||
// operations are always applied to individual translations.
|
||||
$edit = array(
|
||||
// Original and all translations.
|
||||
'node_bulk_form[0]' => TRUE, // Node 1, English, original.
|
||||
'node_bulk_form[1]' => TRUE, // Node 1, French.
|
||||
'node_bulk_form[2]' => TRUE, // Node 1, Italian.
|
||||
// Original and only one translation.
|
||||
'node_bulk_form[3]' => TRUE, // Node 2, English.
|
||||
'node_bulk_form[4]' => TRUE, // Node 2, French, original.
|
||||
'node_bulk_form[5]' => FALSE, // Node 2, Italian.
|
||||
// Only a single translation.
|
||||
'node_bulk_form[6]' => TRUE, // Node 3, English.
|
||||
'node_bulk_form[7]' => FALSE, // Node 3, Italian, original.
|
||||
// Only a single untranslated node.
|
||||
'node_bulk_form[8]' => TRUE, // Node 4, English, untranslated.
|
||||
'node_bulk_form[9]' => FALSE, // Node 5, French, untranslated.
|
||||
'action' => 'node_unpublish_action',
|
||||
);
|
||||
$this->drupalPostForm(NULL, $edit, t('Apply'));
|
||||
$node = $this->loadNode(1);
|
||||
$this->assertFalse($node->getTranslation('en')->isPublished(), '1: English translation has been unpublished');
|
||||
$this->assertFalse($node->getTranslation('fr')->isPublished(), '1: French translation has been unpublished');
|
||||
$this->assertFalse($node->getTranslation('it')->isPublished(), '1: Italian translation has been unpublished');
|
||||
$node = $this->loadNode(2);
|
||||
$this->assertFalse($node->getTranslation('en')->isPublished(), '2: English translation has been unpublished');
|
||||
$this->assertFalse($node->getTranslation('fr')->isPublished(), '2: French translation has been unpublished');
|
||||
$this->assertTrue($node->getTranslation('it')->isPublished(), '2: Italian translation has not been unpublished');
|
||||
$node = $this->loadNode(3);
|
||||
$this->assertFalse($node->getTranslation('en')->isPublished(), '3: English translation has been unpublished');
|
||||
$this->assertTrue($node->getTranslation('it')->isPublished(), '3: Italian translation has not been unpublished');
|
||||
$node = $this->loadNode(4);
|
||||
$this->assertFalse($node->isPublished(), '4: Node has been unpublished');
|
||||
$node = $this->loadNode(5);
|
||||
$this->assertTrue($node->isPublished(), '5: Node has not been unpublished');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test multiple deletion.
|
||||
*/
|
||||
public function testBulkDeletion() {
|
||||
// Select a bunch of translated and untranslated nodes and check that
|
||||
// nodes and individual translations are properly deleted.
|
||||
$edit = array(
|
||||
// Original and all translations.
|
||||
'node_bulk_form[0]' => TRUE, // Node 1, English, original.
|
||||
'node_bulk_form[1]' => TRUE, // Node 1, French.
|
||||
'node_bulk_form[2]' => TRUE, // Node 1, Italian.
|
||||
// Original and only one translation.
|
||||
'node_bulk_form[3]' => TRUE, // Node 2, English.
|
||||
'node_bulk_form[4]' => TRUE, // Node 2, French, original.
|
||||
'node_bulk_form[5]' => FALSE, // Node 2, Italian.
|
||||
// Only a single translation.
|
||||
'node_bulk_form[6]' => TRUE, // Node 3, English.
|
||||
'node_bulk_form[7]' => FALSE, // Node 3, Italian, original.
|
||||
// Only a single untranslated node.
|
||||
'node_bulk_form[8]' => TRUE, // Node 4, English, untranslated.
|
||||
'node_bulk_form[9]' => FALSE, // Node 5, French, untranslated.
|
||||
'action' => 'node_delete_action',
|
||||
);
|
||||
$this->drupalPostForm(NULL, $edit, t('Apply'));
|
||||
|
||||
$label = $this->loadNode(1)->label();
|
||||
$this->assertText("$label (Original translation) - The following content translations will be deleted:");
|
||||
$label = $this->loadNode(2)->label();
|
||||
$this->assertText("$label (Original translation) - The following content translations will be deleted:");
|
||||
$label = $this->loadNode(3)->getTranslation('en')->label();
|
||||
$this->assertText($label);
|
||||
$this->assertNoText("$label (Original translation) - The following content translations will be deleted:");
|
||||
$label = $this->loadNode(4)->label();
|
||||
$this->assertText($label);
|
||||
$this->assertNoText("$label (Original translation) - The following content translations will be deleted:");
|
||||
|
||||
$this->drupalPostForm(NULL, array(), t('Delete'));
|
||||
|
||||
$node = $this->loadNode(1);
|
||||
$this->assertNull($node, '1: Node has been deleted');
|
||||
$node = $this->loadNode(2);
|
||||
$this->assertNull($node, '2: Node has been deleted');
|
||||
$node = $this->loadNode(3);
|
||||
$result = count($node->getTranslationLanguages()) && $node->language()->getId() == 'it';
|
||||
$this->assertTrue($result, '3: English translation has been deleted');
|
||||
$node = $this->loadNode(4);
|
||||
$this->assertNull($node, '4: Node has been deleted');
|
||||
$node = $this->loadNode(5);
|
||||
$this->assertTrue($node, '5: Node has not been deleted');
|
||||
|
||||
$this->assertText('Deleted 8 posts.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the specified node from the storage.
|
||||
*
|
||||
* @param int $id
|
||||
* The node identifier.
|
||||
*
|
||||
* @return \Drupal\node\NodeInterface
|
||||
* The loaded node.
|
||||
*/
|
||||
protected function loadNode($id) {
|
||||
/** @var \Drupal\node\NodeStorage $storage */
|
||||
$storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
$storage->resetCache([$id]);
|
||||
return $storage->load($id);
|
||||
}
|
||||
|
||||
}
|
59
core/modules/node/src/Tests/Views/FilterUidRevisionTest.php
Normal file
59
core/modules/node/src/Tests/Views/FilterUidRevisionTest.php
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\Views\FilterUidRevisionTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests\Views;
|
||||
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the node_uid_revision handler.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class FilterUidRevisionTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = array('test_filter_node_uid_revision');
|
||||
|
||||
/**
|
||||
* Tests the node_uid_revision filter.
|
||||
*/
|
||||
public function testFilter() {
|
||||
$author = $this->drupalCreateUser();
|
||||
$no_author = $this->drupalCreateUser();
|
||||
|
||||
$expected_result = array();
|
||||
// Create one node, with the author as the node author.
|
||||
$node = $this->drupalCreateNode(array('uid' => $author->id()));
|
||||
$expected_result[] = array('nid' => $node->id());
|
||||
// Create one node of which an additional revision author will be the
|
||||
// author.
|
||||
$node = $this->drupalCreateNode(array('revision_uid' => $no_author->id()));
|
||||
$expected_result[] = array('nid' => $node->id());
|
||||
$revision = clone $node;
|
||||
// Force to add a new revision.
|
||||
$revision->set('vid', NULL);
|
||||
$revision->set('revision_uid', $author->id());
|
||||
$revision->save();
|
||||
|
||||
// Create one node on which the author has neither authorship of revisions
|
||||
// or the main node.
|
||||
$this->drupalCreateNode(array('uid' => $no_author->id()));
|
||||
|
||||
$view = Views::getView('test_filter_node_uid_revision');
|
||||
$view->initHandlers();
|
||||
$view->filter['uid_revision']->value = array($author->id());
|
||||
|
||||
$this->executeView($view);
|
||||
$this->assertIdenticalResultset($view, $expected_result, array('nid' => 'nid'), 'Make sure that the view only returns nodes which match either the node or the revision author.');
|
||||
}
|
||||
|
||||
}
|
363
core/modules/node/src/Tests/Views/FrontPageTest.php
Normal file
363
core/modules/node/src/Tests/Views/FrontPageTest.php
Normal file
|
@ -0,0 +1,363 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\Views\FrontPageTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests\Views;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\views\Tests\AssertViewsCacheTagsTrait;
|
||||
use Drupal\views\Tests\ViewTestBase;
|
||||
use Drupal\views\ViewExecutable;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the default frontpage provided by views.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class FrontPageTest extends ViewTestBase {
|
||||
|
||||
use AssertViewsCacheTagsTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $dumpHeaders = TRUE;
|
||||
|
||||
/**
|
||||
* The entity storage for nodes.
|
||||
*
|
||||
* @var \Drupal\node\NodeStorage
|
||||
*/
|
||||
protected $nodeStorage;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node', 'contextual');
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->nodeStorage = $this->container->get('entity.manager')
|
||||
->getStorage('node');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the frontpage.
|
||||
*/
|
||||
public function testFrontPage() {
|
||||
$site_name = $this->randomMachineName();
|
||||
$this->config('system.site')
|
||||
->set('name', $site_name)
|
||||
->save();
|
||||
|
||||
$view = Views::getView('frontpage');
|
||||
|
||||
// Tests \Drupal\node\Plugin\views\row\RssPluginBase::calculateDependencies().
|
||||
$expected = [
|
||||
'config' => [
|
||||
'core.entity_view_mode.node.rss',
|
||||
'core.entity_view_mode.node.teaser',
|
||||
],
|
||||
'module' => [
|
||||
'node',
|
||||
'user',
|
||||
],
|
||||
];
|
||||
$this->assertIdentical($expected, $view->calculateDependencies());
|
||||
|
||||
$view->setDisplay('page_1');
|
||||
$this->executeView($view);
|
||||
$view->preview();
|
||||
|
||||
$this->assertEqual($view->getTitle(), format_string('Welcome to @site_name', array('@site_name' => $site_name)), 'The welcome title is used for the empty view.');
|
||||
$view->destroy();
|
||||
|
||||
// Create some nodes on the frontpage view. Add more than 10 nodes in order
|
||||
// to enable paging.
|
||||
$expected = array();
|
||||
for ($i = 0; $i < 20; $i++) {
|
||||
$values = array();
|
||||
$values['type'] = 'article';
|
||||
$values['title'] = $this->randomMachineName();
|
||||
$values['promote'] = TRUE;
|
||||
$values['status'] = TRUE;
|
||||
// Test descending sort order.
|
||||
$values['created'] = REQUEST_TIME - $i;
|
||||
// Test the sticky order.
|
||||
if ($i == 5) {
|
||||
$values['sticky'] = TRUE;
|
||||
$node = $this->nodeStorage->create($values);
|
||||
$node->save();
|
||||
// Put the sticky on at the front.
|
||||
array_unshift($expected, array('nid' => $node->id()));
|
||||
}
|
||||
else {
|
||||
$values['sticky'] = FALSE;
|
||||
$node = $this->nodeStorage->create($values);
|
||||
$node->save();
|
||||
array_push($expected, array('nid' => $node->id()));
|
||||
}
|
||||
}
|
||||
|
||||
// Create some nodes which aren't on the frontpage, either because they
|
||||
// aren't promoted or because they aren't published.
|
||||
$not_expected_nids = array();
|
||||
|
||||
$values = array();
|
||||
$values['type'] = 'article';
|
||||
$values['title'] = $this->randomMachineName();
|
||||
$values['status'] = TRUE;
|
||||
$values['promote'] = FALSE;
|
||||
$node = $this->nodeStorage->create($values);
|
||||
$node->save();
|
||||
$not_expected_nids[] = $node->id();
|
||||
|
||||
$values['promote'] = TRUE;
|
||||
$values['status'] = FALSE;
|
||||
$values['title'] = $this->randomMachineName();
|
||||
$node = $this->nodeStorage->create($values);
|
||||
$node->save();
|
||||
$not_expected_nids[] = $node->id();
|
||||
|
||||
$values['promote'] = TRUE;
|
||||
$values['sticky'] = TRUE;
|
||||
$values['status'] = FALSE;
|
||||
$values['title'] = $this->randomMachineName();
|
||||
$node = $this->nodeStorage->create($values);
|
||||
$node->save();
|
||||
$not_expected_nids[] = $node->id();
|
||||
|
||||
$column_map = array('nid' => 'nid');
|
||||
|
||||
$view->setDisplay('page_1');
|
||||
$this->executeView($view);
|
||||
$this->assertIdenticalResultset($view, array_slice($expected, 0, 10), $column_map, 'Ensure that the right nodes are displayed on the frontpage.');
|
||||
$this->assertNotInResultSet($view, $not_expected_nids, 'Ensure no unexpected node is in the result.');
|
||||
$view->destroy();
|
||||
|
||||
$view->setDisplay('page_1');
|
||||
$view->setCurrentPage(1);
|
||||
$this->executeView($view);
|
||||
$this->assertIdenticalResultset($view, array_slice($expected, 10, 10), $column_map, 'Ensure that the right nodes are displayed on second page of the frontpage.');
|
||||
$this->assertNotInResultSet($view, $not_expected_nids, 'Ensure no unexpected node is in the result.');
|
||||
$view->destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that an amount of nids aren't in the result.
|
||||
*
|
||||
* @param \Drupal\views\ViewExecutable $view
|
||||
* An executed View.
|
||||
* @param array $not_expected_nids
|
||||
* An array of nids which should not be part of the resultset.
|
||||
* @param string $message
|
||||
* (optional) A custom message to display with the assertion.
|
||||
*/
|
||||
protected function assertNotInResultSet(ViewExecutable $view, array $not_expected_nids, $message = '') {
|
||||
$found_nids = array_filter($view->result, function ($row) use ($not_expected_nids) {
|
||||
return in_array($row->nid, $not_expected_nids);
|
||||
});
|
||||
$this->assertFalse($found_nids, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the frontpage when logged in as admin.
|
||||
*/
|
||||
public function testAdminFrontPage() {
|
||||
// When a user with sufficient permissions is logged in, views_ui adds
|
||||
// contextual links to the homepage view. This verifies there are no errors.
|
||||
\Drupal::service('module_installer')->install(array('views_ui'));
|
||||
// Login root user with sufficient permissions.
|
||||
$this->drupalLogin($this->rootUser);
|
||||
// Test frontpage view.
|
||||
$this->drupalGet('node');
|
||||
$this->assertResponse(200);
|
||||
// Check that the frontpage view was rendered.
|
||||
$this->assertPattern('/class=".+view-frontpage/', 'Frontpage view was rendered');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the cache tags when using the "none" cache plugin.
|
||||
*/
|
||||
public function testCacheTagsWithCachePluginNone() {
|
||||
$this->enablePageCaching();
|
||||
$this->assertFrontPageViewCacheTags(FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the cache tags when using the "tag" cache plugin.
|
||||
*/
|
||||
public function testCacheTagsWithCachePluginTag() {
|
||||
$this->enablePageCaching();
|
||||
|
||||
$view = Views::getView('frontpage');
|
||||
$view->setDisplay('page_1');
|
||||
$view->display_handler->overrideOption('cache', [
|
||||
'type' => 'tag',
|
||||
]);
|
||||
$view->save();
|
||||
|
||||
$this->assertFrontPageViewCacheTags(TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the cache tags when using the "time" cache plugin.
|
||||
*/
|
||||
public function testCacheTagsWithCachePluginTime() {
|
||||
$this->enablePageCaching();
|
||||
|
||||
$view = Views::getView('frontpage');
|
||||
$view->setDisplay('page_1');
|
||||
$view->display_handler->overrideOption('cache', [
|
||||
'type' => 'time',
|
||||
'options' => [
|
||||
'results_lifespan' => 3600,
|
||||
'output_lifespan' => 3600,
|
||||
],
|
||||
]);
|
||||
$view->save();
|
||||
|
||||
$this->assertFrontPageViewCacheTags(TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the cache tags on the front page.
|
||||
*
|
||||
* @param bool $do_assert_views_caches
|
||||
* Whether to check Views' result & output caches.
|
||||
*/
|
||||
protected function assertFrontPageViewCacheTags($do_assert_views_caches) {
|
||||
$view = Views::getView('frontpage');
|
||||
$view->setDisplay('page_1');
|
||||
|
||||
$cache_contexts = [
|
||||
// Cache contexts associated with the view.
|
||||
'user.node_grants:view',
|
||||
'languages:' . LanguageInterface::TYPE_INTERFACE,
|
||||
// Cache contexts associated with the route's access checking.
|
||||
'user.permissions',
|
||||
// Default cache contexts of the renderer.
|
||||
'theme',
|
||||
'url.query_args.pagers:0',
|
||||
];
|
||||
|
||||
// Test before there are any nodes.
|
||||
$empty_node_listing_cache_tags = [
|
||||
'config:views.view.frontpage',
|
||||
'node_list',
|
||||
];
|
||||
$this->assertViewsCacheTags(
|
||||
$view,
|
||||
$empty_node_listing_cache_tags,
|
||||
$do_assert_views_caches,
|
||||
$empty_node_listing_cache_tags
|
||||
);
|
||||
$this->assertPageCacheContextsAndTags(
|
||||
Url::fromRoute('view.frontpage.page_1'),
|
||||
$cache_contexts,
|
||||
Cache::mergeTags($empty_node_listing_cache_tags, ['rendered', 'config:user.role.anonymous'])
|
||||
);
|
||||
|
||||
// Create some nodes on the frontpage view. Add more than 10 nodes in order
|
||||
// to enable paging.
|
||||
$this->drupalCreateContentType(['type' => 'article']);
|
||||
for ($i = 0; $i < 15; $i++) {
|
||||
$node = Node::create([
|
||||
'body' => [
|
||||
[
|
||||
'value' => $this->randomMachineName(32),
|
||||
'format' => filter_default_format(),
|
||||
]
|
||||
],
|
||||
'type' => 'article',
|
||||
'created' => $i,
|
||||
'title' => $this->randomMachineName(8),
|
||||
'nid' => $i + 1,
|
||||
]);
|
||||
$node->enforceIsNew(TRUE);
|
||||
$node->save();
|
||||
}
|
||||
$cache_contexts = Cache::mergeContexts($cache_contexts, [
|
||||
'timezone',
|
||||
]);
|
||||
|
||||
$this->pass('First page');
|
||||
// First page.
|
||||
$first_page_result_cache_tags = [
|
||||
'config:views.view.frontpage',
|
||||
'node_list',
|
||||
'node:6',
|
||||
'node:7',
|
||||
'node:8',
|
||||
'node:9',
|
||||
'node:10',
|
||||
'node:11',
|
||||
'node:12',
|
||||
'node:13',
|
||||
'node:14',
|
||||
'node:15',
|
||||
];
|
||||
$first_page_output_cache_tags = Cache::mergeTags($first_page_result_cache_tags, [
|
||||
'config:filter.format.plain_text',
|
||||
'node_view',
|
||||
'user_view',
|
||||
'user:0',
|
||||
]);
|
||||
$view->setDisplay('page_1');
|
||||
$view->setCurrentPage(0);
|
||||
$this->assertViewsCacheTags(
|
||||
$view,
|
||||
$first_page_result_cache_tags,
|
||||
$do_assert_views_caches,
|
||||
$first_page_output_cache_tags
|
||||
);
|
||||
$this->assertPageCacheContextsAndTags(
|
||||
Url::fromRoute('view.frontpage.page_1'),
|
||||
$cache_contexts,
|
||||
Cache::mergeTags($first_page_output_cache_tags, ['rendered', 'config:user.role.anonymous'])
|
||||
);
|
||||
|
||||
// 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',
|
||||
'node:2',
|
||||
'node:3',
|
||||
'node:4',
|
||||
'node:5',
|
||||
// The rest.
|
||||
'config:filter.format.plain_text',
|
||||
'config:views.view.frontpage',
|
||||
'node_list',
|
||||
'node_view',
|
||||
'user_view',
|
||||
'user:0',
|
||||
'rendered',
|
||||
// FinishResponseSubscriber adds this cache tag to responses that have the
|
||||
// 'user.permissions' cache context for anonymous users.
|
||||
'config:user.role.anonymous',
|
||||
]);
|
||||
|
||||
// Let's update a node title on the first page and ensure that the page
|
||||
// cache entry invalidates.
|
||||
$node = Node::load(10);
|
||||
$title = $node->getTitle() . 'a';
|
||||
$node->setTitle($title);
|
||||
$node->save();
|
||||
|
||||
$this->drupalGet(Url::fromRoute('view.frontpage.page_1'));
|
||||
$this->assertText($title);
|
||||
}
|
||||
|
||||
}
|
123
core/modules/node/src/Tests/Views/NodeContextualLinksTest.php
Normal file
123
core/modules/node/src/Tests/Views/NodeContextualLinksTest.php
Normal file
|
@ -0,0 +1,123 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\Views\NodeContextualLinksTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests\Views;
|
||||
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* Tests views contextual links on nodes.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeContextualLinksTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('contextual');
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = array('test_contextual_links');
|
||||
|
||||
/**
|
||||
* Tests contextual links.
|
||||
*/
|
||||
public function testNodeContextualLinks() {
|
||||
$this->drupalCreateContentType(array('type' => 'page'));
|
||||
$this->drupalCreateNode(array('promote' => 1));
|
||||
$this->drupalGet('node');
|
||||
|
||||
$user = $this->drupalCreateUser(array('administer nodes', 'access contextual links'));
|
||||
$this->drupalLogin($user);
|
||||
|
||||
$response = $this->renderContextualLinks(array('node:node=1:'), 'node');
|
||||
$this->assertResponse(200);
|
||||
$json = Json::decode($response);
|
||||
$this->setRawContent($json['node:node=1:']);
|
||||
|
||||
// @todo Add these back when the functionality for making Views displays
|
||||
// appear in contextual links is working again.
|
||||
// $this->assertLinkByHref('node/1/contextual-links', 0, 'The contextual link to the view was found.');
|
||||
// $this->assertLink('Test contextual link', 0, 'The contextual link to the view was found.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get server-rendered contextual links for the given contextual link ids.
|
||||
*
|
||||
* Copied from \Drupal\contextual\Tests\ContextualDynamicContextTest::renderContextualLinks().
|
||||
*
|
||||
* @param array $ids
|
||||
* An array of contextual link ids.
|
||||
* @param string $current_path
|
||||
* The Drupal path for the page for which the contextual links are rendered.
|
||||
*
|
||||
* @return string
|
||||
* The response body.
|
||||
*/
|
||||
protected function renderContextualLinks($ids, $current_path) {
|
||||
// Build POST values.
|
||||
$post = array();
|
||||
for ($i = 0; $i < count($ids); $i++) {
|
||||
$post['ids[' . $i . ']'] = $ids[$i];
|
||||
}
|
||||
|
||||
// Serialize POST values.
|
||||
foreach ($post as $key => $value) {
|
||||
// Encode according to application/x-www-form-urlencoded
|
||||
// Both names and values needs to be urlencoded, according to
|
||||
// http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1
|
||||
$post[$key] = urlencode($key) . '=' . urlencode($value);
|
||||
}
|
||||
$post = implode('&', $post);
|
||||
|
||||
// Perform HTTP request.
|
||||
return $this->curlExec(array(
|
||||
CURLOPT_URL => \Drupal::url('contextual.render', [], ['absolute' => TRUE, 'query' => array('destination' => $current_path)]),
|
||||
CURLOPT_POST => TRUE,
|
||||
CURLOPT_POSTFIELDS => $post,
|
||||
CURLOPT_HTTPHEADER => array(
|
||||
'Accept: application/json',
|
||||
'Content-Type: application/x-www-form-urlencoded',
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the node page works if Contextual Links is disabled.
|
||||
*
|
||||
* All views have Contextual links enabled by default, even with the
|
||||
* Contextual links module disabled. This tests if no calls are done to the
|
||||
* Contextual links module by views when it is disabled.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2379811
|
||||
*/
|
||||
public function testPageWithDisabledContextualModule() {
|
||||
\Drupal::service('module_installer')->uninstall(['contextual']);
|
||||
\Drupal::service('module_installer')->install(['views_ui']);
|
||||
|
||||
// Ensure that contextual links don't get called for admin users.
|
||||
$admin_user = User::load(1);
|
||||
$admin_user->setPassword('new_password');
|
||||
$admin_user->pass_raw = 'new_password';
|
||||
$admin_user->save();
|
||||
|
||||
$this->drupalCreateContentType(array('type' => 'page'));
|
||||
$this->drupalCreateNode(array('promote' => 1));
|
||||
|
||||
$this->drupalLogin($admin_user);
|
||||
$this->drupalGet('node');
|
||||
}
|
||||
|
||||
}
|
113
core/modules/node/src/Tests/Views/NodeFieldFilterTest.php
Normal file
113
core/modules/node/src/Tests/Views/NodeFieldFilterTest.php
Normal file
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\Views\NodeFieldFilterTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests\Views;
|
||||
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
|
||||
/**
|
||||
* Tests node field filters with translations.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeFieldFilterTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = array('language');
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = array('test_field_filters');
|
||||
|
||||
/**
|
||||
* List of node titles by language.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $nodeTitles = [];
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create Page content type.
|
||||
if ($this->profile != 'standard') {
|
||||
$this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
|
||||
}
|
||||
|
||||
// Add two new languages.
|
||||
ConfigurableLanguage::createFromLangcode('fr')->save();
|
||||
ConfigurableLanguage::createFromLangcode('es')->save();
|
||||
|
||||
// Set up node titles.
|
||||
$this->nodeTitles = array(
|
||||
'en' => 'Food in Paris',
|
||||
'es' => 'Comida en Paris',
|
||||
'fr' => 'Nouriture en Paris',
|
||||
);
|
||||
|
||||
// Create node with translations.
|
||||
$node = $this->drupalCreateNode(['title' => $this->nodeTitles['en'], 'langcode' => 'en', 'type' => 'page', 'body' => [['value' => $this->nodeTitles['en']]]]);
|
||||
foreach (array('es', 'fr') as $langcode) {
|
||||
$translation = $node->addTranslation($langcode, ['title' => $this->nodeTitles[$langcode]]);
|
||||
$translation->body->value = $this->nodeTitles[$langcode];
|
||||
}
|
||||
$node->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests body and title filters.
|
||||
*/
|
||||
public function testFilters() {
|
||||
// Test the title filter page, which filters for title contains 'Comida'.
|
||||
// Should show just the Spanish translation, once.
|
||||
$this->assertPageCounts('test-title-filter', array('es' => 1, 'fr' => 0, 'en' => 0), 'Comida title filter');
|
||||
|
||||
// Test the body filter page, which filters for body contains 'Comida'.
|
||||
// Should show just the Spanish translation, once.
|
||||
$this->assertPageCounts('test-body-filter', array('es' => 1, 'fr' => 0, 'en' => 0), 'Comida body filter');
|
||||
|
||||
// Test the title Paris filter page, which filters for title contains
|
||||
// 'Paris'. Should show each translation once.
|
||||
$this->assertPageCounts('test-title-paris', array('es' => 1, 'fr' => 1, 'en' => 1), 'Paris title filter');
|
||||
|
||||
// Test the body Paris filter page, which filters for body contains
|
||||
// 'Paris'. Should show each translation once.
|
||||
$this->assertPageCounts('test-body-paris', array('es' => 1, 'fr' => 1, 'en' => 1), 'Paris body filter');
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the given node translation counts are correct.
|
||||
*
|
||||
* @param string $path
|
||||
* Path of the page to test.
|
||||
* @param array $counts
|
||||
* Array whose keys are languages, and values are the number of times
|
||||
* that translation should be shown on the given page.
|
||||
* @param string $message
|
||||
* Message suffix to display.
|
||||
*/
|
||||
protected function assertPageCounts($path, $counts, $message) {
|
||||
// Disable read more links.
|
||||
entity_get_display('node', 'page', 'teaser')->removeComponent('links')->save();
|
||||
|
||||
// Get the text of the page.
|
||||
$this->drupalGet($path);
|
||||
$text = $this->getTextContent();
|
||||
|
||||
// Check the counts. Note that the title and body are both shown on the
|
||||
// page, and they are the same. So the title/body string should appear on
|
||||
// the page twice as many times as the input count.
|
||||
foreach ($counts as $langcode => $count) {
|
||||
$this->assertEqual(substr_count($text, $this->nodeTitles[$langcode]), 2 * $count, 'Translation ' . $langcode . ' has count ' . $count . ' with ' . $message);
|
||||
}
|
||||
}
|
||||
}
|
71
core/modules/node/src/Tests/Views/NodeIntegrationTest.php
Normal file
71
core/modules/node/src/Tests/Views/NodeIntegrationTest.php
Normal file
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\Views\NodeIntegrationTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests\Views;
|
||||
|
||||
/**
|
||||
* Tests the node integration into views.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeIntegrationTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = array('test_node_view');
|
||||
|
||||
/**
|
||||
* Tests basic node view with a node type argument.
|
||||
*/
|
||||
public function testNodeViewTypeArgument() {
|
||||
// Create two content types with three nodes each.
|
||||
$types = array();
|
||||
$all_nids = array();
|
||||
for ($i = 0; $i < 2; $i++) {
|
||||
$type = $this->drupalCreateContentType();
|
||||
$types[] = $type;
|
||||
|
||||
for ($j = 0; $j < 5; $j++) {
|
||||
// Ensure the right order of the nodes.
|
||||
$node = $this->drupalCreateNode(array('type' => $type->id(), 'created' => REQUEST_TIME - ($i * 5 + $j)));
|
||||
$nodes[$type->id()][$node->id()] = $node;
|
||||
$all_nids[] = $node->id();
|
||||
}
|
||||
}
|
||||
|
||||
$this->drupalGet('test-node-view');
|
||||
$this->assertResponse(404);
|
||||
|
||||
$this->drupalGet('test-node-view/all');
|
||||
$this->assertResponse(200);
|
||||
$this->assertNids($all_nids);
|
||||
|
||||
foreach ($types as $type) {
|
||||
$this->drupalGet("test-node-view/{$type->id()}");
|
||||
$this->assertNids(array_keys($nodes[$type->id()]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that a list of nodes appear on the page.
|
||||
*
|
||||
* @param array $expected_nids
|
||||
* An array of node IDs.
|
||||
*/
|
||||
protected function assertNids(array $expected_nids = array()) {
|
||||
$result = $this->xpath('//span[@class="field-content"]');
|
||||
$nids = array();
|
||||
foreach ($result as $element) {
|
||||
$nids[] = (int) $element;
|
||||
}
|
||||
$this->assertEqual($nids, $expected_nids);
|
||||
}
|
||||
|
||||
}
|
282
core/modules/node/src/Tests/Views/NodeLanguageTest.php
Normal file
282
core/modules/node/src/Tests/Views/NodeLanguageTest.php
Normal file
|
@ -0,0 +1,282 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\Views\NodeLanguageTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests\Views;
|
||||
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\views\Plugin\views\PluginBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests node language fields, filters, and sorting.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeLanguageTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = array('language', 'node_test_views');
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = array('test_language');
|
||||
|
||||
/**
|
||||
* List of node titles by language.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $nodeTitles = [];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp(FALSE);
|
||||
|
||||
// Create Page content type.
|
||||
if ($this->profile != 'standard') {
|
||||
$this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
|
||||
ViewTestData::createTestViews(get_class($this), array('node_test_views'));
|
||||
}
|
||||
|
||||
// Add two new languages.
|
||||
ConfigurableLanguage::createFromLangcode('fr')->save();
|
||||
ConfigurableLanguage::createFromLangcode('es')->save();
|
||||
|
||||
// Make the body field translatable. The title is already translatable by
|
||||
// definition.
|
||||
$field_storage = FieldStorageConfig::loadByName('node', 'body');
|
||||
$field_storage->setTranslatable(TRUE);
|
||||
$field_storage->save();
|
||||
|
||||
// Set up node titles. They should not include the words "French",
|
||||
// "English", or "Spanish", as there is a language field in the view
|
||||
// that prints out those words.
|
||||
$this->nodeTitles = array(
|
||||
'es' => array(
|
||||
'Primero nodo es',
|
||||
'Segundo nodo es',
|
||||
'Tercera nodo es',
|
||||
),
|
||||
'en' => array(
|
||||
'First node en',
|
||||
'Second node en',
|
||||
),
|
||||
'fr' => array(
|
||||
'Premier nœud fr',
|
||||
)
|
||||
);
|
||||
|
||||
// Create nodes with translations.
|
||||
foreach ($this->nodeTitles['es'] as $index => $title) {
|
||||
$node = $this->drupalCreateNode(array('title' => $title, 'langcode' => 'es', 'type' => 'page', 'promote' => 1));
|
||||
foreach (array('en', 'fr') as $langcode) {
|
||||
if (isset($this->nodeTitles[$langcode][$index])) {
|
||||
$translation = $node->addTranslation($langcode, array('title' => $this->nodeTitles[$langcode][$index]));
|
||||
$translation->body->value = $this->randomMachineName(32);
|
||||
}
|
||||
}
|
||||
$node->save();
|
||||
}
|
||||
$this->container->get('router.builder')->rebuild();
|
||||
|
||||
$user = $this->drupalCreateUser(array('access content overview', 'access content'));
|
||||
$this->drupalLogin($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests translation language filter, field, and sort.
|
||||
*/
|
||||
public function testLanguages() {
|
||||
// Test the page with no arguments. It is filtered to Spanish and French.
|
||||
// The page shows node titles and languages.
|
||||
$this->drupalGet('test-language');
|
||||
$message = 'French/Spanish page';
|
||||
|
||||
// Test that the correct nodes are shown.
|
||||
foreach ($this->nodeTitles as $langcode => $list) {
|
||||
foreach ($list as $title) {
|
||||
if ($langcode == 'en') {
|
||||
$this->assertNoText($title, $title . ' does not appear on ' . $message);
|
||||
}
|
||||
else {
|
||||
$this->assertText($title, $title . ' does appear on ' . $message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test that the language field value is shown.
|
||||
$this->assertNoText('English', 'English language is not shown on ' . $message);
|
||||
$this->assertText('French', 'French language is shown on ' . $message);
|
||||
$this->assertText('Spanish', 'Spanish language is shown on ' . $message);
|
||||
|
||||
// Test page sorting, which is by language code, ascending. So the
|
||||
// Spanish nodes should appear before the French nodes.
|
||||
$page = $this->getTextContent();
|
||||
$pos_es_max = 0;
|
||||
$pos_fr_min = 10000;
|
||||
foreach ($this->nodeTitles['es'] as $title) {
|
||||
$pos_es_max = max($pos_es_max, strpos($page, $title));
|
||||
}
|
||||
foreach ($this->nodeTitles['fr'] as $title) {
|
||||
$pos_fr_min = min($pos_fr_min, strpos($page, $title));
|
||||
}
|
||||
$this->assertTrue($pos_es_max < $pos_fr_min, 'Spanish translations appear before French on ' . $message);
|
||||
|
||||
// Test the argument -- filter to just Spanish.
|
||||
$this->drupalGet('test-language/es');
|
||||
// This time, test just the language field.
|
||||
$message = 'Spanish argument page';
|
||||
$this->assertNoText('English', 'English language is not shown on ' . $message);
|
||||
$this->assertNoText('French', 'French language is not shown on ' . $message);
|
||||
$this->assertText('Spanish', 'Spanish language is shown on ' . $message);
|
||||
|
||||
// Test the front page view filter. Only node titles in the current language
|
||||
// should be displayed on the front page by default.
|
||||
foreach ($this->nodeTitles as $langcode => $titles) {
|
||||
$this->drupalGet(($langcode == 'en' ? '' : "$langcode/") . 'node');
|
||||
foreach ($titles as $title) {
|
||||
$this->assertText($title);
|
||||
}
|
||||
foreach ($this->nodeTitles as $control_langcode => $control_titles) {
|
||||
if ($langcode != $control_langcode) {
|
||||
foreach ($control_titles as $title) {
|
||||
$this->assertNoText($title);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test the node admin view filter. By default all translations should show.
|
||||
$this->drupalGet('admin/content');
|
||||
foreach ($this->nodeTitles as $titles) {
|
||||
foreach ($titles as $title) {
|
||||
$this->assertText($title);
|
||||
}
|
||||
}
|
||||
// When filtered, only the specific languages should show.
|
||||
foreach ($this->nodeTitles as $langcode => $titles) {
|
||||
$this->drupalGet('admin/content', array('query' => array('langcode' => $langcode)));
|
||||
foreach ($titles as $title) {
|
||||
$this->assertText($title);
|
||||
}
|
||||
foreach ($this->nodeTitles as $control_langcode => $control_titles) {
|
||||
if ($langcode != $control_langcode) {
|
||||
foreach ($control_titles as $title) {
|
||||
$this->assertNoText($title);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Override the config for the front page view, so that the language
|
||||
// filter is set to the site default language instead. This should just
|
||||
// show the English nodes, no matter what the content language is.
|
||||
$config = $this->config('views.view.frontpage');
|
||||
$config->set('display.default.display_options.filters.langcode.value', array(PluginBase::VIEWS_QUERY_LANGUAGE_SITE_DEFAULT => PluginBase::VIEWS_QUERY_LANGUAGE_SITE_DEFAULT));
|
||||
$config->save();
|
||||
foreach ($this->nodeTitles as $langcode => $titles) {
|
||||
$this->drupalGet(($langcode == 'en' ? '' : "$langcode/") . 'node');
|
||||
foreach ($this->nodeTitles as $control_langcode => $control_titles) {
|
||||
foreach ($control_titles as $title) {
|
||||
if ($control_langcode == 'en') {
|
||||
$this->assertText($title, 'English title is shown when filtering is site default');
|
||||
}
|
||||
else {
|
||||
$this->assertNoText($title, 'Non-English title is not shown when filtering is site default');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Override the config so that the language filter is set to the UI
|
||||
// language, and make that have a fixed value of 'es'.
|
||||
//
|
||||
// IMPORTANT: Make sure this part of the test is last -- it is changing
|
||||
// language configuration!
|
||||
$config->set('display.default.display_options.filters.langcode.value', array('***LANGUAGE_language_interface***' => '***LANGUAGE_language_interface***'));
|
||||
$config->save();
|
||||
$language_config = $this->config('language.types');
|
||||
$language_config->set('negotiation.language_interface.enabled', array('language-selected' => 1));
|
||||
$language_config->save();
|
||||
$language_config = $this->config('language.negotiation');
|
||||
$language_config->set('selected_langcode', 'es');
|
||||
$language_config->save();
|
||||
|
||||
// With a fixed language selected, there is no language-based URL.
|
||||
$this->drupalGet('node');
|
||||
foreach ($this->nodeTitles as $control_langcode => $control_titles) {
|
||||
foreach ($control_titles as $title) {
|
||||
if ($control_langcode == 'es') {
|
||||
$this->assertText($title, 'Spanish title is shown when filtering is fixed UI language');
|
||||
}
|
||||
else {
|
||||
$this->assertNoText($title, 'Non-Spanish title is not shown when filtering is fixed UI language');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests native name display in language field.
|
||||
*/
|
||||
public function testNativeLanguageField() {
|
||||
$this->assertLanguageNames();
|
||||
|
||||
// Modify test view to display native language names and set translations.
|
||||
$config = $this->config('views.view.test_language');
|
||||
$config->set('display.default.display_options.fields.langcode.settings.native_language', TRUE);
|
||||
$config->save();
|
||||
\Drupal::languageManager()->getLanguageConfigOverride('fr', 'language.entity.fr')->set('label', 'Français')->save();
|
||||
\Drupal::languageManager()->getLanguageConfigOverride('es', 'language.entity.es')->set('label', 'Español')->save();
|
||||
$this->assertLanguageNames(TRUE);
|
||||
|
||||
// Modify test view to use the views built-in language field and test that.
|
||||
\Drupal::state()->set('node_test_views.use_basic_handler', TRUE);
|
||||
Views::viewsData()->clear();
|
||||
$config = $this->config('views.view.test_language');
|
||||
$config->set('display.default.display_options.fields.langcode.native_language', FALSE);
|
||||
$config->clear('display.default.display_options.fields.langcode.settings');
|
||||
$config->clear('display.default.display_options.fields.langcode.type');
|
||||
$config->set('display.default.display_options.fields.langcode.plugin_id', 'language');
|
||||
$config->save();
|
||||
$this->assertLanguageNames();
|
||||
$config->set('display.default.display_options.fields.langcode.native_language', TRUE)->save();
|
||||
$this->assertLanguageNames(TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts the presence of language names in their English or native forms.
|
||||
*
|
||||
* @param bool $native
|
||||
* (optional) Whether to assert the language name in its native form.
|
||||
*/
|
||||
protected function assertLanguageNames($native = FALSE) {
|
||||
$this->drupalGet('test-language');
|
||||
if ($native) {
|
||||
$this->assertText('Français', 'French language shown in native form.');
|
||||
$this->assertText('Español', 'Spanish language shown in native form.');
|
||||
$this->assertNoText('French', 'French language not shown in English.');
|
||||
$this->assertNoText('Spanish', 'Spanish language not shown in English.');
|
||||
}
|
||||
else {
|
||||
$this->assertNoText('Français', 'French language not shown in native form.');
|
||||
$this->assertNoText('Español', 'Spanish language not shown in native form.');
|
||||
$this->assertText('French', 'French language shown in English.');
|
||||
$this->assertText('Spanish', 'Spanish language shown in English.');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
67
core/modules/node/src/Tests/Views/NodeRevisionWizardTest.php
Normal file
67
core/modules/node/src/Tests/Views/NodeRevisionWizardTest.php
Normal file
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\Views\NodeRevisionWizardTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests\Views;
|
||||
|
||||
use Drupal\views\Tests\Wizard\WizardTestBase;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the wizard with node_revision as base table.
|
||||
*
|
||||
* @group node
|
||||
* @see \Drupal\node\Plugin\views\wizard\NodeRevision
|
||||
*/
|
||||
class NodeRevisionWizardTest extends WizardTestBase {
|
||||
|
||||
/**
|
||||
* Tests creating a node revision view.
|
||||
*/
|
||||
public function testViewAdd() {
|
||||
$this->drupalCreateContentType(array('type' => 'article'));
|
||||
// Create two nodes with two revision.
|
||||
$node_storage = \Drupal::entityManager()->getStorage('node');
|
||||
/** @var \Drupal\node\NodeInterface $node */
|
||||
$node = $node_storage->create(array('type' => 'article', 'created' => REQUEST_TIME + 40));
|
||||
$node->save();
|
||||
|
||||
$node = $node->createDuplicate();
|
||||
$node->setNewRevision();
|
||||
$node->created->value = REQUEST_TIME + 20;
|
||||
$node->save();
|
||||
|
||||
$node = $node_storage->create(array('type' => 'article', 'created' => REQUEST_TIME + 30));
|
||||
$node->save();
|
||||
|
||||
$node = $node->createDuplicate();
|
||||
$node->setNewRevision();
|
||||
$node->created->value = REQUEST_TIME + 10;
|
||||
$node->save();
|
||||
|
||||
$view = array();
|
||||
$view['label'] = $this->randomMachineName(16);
|
||||
$view['id'] = strtolower($this->randomMachineName(16));
|
||||
$view['description'] = $this->randomMachineName(16);
|
||||
$view['page[create]'] = FALSE;
|
||||
$view['show[wizard_key]'] = 'node_revision';
|
||||
$this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit'));
|
||||
|
||||
$view_storage_controller = \Drupal::entityManager()->getStorage('view');
|
||||
/** @var \Drupal\views\Entity\View $view */
|
||||
$view = $view_storage_controller->load($view['id']);
|
||||
|
||||
$this->assertEqual($view->get('base_table'), 'node_field_revision');
|
||||
|
||||
$executable = Views::executableFactory()->get($view);
|
||||
$this->executeView($executable);
|
||||
|
||||
$this->assertIdenticalResultset($executable, array(array('vid' => 1), array('vid' => 3), array('vid' => 2), array('vid' => 4)),
|
||||
array('vid' => 'vid'));
|
||||
}
|
||||
|
||||
}
|
||||
|
33
core/modules/node/src/Tests/Views/NodeTestBase.php
Normal file
33
core/modules/node/src/Tests/Views/NodeTestBase.php
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\Views\NodeTestBase.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests\Views;
|
||||
|
||||
use Drupal\views\Tests\ViewTestBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
|
||||
/**
|
||||
* Base class for all node tests.
|
||||
*/
|
||||
abstract class NodeTestBase extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node_test_views');
|
||||
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
if ($import_test_views) {
|
||||
ViewTestData::createTestViews(get_class($this), array('node_test_views'));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\Views\NodeViewsFieldAccessTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests\Views;
|
||||
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\user\Entity\User;
|
||||
use Drupal\views\Tests\Handler\FieldFieldAccessTestBase;
|
||||
|
||||
/**
|
||||
* Tests base field access in Views for the node entity.
|
||||
*
|
||||
* @group Node
|
||||
*/
|
||||
class NodeViewsFieldAccessTest extends FieldFieldAccessTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['node', 'entity_test'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$this->installEntitySchema('node');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check access for node fields.
|
||||
*/
|
||||
public function testNodeFields() {
|
||||
$user = User::create([
|
||||
'name' => 'test user',
|
||||
]);
|
||||
$user->save();
|
||||
NodeType::create([
|
||||
'type' => 'article',
|
||||
'name' => 'Article',
|
||||
])->save();
|
||||
$node = Node::create([
|
||||
'type' => 'article',
|
||||
'title' => 'Test title',
|
||||
'uid' => $user->id(),
|
||||
'status' => 1,
|
||||
'promote' => 1,
|
||||
'sticky' => 0,
|
||||
'created' => 123456,
|
||||
]);
|
||||
|
||||
$node->save();
|
||||
|
||||
// @todo Expand the test coverage in https://www.drupal.org/node/2464635
|
||||
|
||||
$this->assertFieldAccess('node', 'nid', $node->id());
|
||||
$this->assertFieldAccess('node', 'uuid', $node->uuid());
|
||||
$this->assertFieldAccess('node', 'vid', $node->id());
|
||||
$this->assertFieldAccess('node', 'type', $node->type->entity->label());
|
||||
$this->assertFieldAccess('node', 'langcode', $node->language()->getName());
|
||||
$this->assertFieldAccess('node', 'title', 'Test title');
|
||||
$this->assertFieldAccess('node', 'uid', $user->getUsername());
|
||||
// @todo Don't we want to display Published / Unpublished by default,
|
||||
// see https://www.drupal.org/node/2465623
|
||||
$this->assertFieldAccess('node', 'status', 'On');
|
||||
$this->assertFieldAccess('node', 'promote', 'On');
|
||||
$this->assertFieldAccess('node', 'sticky', 'Off');
|
||||
|
||||
// $this->assertFieldAccess('node', 'created', \Drupal::service('date.formatter')->format(123456));
|
||||
// $this->assertFieldAccess('node', 'changed', \Drupal::service('date.formatter')->format(REQUEST_TIME));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\Views\RevisionRelationshipsTest.
|
||||
*/
|
||||
namespace Drupal\node\Tests\Views;
|
||||
|
||||
use Drupal\views\Views;
|
||||
use Drupal\views\Tests\ViewTestBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
|
||||
/**
|
||||
* Tests the integration of node_revision table of node module.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class RevisionRelationshipsTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node' ,'node_test_views');
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
ViewTestData::createTestViews(get_class($this), array('node_test_views'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = array('test_node_revision_nid', 'test_node_revision_vid');
|
||||
|
||||
/**
|
||||
* Create a node with revision and rest result count for both views.
|
||||
*/
|
||||
public function testNodeRevisionRelationship() {
|
||||
$node = $this->drupalCreateNode();
|
||||
// Create revision of the node.
|
||||
$node_revision = clone $node;
|
||||
$node_revision->setNewRevision();
|
||||
$node_revision->save();
|
||||
$column_map = array(
|
||||
'vid' => 'vid',
|
||||
'node_field_data_node_field_revision_nid' => 'node_node_revision_nid',
|
||||
'nid_1' => 'nid_1',
|
||||
);
|
||||
|
||||
// Here should be two rows.
|
||||
$view_nid = Views::getView('test_node_revision_nid');
|
||||
$this->executeView($view_nid, array($node->id()));
|
||||
$resultset_nid = array(
|
||||
array(
|
||||
'vid' => '1',
|
||||
'node_node_revision_nid' => '1',
|
||||
'nid_1' => '1',
|
||||
),
|
||||
array(
|
||||
'vid' => '2',
|
||||
'node_revision_nid' => '1',
|
||||
'node_node_revision_nid' => '1',
|
||||
'nid_1' => '1',
|
||||
),
|
||||
);
|
||||
$this->assertIdenticalResultset($view_nid, $resultset_nid, $column_map);
|
||||
|
||||
// There should be only one row with active revision 2.
|
||||
$view_vid = Views::getView('test_node_revision_vid');
|
||||
$this->executeView($view_vid, array($node->id()));
|
||||
$resultset_vid = array(
|
||||
array(
|
||||
'vid' => '2',
|
||||
'node_node_revision_nid' => '1',
|
||||
'nid_1' => '1',
|
||||
),
|
||||
);
|
||||
$this->assertIdenticalResultset($view_vid, $resultset_vid, $column_map);
|
||||
}
|
||||
|
||||
}
|
93
core/modules/node/src/Tests/Views/RowPluginTest.php
Normal file
93
core/modules/node/src/Tests/Views/RowPluginTest.php
Normal file
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\Views\RowPluginTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests\Views;
|
||||
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the node row plugin.
|
||||
*
|
||||
* @group node
|
||||
* @see \Drupal\node\Plugin\views\row\NodeRow
|
||||
*/
|
||||
class RowPluginTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node');
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = array('test_node_row_plugin');
|
||||
|
||||
/**
|
||||
* Contains all nodes used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $nodes;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalCreateContentType(array('type' => 'article'));
|
||||
|
||||
// Create two nodes.
|
||||
for ($i = 0; $i < 2; $i++) {
|
||||
$this->nodes[] = $this->drupalCreateNode(
|
||||
array(
|
||||
'type' => 'article',
|
||||
'body' => array(
|
||||
array(
|
||||
'value' => $this->randomMachineName(42),
|
||||
'format' => filter_default_format(),
|
||||
'summary' => $this->randomMachineName(),
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the node row plugin.
|
||||
*/
|
||||
public function testRowPlugin() {
|
||||
/** @var \Drupal\Core\Render\RendererInterface $renderer */
|
||||
$renderer = $this->container->get('renderer');
|
||||
$view = Views::getView('test_node_row_plugin');
|
||||
$view->initDisplay();
|
||||
$view->setDisplay('page_1');
|
||||
$view->initStyle();
|
||||
$view->rowPlugin->options['view_mode'] = 'full';
|
||||
|
||||
// Test with view_mode full.
|
||||
$output = $view->preview();
|
||||
$output = $renderer->renderRoot($output);
|
||||
foreach ($this->nodes as $node) {
|
||||
$this->assertFalse(strpos($output, $node->body->summary) !== FALSE, 'Make sure the teaser appears in the output of the view.');
|
||||
$this->assertTrue(strpos($output, $node->body->value) !== FALSE, 'Make sure the full text appears in the output of the view.');
|
||||
}
|
||||
|
||||
// Test with teasers.
|
||||
$view->rowPlugin->options['view_mode'] = 'teaser';
|
||||
$output = $view->preview();
|
||||
$output = $renderer->renderRoot($output);
|
||||
foreach ($this->nodes as $node) {
|
||||
$this->assertTrue(strpos($output, $node->body->summary) !== FALSE, 'Make sure the teaser appears in the output of the view.');
|
||||
$this->assertFalse(strpos($output, $node->body->value) !== FALSE, 'Make sure the full text does not appears in the output of the view if teaser is set as viewmode.');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
79
core/modules/node/src/Tests/Views/StatusExtraTest.php
Normal file
79
core/modules/node/src/Tests/Views/StatusExtraTest.php
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\node\Tests\Views\StatusExtraTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests\Views;
|
||||
|
||||
/**
|
||||
* Tests the node.status_extra field handler.
|
||||
*
|
||||
* @group node
|
||||
* @see \Drupal\node\Plugin\views\filter\Status
|
||||
*/
|
||||
class StatusExtraTest extends NodeTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = array('test_status_extra');
|
||||
|
||||
/**
|
||||
* Tests the status extra filter.
|
||||
*/
|
||||
public function testStatusExtra() {
|
||||
$node_author = $this->drupalCreateUser(array('view own unpublished content'));
|
||||
$node_author_not_unpublished = $this->drupalCreateUser();
|
||||
$normal_user = $this->drupalCreateUser();
|
||||
$admin_user = $this->drupalCreateUser(array('bypass node access'));
|
||||
|
||||
// Create one published and one unpublished node by the admin.
|
||||
$node_published = $this->drupalCreateNode(array('uid' => $admin_user->id()));
|
||||
$node_unpublished = $this->drupalCreateNode(array('uid' => $admin_user->id(), 'status' => NODE_NOT_PUBLISHED));
|
||||
|
||||
// Create one unpublished node by a certain author user.
|
||||
$node_unpublished2 = $this->drupalCreateNode(array('uid' => $node_author->id(), 'status' => NODE_NOT_PUBLISHED));
|
||||
|
||||
// Create one unpublished node by a user who does not have the `view own
|
||||
// unpublished content` permission.
|
||||
$node_unpublished3 = $this->drupalCreateNode(array('uid' => $node_author_not_unpublished->id(), 'status' => NODE_NOT_PUBLISHED));
|
||||
|
||||
// The administrator should simply see all nodes.
|
||||
$this->drupalLogin($admin_user);
|
||||
$this->drupalGet('test_status_extra');
|
||||
$this->assertText($node_published->label());
|
||||
$this->assertText($node_unpublished->label());
|
||||
$this->assertText($node_unpublished2->label());
|
||||
$this->assertText($node_unpublished3->label());
|
||||
|
||||
// The node author should see the published node and his own node.
|
||||
$this->drupalLogin($node_author);
|
||||
$this->drupalGet('test_status_extra');
|
||||
$this->assertText($node_published->label());
|
||||
$this->assertNoText($node_unpublished->label());
|
||||
$this->assertText($node_unpublished2->label());
|
||||
$this->assertNoText($node_unpublished3->label());
|
||||
|
||||
// The normal user should just see the published node.
|
||||
$this->drupalLogin($normal_user);
|
||||
$this->drupalGet('test_status_extra');
|
||||
$this->assertText($node_published->label());
|
||||
$this->assertNoText($node_unpublished->label());
|
||||
$this->assertNoText($node_unpublished2->label());
|
||||
$this->assertNoText($node_unpublished3->label());
|
||||
|
||||
// The author without the permission to see his own unpublished node should
|
||||
// just see the published node.
|
||||
$this->drupalLogin($node_author_not_unpublished);
|
||||
$this->drupalGet('test_status_extra');
|
||||
$this->assertText($node_published->label());
|
||||
$this->assertNoText($node_unpublished->label());
|
||||
$this->assertNoText($node_unpublished2->label());
|
||||
$this->assertNoText($node_unpublished3->label());
|
||||
}
|
||||
|
||||
}
|
Reference in a new issue