updated core to 8.6.3

This commit is contained in:
2018-11-21 12:49:46 +01:00
parent 8ca34853a3
commit c92c348eee
521 changed files with 12199 additions and 4578 deletions
@@ -1052,6 +1052,12 @@ class EntityField extends FieldPluginBase implements CacheableDependencyInterfac
*/
public function getValue(ResultRow $values, $field = NULL) {
$entity = $this->getEntity($values);
// Ensure the object is not NULL before attempting to translate it.
if ($entity === NULL) {
return NULL;
}
// Retrieve the translated object.
$translated_entity = $this->getEntityFieldRenderer()->getEntityTranslation($entity, $values);
@@ -106,7 +106,7 @@ abstract class FieldPluginBase extends HandlerBase implements FieldHandlerInterf
/**
* Keeps track of the last render index.
*
* @var int|NULL
* @var int|null
*/
protected $lastRenderIndex;
@@ -5,7 +5,7 @@ namespace Drupal\views\Plugin\views\field;
use Drupal\views\ResultRow;
/**
* Defines a field hander which renders multiple items per row.
* Defines a field handler which renders multiple items per row.
*/
interface MultiItemsFieldHandlerInterface extends FieldHandlerInterface {
@@ -103,7 +103,7 @@ abstract class WizardPluginBase extends PluginBase implements WizardInterface {
* By default, filters are not exposed and added to the first non-reserved
* filter group.
*
* @var array()
* @var array
*/
protected $filter_defaults = [
'id' => NULL,
@@ -1,379 +0,0 @@
<?php
namespace Drupal\views\Tests;
use Drupal\Component\Render\MarkupInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Tests\Views\FieldTestBase;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\language\Entity\ContentLanguageSettings;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\views\Views;
/**
* Tests the Field Views data.
*
* @group views
*/
class FieldApiDataTest extends FieldTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['language'];
/**
* {@inheritdoc}
*/
public static $testViews = ['test_field_config_translation_filter'];
/**
* The nodes used by the translation filter tests.
*
* @var \Drupal\node\NodeInterface[]
*/
protected $translationNodes;
protected function setUp($import_test_views = TRUE) {
parent::setUp($import_test_views);
$field_names = $this->setUpFieldStorages(4);
// Attach the field to nodes only.
$field = [
'field_name' => $field_names[0],
'entity_type' => 'node',
'bundle' => 'page',
'label' => 'GiraffeA" label',
];
FieldConfig::create($field)->save();
// Attach the same field to a different bundle with a different label.
$this->drupalCreateContentType(['type' => 'article']);
FieldConfig::create([
'field_name' => $field_names[0],
'entity_type' => 'node',
'bundle' => 'article',
'label' => 'GiraffeB" label',
])->save();
// Now create some example nodes/users for the view result.
for ($i = 0; $i < 5; $i++) {
$edit = [
$field_names[0] => [(['value' => $this->randomMachineName()])],
];
$nodes[] = $this->drupalCreateNode($edit);
}
$bundles = [];
$bundles[] = $bundle = NodeType::create(['type' => 'bundle1']);
$bundle->save();
$bundles[] = $bundle = NodeType::create(['type' => 'bundle2']);
$bundle->save();
// Make the first field translatable on all bundles.
$field = FieldConfig::create([
'field_name' => $field_names[1],
'entity_type' => 'node',
'bundle' => $bundles[0]->id(),
'translatable' => TRUE,
]);
$field->save();
$field = FieldConfig::create([
'field_name' => $field_names[1],
'entity_type' => 'node',
'bundle' => $bundles[1]->id(),
'translatable' => TRUE,
]);
$field->save();
// Make the second field not translatable on any bundle.
$field = FieldConfig::create([
'field_name' => $field_names[2],
'entity_type' => 'node',
'bundle' => $bundles[0]->id(),
'translatable' => FALSE,
]);
$field->save();
$field = FieldConfig::create([
'field_name' => $field_names[2],
'entity_type' => 'node',
'bundle' => $bundles[1]->id(),
'translatable' => FALSE,
]);
$field->save();
// Make the last field translatable on some bundles.
$field = FieldConfig::create([
'field_name' => $field_names[3],
'entity_type' => 'node',
'bundle' => $bundles[0]->id(),
'translatable' => TRUE,
]);
$field->save();
$field = FieldConfig::create([
'field_name' => $field_names[3],
'entity_type' => 'node',
'bundle' => $bundles[1]->id(),
'translatable' => FALSE,
]);
$field->save();
// Create some example content.
ConfigurableLanguage::create([
'id' => 'es',
])->save();
ConfigurableLanguage::create([
'id' => 'fr',
])->save();
$config = ContentLanguageSettings::loadByEntityTypeBundle('node', $bundles[0]->id());
$config->setDefaultLangcode('es')
->setLanguageAlterable(TRUE)
->save();
$config = ContentLanguageSettings::loadByEntityTypeBundle('node', $bundles[1]->id());
$config->setDefaultLangcode('es')
->setLanguageAlterable(TRUE)
->save();
$node = Node::create([
'title' => 'Test title ' . $bundles[0]->id(),
'type' => $bundles[0]->id(),
'langcode' => 'es',
$field_names[1] => 'field name 1: es',
$field_names[2] => 'field name 2: es',
$field_names[3] => 'field name 3: es',
]);
$node->save();
$this->translationNodes[] = $node;
$translation = $node->addTranslation('fr');
$translation->{$field_names[1]}->value = 'field name 1: fr';
$translation->{$field_names[3]}->value = 'field name 3: fr';
$translation->title->value = $node->title->value;
$translation->save();
$node = Node::create([
'title' => 'Test title ' . $bundles[1]->id(),
'type' => $bundles[1]->id(),
'langcode' => 'es',
$field_names[1] => 'field name 1: es',
$field_names[2] => 'field name 2: es',
$field_names[3] => 'field name 3: es',
]);
$node->save();
$this->translationNodes[] = $node;
$translation = $node->addTranslation('fr');
$translation->{$field_names[1]}->value = 'field name 1: fr';
$translation->title->value = $node->title->value;
$translation->save();
}
/**
* Unit testing the views data structure.
*
* We check data structure for both node and node revision tables.
*/
public function testViewsData() {
$table_mapping = \Drupal::entityManager()->getStorage('node')->getTableMapping();
$field_storage = $this->fieldStorages[0];
$current_table = $table_mapping->getDedicatedDataTableName($field_storage);
$revision_table = $table_mapping->getDedicatedRevisionTableName($field_storage);
$data = $this->getViewsData();
$this->assertTrue(isset($data[$current_table]));
$this->assertTrue(isset($data[$revision_table]));
// The node field should join against node_field_data.
$this->assertTrue(isset($data[$current_table]['table']['join']['node_field_data']));
$this->assertTrue(isset($data[$revision_table]['table']['join']['node_field_revision']));
$expected_join = [
'table' => $current_table,
'left_field' => 'nid',
'field' => 'entity_id',
'extra' => [
['field' => 'deleted', 'value' => 0, 'numeric' => TRUE],
['left_field' => 'langcode', 'field' => 'langcode'],
],
];
$this->assertEqual($expected_join, $data[$current_table]['table']['join']['node_field_data']);
$expected_join = [
'table' => $revision_table,
'left_field' => 'vid',
'field' => 'revision_id',
'extra' => [
['field' => 'deleted', 'value' => 0, 'numeric' => TRUE],
['left_field' => 'langcode', 'field' => 'langcode'],
],
];
$this->assertEqual($expected_join, $data[$revision_table]['table']['join']['node_field_revision']);
// Test click sortable.
$this->assertTrue($data[$current_table][$field_storage->getName()]['field']['click sortable'], 'String field is click sortable.');
// Click sort should only be on the primary field.
$this->assertTrue(empty($data[$revision_table][$field_storage->getName()]['field']['click sortable']), 'Non-primary fields are not click sortable');
$this->assertTrue($data[$current_table][$field_storage->getName()]['help'] instanceof MarkupInterface);
$this->assertEqual($data[$current_table][$field_storage->getName()]['help'], 'Appears in: page, article. Also known as: Content: GiraffeB&quot; label');
$this->assertTrue($data[$current_table][$field_storage->getName() . '_value']['help'] instanceof MarkupInterface);
$this->assertEqual($data[$current_table][$field_storage->getName() . '_value']['help'], 'Appears in: page, article. Also known as: Content: GiraffeA&quot; label (field_name_0)');
// Since each label is only used once, views_entity_field_label() will
// return a label using alphabetical sorting.
$this->assertEqual('GiraffeA&quot; label (field_name_0)', $data[$current_table][$field_storage->getName() . '_value']['title']);
// Attach the same field to a different bundle with a different label.
$this->drupalCreateContentType(['type' => 'news']);
FieldConfig::create([
'field_name' => $this->fieldStorages[0]->getName(),
'entity_type' => 'node',
'bundle' => 'news',
'label' => 'GiraffeB" label',
])->save();
$this->container->get('views.views_data')->clear();
$data = $this->getViewsData();
// Now the 'GiraffeB&quot; label' is used twice and therefore will be
// selected by views_entity_field_label().
$this->assertEqual('GiraffeB&quot; label (field_name_0)', $data[$current_table][$field_storage->getName() . '_value']['title']);
$this->assertTrue($data[$current_table][$field_storage->getName()]['help'] instanceof MarkupInterface);
$this->assertEqual($data[$current_table][$field_storage->getName()]['help'], 'Appears in: page, article, news. Also known as: Content: GiraffeA&quot; label');
}
/**
* Gets the views data for the field created in setUp().
*
* @return array
*/
protected function getViewsData() {
$views_data = $this->container->get('views.views_data');
$data = [];
// Check the table and the joins of the first field.
// Attached to node only.
/** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
$table_mapping = \Drupal::entityManager()->getStorage('node')->getTableMapping();
$current_table = $table_mapping->getDedicatedDataTableName($this->fieldStorages[0]);
$revision_table = $table_mapping->getDedicatedRevisionTableName($this->fieldStorages[0]);
$data[$current_table] = $views_data->get($current_table);
$data[$revision_table] = $views_data->get($revision_table);
return $data;
}
/**
* Tests filtering entries with different translatabilty.
*/
public function testEntityFieldFilter() {
$map = [
'nid' => 'nid',
'langcode' => 'langcode',
];
$view = Views::getView('test_field_config_translation_filter');
// Filter by 'field name 1: es'.
$view->setDisplay('embed_1');
$this->executeView($view);
$expected = [
[
'nid' => $this->translationNodes[0]->id(),
'langcode' => 'es',
],
[
'nid' => $this->translationNodes[1]->id(),
'langcode' => 'es',
],
];
$this->assertIdenticalResultset($view, $expected, $map);
$view->destroy();
// Filter by 'field name 1: fr'.
$view->setDisplay('embed_2');
$this->executeView($view);
$expected = [
[
'nid' => $this->translationNodes[0]->id(),
'langcode' => 'fr',
],
[
'nid' => $this->translationNodes[1]->id(),
'langcode' => 'fr',
],
];
$this->assertIdenticalResultset($view, $expected, $map);
$view->destroy();
// Filter by 'field name 2: es'.
$view->setDisplay('embed_3');
$this->executeView($view);
$expected = [
[
'nid' => $this->translationNodes[0]->id(),
'langcode' => 'es',
],
[
'nid' => $this->translationNodes[0]->id(),
'langcode' => 'fr',
],
[
'nid' => $this->translationNodes[1]->id(),
'langcode' => 'es',
],
[
'nid' => $this->translationNodes[1]->id(),
'langcode' => 'fr',
],
];
$this->assertIdenticalResultset($view, $expected, $map);
$view->destroy();
// Filter by 'field name 2: fr', which doesn't exist.
$view->setDisplay('embed_4');
$this->executeView($view);
$expected = [];
$this->assertIdenticalResultset($view, $expected, $map);
$view->destroy();
// Filter by 'field name 3: es'.
$view->setDisplay('embed_5');
$this->executeView($view);
$expected = [
[
'nid' => $this->translationNodes[0]->id(),
'langcode' => 'es',
],
[
'nid' => $this->translationNodes[1]->id(),
'langcode' => 'es',
],
// Why is this one returned?
[
'nid' => $this->translationNodes[1]->id(),
'langcode' => 'fr',
],
];
$this->assertIdenticalResultset($view, $expected, $map);
$view->destroy();
// Filter by 'field name 3: fr'.
$view->setDisplay('embed_6');
$this->executeView($view);
$expected = [
[
'nid' => $this->translationNodes[0]->id(),
'langcode' => 'fr',
],
];
$this->assertIdenticalResultset($view, $expected, $map);
$view->destroy();
}
}
@@ -1,176 +0,0 @@
<?php
namespace Drupal\views\Tests\Plugin;
use Drupal\views\Views;
/**
* Tests the feed display plugin.
*
* @group views
* @see \Drupal\views\Plugin\views\display\Feed
*/
class DisplayFeedTest extends PluginTestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_display_feed', 'test_attached_disabled', 'test_feed_icon'];
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['block', 'node', 'views'];
protected function setUp($import_test_views = TRUE) {
parent::setUp($import_test_views);
$this->enableViewsTestModule();
$admin_user = $this->drupalCreateUser(['administer site configuration']);
$this->drupalLogin($admin_user);
}
/**
* Tests the rendered output.
*/
public function testFeedOutput() {
$this->drupalCreateContentType(['type' => 'page']);
// Verify a title with HTML entities is properly escaped.
$node_title = 'This "cool" & "neat" article\'s title';
$node = $this->drupalCreateNode([
'title' => $node_title,
'body' => [
0 => [
'value' => 'A paragraph',
'format' => filter_default_format(),
],
],
]);
// Test the site name setting.
$site_name = $this->randomMachineName();
$this->config('system.site')->set('name', $site_name)->save();
$this->drupalGet('test-feed-display.xml');
$result = $this->xpath('//title');
$this->assertEqual($result[0], $site_name, 'The site title is used for the feed title.');
$this->assertEqual($result[1], $node_title, 'Node title with HTML entities displays correctly.');
// Verify HTML is properly escaped in the description field.
$this->assertRaw('&lt;p&gt;A paragraph&lt;/p&gt;');
$view = $this->container->get('entity.manager')->getStorage('view')->load('test_display_feed');
$display = &$view->getDisplay('feed_1');
$display['display_options']['sitename_title'] = 0;
$view->save();
$this->drupalGet('test-feed-display.xml');
$result = $this->xpath('//title');
$this->assertEqual($result[0], 'test_display_feed', 'The display title is used for the feed title.');
// Add a block display and attach the feed.
$view->getExecutable()->newDisplay('block', NULL, 'test');
$display = &$view->getDisplay('feed_1');
$display['display_options']['displays']['test'] = 'test';
$view->save();
// Test the feed display adds a feed icon to the block display.
$this->drupalPlaceBlock('views_block:test_display_feed-test');
$this->drupalGet('<front>');
$feed_icon = $this->cssSelect('div.view-id-test_display_feed a.feed-icon');
$this->assertTrue(strpos($feed_icon[0]['href'], 'test-feed-display.xml'), 'The feed icon was found.');
// Test feed display attached to page display with arguments.
$this->drupalGet('test-feed-icon/' . $node->id());
$page_url = $this->getUrl();
$icon_href = $this->cssSelect('a.feed-icon[href *= "test-feed-icon"]')[0]['href'];
$this->assertEqual($icon_href, $page_url . '/feed', 'The feed icon was found.');
$link_href = $this->cssSelect('link[type = "application/rss+xml"][href *= "test-feed-icon"]')[0]['href'];
$this->assertEqual($link_href, $page_url . '/feed', 'The RSS link was found.');
$feed_link = simplexml_load_string($this->drupalGet($icon_href))->channel->link;
$this->assertEqual($feed_link, $page_url, 'The channel link was found.');
}
/**
* Tests the rendered output for fields display.
*/
public function testFeedFieldOutput() {
$this->drupalCreateContentType(['type' => 'page']);
// Verify a title with HTML entities is properly escaped.
$node_title = 'This "cool" & "neat" article\'s title';
$this->drupalCreateNode([
'title' => $node_title,
'body' => [
0 => [
'value' => 'A paragraph',
'format' => filter_default_format(),
],
],
]);
$this->drupalGet('test-feed-display-fields.xml');
$result = $this->xpath('//title/a');
$this->assertEqual($result[0], $node_title, 'Node title with HTML entities displays correctly.');
// Verify HTML is properly escaped in the description field.
$this->assertRaw('&lt;p&gt;A paragraph&lt;/p&gt;');
}
/**
* Tests that nothing is output when the feed display is disabled.
*/
public function testDisabledFeed() {
$this->drupalCreateContentType(['type' => 'page']);
$this->drupalCreateNode();
// Ensure that the feed_1 display is attached to the page_1 display.
$view = Views::getView('test_attached_disabled');
$view->setDisplay('page_1');
$attached_displays = $view->display_handler->getAttachedDisplays();
$this->assertTrue(in_array('feed_1', $attached_displays), 'The feed display is attached to the page display.');
// Check that the rss header is output on the page display.
$this->drupalGet('/test-attached-disabled');
$feed_header = $this->xpath('//link[@rel="alternate"]');
$this->assertEqual($feed_header[0]['type'], 'application/rss+xml', 'The feed link has the type application/rss+xml.');
$this->assertTrue(strpos($feed_header[0]['href'], 'test-attached-disabled.xml'), 'Page display contains the correct feed URL.');
// Disable the feed display.
$view->displayHandlers->get('feed_1')->setOption('enabled', FALSE);
$view->save();
// Ensure there is no link rel present on the page.
$this->drupalGet('/test-attached-disabled');
$result = $this->xpath('//link[@rel="alternate"]');
$this->assertTrue(empty($result), 'Page display does not contain a feed header.');
// Ensure the feed attachment returns 'Not found'.
$this->drupalGet('/test-attached-disabled.xml');
$this->assertResponse(404);
}
/**
* Tests that the feed display works when the linked display is disabled.
*/
public function testDisabledLinkedDisplay() {
$view = Views::getView('test_attached_disabled');
$view->setDisplay();
// Disable the page and link the feed to the page.
$view->displayHandlers->get('feed_1')->setOption('link_display', 'page_1');
$view->displayHandlers->get('page_1')->setOption('enabled', FALSE);
$view->save();
\Drupal::service('router.builder')->rebuild();
$this->drupalGet('test-attached-disabled');
$this->assertResponse(404);
// Ensure the feed can still be reached.
$this->drupalGet('test-attached-disabled.xml');
$this->assertResponse(200);
}
}
@@ -1,77 +0,0 @@
<?php
namespace Drupal\views\Tests\Plugin;
/**
* Tests the OPML feed style plugin.
*
* @group views
* @see \Drupal\views\Plugin\views\style\Opml
*/
class StyleOpmlTest extends PluginTestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_style_opml'];
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['aggregator'];
/**
* {@inheritdoc}
*/
protected function setUp($import_test_views = TRUE) {
parent::setUp($import_test_views);
$this->enableViewsTestModule();
$admin_user = $this->drupalCreateUser(['administer news feeds']);
$this->drupalLogin($admin_user);
}
/**
* Tests the rendered output.
*/
public function testOpmlOutput() {
// Create a test feed.
$values = [
'title' => $this->randomMachineName(10),
'url' => 'http://example.com/rss.xml',
'refresh' => '900',
];
$feed = $this->container->get('entity.manager')
->getStorage('aggregator_feed')
->create($values);
$feed->save();
$this->drupalGet('test-feed-opml-style');
$outline = $this->xpath('//outline[1]');
$this->assertEqual($outline[0]['type'], 'rss', 'The correct type attribute is used for rss OPML.');
$this->assertEqual($outline[0]['text'], $feed->label(), 'The correct text attribute is used for rss OPML.');
$this->assertEqual($outline[0]['xmlurl'], $feed->getUrl(), 'The correct xmlUrl attribute is used for rss OPML.');
$view = $this->container->get('entity.manager')
->getStorage('view')
->load('test_style_opml');
$display = &$view->getDisplay('feed_1');
$display['display_options']['row']['options']['type_field'] = 'link';
$display['display_options']['row']['options']['url_field'] = 'url';
$view->save();
$this->drupalGet('test-feed-opml-style');
$outline = $this->xpath('//outline[1]');
$this->assertEqual($outline[0]['type'], 'link', 'The correct type attribute is used for link OPML.');
$this->assertEqual($outline[0]['text'], $feed->label(), 'The correct text attribute is used for link OPML.');
$this->assertEqual($outline[0]['url'], $feed->getUrl(), 'The correct URL attribute is used for link OPML.');
// xmlUrl should not be present when type is link.
$this->assertNull($outline[0]['xmlUrl'], 'The xmlUrl attribute is not used for link OPML.');
}
}
@@ -32,7 +32,7 @@ abstract class ViewKernelTestBase extends KernelTestBase {
* {@inheritdoc}
*
* @param bool $import_test_views
* Should the views specififed on the test class be imported. If you need
* Should the views specified on the test class be imported. If you need
* to setup some additional stuff, like fields, you need to call false and
* then call createTestViews for your own.
*/
+2 -2
View File
@@ -114,7 +114,7 @@ class ViewExecutable {
/**
* Attachments to place before the view.
*
* @var array()
* @var array
*/
public $attachment_before = [];
@@ -1522,7 +1522,7 @@ class ViewExecutable {
// Let modules modify the view just prior to rendering it.
$module_handler->invokeAll('views_pre_render', [$this]);
// Let the themes play too, because pre render is a very themey thing.
// Let the themes play too, because prerender is a very themey thing.
foreach ($themes as $theme_name) {
$function = $theme_name . '_views_pre_render';
if (function_exists($function)) {