Update to Drupal 8.1.5. For more information, see https://www.drupal.org/project/drupal/releases/8.1.5

This commit is contained in:
Pantheon Automation 2016-07-07 09:44:38 -07:00 committed by Greg Anderson
parent 13b6ca7cc2
commit 38ba7c357d
342 changed files with 7814 additions and 1534 deletions

View file

@ -0,0 +1,346 @@
langcode: en
status: true
dependencies:
module:
- node
- user
id: base_and_revision
label: base_and_revision
module: views
description: ''
tag: ''
base_table: node_field_revision
base_field: vid
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: 0
display_options:
access:
type: perm
options:
perm: 'view all revisions'
cache:
type: none
options: { }
query:
type: views_query
options:
disable_sql_rewrite: false
distinct: false
replica: false
query_comment: ''
query_tags: { }
exposed_form:
type: basic
options:
submit_button: Apply
reset_button: false
reset_button_label: Reset
exposed_sorts_label: 'Sort by'
expose_sort_order: true
sort_asc_label: Asc
sort_desc_label: Desc
pager:
type: mini
options:
items_per_page: 10
offset: 0
id: 0
total_pages: null
expose:
items_per_page: false
items_per_page_label: 'Items per page'
items_per_page_options: '5, 10, 25, 50'
items_per_page_options_all: false
items_per_page_options_all_label: '- All -'
offset: false
offset_label: Offset
tags:
previous:
next:
style:
type: default
options:
grouping: { }
row_class: ''
default_row_class: true
uses_fields: false
row:
type: fields
options:
inline: { }
separator: ''
hide_empty: false
default_field_elements: true
fields:
nid:
id: nid
table: node_field_revision
field: nid
relationship: none
group_type: group
admin_label: ''
label: ''
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: false
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
click_sort_column: value
type: number_integer
settings:
thousand_separator: ''
prefix_suffix: true
group_column: value
group_columns: { }
group_rows: true
delta_limit: 0
delta_offset: 0
delta_reversed: false
delta_first_last: false
multi_type: separator
separator: ', '
field_api_classes: false
entity_type: node
entity_field: nid
plugin_id: field
vid:
id: vid
table: node_field_revision
field: vid
relationship: none
group_type: group
admin_label: ''
label: ''
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: false
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
click_sort_column: value
type: number_integer
settings:
thousand_separator: ''
prefix_suffix: true
group_column: value
group_columns: { }
group_rows: true
delta_limit: 0
delta_offset: 0
delta_reversed: false
delta_first_last: false
multi_type: separator
separator: ', '
field_api_classes: false
entity_type: node
entity_field: vid
plugin_id: field
vid_1:
id: vid_1
table: node_field_data
field: vid
relationship: nid
group_type: group
admin_label: ''
label: ''
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: false
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
click_sort_column: value
type: number_integer
settings:
thousand_separator: ''
prefix_suffix: true
group_column: value
group_columns: { }
group_rows: true
delta_limit: 0
delta_offset: 0
delta_reversed: false
delta_first_last: false
multi_type: separator
separator: ', '
field_api_classes: false
entity_type: node
entity_field: vid
plugin_id: field
filters:
vid:
id: vid
table: node_field_revision
field: vid
relationship: none
group_type: group
admin_label: ''
operator: '='
value:
min: ''
max: ''
value: '3'
group: 1
exposed: false
expose:
operator_id: ''
label: ''
description: ''
use_operator: false
operator: ''
identifier: ''
required: false
remember: false
multiple: false
remember_roles:
authenticated: authenticated
is_grouped: false
group_info:
label: ''
description: ''
identifier: ''
optional: true
widget: select
multiple: false
remember: false
default_group: All
default_group_multiple: { }
group_items: { }
entity_type: node
entity_field: vid
plugin_id: numeric
sorts: { }
header: { }
footer: { }
empty: { }
relationships:
nid:
id: nid
table: node_field_revision
field: nid
relationship: none
group_type: group
admin_label: Node
required: false
entity_type: node
entity_field: nid
plugin_id: standard
arguments: { }
display_extenders: { }
rendering_language: en
cache_metadata:
max-age: -1
contexts:
- 'languages:language_interface'
- url.query_args
- 'user.node_grants:view'
- user.permissions
tags: { }

View file

@ -0,0 +1,45 @@
langcode: en
status: true
dependencies:
module:
- entity_test
id: test_entity_multivalue_basefield
label: ''
module: views
description: ''
tag: ''
base_table: entity_test_multivalue_basefield
base_field: id
core: '8'
display:
default:
display_plugin: default
id: default
display_title: Master
position: 0
display_options:
fields:
id:
id: id
table: entity_test_multivalue_basefield
field: nid
relationship: none
plugin_id: field
entity_type: entity_test_multivalue_basefield
entity_field: id
name:
id: name
table: entity_test_multivalue_basefield__name
field: name
plugin_id: field
entity_type: entity_test_multivalue_basefield
entity_field: name
defaults:
fields: false
filters: false
sorts:
id:
id: id
table: entity_test_multivalue_basefield
field: id
order: asc

View file

@ -0,0 +1,188 @@
langcode: en
status: true
dependencies:
config:
- field.storage.node.body
module:
- node
- text
- user
id: test_field_body
label: test_field_body
module: views
description: ''
tag: ''
base_table: node_field_data
base_field: nid
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: 0
display_options:
access:
type: perm
options:
perm: 'access content'
cache:
type: tag
options: { }
query:
type: views_query
options:
disable_sql_rewrite: false
distinct: false
replica: false
query_comment: ''
query_tags: { }
exposed_form:
type: basic
options:
submit_button: Apply
reset_button: false
reset_button_label: Reset
exposed_sorts_label: 'Sort by'
expose_sort_order: true
sort_asc_label: Asc
sort_desc_label: Desc
pager:
type: mini
options:
items_per_page: 10
offset: 0
id: 0
total_pages: null
expose:
items_per_page: false
items_per_page_label: 'Items per page'
items_per_page_options: '5, 10, 25, 50'
items_per_page_options_all: false
items_per_page_options_all_label: '- All -'
offset: false
offset_label: Offset
tags:
previous:
next:
style:
type: default
options:
grouping: { }
row_class: ''
default_row_class: true
uses_fields: false
row:
type: fields
options:
inline: { }
separator: ''
hide_empty: false
default_field_elements: true
fields:
body:
id: body
table: node__body
field: body
relationship: none
group_type: group
admin_label: 'Body field'
label: ''
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: false
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
click_sort_column: value
type: text_default
settings: { }
group_column: value
group_columns: { }
group_rows: true
delta_limit: 0
delta_offset: 0
delta_reversed: false
delta_first_last: false
multi_type: separator
separator: ', '
field_api_classes: false
plugin_id: field
filters:
status:
value: true
table: node_field_data
field: status
plugin_id: boolean
entity_type: node
entity_field: status
id: status
expose:
operator: ''
group: 1
sorts:
created:
id: created
table: node_field_data
field: created
order: DESC
entity_type: node
entity_field: created
plugin_id: date
relationship: none
group_type: group
admin_label: ''
exposed: false
expose:
label: ''
granularity: second
header: { }
footer: { }
empty: { }
relationships: { }
arguments: { }
display_extenders: { }
cache_metadata:
max-age: -1
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- url.query_args
- 'user.node_grants:view'
- user.permissions
tags:
- 'config:field.storage.node.body'

View file

@ -0,0 +1,105 @@
<?php
namespace Drupal\Tests\views\FunctionalJavascript\Plugin\views\Handler;
use Drupal\config\Tests\SchemaCheckTestTrait;
use Drupal\field\Entity\FieldConfig;
use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
use Drupal\node\Entity\NodeType;
use Drupal\views\Tests\ViewTestData;
/**
* Tests the field field handler UI.
*
* @group views
*/
class FieldTest extends JavascriptTestBase {
use SchemaCheckTestTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['node', 'views', 'views_ui', 'views_test_config'];
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_field_body'];
/**
* The account.
*
* @var \Drupal\user\UserInterface
*/
protected $account;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
ViewTestData::createTestViews(get_class($this), ['views_test_config']);
// Disable automatic live preview to make the sequence of calls clearer.
\Drupal::configFactory()->getEditable('views.settings')->set('ui.always_live_preview', FALSE)->save();
$this->account = $this->drupalCreateUser(['administer views']);
$this->drupalLogin($this->account);
NodeType::create([
'type' => 'page',
])->save();
FieldConfig::create([
'entity_type' => 'node',
'field_name' => 'body',
'bundle' => 'page',
])->save();
}
public function testFormatterChanging() {
$web_assert = $this->assertSession();
$url = '/admin/structure/views/view/test_field_body';
$this->drupalGet($url);
$page = $this->getSession()->getPage();
$page->clickLink('Body field');
$web_assert->assertWaitOnAjaxRequest();
$page->fillField('options[type]', 'text_trimmed');
// Add a value to the trim_length setting.
$web_assert->assertWaitOnAjaxRequest();
$page->fillField('options[settings][trim_length]', '700');
$apply_button = $page->find('css', '.views-ui-dialog button.button--primary');
$this->assertTrue(!empty($apply_button));
$apply_button->press();
$web_assert->assertWaitOnAjaxRequest();
// Save the page.
$save_button = $page->find('css', '#edit-actions-submit');
$save_button->press();
// Set the body field back to 'default' and test that the trim_length
// settings are not in the config.
$this->drupalGet($url);
$page->clickLink('Body field');
$web_assert->assertWaitOnAjaxRequest();
$page->fillField('options[type]', 'text_default');
$web_assert->assertWaitOnAjaxRequest();
$apply_button = $page->find('css', '.views-ui-dialog button.button--primary');
$apply_button->press();
$web_assert->assertWaitOnAjaxRequest();
// Save the page.
$save_button = $page->find('css', '#edit-actions-submit');
$save_button->press();
$this->assertConfigSchemaByName('views.view.test_field_body');
}
}

View file

@ -0,0 +1,54 @@
<?php
namespace Drupal\Tests\views\Kernel\Entity;
use Drupal\entity_test\Entity\EntityTestMultiValueBasefield;
use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
use Drupal\views\Views;
/**
* Tests entity views with multivalue base fields.
*
* @group views
*/
class EntityViewsWithMultivalueBasefieldTest extends ViewsKernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['entity_test'];
/**
* {@inheritdoc}
*/
public static $testViews = ['test_entity_multivalue_basefield'];
/**
* {@inheritdoc}
*/
protected function setUp($import_test_views = TRUE) {
parent::setUp($import_test_views);
$this->installEntitySchema('entity_test_multivalue_basefield');
}
/**
* Tests entity views with multivalue base fields.
*/
public function testView() {
EntityTestMultiValueBasefield::create([
'name' => 'test',
])->save();
EntityTestMultiValueBasefield::create([
'name' => ['test2', 'test3'],
])->save();
$view = Views::getView('test_entity_multivalue_basefield');
$view->execute();
$this->assertIdenticalResultset($view, [
['name' => ['test']],
['name' => ['test2', 'test3']],
], ['name' => 'name']);
}
}

View file

@ -0,0 +1,98 @@
<?php
namespace Drupal\Tests\views\Kernel\Plugin\Display;
use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
/**
* Menu link test.
*
* @group views
*/
class ViewsMenuLinkTest extends ViewsKernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = [
'menu_ui',
'user',
'views'
];
/**
* {@inheritdoc}
*/
public static $testViews = ['test_page_display_menu'];
/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
*/
protected $entityManger;
/**
* The menu link manager.
*
* @var \Drupal\Core\Menu\MenuLinkManagerInterface
*/
protected $menuLinkManager;
/**
* The menu link overrides.
*
* @var \Drupal\Core\Menu\StaticMenuLinkOverridesInterface
*/
protected $menuLinkOverrides;
/**
* {@inheritdoc}
*/
protected function setUp($import_test_views = TRUE) {
parent::setUp($import_test_views);
$this->entityManger = $this->container->get('entity.manager');
$this->menuLinkManager = $this->container->get('plugin.manager.menu.link');
$this->menuLinkOverrides = $this->container->get('menu_link.static.overrides');
}
/**
* Test views internal menu link options.
*/
public function testMenuLinkOverrides() {
// Link from views module.
$views_link = $this->menuLinkManager->getDefinition('views_view:views.test_page_display_menu.page_3');
$this->assertTrue($views_link['enabled'], 'Menu link is enabled.');
$this->assertFalse($views_link['expanded'], 'Menu link is not expanded.');
$views_link['enabled'] = 0;
$views_link['expanded'] = 1;
$this->menuLinkManager->updateDefinition($views_link['id'], $views_link);
$views_link = $this->menuLinkManager->getDefinition($views_link['id']);
$this->assertFalse($views_link['enabled'], 'Menu link is disabled.');
$this->assertTrue($views_link['expanded'], 'Menu link is expanded.');
$this->menuLinkManager->rebuild();
$this->assertFalse($views_link['enabled'], 'Menu link is disabled.');
$this->assertTrue($views_link['expanded'], 'Menu link is expanded.');
// Link from user module.
$user_link = $this->menuLinkManager->getDefinition('user.page');
$this->assertTrue($user_link['enabled'], 'Menu link is enabled.');
$user_link['enabled'] = 0;
$views_link['expanded'] = 1;
$this->menuLinkManager->updateDefinition($user_link['id'], $user_link);
$this->assertFalse($user_link['enabled'], 'Menu link is disabled.');
$this->menuLinkManager->rebuild();
$this->assertFalse($user_link['enabled'], 'Menu link is disabled.');
$this->menuLinkOverrides->reload();
$views_link = $this->menuLinkManager->getDefinition('views_view:views.test_page_display_menu.page_3');
$this->assertFalse($views_link['enabled'], 'Menu link is disabled.');
$this->assertTrue($views_link['expanded'], 'Menu link is expanded.');
$user_link = $this->menuLinkManager->getDefinition('user.page');
$this->assertFalse($user_link['enabled'], 'Menu link is disabled.');
}
}

View file

@ -172,7 +172,8 @@ class JoinTest extends RelationshipJoinTestBase {
$join_info = $tables['users4'];
$this->assertTrue(strpos($join_info['condition'], "views_test_data.uid = users4.uid") !== FALSE, 'Make sure the join condition appears in the query.');
$this->assertTrue(strpos($join_info['condition'], "users4.name = :views_join_condition_2") !== FALSE, 'Make sure the first extra join condition appears in the query.');
$this->assertTrue(strpos($join_info['condition'], "users4.name IN ( :views_join_condition_3, :views_join_condition_4, :views_join_condition_5 )") !== FALSE, 'The IN condition for the join is properly formed.');
$this->assertTrue(strpos($join_info['condition'], "users4.name IN ( :views_join_condition_3[] )") !== FALSE, 'The IN condition for the join is properly formed.');
$this->assertEqual($join_info['arguments'][':views_join_condition_3[]'], array($random_name_2, $random_name_3, $random_name_4), 'Make sure the IN arguments are still part of an array.');
// Test that all the conditions are properly built.
$configuration['extra'] = array(
@ -197,8 +198,8 @@ class JoinTest extends RelationshipJoinTestBase {
$tables = $query->getTables();
$join_info = $tables['users5'];
$this->assertTrue(strpos($join_info['condition'], "views_test_data.uid = users5.uid") !== FALSE, 'Make sure the join condition appears in the query.');
$this->assertTrue(strpos($join_info['condition'], "users5.langcode = :views_join_condition_6") !== FALSE, 'Make sure the first extra join condition appears in the query.');
$this->assertTrue(strpos($join_info['condition'], "views_test_data.status = :views_join_condition_7") !== FALSE, 'Make sure the second extra join condition appears in the query.');
$this->assertTrue(strpos($join_info['condition'], "users5.langcode = :views_join_condition_4") !== FALSE, 'Make sure the first extra join condition appears in the query.');
$this->assertTrue(strpos($join_info['condition'], "views_test_data.status = :views_join_condition_5") !== FALSE, 'Make sure the second extra join condition appears in the query.');
$this->assertTrue(strpos($join_info['condition'], "users5.name = views_test_data.name") !== FALSE, 'Make sure the third extra join condition appears in the query.');
$this->assertEqual(array_values($join_info['arguments']), array('en', 0), 'Make sure the arguments are in the right order');
}

View file

@ -0,0 +1,95 @@
<?php
/**
* @file
* Contains \Drupal\views\Tests\Plugin\PluginBaseTest.
*/
namespace Drupal\Tests\views\Kernel\Plugin;
use Drupal\Core\Render\RenderContext;
use Drupal\Core\Render\Markup;
use Drupal\KernelTests\KernelTestBase;
use Drupal\views\Plugin\views\PluginBase;
/**
* Tests the PluginBase class.
*
* @group views
*/
class PluginBaseTest extends KernelTestBase {
/**
* @var TestPluginBase
*/
protected $testPluginBase;
protected function setUp() {
parent::setUp();
$this->testPluginBase = new TestPluginBase();
}
/**
* Test that the token replacement in views works correctly.
*/
public function testViewsTokenReplace() {
$text = '{{ langcode__value }} means {{ langcode }}';
$tokens = ['{{ langcode }}' => Markup::create('English'), '{{ langcode__value }}' => 'en'];
$result = \Drupal::service('renderer')->executeInRenderContext(new RenderContext(), function () use ($text, $tokens) {
return $this->testPluginBase->viewsTokenReplace($text, $tokens);
});
$this->assertIdentical($result, 'en means English');
}
/**
* Test that the token replacement in views works correctly with dots.
*/
public function testViewsTokenReplaceWithDots() {
$text = '{{ argument.first }} comes before {{ argument.second }}';
$tokens = ['{{ argument.first }}' => 'first', '{{ argument.second }}' => 'second'];
$result = \Drupal::service('renderer')->executeInRenderContext(new RenderContext(), function () use ($text, $tokens) {
return $this->testPluginBase->viewsTokenReplace($text, $tokens);
});
$this->assertIdentical($result, 'first comes before second');
// Test tokens with numeric indexes.
$text = '{{ argument.0.first }} comes before {{ argument.1.second }}';
$tokens = ['{{ argument.0.first }}' => 'first', '{{ argument.1.second }}' => 'second'];
$result = \Drupal::service('renderer')->executeInRenderContext(new RenderContext(), function () use ($text, $tokens) {
return $this->testPluginBase->viewsTokenReplace($text, $tokens);
});
$this->assertIdentical($result, 'first comes before second');
}
/**
* Tests viewsTokenReplace without any twig tokens.
*/
public function testViewsTokenReplaceWithTwigTokens() {
$text = 'Just some text';
$tokens = [];
$result = $this->testPluginBase->viewsTokenReplace($text, $tokens);
$this->assertIdentical($result, 'Just some text');
}
}
/**
* Helper class for using the PluginBase abstract class.
*/
class TestPluginBase extends PluginBase {
public function __construct() {
parent::__construct([], '', []);
}
public function viewsTokenReplace($text, $tokens) {
return parent::viewsTokenReplace($text, $tokens);
}
}

View file

@ -0,0 +1,83 @@
<?php
namespace Drupal\Tests\views\Kernel\Plugin;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
use Drupal\views\Views;
/**
* Tests the loading of entities and entity revisions.
*
* @group views
*
* @see \Drupal\views\Plugin\views\query\Sql
*/
class SqlEntityLoadingTest extends ViewsKernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['node', 'user'];
/**
* {@inheritdoc}
*/
public static $testViews = ['base_and_revision'];
/**
* {@inheritdoc}
*/
protected function setUp($import_test_views = TRUE) {
parent::setUp($import_test_views);
$this->installEntitySchema('node');
$this->installEntitySchema('user');
$this->installSchema('node', 'node_access');
}
public function testViewWithNonDefaultForwardRevision() {
$node_type = NodeType::create([
'type' => 'page',
]);
$node_type->save();
$node = Node::create([
'type' => 'page',
'title' => 'test title',
]);
$node->save();
// Creates the first revision, which is set as default.
$revision = clone $node;
$revision->setNewRevision(TRUE);
$revision->isDefaultRevision(TRUE);
$revision->save();
// Creates the second revision, which is not set as default.
$revision2 = clone $node;
$revision2->setNewRevision(TRUE);
$revision2->isDefaultRevision(FALSE);
$revision2->save();
$view = Views::getView('base_and_revision');
$view->execute();
$expected = [
[
'nid' => $node->id(),
// The default revision ID.
'vid_1' => $revision->getRevisionId(),
// THe latest revision ID.
'vid' => $revision2->getRevisionId(),
],
];
$this->assertIdenticalResultset($view, $expected, [
'node_field_data_node_field_revision_nid' => 'nid',
'vid_1' => 'vid_1',
'vid' => 'vid',
]);
}
}

View file

@ -11,7 +11,7 @@ use Drupal\views\Tests\ViewTestData;
/**
* Defines a base class for Views kernel testing.
*/
class ViewsKernelTestBase extends KernelTestBase {
abstract class ViewsKernelTestBase extends KernelTestBase {
use ViewResultAssertionTrait;

View file

@ -11,6 +11,7 @@ use Drupal\Core\Config\Entity\ConfigEntityType;
use Drupal\Core\Entity\ContentEntityType;
use Drupal\Core\Entity\EntityType;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\Sql\DefaultTableMapping;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
use Drupal\Core\Field\Plugin\Field\FieldType\IntegerItem;
@ -160,6 +161,12 @@ class EntityViewsDataTest extends UnitTestCase {
->setTranslatable(TRUE)
->setSetting('max_length', 255);
// A base field with cardinality > 1
$base_fields['string'] = BaseFieldDefinition::create('string')
->setLabel('Strong')
->setTranslatable(TRUE)
->setCardinality(2);
foreach ($base_fields as $name => $base_field) {
$base_field->setName($name);
}
@ -376,6 +383,10 @@ class EntityViewsDataTest extends UnitTestCase {
$homepage_field_storage_definition->expects($this->any())
->method('getSchema')
->willReturn(UriItem::schema($homepage_field_storage_definition));
$string_field_storage_definition = $this->getMock('Drupal\Core\Field\FieldStorageDefinitionInterface');
$string_field_storage_definition->expects($this->any())
->method('getSchema')
->willReturn(StringItem::schema($string_field_storage_definition));
// Setup the user_id entity reference field.
$this->entityManager->expects($this->any())
@ -411,6 +422,7 @@ class EntityViewsDataTest extends UnitTestCase {
'name' => $name_field_storage_definition,
'description' => $description_field_storage_definition,
'homepage' => $homepage_field_storage_definition,
'string' => $string_field_storage_definition,
'user_id' => $user_id_field_storage_definition,
'revision_id' => $revision_id_field_storage_definition,
]);
@ -435,10 +447,12 @@ class EntityViewsDataTest extends UnitTestCase {
['entity_test', $base_field_definitions],
]));
// Setup the table mapping.
$table_mapping = $this->getMock('Drupal\Core\Entity\Sql\TableMappingInterface');
$table_mapping = $this->getMockBuilder(DefaultTableMapping::class)
->disableOriginalConstructor()
->getMock();
$table_mapping->expects($this->any())
->method('getTableNames')
->willReturn(['entity_test']);
->willReturn(['entity_test', 'entity_test__string']);
$table_mapping->expects($this->any())
->method('getColumnNames')
->willReturnMap([
@ -450,12 +464,26 @@ class EntityViewsDataTest extends UnitTestCase {
['description', ['value' => 'description__value', 'format' => 'description__format']],
['homepage', ['value' => 'homepage']],
['user_id', ['target_id' => 'user_id']],
['string', ['value' => 'value']],
]);
$table_mapping->expects($this->any())
->method('getFieldNames')
->willReturnMap([
['entity_test', ['id', 'uuid', 'type', 'langcode', 'name', 'description', 'homepage', 'user_id']]
['entity_test', ['id', 'uuid', 'type', 'langcode', 'name', 'description', 'homepage', 'user_id']],
['entity_test__string', ['string']],
]);
$table_mapping->expects($this->any())
->method('requiresDedicatedTableStorage')
->willReturnCallback(function (BaseFieldDefinition $base_field) {
return $base_field->getName() === 'string';
});
$table_mapping->expects($this->any())
->method('getDedicatedDataTableName')
->willReturnCallback(function (BaseFieldDefinition $base_field) {
if ($base_field->getName() === 'string') {
return 'entity_test__string';
}
});
$this->entityStorage->expects($this->once())
->method('getTableMapping')
@ -492,6 +520,18 @@ class EntityViewsDataTest extends UnitTestCase {
$relationship = $data['entity_test']['user_id']['relationship'];
$this->assertEquals('users_field_data', $relationship['base']);
$this->assertEquals('uid', $relationship['base field']);
$this->assertStringField($data['entity_test__string']['string']);
$this->assertField($data['entity_test__string']['string'], 'string');
$this->assertEquals([
'left_field' => 'id',
'field' => 'entity_id',
'extra' => [[
'field' => 'deleted',
'value' => 0,
'numeric' => TRUE,
]],
], $data['entity_test__string']['table']['join']['entity_test']);
}
/**
@ -529,10 +569,12 @@ class EntityViewsDataTest extends UnitTestCase {
$this->viewsData->setEntityType($entity_type);
// Setup the table mapping.
$table_mapping = $this->getMock('Drupal\Core\Entity\Sql\TableMappingInterface');
$table_mapping = $this->getMockBuilder(DefaultTableMapping::class)
->disableOriginalConstructor()
->getMock();
$table_mapping->expects($this->any())
->method('getTableNames')
->willReturn(['entity_test_mul', 'entity_test_mul_property_data']);
->willReturn(['entity_test_mul', 'entity_test_mul_property_data', 'entity_test_mul__string']);
$table_mapping->expects($this->any())
->method('getColumnNames')
->willReturnMap([
@ -544,12 +586,14 @@ class EntityViewsDataTest extends UnitTestCase {
['description', ['value' => 'description__value', 'format' => 'description__format']],
['homepage', ['value' => 'homepage']],
['user_id', ['target_id' => 'user_id']],
['string', ['value' => 'value']],
]);
$table_mapping->expects($this->any())
->method('getFieldNames')
->willReturnMap([
['entity_test_mul', ['uuid']],
['entity_test_mul_property_data', ['id', 'type', 'langcode', 'name', 'description', 'homepage', 'user_id']],
['entity_test_mul__string', ['string']],
]);
$table_mapping->expects($this->any())
@ -560,6 +604,18 @@ class EntityViewsDataTest extends UnitTestCase {
}
return 'entity_test_mul_property_data';
});
$table_mapping->expects($this->any())
->method('requiresDedicatedTableStorage')
->willReturnCallback(function (BaseFieldDefinition $base_field) {
return $base_field->getName() === 'string';
});
$table_mapping->expects($this->any())
->method('getDedicatedDataTableName')
->willReturnCallback(function (BaseFieldDefinition $base_field) {
if ($base_field->getName() === 'string') {
return 'entity_test_mul__string';
}
});
$this->entityStorage->expects($this->once())
->method('getTableMapping')
@ -619,6 +675,18 @@ class EntityViewsDataTest extends UnitTestCase {
$relationship = $data['entity_test_mul_property_data']['user_id']['relationship'];
$this->assertEquals('users_field_data', $relationship['base']);
$this->assertEquals('uid', $relationship['base field']);
$this->assertStringField($data['entity_test_mul__string']['string']);
$this->assertField($data['entity_test_mul__string']['string'], 'string');
$this->assertEquals([
'left_field' => 'id',
'field' => 'entity_id',
'extra' => [[
'field' => 'deleted',
'value' => 0,
'numeric' => TRUE,
]],
], $data['entity_test_mul__string']['table']['join']['entity_test_mul']);
}
/**
@ -650,10 +718,12 @@ class EntityViewsDataTest extends UnitTestCase {
$this->viewsData->setEntityType($entity_type);
// Setup the table mapping.
$table_mapping = $this->getMock('Drupal\Core\Entity\Sql\TableMappingInterface');
$table_mapping = $this->getMockBuilder(DefaultTableMapping::class)
->disableOriginalConstructor()
->getMock();
$table_mapping->expects($this->any())
->method('getTableNames')
->willReturn(['entity_test_mulrev', 'entity_test_mulrev_revision', 'entity_test_mulrev_property_data', 'entity_test_mulrev_property_revision']);
->willReturn(['entity_test_mulrev', 'entity_test_mulrev_revision', 'entity_test_mulrev_property_data', 'entity_test_mulrev_property_revision', 'entity_test_mulrev__string', 'entity_test_mulrev_revision__string']);
$table_mapping->expects($this->any())
->method('getColumnNames')
->willReturnMap([
@ -666,6 +736,7 @@ class EntityViewsDataTest extends UnitTestCase {
['homepage', ['value' => 'homepage']],
['user_id', ['target_id' => 'user_id']],
['revision_id', ['value' => 'id']],
['string', ['value' => 'value']],
]);
$table_mapping->expects($this->any())
->method('getFieldNames')
@ -674,7 +745,29 @@ class EntityViewsDataTest extends UnitTestCase {
['entity_test_mulrev_revision', ['id', 'revision_id', 'langcode']],
['entity_test_mulrev_property_data', ['id', 'revision_id', 'langcode', 'name', 'description', 'homepage', 'user_id']],
['entity_test_mulrev_property_revision', ['id', 'revision_id', 'langcode', 'name', 'description', 'homepage', 'user_id']],
['entity_test_mulrev__string', ['string']],
['entity_test_mulrev_revision__string', ['string']],
]);
$table_mapping->expects($this->any())
->method('requiresDedicatedTableStorage')
->willReturnCallback(function (BaseFieldDefinition $base_field) {
return $base_field->getName() === 'string';
});
$table_mapping->expects($this->any())
->method('getDedicatedDataTableName')
->willReturnCallback(function (BaseFieldDefinition $base_field) {
if ($base_field->getName() === 'string') {
return 'entity_test_mulrev__string';
}
});
$table_mapping->expects($this->any())
->method('getDedicatedRevisionTableName')
->willReturnCallback(function (BaseFieldDefinition $base_field) {
if ($base_field->getName() === 'string') {
return 'entity_test_mulrev_revision__string';
}
});
$table_mapping->expects($this->any())
->method('getFieldTableName')
@ -767,6 +860,30 @@ class EntityViewsDataTest extends UnitTestCase {
$relationship = $data['entity_test_mulrev_property_revision']['user_id']['relationship'];
$this->assertEquals('users_field_data', $relationship['base']);
$this->assertEquals('uid', $relationship['base field']);
$this->assertStringField($data['entity_test_mulrev__string']['string']);
$this->assertField($data['entity_test_mulrev__string']['string'], 'string');
$this->assertEquals([
'left_field' => 'id',
'field' => 'entity_id',
'extra' => [[
'field' => 'deleted',
'value' => 0,
'numeric' => TRUE,
]],
], $data['entity_test_mulrev__string']['table']['join']['entity_test_mulrev_property_data']);
$this->assertStringField($data['entity_test_mulrev_revision__string']['string']);
$this->assertField($data['entity_test_mulrev_revision__string']['string'], 'string');
$this->assertEquals([
'left_field' => 'revision_id',
'field' => 'entity_id',
'extra' => [[
'field' => 'deleted',
'value' => 0,
'numeric' => TRUE,
]],
], $data['entity_test_mulrev_revision__string']['table']['join']['entity_test_mulrev_property_revision']);
}
/**

View file

@ -2,9 +2,18 @@
namespace Drupal\Tests\views\Unit\Plugin\query;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityType;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Tests\UnitTestCase;
use Drupal\views\Plugin\views\query\Sql;
use Drupal\views\Plugin\views\relationship\RelationshipPluginBase;
use Drupal\views\ResultRow;
use Drupal\views\ViewEntityInterface;
use Drupal\views\ViewExecutable;
use Drupal\views\ViewsData;
use Symfony\Component\DependencyInjection\ContainerBuilder;
/**
* @coversDefaultClass \Drupal\views\Plugin\views\query\Sql
@ -19,8 +28,9 @@ class SqlTest extends UnitTestCase {
*/
public function testGetCacheTags() {
$view = $this->prophesize('Drupal\views\ViewExecutable')->reveal();
$entity_type_manager = $this->prophesize(EntityTypeManagerInterface::class);
$query = new Sql([], 'sql', []);
$query = new Sql([], 'sql', [], $entity_type_manager->reveal());
$query->view = $view;
$result = [];
@ -64,8 +74,9 @@ class SqlTest extends UnitTestCase {
*/
public function testGetCacheMaxAge() {
$view = $this->prophesize('Drupal\views\ViewExecutable')->reveal();
$entity_type_manager = $this->prophesize(EntityTypeManagerInterface::class);
$query = new Sql([], 'sql', []);
$query = new Sql([], 'sql', [], $entity_type_manager->reveal());
$query->view = $view;
$view->result = [];
@ -98,4 +109,427 @@ class SqlTest extends UnitTestCase {
$this->assertEquals(10, $query->getCacheMaxAge());
}
/**
* Sets up the views data in the container.
*
* @param \Drupal\views\ViewsData $views_data
* The views data.
*/
protected function setupViewsData(ViewsData $views_data) {
$container = \Drupal::hasContainer() ? \Drupal::getContainer() : new ContainerBuilder();
$container->set('views.views_data', $views_data);
\Drupal::setContainer($container);
}
/**
* Sets up the entity type manager in the container.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
*/
protected function setupEntityTypeManager(EntityTypeManagerInterface $entity_type_manager) {
$container = \Drupal::hasContainer() ? \Drupal::getContainer() : new ContainerBuilder();
$container->set('entity_type.manager', $entity_type_manager);
$container->set('entity.manager', $entity_type_manager);
\Drupal::setContainer($container);
}
/**
* Sets up some test entity types and corresponding views data.
*
* @param \Drupal\Core\Entity\EntityInterface[][] $entities_by_type
* Test entities keyed by entity type and entity ID.
* @param \Drupal\Core\Entity\EntityInterface[][] $entities_by_type
* Test entities keyed by entity type and revision ID.
*
* @return \Prophecy\Prophecy\ObjectProphecy
*/
protected function setupEntityTypes($entities_by_type = [], $entity_revisions_by_type = []) {
$entity_type_manager = $this->prophesize(EntityTypeManagerInterface::class);
$entity_type0 = new EntityType([
'label' => 'First',
'id' => 'first',
'base_table' => 'entity_first',
'revision_table' => 'entity_first__revision',
'entity_keys' => [
'id' => 'id',
'revision' => 'vid',
],
]);
$entity_type1 = new EntityType([
'label' => 'second',
'id' => 'second',
'base_table' => 'entity_second',
'revision_table' => 'entity_second__revision',
'entity_keys' => [
'id' => 'id',
'revision' => 'vid',
],
]);
$entity_type_manager->getDefinitions()->willReturn([
'first' => $entity_type0,
'second' => $entity_type1,
'base_table' => 'entity_second',
]);
$entity_type_manager->getDefinition('first')->willReturn($entity_type0);
$entity_type_manager->getDefinition('second')->willReturn($entity_type1);
// Setup the views data corresponding to the entity types.
$views_data = $this->prophesize(ViewsData::class);
$views_data->get('entity_first')->willReturn([
'table' => [
'entity type' => 'first',
'entity revision' => FALSE,
],
]);
$views_data->get('entity_first__revision')->willReturn([
'table' => [
'entity type' => 'first',
'entity revision' => TRUE,
],
]);
$views_data->get('entity_second')->willReturn([
'table' => [
'entity type' => 'second',
'entity revision' => FALSE,
],
]);
$views_data->get('entity_second__revision')->willReturn([
'table' => [
'entity type' => 'second',
'entity revision' => TRUE,
],
]);
$this->setupViewsData($views_data->reveal());
// Setup the loading of entities and entity revisions.
$entity_storages = [
'first' => $this->prophesize(EntityStorageInterface::class),
'second' => $this->prophesize(EntityStorageInterface::class),
];
foreach ($entities_by_type as $entity_type_id => $entities) {
foreach ($entities as $entity_id => $entity) {
$entity_storages[$entity_type_id]->load($entity_id)->willReturn($entity);
}
$entity_storages[$entity_type_id]->loadMultiple(array_keys($entities))->willReturn($entities);
}
foreach ($entity_revisions_by_type as $entity_type_id => $entity_revisions) {
foreach ($entity_revisions as $revision_id => $revision) {
$entity_storages[$entity_type_id]->loadRevision($revision_id)->willReturn($revision);
}
}
$entity_type_manager->getStorage('first')->willReturn($entity_storages['first']);
$entity_type_manager->getStorage('second')->willReturn($entity_storages['second']);
$this->setupEntityTypeManager($entity_type_manager->reveal());
return $entity_type_manager;
}
/**
* @covers ::loadEntities
* @covers ::_assignEntitiesToResult
*/
public function testLoadEntitiesWithEmptyResult() {
$view = $this->prophesize('Drupal\views\ViewExecutable')->reveal();
$view_entity = $this->prophesize(ViewEntityInterface::class);
$view_entity->get('base_table')->willReturn('entity_first');
$view_entity->get('base_field')->willReturn('id');
$view->storage = $view_entity->reveal();
$entity_type_manager = $this->setupEntityTypes();
$query = new Sql([], 'sql', [], $entity_type_manager->reveal());
$query->view = $view;
$result = [];
$query->addField('entity_first', 'id', 'id');
$query->loadEntities($result);
$this->assertEmpty($result);
}
/**
* @covers ::loadEntities
* @covers ::_assignEntitiesToResult
*/
public function testLoadEntitiesWithNoRelationshipAndNoRevision() {
$view = $this->prophesize('Drupal\views\ViewExecutable')->reveal();
$view_entity = $this->prophesize(ViewEntityInterface::class);
$view_entity->get('base_table')->willReturn('entity_first');
$view_entity->get('base_field')->willReturn('id');
$view->storage = $view_entity->reveal();
$entities = [
'first' => [
1 => $this->prophesize(EntityInterface::class)->reveal(),
2 => $this->prophesize(EntityInterface::class)->reveal(),
],
];
$entity_type_manager = $this->setupEntityTypes($entities);
$query = new Sql([], 'sql', [], $entity_type_manager->reveal());
$query->view = $view;
$result = [];
$result[] = new ResultRow([
'id' => 1,
]);
// Note: Let the same entity be returned multiple times, for example to
// support the translation usecase.
$result[] = new ResultRow([
'id' => 2,
]);
$result[] = new ResultRow([
'id' => 2,
]);
$query->addField('entity_first', 'id', 'id');
$query->loadEntities($result);
$this->assertSame($entities['first'][1], $result[0]->_entity);
$this->assertSame($entities['first'][2], $result[1]->_entity);
$this->assertSame($entities['first'][2], $result[2]->_entity);
}
/**
* Create a view with a relationship.
*/
protected function setupViewWithRelationships(ViewExecutable $view, $base = 'entity_second') {
// We don't use prophecy, because prophecy enforces methods.
$relationship = $this->getMockBuilder(RelationshipPluginBase::class)->disableOriginalConstructor()->getMock();
$relationship->definition['base'] = $base;
$relationship->tableAlias = $base;
$relationship->alias = $base;
$view->relationship[$base] = $relationship;
}
/**
* @covers ::loadEntities
* @covers ::_assignEntitiesToResult
*/
public function testLoadEntitiesWithRelationship() {
// We don't use prophecy, because prophecy enforces methods.
$view = $this->getMockBuilder(ViewExecutable::class)->disableOriginalConstructor()->getMock();
$this->setupViewWithRelationships($view);
$view_entity = $this->prophesize(ViewEntityInterface::class);
$view_entity->get('base_table')->willReturn('entity_first');
$view_entity->get('base_field')->willReturn('id');
$view->storage = $view_entity->reveal();
$entities = [
'first' => [
1 => $this->prophesize(EntityInterface::class)->reveal(),
2 => $this->prophesize(EntityInterface::class)->reveal(),
],
'second' => [
11 => $this->prophesize(EntityInterface::class)->reveal(),
12 => $this->prophesize(EntityInterface::class)->reveal(),
],
];
$entity_type_manager = $this->setupEntityTypes($entities);
$query = new Sql([], 'sql', [], $entity_type_manager->reveal());
$query->view = $view;
$result = [];
$result[] = new ResultRow([
'id' => 1,
'entity_second__id' => 11,
]);
// Provide an explicit NULL value, to test the case of a non required
// relationship.
$result[] = new ResultRow([
'id' => 2,
'entity_second__id' => NULL,
]);
$result[] = new ResultRow([
'id' => 2,
'entity_second__id' => 12,
]);
$query->addField('entity_first', 'id', 'id');
$query->addField('entity_second', 'id', 'entity_second__id');
$query->loadEntities($result);
$this->assertSame($entities['first'][1], $result[0]->_entity);
$this->assertSame($entities['first'][2], $result[1]->_entity);
$this->assertSame($entities['first'][2], $result[2]->_entity);
$this->assertSame($entities['second'][11], $result[0]->_relationship_entities['entity_second']);
$this->assertEquals([], $result[1]->_relationship_entities);
$this->assertSame($entities['second'][12], $result[2]->_relationship_entities['entity_second']);
}
/**
* @covers ::loadEntities
* @covers ::_assignEntitiesToResult
*/
public function testLoadEntitiesWithRevision() {
// We don't use prophecy, because prophecy enforces methods.
$view = $this->getMockBuilder(ViewExecutable::class)
->disableOriginalConstructor()
->getMock();
$view_entity = $this->prophesize(ViewEntityInterface::class);
$view_entity->get('base_table')->willReturn('entity_first__revision');
$view_entity->get('base_field')->willReturn('vid');
$view->storage = $view_entity->reveal();
$entity_revisions = [
'first' => [
1 => $this->prophesize(EntityInterface::class)->reveal(),
3 => $this->prophesize(EntityInterface::class)->reveal(),
],
];
$entity_type_manager = $this->setupEntityTypes([], $entity_revisions);
$query = new Sql([], 'sql', [], $entity_type_manager->reveal());
$query->view = $view;
$result = [];
$result[] = new ResultRow([
'vid' => 1,
]);
$result[] = new ResultRow([
'vid' => 1,
]);
$result[] = new ResultRow([
'vid' => 3,
]);
$query->addField('entity_first__revision', 'vid', 'vid');
$query->loadEntities($result);
$this->assertSame($entity_revisions['first'][1], $result[0]->_entity);
$this->assertSame($entity_revisions['first'][1], $result[1]->_entity);
$this->assertSame($entity_revisions['first'][3], $result[2]->_entity);
}
/**
* @covers ::loadEntities
* @covers ::_assignEntitiesToResult
*/
public function testLoadEntitiesWithRevisionOfSameEntityType() {
// We don't use prophecy, because prophecy enforces methods.
$view = $this->getMockBuilder(ViewExecutable::class)
->disableOriginalConstructor()
->getMock();
$this->setupViewWithRelationships($view, 'entity_first__revision');
$view_entity = $this->prophesize(ViewEntityInterface::class);
$view_entity->get('base_table')->willReturn('entity_first');
$view_entity->get('base_field')->willReturn('id');
$view->storage = $view_entity->reveal();
$entity = [
'first' => [
1 => $this->prophesize(EntityInterface::class)->reveal(),
2 => $this->prophesize(EntityInterface::class)->reveal(),
],
];
$entity_revisions = [
'first' => [
1 => $this->prophesize(EntityInterface::class)->reveal(),
2 => $this->prophesize(EntityInterface::class)->reveal(),
3 => $this->prophesize(EntityInterface::class)->reveal(),
],
];
$entity_type_manager = $this->setupEntityTypes($entity, $entity_revisions);
$query = new Sql([], 'sql', [], $entity_type_manager->reveal());
$query->view = $view;
$result = [];
$result[] = new ResultRow([
'id' => 1,
'entity_first__revision__vid' => 1,
]);
$result[] = new ResultRow([
'id' => 2,
'entity_first__revision__vid' => 2,
]);
$result[] = new ResultRow([
'id' => 2,
'entity_first__revision__vid' => 3,
]);
$query->addField('entity_first', 'id', 'id');
$query->addField('entity_first__revision', 'vid', 'entity_first__revision__vid');
$query->loadEntities($result);
$this->assertSame($entity['first'][1], $result[0]->_entity);
$this->assertSame($entity['first'][2], $result[1]->_entity);
$this->assertSame($entity['first'][2], $result[2]->_entity);
$this->assertSame($entity_revisions['first'][1], $result[0]->_relationship_entities['entity_first__revision']);
$this->assertSame($entity_revisions['first'][2], $result[1]->_relationship_entities['entity_first__revision']);
$this->assertSame($entity_revisions['first'][3], $result[2]->_relationship_entities['entity_first__revision']);
}
/**
* @covers ::loadEntities
* @covers ::_assignEntitiesToResult
*/
public function testLoadEntitiesWithRelationshipAndRevision() {
// We don't use prophecy, because prophecy enforces methods.
$view = $this->getMockBuilder(ViewExecutable::class)->disableOriginalConstructor()->getMock();
$this->setupViewWithRelationships($view);
$view_entity = $this->prophesize(ViewEntityInterface::class);
$view_entity->get('base_table')->willReturn('entity_first__revision');
$view_entity->get('base_field')->willReturn('vid');
$view->storage = $view_entity->reveal();
$entities = [
'second' => [
11 => $this->prophesize(EntityInterface::class)->reveal(),
12 => $this->prophesize(EntityInterface::class)->reveal(),
],
];
$entity_revisions = [
'first' => [
1 => $this->prophesize(EntityInterface::class)->reveal(),
3 => $this->prophesize(EntityInterface::class)->reveal(),
],
];
$entity_type_manager = $this->setupEntityTypes($entities, $entity_revisions);
$query = new Sql([], 'sql', [], $entity_type_manager->reveal());
$query->view = $view;
$result = [];
$result[] = new ResultRow([
'vid' => 1,
'entity_second__id' => 11,
]);
// Provide an explicit NULL value, to test the case of a non required
// relationship.
$result[] = new ResultRow([
'vid' => 1,
'entity_second__id' => NULL,
]);
$result[] = new ResultRow([
'vid' => 3,
'entity_second__id' => 12,
]);
$query->addField('entity_first__revision', 'vid', 'vid');
$query->addField('entity_second', 'id', 'entity_second__id');
$query->loadEntities($result);
$this->assertSame($entity_revisions['first'][1], $result[0]->_entity);
$this->assertSame($entity_revisions['first'][1], $result[1]->_entity);
$this->assertSame($entity_revisions['first'][3], $result[2]->_entity);
$this->assertSame($entities['second'][11], $result[0]->_relationship_entities['entity_second']);
$this->assertEquals([], $result[1]->_relationship_entities);
$this->assertSame($entities['second'][12], $result[2]->_relationship_entities['entity_second']);
}
}