Update to Drupal 8.0.3. For more information, see https://www.drupal.org/drupal-8.0.3-release-notes
This commit is contained in:
parent
10f9f7fbde
commit
9db4fae9a7
202 changed files with 3806 additions and 760 deletions
|
@ -12,6 +12,8 @@ use Drupal\Core\Ajax\ReplaceCommand;
|
|||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\EventSubscriber\AjaxResponseSubscriber;
|
||||
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
|
||||
use Drupal\Core\Form\FormBuilderInterface;
|
||||
use Drupal\Core\Path\CurrentPathStack;
|
||||
use Drupal\Core\Render\BubbleableMetadata;
|
||||
use Drupal\Core\Render\RenderContext;
|
||||
|
@ -161,7 +163,15 @@ class ViewAjaxController implements ContainerInjectionInterface {
|
|||
// Overwrite the destination.
|
||||
// @see the redirect.destination service.
|
||||
$origin_destination = $path;
|
||||
$query = UrlHelper::buildQuery($request->query->all());
|
||||
|
||||
// Remove some special parameters you never want to have part of the
|
||||
// destination query.
|
||||
$used_query_parameters = $request->query->all();
|
||||
// @todo Remove this parsing once these are removed from the request in
|
||||
// https://www.drupal.org/node/2504709.
|
||||
unset($used_query_parameters[FormBuilderInterface::AJAX_FORM_REQUEST], $used_query_parameters[MainContentViewSubscriber::WRAPPER_FORMAT], $used_query_parameters['ajax_page_state']);
|
||||
|
||||
$query = UrlHelper::buildQuery($used_query_parameters);
|
||||
if ($query != '') {
|
||||
$origin_destination .= '?' . $query;
|
||||
}
|
||||
|
|
|
@ -236,7 +236,7 @@ class ManyToOneHelper {
|
|||
$join = $this->getJoin();
|
||||
$join->type = 'LEFT';
|
||||
$join->extra = array();
|
||||
$join->extra_type = 'OR';
|
||||
$join->extraOperator = 'OR';
|
||||
foreach ($this->handler->value as $value) {
|
||||
$join->extra[] = array(
|
||||
'field' => $this->handler->realField,
|
||||
|
@ -311,10 +311,21 @@ class ManyToOneHelper {
|
|||
$placeholder = $this->placeholder();
|
||||
if (count($this->handler->value) > 1) {
|
||||
$placeholder .= '[]';
|
||||
$this->handler->query->addWhereExpression(0, "$field $operator($placeholder)", array($placeholder => $value));
|
||||
|
||||
if ($operator == 'IS NULL') {
|
||||
$this->handler->query->addWhereExpression(0, "$field $operator");
|
||||
}
|
||||
else {
|
||||
$this->handler->query->addWhereExpression(0, "$field $operator($placeholder)", array($placeholder => $value));
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->handler->query->addWhereExpression(0, "$field $operator $placeholder", array($placeholder => $value));
|
||||
if ($operator == 'IS NULL') {
|
||||
$this->handler->query->addWhereExpression(0, "$field $operator");
|
||||
}
|
||||
else {
|
||||
$this->handler->query->addWhereExpression(0, "$field $operator $placeholder", array($placeholder => $value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2335,13 +2335,17 @@ abstract class DisplayPluginBase extends PluginBase implements DisplayPluginInte
|
|||
'#cache_properties' => ['#view_id', '#view_display_show_admin_links', '#view_display_plugin_id'],
|
||||
];
|
||||
|
||||
// When something passes $cache = FALSE, they're asking us not to create our
|
||||
// own render cache for it. However, we still need to include certain pieces
|
||||
// of cacheability metadata (e.g.: cache contexts), so they can bubble up.
|
||||
// Thus, we add the cacheability metadata first, then modify / remove the
|
||||
// cache keys depending on the $cache argument.
|
||||
$this->applyDisplayCachablityMetadata($this->view->element);
|
||||
if ($cache) {
|
||||
$this->view->element['#cache'] += ['keys' => []];
|
||||
// Places like \Drupal\views\ViewExecutable::setCurrentPage() set up an
|
||||
// additional cache context.
|
||||
$this->view->element['#cache']['keys'] = array_merge(['views', 'display', $this->view->element['#name'], $this->view->element['#display_id']], $this->view->element['#cache']['keys']);
|
||||
|
||||
$this->applyDisplayCachablityMetadata($this->view->element);
|
||||
}
|
||||
else {
|
||||
// Remove the cache keys, to ensure render caching is not triggered. We
|
||||
|
|
|
@ -138,7 +138,8 @@ class EntityReference extends DisplayPluginBase {
|
|||
foreach ($style_options['options']['search_fields'] as $field_id) {
|
||||
if (!empty($field_id)) {
|
||||
// Get the table and field names for the checked field.
|
||||
$field_alias = $this->view->query->addField($this->view->field[$field_id]->table, $field_id);
|
||||
$field_handler = $this->view->field[$field_id];
|
||||
$field_alias = $this->view->query->addField($field_handler->table, $field_handler->realField);
|
||||
$field = $this->view->query->fields[$field_alias];
|
||||
// Add an OR condition for the field.
|
||||
$conditions->condition($field['table'] . '.' . $field['field'], $value, 'LIKE');
|
||||
|
|
|
@ -22,6 +22,7 @@ use Drupal\Core\Render\BubbleableMetadata;
|
|||
use Drupal\Core\Render\Element;
|
||||
use Drupal\Core\Render\RendererInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\TypedData\TypedDataInterface;
|
||||
use Drupal\views\FieldAPIHandlerTrait;
|
||||
use Drupal\views\Entity\Render\EntityFieldRenderer;
|
||||
use Drupal\views\Plugin\views\display\DisplayPluginBase;
|
||||
|
@ -820,9 +821,10 @@ class Field extends FieldPluginBase implements CacheableDependencyInterface, Mul
|
|||
'settings' => $this->options['settings'],
|
||||
'label' => 'hidden',
|
||||
];
|
||||
$build_list = $this->createEntityForGroupBy($this->getEntity($values), $values)
|
||||
->{$this->definition['field_name']}
|
||||
->view($display);
|
||||
// Some bundles might not have a specific field, in which case the faked
|
||||
// entity doesn't have it either.
|
||||
$entity = $this->createEntityForGroupBy($this->getEntity($values), $values);
|
||||
$build_list = isset($entity->{$this->definition['field_name']}) ? $entity->{$this->definition['field_name']}->view($display) : NULL;
|
||||
}
|
||||
|
||||
if (!$build_list) {
|
||||
|
@ -932,8 +934,10 @@ class Field extends FieldPluginBase implements CacheableDependencyInterface, Mul
|
|||
|
||||
if (is_object($raw)) {
|
||||
$property = $raw->get($id);
|
||||
if (!empty($property)) {
|
||||
$tokens['{{ ' . $this->options['id'] . '__' . $id . ' }}'] = Xss::filterAdmin($property->getValue());
|
||||
// Check if TypedDataInterface is implemented so we know how to render
|
||||
// the item as a string.
|
||||
if (!empty($property) && $property instanceof TypedDataInterface) {
|
||||
$tokens['{{ ' . $this->options['id'] . '__' . $id . ' }}'] = Xss::filterAdmin($property->getString());
|
||||
}
|
||||
else {
|
||||
// Make sure that empty values are replaced as well.
|
||||
|
@ -1002,8 +1006,17 @@ class Field extends FieldPluginBase implements CacheableDependencyInterface, Mul
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getValue(ResultRow $values, $field = NULL) {
|
||||
$entity = $this->getEntity($values);
|
||||
// Some bundles might not have a specific field, in which case the entity
|
||||
// (potentially a fake one) doesn't have it either.
|
||||
/** @var \Drupal\Core\Field\FieldItemListInterface $field_item_list */
|
||||
$field_item_list = $this->getEntity($values)->{$this->definition['field_name']};
|
||||
$field_item_list = isset($entity->{$this->definition['field_name']}) ? $entity->{$this->definition['field_name']} : NULL;
|
||||
|
||||
if (!isset($field_item_list)) {
|
||||
// There isn't anything we can do without a valid field.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
$field_item_definition = $field_item_list->getFieldDefinition();
|
||||
|
||||
if ($field_item_definition->getFieldStorageDefinition()->getCardinality() == 1) {
|
||||
|
|
|
@ -482,9 +482,17 @@ abstract class StylePluginBase extends PluginBase {
|
|||
* grouping.
|
||||
*
|
||||
* @param $sets
|
||||
* Array containing the grouping sets to render.
|
||||
* An array keyed by group content containing the grouping sets to render.
|
||||
* Each set contains the following associative array:
|
||||
* - group: The group content.
|
||||
* - level: The hierarchical level of the grouping.
|
||||
* - rows: The result rows to be rendered in this group..
|
||||
* @param $level
|
||||
* Integer indicating the hierarchical level of the grouping.
|
||||
* (deprecated) This is no longer used and will be removed in Drupal 9. The
|
||||
* 'level' key in $sets is used to indicate the hierarchical level of the
|
||||
* grouping.
|
||||
*
|
||||
* @todo Remove the $level parameter in https://www.drupal.org/node/2633890.
|
||||
*
|
||||
* @return string
|
||||
* Rendered output of given grouping sets.
|
||||
|
@ -493,16 +501,16 @@ abstract class StylePluginBase extends PluginBase {
|
|||
$output = array();
|
||||
$theme_functions = $this->view->buildThemeFunctions($this->groupingTheme);
|
||||
foreach ($sets as $set) {
|
||||
$level = isset($set['level']) ? $set['level'] : 0;
|
||||
|
||||
$row = reset($set['rows']);
|
||||
// Render as a grouping set.
|
||||
if (is_array($row) && isset($row['group'])) {
|
||||
$output[] = array(
|
||||
$single_output = array(
|
||||
'#theme' => $theme_functions,
|
||||
'#view' => $this->view,
|
||||
'#grouping' => $this->options['grouping'][$level],
|
||||
'#grouping_level' => $level,
|
||||
'#rows' => $set['rows'],
|
||||
'#title' => $set['group'],
|
||||
);
|
||||
}
|
||||
// Render as a record set.
|
||||
|
@ -515,10 +523,11 @@ abstract class StylePluginBase extends PluginBase {
|
|||
}
|
||||
|
||||
$single_output = $this->renderRowGroup($set['rows']);
|
||||
$single_output['#grouping_level'] = $level;
|
||||
$single_output['#title'] = $set['group'];
|
||||
$output[] = $single_output;
|
||||
}
|
||||
|
||||
$single_output['#grouping_level'] = $level;
|
||||
$single_output['#title'] = $set['group'];
|
||||
$output[] = $single_output;
|
||||
}
|
||||
unset($this->view->row_index);
|
||||
return $output;
|
||||
|
@ -546,9 +555,11 @@ abstract class StylePluginBase extends PluginBase {
|
|||
* array(
|
||||
* 'grouping_field_1:grouping_1' => array(
|
||||
* 'group' => 'grouping_field_1:content_1',
|
||||
* 'level' => 0,
|
||||
* 'rows' => array(
|
||||
* 'grouping_field_2:grouping_a' => array(
|
||||
* 'group' => 'grouping_field_2:content_a',
|
||||
* 'level' => 1,
|
||||
* 'rows' => array(
|
||||
* $row_index_1 => $row_1,
|
||||
* $row_index_2 => $row_2,
|
||||
|
@ -580,7 +591,7 @@ abstract class StylePluginBase extends PluginBase {
|
|||
// hierarchically positioned set where the current row belongs to.
|
||||
// While iterating, parent groups, that do not exist yet, are added.
|
||||
$set = &$sets;
|
||||
foreach ($groupings as $info) {
|
||||
foreach ($groupings as $level => $info) {
|
||||
$field = $info['field'];
|
||||
$rendered = isset($info['rendered']) ? $info['rendered'] : $group_rendered;
|
||||
$rendered_strip = isset($info['rendered_strip']) ? $info['rendered_strip'] : FALSE;
|
||||
|
@ -613,6 +624,7 @@ abstract class StylePluginBase extends PluginBase {
|
|||
// Create the group if it does not exist yet.
|
||||
if (empty($set[$grouping])) {
|
||||
$set[$grouping]['group'] = $group_content;
|
||||
$set[$grouping]['level'] = $level;
|
||||
$set[$grouping]['rows'] = array();
|
||||
}
|
||||
|
||||
|
|
|
@ -84,4 +84,15 @@ class CacheWebTest extends PluginTestBase {
|
|||
$this->assertCacheTags($cache_tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a display without caching still contains the cache metadata.
|
||||
*/
|
||||
public function testDisplayWithoutCacheStillBubblesMetadata() {
|
||||
$view = Views::getView('test_display');
|
||||
|
||||
$uncached_block = $view->buildRenderable('block_1', [], FALSE);
|
||||
$cached_block = $view->buildRenderable('block_1', [], TRUE);
|
||||
$this->assertEqual($uncached_block['#cache']['contexts'], $cached_block['#cache']['contexts'], 'Cache contexts are the same when you render the view cached and uncached.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\views\Tests\Plugin\DisplayEntityReferenceTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\views\Tests\Plugin;
|
||||
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the entity reference display plugin.
|
||||
*
|
||||
* @group views
|
||||
*
|
||||
* @see \Drupal\views\Plugin\views\display\EntityReference
|
||||
*/
|
||||
class DisplayEntityReferenceTest extends PluginTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = array('test_display_entity_reference');
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('entity_test', 'field', 'views_ui');
|
||||
|
||||
/**
|
||||
* The used field name in the test.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $fieldName;
|
||||
|
||||
/**
|
||||
* The field storage.
|
||||
*
|
||||
* @var \Drupal\field\Entity\FieldStorageConfig
|
||||
*/
|
||||
protected $fieldStorage;
|
||||
|
||||
/**
|
||||
* The field config.
|
||||
*
|
||||
* @var \Drupal\field\Entity\FieldConfig
|
||||
*/
|
||||
protected $field;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalLogin($this->drupalCreateUser(array('administer views')));
|
||||
|
||||
// Create the text field.
|
||||
$this->fieldName = 'field_test_entity_ref_display';
|
||||
$this->fieldStorage = FieldStorageConfig::create([
|
||||
'field_name' => $this->fieldName,
|
||||
'entity_type' => 'entity_test',
|
||||
'type' => 'text',
|
||||
]);
|
||||
$this->fieldStorage->save();
|
||||
|
||||
// Create an instance of the text field on the content type.
|
||||
$this->field = FieldConfig::create([
|
||||
'field_storage' => $this->fieldStorage,
|
||||
'bundle' => 'entity_test',
|
||||
]);
|
||||
$this->field->save();
|
||||
|
||||
// Create some entities to search. Add a common string to the name and
|
||||
// the text field in two entities so we can test that we can search in both.
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
EntityTest::create([
|
||||
'bundle' => 'entity_test',
|
||||
'name' => 'name' . $i,
|
||||
$this->fieldName => 'text',
|
||||
])->save();
|
||||
EntityTest::create([
|
||||
'bundle' => 'entity_test',
|
||||
'name' => 'name',
|
||||
$this->fieldName => 'text' . $i,
|
||||
])->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the entity reference display plugin.
|
||||
*/
|
||||
public function testEntityReferenceDisplay() {
|
||||
// Add the new field to the fields.
|
||||
$this->drupalPostForm('admin/structure/views/nojs/add-handler/test_display_entity_reference/default/field', ['name[entity_test__' . $this->fieldName . '.' . $this->fieldName . ']' => TRUE], t('Add and configure fields'));
|
||||
$this->drupalPostForm(NULL, [], t('Apply'));
|
||||
|
||||
// Test that the right fields are shown on the display settings form.
|
||||
$this->drupalGet('admin/structure/views/nojs/display/test_display_entity_reference/entity_reference_1/style_options');
|
||||
$this->assertText('Test entity: Name');
|
||||
$this->assertText('Test entity: ' . $this->field->label());
|
||||
|
||||
// Add the new field to the search fields.
|
||||
$this->drupalPostForm(NULL, ['style_options[search_fields][' . $this->fieldName . ']' => $this->fieldName], t('Apply'));
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
|
||||
$view = Views::getView('test_display_entity_reference');
|
||||
$view->setDisplay('entity_reference_1');
|
||||
|
||||
// Add the required settings to test a search operation.
|
||||
$options = [
|
||||
'match' => '1',
|
||||
'match_operator' => 'CONTAINS',
|
||||
'limit' => 0,
|
||||
'ids' => NULL,
|
||||
];
|
||||
$view->display_handler->setOption('entity_reference_options', $options);
|
||||
|
||||
$this->executeView($view);
|
||||
|
||||
// Test that we have searched in both fields.
|
||||
$this->assertEqual(count($view->result), 2, 'Search returned two rows');
|
||||
}
|
||||
|
||||
}
|
|
@ -149,8 +149,10 @@ class StyleTest extends ViewTestBase {
|
|||
$expected = array();
|
||||
$expected['Job: Singer'] = array();
|
||||
$expected['Job: Singer']['group'] = 'Job: Singer';
|
||||
$expected['Job: Singer']['level'] = 0;
|
||||
$expected['Job: Singer']['rows']['Age: 25'] = array();
|
||||
$expected['Job: Singer']['rows']['Age: 25']['group'] = 'Age: 25';
|
||||
$expected['Job: Singer']['rows']['Age: 25']['level'] = 1;
|
||||
$expected['Job: Singer']['rows']['Age: 25']['rows'][0] = new ResultRow(['index' => 0]);
|
||||
$expected['Job: Singer']['rows']['Age: 25']['rows'][0]->views_test_data_name = 'John';
|
||||
$expected['Job: Singer']['rows']['Age: 25']['rows'][0]->views_test_data_job = 'Singer';
|
||||
|
@ -158,6 +160,7 @@ class StyleTest extends ViewTestBase {
|
|||
$expected['Job: Singer']['rows']['Age: 25']['rows'][0]->views_test_data_id = '1';
|
||||
$expected['Job: Singer']['rows']['Age: 27'] = array();
|
||||
$expected['Job: Singer']['rows']['Age: 27']['group'] = 'Age: 27';
|
||||
$expected['Job: Singer']['rows']['Age: 27']['level'] = 1;
|
||||
$expected['Job: Singer']['rows']['Age: 27']['rows'][1] = new ResultRow(['index' => 1]);
|
||||
$expected['Job: Singer']['rows']['Age: 27']['rows'][1]->views_test_data_name = 'George';
|
||||
$expected['Job: Singer']['rows']['Age: 27']['rows'][1]->views_test_data_job = 'Singer';
|
||||
|
@ -165,8 +168,10 @@ class StyleTest extends ViewTestBase {
|
|||
$expected['Job: Singer']['rows']['Age: 27']['rows'][1]->views_test_data_id = '2';
|
||||
$expected['Job: Drummer'] = array();
|
||||
$expected['Job: Drummer']['group'] = 'Job: Drummer';
|
||||
$expected['Job: Drummer']['level'] = 0;
|
||||
$expected['Job: Drummer']['rows']['Age: 28'] = array();
|
||||
$expected['Job: Drummer']['rows']['Age: 28']['group'] = 'Age: 28';
|
||||
$expected['Job: Drummer']['rows']['Age: 28']['level'] = 1;
|
||||
$expected['Job: Drummer']['rows']['Age: 28']['rows'][2] = new ResultRow(['index' => 2]);
|
||||
$expected['Job: Drummer']['rows']['Age: 28']['rows'][2]->views_test_data_name = 'Ringo';
|
||||
$expected['Job: Drummer']['rows']['Age: 28']['rows'][2]->views_test_data_job = 'Drummer';
|
||||
|
|
|
@ -25,7 +25,7 @@ class QueryGroupByTest extends ViewKernelTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = array('test_group_by_in_filters', 'test_aggregate_count', 'test_group_by_count', 'test_group_by_count_multicardinality');
|
||||
public static $testViews = array('test_group_by_in_filters', 'test_aggregate_count', 'test_group_by_count', 'test_group_by_count_multicardinality', 'test_group_by_field_not_within_bundle');
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
|
@ -292,4 +292,48 @@ class QueryGroupByTest extends ViewKernelTestBase {
|
|||
$this->assertEqual('6', $view->getStyle()->getField(5, 'field_test'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests groupby with a field not existing on some bundle.
|
||||
*/
|
||||
public function testGroupByWithFieldsNotExistingOnBundle() {
|
||||
$field_storage = FieldStorageConfig::create([
|
||||
'type' => 'integer',
|
||||
'field_name' => 'field_test',
|
||||
'cardinality' => 4,
|
||||
'entity_type' => 'entity_test_mul',
|
||||
]);
|
||||
$field_storage->save();
|
||||
$field = FieldConfig::create([
|
||||
'field_name' => 'field_test',
|
||||
'entity_type' => 'entity_test_mul',
|
||||
'bundle' => 'entity_test_mul',
|
||||
]);
|
||||
$field->save();
|
||||
|
||||
$entities = [];
|
||||
$entity = EntityTestMul::create([
|
||||
'field_test' => [1],
|
||||
'type' => 'entity_test_mul',
|
||||
]);
|
||||
$entity->save();
|
||||
$entities[] = $entity;
|
||||
|
||||
$entity = EntityTestMul::create([
|
||||
'type' => 'entity_test_mul2',
|
||||
]);
|
||||
$entity->save();
|
||||
$entities[] = $entity;
|
||||
|
||||
$view = Views::getView('test_group_by_field_not_within_bundle');
|
||||
$this->executeView($view);
|
||||
|
||||
$this->assertEqual(2, count($view->result));
|
||||
// The first result is coming from entity_test_mul2, so no field could be
|
||||
// rendered.
|
||||
$this->assertEqual('', $view->getStyle()->getField(0, 'field_test'));
|
||||
// The second result is coming from entity_test_mul, so its field value
|
||||
// could be rendered.
|
||||
$this->assertEqual('1', $view->getStyle()->getField(1, 'field_test'));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
80
core/modules/views/src/Tests/RenderCacheWebTest.php
Normal file
80
core/modules/views/src/Tests/RenderCacheWebTest.php
Normal file
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\views\Tests\RenderCacheWebTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\views\Tests;
|
||||
|
||||
use Drupal\node\Entity\Node;
|
||||
|
||||
/**
|
||||
* Tests render caching of blocks provided by views.
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class RenderCacheWebTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['node', 'block'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $testViews = ['node_id_argument'];
|
||||
|
||||
/**
|
||||
* The created nodes.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface[]
|
||||
*/
|
||||
protected $nodes;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$node_type = $this->drupalCreateContentType(['type' => 'test_type']);
|
||||
$node = Node::create([
|
||||
'title' => 'test title 1',
|
||||
'type' => $node_type->id(),
|
||||
]);
|
||||
$node->save();
|
||||
$this->nodes[] = $node;
|
||||
|
||||
$node = Node::create([
|
||||
'title' => 'test title 2',
|
||||
'type' => $node_type->id(),
|
||||
]);
|
||||
$node->save();
|
||||
$this->nodes[] = $node;
|
||||
|
||||
$this->placeBlock('views_block:node_id_argument-block_1', ['region' => 'header']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests rendering caching of a views block with arguments.
|
||||
*/
|
||||
public function testEmptyView() {
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertEqual([], $this->cssSelect('div.region-header div.views-field-title'));
|
||||
|
||||
$this->drupalGet($this->nodes[0]->toUrl());
|
||||
$result = (string) $this->cssSelect('div.region-header div.views-field-title')[0]->span;
|
||||
$this->assertEqual('test title 1', $result);
|
||||
|
||||
$this->drupalGet($this->nodes[1]->toUrl());
|
||||
$result = (string) $this->cssSelect('div.region-header div.views-field-title')[0]->span;
|
||||
$this->assertEqual('test title 2', $result);
|
||||
|
||||
$this->drupalGet($this->nodes[0]->toUrl());
|
||||
$result = (string) $this->cssSelect('div.region-header div.views-field-title')[0]->span;
|
||||
$this->assertEqual('test title 1', $result);
|
||||
}
|
||||
|
||||
}
|
|
@ -77,4 +77,23 @@ class TokenReplaceTest extends ViewKernelTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests core token replacements generated from a view without results.
|
||||
*/
|
||||
function testTokenReplacementNoResults() {
|
||||
$token_handler = \Drupal::token();
|
||||
$view = Views::getView('test_tokens');
|
||||
$view->setDisplay('page_2');
|
||||
$this->executeView($view);
|
||||
|
||||
$expected = array(
|
||||
'[view:page-count]' => '1',
|
||||
);
|
||||
|
||||
foreach ($expected as $token => $expected_output) {
|
||||
$output = $token_handler->replace($token, array('view' => $view));
|
||||
$this->assertIdentical($output, $expected_output, format_string('Token %token replaced correctly.', array('%token' => $token)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,215 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- node
|
||||
- user
|
||||
id: node_id_argument
|
||||
label: node_id_argument
|
||||
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: some
|
||||
options:
|
||||
items_per_page: 5
|
||||
offset: 0
|
||||
style:
|
||||
type: default
|
||||
row:
|
||||
type: fields
|
||||
fields:
|
||||
title:
|
||||
id: title
|
||||
table: node_field_data
|
||||
field: title
|
||||
settings:
|
||||
link_to_entity: false
|
||||
plugin_id: field
|
||||
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: true
|
||||
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: string
|
||||
group_column: value
|
||||
group_columns: { }
|
||||
group_rows: true
|
||||
delta_limit: 0
|
||||
delta_offset: 0
|
||||
delta_reversed: false
|
||||
delta_first_last: false
|
||||
multi_type: separator
|
||||
separator: ', '
|
||||
field_api_classes: false
|
||||
filters:
|
||||
status:
|
||||
value: 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
|
||||
title: node_id_argument
|
||||
header: { }
|
||||
footer: { }
|
||||
empty: { }
|
||||
relationships: { }
|
||||
arguments:
|
||||
nid:
|
||||
id: nid
|
||||
table: node_field_data
|
||||
field: nid
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
default_action: default
|
||||
exception:
|
||||
value: all
|
||||
title_enable: false
|
||||
title: All
|
||||
title_enable: false
|
||||
title: ''
|
||||
default_argument_type: node
|
||||
default_argument_options: { }
|
||||
default_argument_skip_url: false
|
||||
summary_options:
|
||||
base_path: ''
|
||||
count: true
|
||||
items_per_page: 25
|
||||
override: false
|
||||
summary:
|
||||
sort_order: asc
|
||||
number_of_records: 0
|
||||
format: default_summary
|
||||
specify_validation: false
|
||||
validate:
|
||||
type: none
|
||||
fail: 'not found'
|
||||
validate_options: { }
|
||||
break_phrase: false
|
||||
not: false
|
||||
entity_type: node
|
||||
entity_field: nid
|
||||
plugin_id: node_nid
|
||||
display_extenders: { }
|
||||
cache_metadata:
|
||||
max-age: -1
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
tags: { }
|
||||
block_1:
|
||||
display_plugin: block
|
||||
id: block_1
|
||||
display_title: Block
|
||||
position: 1
|
||||
display_options:
|
||||
display_extenders: { }
|
||||
cache_metadata:
|
||||
max-age: -1
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
tags: { }
|
|
@ -0,0 +1,50 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies: { }
|
||||
id: test_display_entity_reference
|
||||
module: views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: entity_test
|
||||
base_field: id
|
||||
core: '8'
|
||||
display:
|
||||
default:
|
||||
display_options:
|
||||
access:
|
||||
type: none
|
||||
cache:
|
||||
type: tag
|
||||
fields:
|
||||
name:
|
||||
id: name
|
||||
table: entity_test
|
||||
field: name
|
||||
plugin_id: field
|
||||
entity_type: entity_test
|
||||
entity_field: name
|
||||
style:
|
||||
type: html_list
|
||||
display_plugin: default
|
||||
display_title: Master
|
||||
id: default
|
||||
position: 0
|
||||
entity_reference_1:
|
||||
display_plugin: entity_reference
|
||||
id: entity_reference_1
|
||||
display_title: 'Entity Reference'
|
||||
position: 1
|
||||
display_options:
|
||||
display_extenders: { }
|
||||
style:
|
||||
type: entity_reference
|
||||
options:
|
||||
search_fields:
|
||||
name: name
|
||||
cache_metadata:
|
||||
max-age: -1
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- 'user.node_grants:view'
|
||||
tags: { }
|
|
@ -0,0 +1,61 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies: { }
|
||||
id: test_group_by_field_not_within_bundle
|
||||
label: ''
|
||||
module: views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: entity_test_mul_property_data
|
||||
base_field: id
|
||||
core: '8'
|
||||
display:
|
||||
default:
|
||||
display_options:
|
||||
access:
|
||||
type: none
|
||||
cache:
|
||||
type: tag
|
||||
exposed_form:
|
||||
type: basic
|
||||
fields:
|
||||
field_test:
|
||||
alter:
|
||||
alter_text: false
|
||||
ellipsis: true
|
||||
html: false
|
||||
make_link: false
|
||||
strip_tags: false
|
||||
trim: false
|
||||
word_boundary: true
|
||||
group_type: group
|
||||
group_column: value
|
||||
empty_zero: false
|
||||
field: field_test
|
||||
hide_empty: false
|
||||
id: field_test
|
||||
table: entity_test_mul__field_test
|
||||
entity_type: entity_test_mul
|
||||
entity_field: field_test
|
||||
plugin_id: field
|
||||
sorts:
|
||||
field_test_value:
|
||||
table: entity_test_mul__field_test
|
||||
field: field_test_value
|
||||
id: field_test_value
|
||||
entity_type: entity_test_mul
|
||||
entity_field: field_test
|
||||
group_type: group
|
||||
order: ASC
|
||||
plugin_id: standard
|
||||
group_by: true
|
||||
pager:
|
||||
type: some
|
||||
style:
|
||||
type: default
|
||||
row:
|
||||
type: fields
|
||||
display_plugin: default
|
||||
display_title: Master
|
||||
id: default
|
||||
position: 0
|
|
@ -57,3 +57,23 @@ display:
|
|||
type: views_query
|
||||
options: { }
|
||||
path: test_tokens
|
||||
page_2:
|
||||
id: page_2
|
||||
display_title: Page
|
||||
display_plugin: page
|
||||
position: 2
|
||||
display_options:
|
||||
defaults:
|
||||
filters: false
|
||||
query:
|
||||
type: views_query
|
||||
options: { }
|
||||
filters:
|
||||
name:
|
||||
field: name
|
||||
id: test_filter
|
||||
table: views_test_data
|
||||
plugin_id: string
|
||||
operator: '='
|
||||
value: 'not an existing name'
|
||||
path: test_tokens_empty
|
||||
|
|
|
@ -185,6 +185,10 @@ class ViewAjaxControllerTest extends UnitTestCase {
|
|||
$request = new Request();
|
||||
$request->request->set('view_name', 'test_view');
|
||||
$request->request->set('view_display_id', 'page_1');
|
||||
$request->request->set('view_path', '/test-page');
|
||||
$request->request->set('_wrapper_format', 'ajax');
|
||||
$request->request->set('ajax_page_state', 'drupal.settings[]');
|
||||
$request->request->set('type', 'article');
|
||||
|
||||
list($view, $executable) = $this->setupValidMocks();
|
||||
|
||||
|
@ -205,6 +209,10 @@ class ViewAjaxControllerTest extends UnitTestCase {
|
|||
|
||||
$executable->displayHandlers = $display_collection;
|
||||
|
||||
$this->redirectDestination->expects($this->atLeastOnce())
|
||||
->method('set')
|
||||
->with('/test-page?type=article');
|
||||
|
||||
$response = $this->viewAjaxController->ajaxView($request);
|
||||
$this->assertTrue($response instanceof ViewAjaxResponse);
|
||||
|
||||
|
|
|
@ -138,8 +138,8 @@ class EntityViewsDataTest extends UnitTestCase {
|
|||
// Add a description field to the fields supplied by the EntityTest
|
||||
// classes. This example comes from the taxonomy Term entity.
|
||||
$base_fields['description'] = BaseFieldDefinition::create('text_long')
|
||||
->setLabel(t('Description'))
|
||||
->setDescription(t('A description of the term.'))
|
||||
->setLabel('Description')
|
||||
->setDescription('A description of the term.')
|
||||
->setTranslatable(TRUE)
|
||||
->setDisplayOptions('view', array(
|
||||
'label' => 'hidden',
|
||||
|
@ -155,8 +155,8 @@ class EntityViewsDataTest extends UnitTestCase {
|
|||
|
||||
// Add a URL field; this example is from the Comment entity.
|
||||
$base_fields['homepage'] = BaseFieldDefinition::create('uri')
|
||||
->setLabel(t('Homepage'))
|
||||
->setDescription(t("The comment author's home page address."))
|
||||
->setLabel('Homepage')
|
||||
->setDescription("The comment author's home page address.")
|
||||
->setTranslatable(TRUE)
|
||||
->setSetting('max_length', 255);
|
||||
|
||||
|
@ -409,8 +409,8 @@ class EntityViewsDataTest extends UnitTestCase {
|
|||
$base_field_definitions = $this->setupBaseFields(EntityTest::baseFieldDefinitions($this->baseEntityType));
|
||||
$user_base_field_definitions = [
|
||||
'uid' => BaseFieldDefinition::create('integer')
|
||||
->setLabel(t('ID'))
|
||||
->setDescription(t('The ID of the user entity.'))
|
||||
->setLabel('ID')
|
||||
->setDescription('The ID of the user entity.')
|
||||
->setReadOnly(TRUE)
|
||||
->setSetting('unsigned', TRUE)
|
||||
];
|
||||
|
@ -498,8 +498,8 @@ class EntityViewsDataTest extends UnitTestCase {
|
|||
$base_field_definitions = $this->setupBaseFields($base_field_definitions);
|
||||
$user_base_field_definitions = [
|
||||
'uid' => BaseFieldDefinition::create('integer')
|
||||
->setLabel(t('ID'))
|
||||
->setDescription(t('The ID of the user entity.'))
|
||||
->setLabel('ID')
|
||||
->setDescription('The ID of the user entity.')
|
||||
->setReadOnly(TRUE)
|
||||
->setSetting('unsigned', TRUE)
|
||||
];
|
||||
|
@ -621,8 +621,8 @@ class EntityViewsDataTest extends UnitTestCase {
|
|||
$base_field_definitions = $this->setupBaseFields(EntityTestMulRev::baseFieldDefinitions($this->baseEntityType));
|
||||
$user_base_field_definitions = [
|
||||
'uid' => BaseFieldDefinition::create('integer')
|
||||
->setLabel(t('ID'))
|
||||
->setDescription(t('The ID of the user entity.'))
|
||||
->setLabel('ID')
|
||||
->setDescription('The ID of the user entity.')
|
||||
->setReadOnly(TRUE)
|
||||
->setSetting('unsigned', TRUE)
|
||||
];
|
||||
|
@ -970,10 +970,11 @@ class TestEntityType extends EntityType {
|
|||
|
||||
}
|
||||
|
||||
namespace {
|
||||
namespace Drupal\entity_test\Entity {
|
||||
if (!function_exists('t')) {
|
||||
function t($string, array $args = []) {
|
||||
return strtr($string, $args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ function views_tokens($type, $tokens, array $data, array $options, BubbleableMet
|
|||
case 'page-count':
|
||||
// If there are no items per page, set this to 1 for the division.
|
||||
$per_page = $view->getItemsPerPage() ?: 1;
|
||||
$replacements[$original] = (int) ceil(count($view->result) / $per_page);
|
||||
$replacements[$original] = max(1, (int) ceil(count($view->result) / $per_page));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue