updated core and modules
This commit is contained in:
@@ -5,15 +5,15 @@
|
||||
* Text fixture.
|
||||
*/
|
||||
|
||||
use Drupal\Component\Serialization\Yaml;
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\Core\Serialization\Yaml;
|
||||
|
||||
$connection = Database::getConnection();
|
||||
|
||||
$connection->insert('config')
|
||||
->fields(array(
|
||||
->fields([
|
||||
'collection' => '',
|
||||
'name' => 'views.view.test_token_view',
|
||||
'data' => serialize(Yaml::decode(file_get_contents('core/modules/views/tests/modules/views_test_config/test_views/views.view.test_token_view.yml'))),
|
||||
))
|
||||
])
|
||||
->execute();
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Test fixture.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\Core\Serialization\Yaml;
|
||||
|
||||
$connection = Database::getConnection();
|
||||
|
||||
$connection->insert('config')
|
||||
->fields([
|
||||
'collection' => '',
|
||||
'name' => 'views.view.test_boolean_filter_values',
|
||||
'data' => serialize(Yaml::decode(file_get_contents('core/modules/views/tests/fixtures/update/views.view.test_boolean_filter_values.yml'))),
|
||||
])
|
||||
->execute();
|
||||
@@ -5,15 +5,15 @@
|
||||
* Test fixture.
|
||||
*/
|
||||
|
||||
use Drupal\Component\Serialization\Yaml;
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\Core\Serialization\Yaml;
|
||||
|
||||
$connection = Database::getConnection();
|
||||
|
||||
$connection->insert('config')
|
||||
->fields(array(
|
||||
->fields([
|
||||
'collection' => '',
|
||||
'name' => 'views.view.test_duplicate_field_handlers',
|
||||
'data' => serialize(Yaml::decode(file_get_contents('core/modules/views/tests/modules/views_test_config/test_views/views.view.test_duplicate_field_handlers.yml'))),
|
||||
))
|
||||
])
|
||||
->execute();
|
||||
|
||||
+604
@@ -0,0 +1,604 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- node
|
||||
- user
|
||||
id: test_boolean_filter_values
|
||||
label: Content
|
||||
module: node
|
||||
description: 'Find and manage content.'
|
||||
tag: default
|
||||
base_table: node_field_data
|
||||
base_field: nid
|
||||
core: 8.x
|
||||
display:
|
||||
default:
|
||||
display_options:
|
||||
access:
|
||||
type: perm
|
||||
options:
|
||||
perm: 'access content overview'
|
||||
cache:
|
||||
type: tag
|
||||
query:
|
||||
type: views_query
|
||||
exposed_form:
|
||||
type: basic
|
||||
options:
|
||||
submit_button: Filter
|
||||
reset_button: true
|
||||
reset_button_label: Reset
|
||||
exposed_sorts_label: 'Sort by'
|
||||
expose_sort_order: true
|
||||
sort_asc_label: Asc
|
||||
sort_desc_label: Desc
|
||||
pager:
|
||||
type: full
|
||||
options:
|
||||
items_per_page: 50
|
||||
tags:
|
||||
previous: '‹ Previous'
|
||||
next: 'Next ›'
|
||||
first: '« First'
|
||||
last: 'Last »'
|
||||
style:
|
||||
type: table
|
||||
options:
|
||||
grouping: { }
|
||||
row_class: ''
|
||||
default_row_class: true
|
||||
override: true
|
||||
sticky: true
|
||||
caption: ''
|
||||
summary: ''
|
||||
description: ''
|
||||
columns:
|
||||
node_bulk_form: node_bulk_form
|
||||
title: title
|
||||
type: type
|
||||
name: name
|
||||
status: status
|
||||
changed: changed
|
||||
edit_node: edit_node
|
||||
delete_node: delete_node
|
||||
dropbutton: dropbutton
|
||||
timestamp: title
|
||||
info:
|
||||
node_bulk_form:
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
title:
|
||||
sortable: true
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
type:
|
||||
sortable: true
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
name:
|
||||
sortable: false
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: priority-low
|
||||
status:
|
||||
sortable: true
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
changed:
|
||||
sortable: true
|
||||
default_sort_order: desc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: priority-low
|
||||
edit_node:
|
||||
sortable: false
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
delete_node:
|
||||
sortable: false
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
dropbutton:
|
||||
sortable: false
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
timestamp:
|
||||
sortable: false
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
default: changed
|
||||
empty_table: true
|
||||
row:
|
||||
type: fields
|
||||
fields:
|
||||
node_bulk_form:
|
||||
id: node_bulk_form
|
||||
table: node
|
||||
field: node_bulk_form
|
||||
label: ''
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
element_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
plugin_id: node_bulk_form
|
||||
entity_type: node
|
||||
title:
|
||||
id: title
|
||||
table: node_field_data
|
||||
field: title
|
||||
label: Title
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
element_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
entity_type: node
|
||||
entity_field: title
|
||||
type: string
|
||||
settings:
|
||||
link_to_entity: true
|
||||
plugin_id: field
|
||||
type:
|
||||
id: type
|
||||
table: node_field_data
|
||||
field: type
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: 'Content type'
|
||||
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: target_id
|
||||
type: entity_reference_label
|
||||
settings:
|
||||
link: false
|
||||
group_column: target_id
|
||||
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: type
|
||||
plugin_id: field
|
||||
name:
|
||||
id: name
|
||||
table: users_field_data
|
||||
field: name
|
||||
relationship: uid
|
||||
label: Author
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
element_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
plugin_id: field
|
||||
type: user_name
|
||||
entity_type: user
|
||||
entity_field: name
|
||||
status:
|
||||
id: status
|
||||
table: node_field_data
|
||||
field: status
|
||||
label: Status
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
element_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
type: boolean
|
||||
settings:
|
||||
format: custom
|
||||
format_custom_true: Published
|
||||
format_custom_false: Unpublished
|
||||
plugin_id: field
|
||||
entity_type: node
|
||||
entity_field: status
|
||||
changed:
|
||||
id: changed
|
||||
table: node_field_data
|
||||
field: changed
|
||||
label: Updated
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
element_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
type: timestamp
|
||||
settings:
|
||||
date_format: short
|
||||
custom_date_format: ''
|
||||
timezone: ''
|
||||
plugin_id: field
|
||||
entity_type: node
|
||||
entity_field: changed
|
||||
operations:
|
||||
id: operations
|
||||
table: node
|
||||
field: operations
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: Operations
|
||||
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
|
||||
destination: true
|
||||
plugin_id: entity_operations
|
||||
filters:
|
||||
status_extra:
|
||||
id: status_extra
|
||||
table: node_field_data
|
||||
field: status_extra
|
||||
operator: '='
|
||||
value: false
|
||||
plugin_id: node_status
|
||||
group: 1
|
||||
entity_type: node
|
||||
status:
|
||||
id: status
|
||||
table: node_field_data
|
||||
field: status
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: '='
|
||||
value: true
|
||||
group: 1
|
||||
exposed: true
|
||||
expose:
|
||||
operator_id: ''
|
||||
label: Status
|
||||
description: ''
|
||||
use_operator: false
|
||||
operator: status_op
|
||||
identifier: status
|
||||
required: false
|
||||
remember: false
|
||||
multiple: false
|
||||
remember_roles:
|
||||
authenticated: authenticated
|
||||
is_grouped: true
|
||||
group_info:
|
||||
label: 'Published status'
|
||||
description: ''
|
||||
identifier: status
|
||||
optional: true
|
||||
widget: select
|
||||
multiple: false
|
||||
remember: false
|
||||
default_group: All
|
||||
default_group_multiple: { }
|
||||
group_items:
|
||||
1:
|
||||
title: Published
|
||||
operator: '='
|
||||
value: '1'
|
||||
2:
|
||||
title: Unpublished
|
||||
operator: '='
|
||||
value: '0'
|
||||
plugin_id: boolean
|
||||
entity_type: node
|
||||
entity_field: status
|
||||
type:
|
||||
id: type
|
||||
table: node_field_data
|
||||
field: type
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: in
|
||||
value: { }
|
||||
group: 1
|
||||
exposed: true
|
||||
expose:
|
||||
operator_id: type_op
|
||||
label: 'Content type'
|
||||
description: ''
|
||||
use_operator: false
|
||||
operator: type_op
|
||||
identifier: type
|
||||
required: false
|
||||
remember: false
|
||||
multiple: false
|
||||
remember_roles:
|
||||
authenticated: authenticated
|
||||
anonymous: '0'
|
||||
administrator: '0'
|
||||
reduce: false
|
||||
is_grouped: false
|
||||
group_info:
|
||||
label: ''
|
||||
description: ''
|
||||
identifier: ''
|
||||
optional: true
|
||||
widget: select
|
||||
multiple: false
|
||||
remember: false
|
||||
default_group: All
|
||||
default_group_multiple: { }
|
||||
group_items: { }
|
||||
plugin_id: bundle
|
||||
entity_type: node
|
||||
entity_field: type
|
||||
title:
|
||||
id: title
|
||||
table: node_field_data
|
||||
field: title
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: contains
|
||||
value: ''
|
||||
group: 1
|
||||
exposed: true
|
||||
expose:
|
||||
operator_id: title_op
|
||||
label: Title
|
||||
description: ''
|
||||
use_operator: false
|
||||
operator: title_op
|
||||
identifier: title
|
||||
required: false
|
||||
remember: false
|
||||
multiple: false
|
||||
remember_roles:
|
||||
authenticated: authenticated
|
||||
anonymous: '0'
|
||||
administrator: '0'
|
||||
is_grouped: false
|
||||
group_info:
|
||||
label: ''
|
||||
description: ''
|
||||
identifier: ''
|
||||
optional: true
|
||||
widget: select
|
||||
multiple: false
|
||||
remember: false
|
||||
default_group: All
|
||||
default_group_multiple: { }
|
||||
group_items: { }
|
||||
plugin_id: string
|
||||
entity_type: node
|
||||
entity_field: title
|
||||
langcode:
|
||||
id: langcode
|
||||
table: node_field_data
|
||||
field: langcode
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: in
|
||||
value: { }
|
||||
group: 1
|
||||
exposed: true
|
||||
expose:
|
||||
operator_id: langcode_op
|
||||
label: Language
|
||||
description: ''
|
||||
use_operator: false
|
||||
operator: langcode_op
|
||||
identifier: langcode
|
||||
required: false
|
||||
remember: false
|
||||
multiple: false
|
||||
remember_roles:
|
||||
authenticated: authenticated
|
||||
anonymous: '0'
|
||||
administrator: '0'
|
||||
reduce: false
|
||||
is_grouped: false
|
||||
group_info:
|
||||
label: ''
|
||||
description: ''
|
||||
identifier: ''
|
||||
optional: true
|
||||
widget: select
|
||||
multiple: false
|
||||
remember: false
|
||||
default_group: All
|
||||
default_group_multiple: { }
|
||||
group_items: { }
|
||||
plugin_id: language
|
||||
entity_type: node
|
||||
entity_field: langcode
|
||||
sorts: { }
|
||||
title: Content
|
||||
empty:
|
||||
area_text_custom:
|
||||
id: area_text_custom
|
||||
table: views
|
||||
field: area_text_custom
|
||||
empty: true
|
||||
content: 'No content available.'
|
||||
plugin_id: text_custom
|
||||
arguments: { }
|
||||
relationships:
|
||||
uid:
|
||||
id: uid
|
||||
table: node_field_data
|
||||
field: uid
|
||||
admin_label: author
|
||||
required: true
|
||||
plugin_id: standard
|
||||
show_admin_links: false
|
||||
filter_groups:
|
||||
operator: AND
|
||||
groups:
|
||||
1: AND
|
||||
display_extenders: { }
|
||||
display_plugin: default
|
||||
display_title: Master
|
||||
id: default
|
||||
position: 0
|
||||
cache_metadata:
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url
|
||||
- url.query_args
|
||||
- user
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
max-age: 0
|
||||
tags: { }
|
||||
page_1:
|
||||
display_options:
|
||||
path: admin/content/node
|
||||
menu:
|
||||
type: 'default tab'
|
||||
title: Content
|
||||
description: ''
|
||||
menu_name: admin
|
||||
weight: -10
|
||||
context: ''
|
||||
tab_options:
|
||||
type: normal
|
||||
title: Content
|
||||
description: 'Find and manage content'
|
||||
menu_name: admin
|
||||
weight: -10
|
||||
display_extenders: { }
|
||||
display_plugin: page
|
||||
display_title: Page
|
||||
id: page_1
|
||||
position: 1
|
||||
cache_metadata:
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url
|
||||
- url.query_args
|
||||
- user
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
max-age: 0
|
||||
tags: { }
|
||||
@@ -8,8 +8,8 @@ dependencies:
|
||||
- views
|
||||
- entity_test
|
||||
|
||||
# Information added by Drupal.org packaging script on 2016-08-03
|
||||
version: '8.1.8'
|
||||
# Information added by Drupal.org packaging script on 2017-08-16
|
||||
version: '8.3.7'
|
||||
core: '8.x'
|
||||
project: 'drupal'
|
||||
datestamp: 1470233790
|
||||
datestamp: 1502903957
|
||||
|
||||
@@ -22,10 +22,10 @@ function views_entity_test_entity_base_field_info(EntityTypeInterface $entity_ty
|
||||
->setLabel(t('Test access'))
|
||||
->setTranslatable(FALSE)
|
||||
->setSetting('max_length', 64)
|
||||
->setDisplayOptions('form', array(
|
||||
->setDisplayOptions('form', [
|
||||
'type' => 'string_textfield',
|
||||
'weight' => 10,
|
||||
));
|
||||
]);
|
||||
return $definitions;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -119,7 +119,7 @@ display:
|
||||
field_api_classes: false
|
||||
filters:
|
||||
status:
|
||||
value: true
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
plugin_id: boolean
|
||||
|
||||
+216
@@ -0,0 +1,216 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
config:
|
||||
- core.entity_view_mode.node.teaser
|
||||
- user.role.authenticated
|
||||
module:
|
||||
- node
|
||||
- rest
|
||||
- user
|
||||
id: rest_export_with_authorization
|
||||
label: 'Rest Export'
|
||||
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: role
|
||||
options:
|
||||
role:
|
||||
authenticated: authenticated
|
||||
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: full
|
||||
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: '‹ Previous'
|
||||
next: 'Next ›'
|
||||
first: '« First'
|
||||
last: 'Last »'
|
||||
quantity: 9
|
||||
style:
|
||||
type: default
|
||||
row:
|
||||
type: 'entity:node'
|
||||
options:
|
||||
view_mode: teaser
|
||||
fields:
|
||||
title:
|
||||
id: title
|
||||
table: node_field_data
|
||||
field: title
|
||||
entity_type: node
|
||||
entity_field: title
|
||||
label: ''
|
||||
alter:
|
||||
alter_text: false
|
||||
make_link: false
|
||||
absolute: false
|
||||
trim: false
|
||||
word_boundary: false
|
||||
ellipsis: false
|
||||
strip_tags: false
|
||||
html: false
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
settings:
|
||||
link_to_entity: true
|
||||
plugin_id: field
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
exclude: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: true
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_alter_empty: true
|
||||
click_sort_column: value
|
||||
type: string
|
||||
group_column: value
|
||||
group_columns: { }
|
||||
group_rows: true
|
||||
delta_limit: 0
|
||||
delta_offset: 0
|
||||
delta_reversed: false
|
||||
delta_first_last: false
|
||||
multi_type: separator
|
||||
separator: ', '
|
||||
field_api_classes: false
|
||||
filters:
|
||||
status:
|
||||
id: status
|
||||
table: node_field_data
|
||||
field: status
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: '='
|
||||
value: '0'
|
||||
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: { }
|
||||
plugin_id: boolean
|
||||
entity_type: node
|
||||
entity_field: status
|
||||
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: 'Rest Export'
|
||||
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.roles
|
||||
tags: { }
|
||||
rest_export_1:
|
||||
display_plugin: rest_export
|
||||
id: rest_export_1
|
||||
display_title: 'REST export'
|
||||
position: 2
|
||||
display_options:
|
||||
display_extenders: { }
|
||||
path: unpublished-content
|
||||
auth:
|
||||
basic_auth: basic_auth
|
||||
cache_metadata:
|
||||
max-age: -1
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- request_format
|
||||
- 'user.node_grants:view'
|
||||
- user.roles
|
||||
tags: { }
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies: { }
|
||||
id: test_area_result
|
||||
label: ''
|
||||
module: views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: views_test_data
|
||||
base_field: nid
|
||||
core: '8'
|
||||
display:
|
||||
default:
|
||||
display_options:
|
||||
defaults:
|
||||
fields: false
|
||||
pager: false
|
||||
sorts: false
|
||||
fields:
|
||||
id:
|
||||
field: id
|
||||
id: id
|
||||
relationship: none
|
||||
table: views_test_data
|
||||
plugin_id: numeric
|
||||
pager:
|
||||
options:
|
||||
offset: 0
|
||||
type: none
|
||||
sorts:
|
||||
id:
|
||||
field: id
|
||||
id: id
|
||||
order: ASC
|
||||
relationship: none
|
||||
table: views_test_data
|
||||
plugin_id: numeric
|
||||
empty:
|
||||
title:
|
||||
field: title
|
||||
id: title
|
||||
table: views
|
||||
plugin_id: title
|
||||
title: test_title_empty
|
||||
header:
|
||||
result:
|
||||
id: result
|
||||
table: views
|
||||
field: result
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
empty: true
|
||||
content: "start: @start | end: @end | total: @total | label: @label | per page: @per_page | current page: @current_page | current record count: @current_record_count | page count: @page_count"
|
||||
plugin_id: result
|
||||
display_plugin: default
|
||||
display_title: Master
|
||||
id: default
|
||||
position: 0
|
||||
page_1:
|
||||
display_options:
|
||||
path: test-area-result
|
||||
defaults:
|
||||
header: false
|
||||
header:
|
||||
result:
|
||||
id: result
|
||||
table: views
|
||||
field: result
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
empty: false
|
||||
content: "start: @start | end: @end | total: @total | label: @label | per page: @per_page | current page: @current_page | current record count: @current_record_count | page count: @page_count"
|
||||
plugin_id: result
|
||||
display_plugin: page
|
||||
display_title: 'Page 1'
|
||||
id: page_1
|
||||
position: 1
|
||||
+1
-1
@@ -121,7 +121,7 @@ display:
|
||||
field_api_classes: false
|
||||
filters:
|
||||
status:
|
||||
value: true
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
plugin_id: boolean
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- node
|
||||
id: test_argument_default_query_param
|
||||
label: ''
|
||||
module: views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: node_field_data
|
||||
base_field: nid
|
||||
core: '8'
|
||||
display:
|
||||
default:
|
||||
display_options:
|
||||
arguments:
|
||||
type:
|
||||
id: type
|
||||
table: node_field_data
|
||||
field: type
|
||||
default_action: default
|
||||
default_argument_type: query_parameter
|
||||
default_argument_options:
|
||||
query_param: the_node_type
|
||||
fallback: all
|
||||
multiple: and
|
||||
entity_type: node
|
||||
entity_field: type
|
||||
plugin_id: node_type
|
||||
fields:
|
||||
title:
|
||||
alter:
|
||||
alter_text: false
|
||||
ellipsis: true
|
||||
html: false
|
||||
make_link: false
|
||||
strip_tags: false
|
||||
trim: false
|
||||
word_boundary: true
|
||||
empty_zero: false
|
||||
field: title
|
||||
hide_empty: false
|
||||
id: title
|
||||
table: node_field_data
|
||||
plugin_id: field
|
||||
entity_type: node
|
||||
entity_field: title
|
||||
pager:
|
||||
options:
|
||||
id: 0
|
||||
items_per_page: 10
|
||||
offset: 0
|
||||
type: full
|
||||
style:
|
||||
type: default
|
||||
row:
|
||||
type: fields
|
||||
display_plugin: default
|
||||
display_title: Master
|
||||
id: default
|
||||
position: 0
|
||||
+1
-1
@@ -115,7 +115,7 @@ display:
|
||||
hide_alter_empty: true
|
||||
filters:
|
||||
status:
|
||||
value: true
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
plugin_id: boolean
|
||||
|
||||
+1
-1
@@ -130,7 +130,7 @@ display:
|
||||
field_api_classes: false
|
||||
filters:
|
||||
status:
|
||||
value: true
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
plugin_id: boolean
|
||||
|
||||
+1
-1
@@ -110,7 +110,7 @@ display:
|
||||
hide_alter_empty: true
|
||||
filters:
|
||||
status:
|
||||
value: true
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
plugin_id: boolean
|
||||
|
||||
+616
@@ -0,0 +1,616 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- node
|
||||
- user
|
||||
id: test_content_ajax
|
||||
label: Content
|
||||
module: node
|
||||
description: 'Find and manage content.'
|
||||
tag: default
|
||||
base_table: node_field_data
|
||||
base_field: nid
|
||||
core: 8.x
|
||||
display:
|
||||
default:
|
||||
display_options:
|
||||
use_ajax: true
|
||||
access:
|
||||
type: perm
|
||||
options:
|
||||
perm: 'access content overview'
|
||||
cache:
|
||||
type: tag
|
||||
query:
|
||||
type: views_query
|
||||
exposed_form:
|
||||
type: basic
|
||||
options:
|
||||
submit_button: Filter
|
||||
reset_button: true
|
||||
reset_button_label: Reset
|
||||
exposed_sorts_label: 'Sort by'
|
||||
expose_sort_order: true
|
||||
sort_asc_label: Asc
|
||||
sort_desc_label: Desc
|
||||
pager:
|
||||
type: full
|
||||
options:
|
||||
items_per_page: 50
|
||||
offset: 0
|
||||
id: 0
|
||||
tags:
|
||||
previous: '‹ Previous'
|
||||
next: 'Next ›'
|
||||
first: '« First'
|
||||
last: 'Last »'
|
||||
expose:
|
||||
items_per_page: true
|
||||
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
|
||||
quantity: 9
|
||||
style:
|
||||
type: table
|
||||
options:
|
||||
grouping: { }
|
||||
row_class: ''
|
||||
default_row_class: true
|
||||
override: true
|
||||
sticky: true
|
||||
caption: ''
|
||||
summary: ''
|
||||
description: ''
|
||||
columns:
|
||||
node_bulk_form: node_bulk_form
|
||||
title: title
|
||||
type: type
|
||||
name: name
|
||||
status: status
|
||||
changed: changed
|
||||
edit_node: edit_node
|
||||
delete_node: delete_node
|
||||
dropbutton: dropbutton
|
||||
timestamp: title
|
||||
info:
|
||||
node_bulk_form:
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
title:
|
||||
sortable: true
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
type:
|
||||
sortable: true
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
name:
|
||||
sortable: false
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: priority-low
|
||||
status:
|
||||
sortable: true
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
changed:
|
||||
sortable: true
|
||||
default_sort_order: desc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: priority-low
|
||||
edit_node:
|
||||
sortable: false
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
delete_node:
|
||||
sortable: false
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
dropbutton:
|
||||
sortable: false
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
timestamp:
|
||||
sortable: false
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
default: changed
|
||||
empty_table: true
|
||||
row:
|
||||
type: fields
|
||||
fields:
|
||||
node_bulk_form:
|
||||
id: node_bulk_form
|
||||
table: node
|
||||
field: node_bulk_form
|
||||
label: ''
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
element_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
plugin_id: node_bulk_form
|
||||
entity_type: node
|
||||
title:
|
||||
id: title
|
||||
table: node_field_data
|
||||
field: title
|
||||
label: Title
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
element_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
entity_type: node
|
||||
entity_field: title
|
||||
type: string
|
||||
settings:
|
||||
link_to_entity: true
|
||||
plugin_id: field
|
||||
type:
|
||||
id: type
|
||||
table: node_field_data
|
||||
field: type
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: 'Content type'
|
||||
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: target_id
|
||||
type: entity_reference_label
|
||||
settings:
|
||||
link: false
|
||||
group_column: target_id
|
||||
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: type
|
||||
plugin_id: field
|
||||
name:
|
||||
id: name
|
||||
table: users_field_data
|
||||
field: name
|
||||
relationship: uid
|
||||
label: Author
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
element_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
plugin_id: field
|
||||
type: user_name
|
||||
entity_type: user
|
||||
entity_field: name
|
||||
status:
|
||||
id: status
|
||||
table: node_field_data
|
||||
field: status
|
||||
label: Status
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
element_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
type: boolean
|
||||
settings:
|
||||
format: custom
|
||||
format_custom_true: Published
|
||||
format_custom_false: Unpublished
|
||||
plugin_id: field
|
||||
entity_type: node
|
||||
entity_field: status
|
||||
changed:
|
||||
id: changed
|
||||
table: node_field_data
|
||||
field: changed
|
||||
label: Updated
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
element_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
type: timestamp
|
||||
settings:
|
||||
date_format: short
|
||||
custom_date_format: ''
|
||||
timezone: ''
|
||||
plugin_id: field
|
||||
entity_type: node
|
||||
entity_field: changed
|
||||
operations:
|
||||
id: operations
|
||||
table: node
|
||||
field: operations
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: Operations
|
||||
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
|
||||
destination: true
|
||||
plugin_id: entity_operations
|
||||
filters:
|
||||
status_extra:
|
||||
id: status_extra
|
||||
table: node_field_data
|
||||
field: status_extra
|
||||
operator: '='
|
||||
value: false
|
||||
plugin_id: node_status
|
||||
group: 1
|
||||
entity_type: node
|
||||
status:
|
||||
id: status
|
||||
table: node_field_data
|
||||
field: status
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: '='
|
||||
value: '1'
|
||||
group: 1
|
||||
exposed: true
|
||||
expose:
|
||||
operator_id: ''
|
||||
label: Status
|
||||
description: ''
|
||||
use_operator: false
|
||||
operator: status_op
|
||||
identifier: status
|
||||
required: false
|
||||
remember: false
|
||||
multiple: false
|
||||
remember_roles:
|
||||
authenticated: authenticated
|
||||
is_grouped: true
|
||||
group_info:
|
||||
label: 'Published status'
|
||||
description: ''
|
||||
identifier: status
|
||||
optional: true
|
||||
widget: select
|
||||
multiple: false
|
||||
remember: false
|
||||
default_group: All
|
||||
default_group_multiple: { }
|
||||
group_items:
|
||||
1:
|
||||
title: Published
|
||||
operator: '='
|
||||
value: '1'
|
||||
2:
|
||||
title: Unpublished
|
||||
operator: '='
|
||||
value: '0'
|
||||
plugin_id: boolean
|
||||
entity_type: node
|
||||
entity_field: status
|
||||
type:
|
||||
id: type
|
||||
table: node_field_data
|
||||
field: type
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: in
|
||||
value: { }
|
||||
group: 1
|
||||
exposed: true
|
||||
expose:
|
||||
operator_id: type_op
|
||||
label: 'Content type'
|
||||
description: ''
|
||||
use_operator: false
|
||||
operator: type_op
|
||||
identifier: type
|
||||
required: false
|
||||
remember: false
|
||||
multiple: false
|
||||
remember_roles:
|
||||
authenticated: authenticated
|
||||
anonymous: '0'
|
||||
administrator: '0'
|
||||
reduce: false
|
||||
is_grouped: false
|
||||
group_info:
|
||||
label: ''
|
||||
description: ''
|
||||
identifier: ''
|
||||
optional: true
|
||||
widget: select
|
||||
multiple: false
|
||||
remember: false
|
||||
default_group: All
|
||||
default_group_multiple: { }
|
||||
group_items: { }
|
||||
plugin_id: bundle
|
||||
entity_type: node
|
||||
entity_field: type
|
||||
title:
|
||||
id: title
|
||||
table: node_field_data
|
||||
field: title
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: contains
|
||||
value: ''
|
||||
group: 1
|
||||
exposed: true
|
||||
expose:
|
||||
operator_id: title_op
|
||||
label: Title
|
||||
description: ''
|
||||
use_operator: false
|
||||
operator: title_op
|
||||
identifier: title
|
||||
required: false
|
||||
remember: false
|
||||
multiple: false
|
||||
remember_roles:
|
||||
authenticated: authenticated
|
||||
anonymous: '0'
|
||||
administrator: '0'
|
||||
is_grouped: false
|
||||
group_info:
|
||||
label: ''
|
||||
description: ''
|
||||
identifier: ''
|
||||
optional: true
|
||||
widget: select
|
||||
multiple: false
|
||||
remember: false
|
||||
default_group: All
|
||||
default_group_multiple: { }
|
||||
group_items: { }
|
||||
plugin_id: string
|
||||
entity_type: node
|
||||
entity_field: title
|
||||
langcode:
|
||||
id: langcode
|
||||
table: node_field_data
|
||||
field: langcode
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: in
|
||||
value: { }
|
||||
group: 1
|
||||
exposed: true
|
||||
expose:
|
||||
operator_id: langcode_op
|
||||
label: Language
|
||||
description: ''
|
||||
use_operator: false
|
||||
operator: langcode_op
|
||||
identifier: langcode
|
||||
required: false
|
||||
remember: false
|
||||
multiple: false
|
||||
remember_roles:
|
||||
authenticated: authenticated
|
||||
anonymous: '0'
|
||||
administrator: '0'
|
||||
reduce: false
|
||||
is_grouped: false
|
||||
group_info:
|
||||
label: ''
|
||||
description: ''
|
||||
identifier: ''
|
||||
optional: true
|
||||
widget: select
|
||||
multiple: false
|
||||
remember: false
|
||||
default_group: All
|
||||
default_group_multiple: { }
|
||||
group_items: { }
|
||||
plugin_id: language
|
||||
entity_type: node
|
||||
entity_field: langcode
|
||||
sorts: { }
|
||||
title: Content
|
||||
empty:
|
||||
area_text_custom:
|
||||
id: area_text_custom
|
||||
table: views
|
||||
field: area_text_custom
|
||||
empty: true
|
||||
content: 'No content available.'
|
||||
plugin_id: text_custom
|
||||
arguments: { }
|
||||
relationships:
|
||||
uid:
|
||||
id: uid
|
||||
table: node_field_data
|
||||
field: uid
|
||||
admin_label: author
|
||||
required: true
|
||||
plugin_id: standard
|
||||
show_admin_links: false
|
||||
filter_groups:
|
||||
operator: AND
|
||||
groups:
|
||||
1: AND
|
||||
display_extenders: { }
|
||||
display_plugin: default
|
||||
display_title: Master
|
||||
id: default
|
||||
position: 0
|
||||
cache_metadata:
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url
|
||||
- url.query_args
|
||||
- user
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
max-age: 0
|
||||
tags: { }
|
||||
page_1:
|
||||
display_options:
|
||||
path: test-content-ajax
|
||||
menu:
|
||||
type: 'default tab'
|
||||
title: Content
|
||||
description: ''
|
||||
menu_name: admin
|
||||
weight: -10
|
||||
context: ''
|
||||
tab_options:
|
||||
type: normal
|
||||
title: Content
|
||||
description: 'Find and manage content'
|
||||
menu_name: admin
|
||||
weight: -10
|
||||
display_extenders: { }
|
||||
display_plugin: page
|
||||
display_title: Page
|
||||
id: page_1
|
||||
position: 1
|
||||
cache_metadata:
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url
|
||||
- url.query_args
|
||||
- user
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
max-age: 0
|
||||
tags: { }
|
||||
+1
-1
@@ -126,7 +126,7 @@ display:
|
||||
entity_type: node
|
||||
entity_field: nid
|
||||
status:
|
||||
field: status
|
||||
field: '1'
|
||||
id: status
|
||||
table: node_field_data
|
||||
plugin_id: boolean
|
||||
|
||||
+1
-1
@@ -109,7 +109,7 @@ display:
|
||||
hide_alter_empty: true
|
||||
filters:
|
||||
status:
|
||||
value: true
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
plugin_id: boolean
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ display:
|
||||
group: 1
|
||||
id: status
|
||||
table: node_field_data
|
||||
value: true
|
||||
value: '1'
|
||||
plugin_id: boolean
|
||||
entity_type: node
|
||||
entity_field: status
|
||||
|
||||
+1
-1
@@ -115,7 +115,7 @@ display:
|
||||
group: 1
|
||||
id: status
|
||||
table: node_field_data
|
||||
value: true
|
||||
value: '1'
|
||||
plugin_id: boolean
|
||||
entity_type: node
|
||||
entity_field: status
|
||||
|
||||
+107
-1
@@ -21,6 +21,8 @@ display:
|
||||
display_options:
|
||||
access:
|
||||
type: perm
|
||||
options:
|
||||
perm: 'access content overview'
|
||||
cache:
|
||||
type: tag
|
||||
query:
|
||||
@@ -159,6 +161,108 @@ display:
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: false
|
||||
edit_node:
|
||||
id: edit_node
|
||||
table: node
|
||||
field: edit_node
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: ''
|
||||
exclude: true
|
||||
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
|
||||
text: edit
|
||||
entity_type: node
|
||||
plugin_id: entity_link_edit
|
||||
delete_node:
|
||||
id: delete_node
|
||||
table: node
|
||||
field: delete_node
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: ''
|
||||
exclude: true
|
||||
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
|
||||
text: delete
|
||||
entity_type: node
|
||||
plugin_id: entity_link_delete
|
||||
dropbutton:
|
||||
id: dropbutton
|
||||
table: views
|
||||
@@ -211,11 +315,13 @@ display:
|
||||
fields:
|
||||
title: title
|
||||
nothing: nothing
|
||||
edit_node: edit_node
|
||||
delete_node: delete_node
|
||||
nid: '0'
|
||||
destination: true
|
||||
filters:
|
||||
status:
|
||||
value: true
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
id: status
|
||||
|
||||
+43
@@ -123,3 +123,46 @@ display:
|
||||
position: null
|
||||
display_options:
|
||||
path: test-entity-operations
|
||||
page_2:
|
||||
display_plugin: page
|
||||
id: page_2
|
||||
display_title: 'Page 2'
|
||||
position: null
|
||||
display_options:
|
||||
path: test-entity-operations-table
|
||||
style:
|
||||
type: table
|
||||
options:
|
||||
grouping: { }
|
||||
row_class: ''
|
||||
default_row_class: true
|
||||
override: true
|
||||
sticky: false
|
||||
caption: ''
|
||||
summary: ''
|
||||
description: ''
|
||||
columns:
|
||||
title: title
|
||||
operations: operations
|
||||
info:
|
||||
title:
|
||||
sortable: false
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
operations:
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
default: '-1'
|
||||
empty_table: false
|
||||
row:
|
||||
type: fields
|
||||
options: { }
|
||||
display_extenders: { }
|
||||
defaults:
|
||||
style: false
|
||||
row: false
|
||||
|
||||
+67
-1
@@ -31,7 +31,7 @@ display:
|
||||
field: type
|
||||
id: type
|
||||
table: node_field_data
|
||||
plugin_id: node_type
|
||||
plugin_id: bundle
|
||||
entity_type: node
|
||||
entity_field: type
|
||||
body_value:
|
||||
@@ -76,6 +76,72 @@ display:
|
||||
plugin_id: string
|
||||
entity_type: node
|
||||
entity_field: body
|
||||
created:
|
||||
id: created
|
||||
table: node_field_data
|
||||
field: created
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: '='
|
||||
value:
|
||||
min: ''
|
||||
max: ''
|
||||
value: ''
|
||||
type: date
|
||||
group: 1
|
||||
exposed: true
|
||||
expose:
|
||||
operator_id: created_op
|
||||
label: 'Authored on'
|
||||
description: null
|
||||
use_operator: false
|
||||
operator: created_op
|
||||
identifier: created
|
||||
required: false
|
||||
remember: false
|
||||
multiple: false
|
||||
remember_roles:
|
||||
authenticated: authenticated
|
||||
is_grouped: true
|
||||
group_info:
|
||||
label: 'Authored on'
|
||||
description: ''
|
||||
identifier: created
|
||||
optional: true
|
||||
widget: select
|
||||
multiple: false
|
||||
remember: false
|
||||
default_group: All
|
||||
default_group_multiple: { }
|
||||
group_items:
|
||||
1:
|
||||
title: Between
|
||||
operator: between
|
||||
value:
|
||||
type: date
|
||||
value: ''
|
||||
min: '2015-01-01'
|
||||
max: '2016-01-01'
|
||||
2:
|
||||
title: 'Not Between'
|
||||
operator: 'not between'
|
||||
value:
|
||||
type: date
|
||||
value: ''
|
||||
min: '2015-01-01'
|
||||
max: '2016-01-01'
|
||||
3:
|
||||
title: Equal
|
||||
operator: '='
|
||||
value:
|
||||
type: date
|
||||
value: '2016-01-01'
|
||||
min: ''
|
||||
max: ''
|
||||
entity_type: node
|
||||
entity_field: created
|
||||
plugin_id: date
|
||||
pager:
|
||||
type: full
|
||||
sorts:
|
||||
|
||||
+1
-1
@@ -224,7 +224,7 @@ display:
|
||||
plugin_id: date
|
||||
filters:
|
||||
status:
|
||||
value: true
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
plugin_id: boolean
|
||||
|
||||
+1
-1
@@ -144,7 +144,7 @@ display:
|
||||
plugin_id: field
|
||||
filters:
|
||||
status:
|
||||
value: true
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
plugin_id: boolean
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ display:
|
||||
group: 1
|
||||
id: status
|
||||
table: node_field_data
|
||||
value: true
|
||||
value: '1'
|
||||
plugin_id: boolean
|
||||
entity_type: node
|
||||
entity_field: status
|
||||
|
||||
+2
-2
@@ -65,7 +65,7 @@ display:
|
||||
group: 1
|
||||
id: status
|
||||
table: node_field_data
|
||||
value: true
|
||||
value: '1'
|
||||
plugin_id: boolean
|
||||
entity_type: node
|
||||
entity_field: status
|
||||
@@ -130,7 +130,7 @@ display:
|
||||
group: 1
|
||||
id: status
|
||||
table: node_field_data
|
||||
value: true
|
||||
value: '1'
|
||||
plugin_id: boolean
|
||||
entity_type: node
|
||||
entity_field: status
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ display:
|
||||
entity_field: title
|
||||
filters:
|
||||
status:
|
||||
value: true
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
id: status
|
||||
|
||||
+435
-41
@@ -5,56 +5,450 @@ dependencies:
|
||||
- node
|
||||
- user
|
||||
id: test_glossary
|
||||
label: test_glossary
|
||||
module: views
|
||||
description: ''
|
||||
label: Test glossary
|
||||
module: node
|
||||
description: 'All content, by letter.'
|
||||
tag: default
|
||||
base_table: node_field_data
|
||||
base_field: nid
|
||||
core: '8'
|
||||
display:
|
||||
default:
|
||||
id: default
|
||||
display_title: Master
|
||||
display_plugin: default
|
||||
position: 0
|
||||
display_options:
|
||||
access:
|
||||
type: perm
|
||||
arguments:
|
||||
title:
|
||||
default_argument_type: fixed
|
||||
field: title
|
||||
glossary: true
|
||||
id: title
|
||||
limit: 1
|
||||
summary:
|
||||
format: default_summary
|
||||
number_of_records: 0
|
||||
summary_options:
|
||||
items_per_page: 25
|
||||
table: node_field_data
|
||||
plugin_id: string
|
||||
entity_type: node
|
||||
entity_field: title
|
||||
cache:
|
||||
type: tag
|
||||
exposed_form:
|
||||
type: basic
|
||||
fields:
|
||||
title:
|
||||
field: title
|
||||
id: title
|
||||
label: ''
|
||||
table: node_field_data
|
||||
plugin_id: field
|
||||
entity_type: node
|
||||
entity_field: title
|
||||
pager:
|
||||
type: full
|
||||
query:
|
||||
type: views_query
|
||||
options:
|
||||
query_comment: ''
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
replica: false
|
||||
query_tags: { }
|
||||
use_ajax: true
|
||||
access:
|
||||
type: perm
|
||||
options:
|
||||
perm: 'access content'
|
||||
cache:
|
||||
type: tag
|
||||
options: { }
|
||||
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: 36
|
||||
offset: 0
|
||||
id: 0
|
||||
total_pages: 0
|
||||
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: ››
|
||||
fields:
|
||||
title:
|
||||
id: title
|
||||
table: node_field_data
|
||||
field: title
|
||||
plugin_id: field
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: Title
|
||||
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
|
||||
entity_type: node
|
||||
entity_field: title
|
||||
name:
|
||||
id: name
|
||||
table: users_field_data
|
||||
field: name
|
||||
label: Author
|
||||
relationship: uid
|
||||
plugin_id: field
|
||||
type: user_name
|
||||
group_type: group
|
||||
admin_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
|
||||
entity_type: user
|
||||
entity_field: name
|
||||
changed:
|
||||
id: changed
|
||||
table: node_field_data
|
||||
field: changed
|
||||
label: 'Last update'
|
||||
type: timestamp
|
||||
settings:
|
||||
date_format: long
|
||||
custom_date_format: ''
|
||||
timezone: ''
|
||||
plugin_id: field
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_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
|
||||
entity_type: node
|
||||
entity_field: changed
|
||||
arguments:
|
||||
title:
|
||||
id: title
|
||||
table: node_field_data
|
||||
field: title
|
||||
default_action: default
|
||||
exception:
|
||||
title_enable: true
|
||||
default_argument_type: fixed
|
||||
default_argument_options:
|
||||
argument: a
|
||||
summary:
|
||||
format: default_summary
|
||||
specify_validation: true
|
||||
glossary: true
|
||||
limit: 1
|
||||
case: upper
|
||||
path_case: lower
|
||||
transform_dash: false
|
||||
plugin_id: string
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
title_enable: false
|
||||
title: ''
|
||||
default_argument_skip_url: false
|
||||
summary_options: { }
|
||||
validate:
|
||||
type: none
|
||||
fail: 'not found'
|
||||
validate_options: { }
|
||||
break_phrase: false
|
||||
entity_type: node
|
||||
entity_field: title
|
||||
relationships:
|
||||
uid:
|
||||
id: uid
|
||||
table: node_field_data
|
||||
field: uid
|
||||
plugin_id: standard
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: author
|
||||
required: false
|
||||
style:
|
||||
type: default
|
||||
type: table
|
||||
options:
|
||||
columns:
|
||||
title: title
|
||||
name: name
|
||||
changed: changed
|
||||
default: title
|
||||
info:
|
||||
title:
|
||||
sortable: true
|
||||
separator: ''
|
||||
name:
|
||||
sortable: true
|
||||
separator: ''
|
||||
changed:
|
||||
sortable: true
|
||||
separator: ''
|
||||
override: true
|
||||
sticky: false
|
||||
grouping: { }
|
||||
row_class: ''
|
||||
default_row_class: true
|
||||
uses_fields: false
|
||||
order: asc
|
||||
summary: ''
|
||||
empty_table: false
|
||||
row:
|
||||
type: fields
|
||||
display_plugin: default
|
||||
display_title: Master
|
||||
id: default
|
||||
position: 0
|
||||
options:
|
||||
inline: { }
|
||||
separator: ''
|
||||
hide_empty: false
|
||||
default_field_elements: true
|
||||
header: { }
|
||||
footer: { }
|
||||
empty: { }
|
||||
sorts: { }
|
||||
filters:
|
||||
langcode:
|
||||
id: langcode
|
||||
table: node_field_data
|
||||
field: langcode
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: in
|
||||
value:
|
||||
'***LANGUAGE_language_content***': '***LANGUAGE_language_content***'
|
||||
group: 1
|
||||
exposed: false
|
||||
expose:
|
||||
operator_id: ''
|
||||
label: ''
|
||||
description: ''
|
||||
use_operator: false
|
||||
operator: ''
|
||||
identifier: ''
|
||||
required: false
|
||||
remember: false
|
||||
multiple: false
|
||||
remember_roles:
|
||||
authenticated: authenticated
|
||||
reduce: false
|
||||
is_grouped: false
|
||||
group_info:
|
||||
label: ''
|
||||
description: ''
|
||||
identifier: ''
|
||||
optional: true
|
||||
widget: select
|
||||
multiple: false
|
||||
remember: false
|
||||
default_group: All
|
||||
default_group_multiple: { }
|
||||
group_items: { }
|
||||
plugin_id: language
|
||||
entity_type: node
|
||||
entity_field: langcode
|
||||
display_extenders: { }
|
||||
cache_metadata:
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url
|
||||
- url.query_args
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
max-age: 0
|
||||
tags: { }
|
||||
attachment_1:
|
||||
id: attachment_1
|
||||
display_title: Attachment
|
||||
display_plugin: attachment
|
||||
position: 2
|
||||
display_options:
|
||||
query:
|
||||
type: views_query
|
||||
options: { }
|
||||
pager:
|
||||
type: none
|
||||
options:
|
||||
offset: 0
|
||||
items_per_page: 0
|
||||
defaults:
|
||||
arguments: false
|
||||
arguments:
|
||||
title:
|
||||
id: title
|
||||
table: node_field_data
|
||||
field: title
|
||||
default_action: summary
|
||||
exception:
|
||||
title_enable: true
|
||||
default_argument_type: fixed
|
||||
default_argument_options:
|
||||
argument: a
|
||||
summary:
|
||||
format: unformatted_summary
|
||||
summary_options:
|
||||
items_per_page: 25
|
||||
inline: true
|
||||
separator: ' | '
|
||||
specify_validation: true
|
||||
glossary: true
|
||||
limit: 1
|
||||
case: upper
|
||||
path_case: lower
|
||||
transform_dash: false
|
||||
plugin_id: string
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
title_enable: false
|
||||
title: ''
|
||||
default_argument_skip_url: false
|
||||
validate:
|
||||
type: none
|
||||
fail: 'not found'
|
||||
validate_options: { }
|
||||
break_phrase: false
|
||||
entity_type: node
|
||||
entity_field: title
|
||||
displays:
|
||||
default: default
|
||||
page_1: page_1
|
||||
inherit_arguments: false
|
||||
display_extenders: { }
|
||||
cache_metadata:
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url
|
||||
- url.query_args
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
max-age: 0
|
||||
tags: { }
|
||||
page_1:
|
||||
id: page_1
|
||||
display_title: Page
|
||||
display_plugin: page
|
||||
position: 1
|
||||
display_options:
|
||||
query:
|
||||
type: views_query
|
||||
options: { }
|
||||
path: test-glossary
|
||||
menu:
|
||||
type: normal
|
||||
title: Glossary
|
||||
weight: 0
|
||||
menu_name: main
|
||||
parent: ''
|
||||
display_extenders: { }
|
||||
cache_metadata:
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url
|
||||
- url.query_args
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
max-age: 0
|
||||
tags: { }
|
||||
|
||||
+2
-2
@@ -107,7 +107,7 @@ display:
|
||||
comments: false
|
||||
filters:
|
||||
status:
|
||||
value: true
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
plugin_id: boolean
|
||||
@@ -152,7 +152,7 @@ display:
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: '='
|
||||
value: true
|
||||
value: '1'
|
||||
group: 1
|
||||
exposed: false
|
||||
expose:
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ display:
|
||||
entity_field: title
|
||||
filters:
|
||||
status:
|
||||
value: true
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
id: status
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies: { }
|
||||
id: test_invalid_tokens
|
||||
label: 'Test invalid tokens'
|
||||
module: views
|
||||
description: 'Test view to invalid token replacement tests.'
|
||||
tag: ''
|
||||
base_table: views_test_data
|
||||
base_field: id
|
||||
core: 8.x
|
||||
display:
|
||||
default:
|
||||
display_options:
|
||||
title: 'Test token default'
|
||||
defaults:
|
||||
fields: false
|
||||
pager: false
|
||||
sorts: false
|
||||
fields:
|
||||
age:
|
||||
field: age
|
||||
id: age
|
||||
relationship: none
|
||||
table: views_test_data
|
||||
plugin_id: numeric
|
||||
id:
|
||||
field: id
|
||||
id: id
|
||||
relationship: none
|
||||
table: views_test_data
|
||||
plugin_id: numeric
|
||||
name:
|
||||
field: name
|
||||
id: name
|
||||
relationship: none
|
||||
table: views_test_data
|
||||
plugin_id: string
|
||||
pager:
|
||||
type: full
|
||||
options:
|
||||
items_per_page: 10
|
||||
display_plugin: default
|
||||
display_title: Master
|
||||
id: default
|
||||
position: 0
|
||||
block_1:
|
||||
display_plugin: block
|
||||
id: block_1
|
||||
display_title: Block
|
||||
position: 1
|
||||
display_options:
|
||||
display_extenders: { }
|
||||
+23
@@ -118,3 +118,26 @@ display:
|
||||
type: mini
|
||||
options:
|
||||
items_per_page: 0
|
||||
page_4:
|
||||
display_plugin: page
|
||||
id: page_4
|
||||
display_title: 'Page 4'
|
||||
position: 4
|
||||
display_options:
|
||||
display_extenders: { }
|
||||
path: test_mini_pager_total
|
||||
empty: { }
|
||||
defaults:
|
||||
empty: false
|
||||
header: false
|
||||
header:
|
||||
result:
|
||||
id: result
|
||||
table: views
|
||||
field: result
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
empty: false
|
||||
content: 'Displaying @start - @end of @total'
|
||||
plugin_id: result
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ display:
|
||||
entity_field: title
|
||||
filters:
|
||||
status:
|
||||
value: true
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
id: status
|
||||
|
||||
+1
-1
@@ -464,7 +464,7 @@ display:
|
||||
plugin_id: entity_operations
|
||||
filters:
|
||||
status:
|
||||
value: true
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
plugin_id: boolean
|
||||
|
||||
+1
-1
@@ -464,7 +464,7 @@ display:
|
||||
plugin_id: entity_operations
|
||||
filters:
|
||||
status:
|
||||
value: true
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
plugin_id: boolean
|
||||
|
||||
+3
-3
@@ -97,7 +97,7 @@ display:
|
||||
link_to_entity: true
|
||||
filters:
|
||||
status:
|
||||
value: true
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
id: status
|
||||
@@ -135,7 +135,7 @@ display:
|
||||
display_description: ''
|
||||
filters:
|
||||
status:
|
||||
value: true
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
id: status
|
||||
@@ -200,7 +200,7 @@ display:
|
||||
display_description: ''
|
||||
filters:
|
||||
status:
|
||||
value: true
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
id: status
|
||||
|
||||
-1
@@ -96,7 +96,6 @@ display:
|
||||
footer: { }
|
||||
empty: { }
|
||||
relationships: { }
|
||||
fields: { }
|
||||
display_extenders: { }
|
||||
cache_metadata:
|
||||
contexts:
|
||||
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- taxonomy
|
||||
id: test_taxonomy_glossary
|
||||
label: test_taxonomy_glossary
|
||||
module: views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: taxonomy_term_field_data
|
||||
base_field: tid
|
||||
core: 8.x
|
||||
display:
|
||||
default:
|
||||
display_plugin: default
|
||||
id: default
|
||||
display_title: Master
|
||||
position: 0
|
||||
display_options:
|
||||
access:
|
||||
type: none
|
||||
options: { }
|
||||
cache:
|
||||
type: tag
|
||||
options: { }
|
||||
query:
|
||||
type: views_query
|
||||
options:
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
replica: false
|
||||
query_comment: ''
|
||||
query_tags: { }
|
||||
exposed_form:
|
||||
type: basic
|
||||
options:
|
||||
submit_button: Apply
|
||||
reset_button: false
|
||||
reset_button_label: Reset
|
||||
exposed_sorts_label: 'Sort by'
|
||||
expose_sort_order: true
|
||||
sort_asc_label: Asc
|
||||
sort_desc_label: Desc
|
||||
pager:
|
||||
type: mini
|
||||
options:
|
||||
items_per_page: 10
|
||||
offset: 0
|
||||
id: 0
|
||||
total_pages: null
|
||||
expose:
|
||||
items_per_page: false
|
||||
items_per_page_label: 'Items per page'
|
||||
items_per_page_options: '5, 10, 25, 50'
|
||||
items_per_page_options_all: false
|
||||
items_per_page_options_all_label: '- All -'
|
||||
offset: false
|
||||
offset_label: Offset
|
||||
tags:
|
||||
previous: ‹‹
|
||||
next: ››
|
||||
style:
|
||||
type: default
|
||||
row:
|
||||
type: fields
|
||||
fields:
|
||||
name:
|
||||
id: name
|
||||
table: taxonomy_term_field_data
|
||||
field: name
|
||||
entity_type: taxonomy_term
|
||||
entity_field: name
|
||||
label: ''
|
||||
alter:
|
||||
alter_text: false
|
||||
make_link: false
|
||||
absolute: false
|
||||
trim: false
|
||||
word_boundary: false
|
||||
ellipsis: false
|
||||
strip_tags: false
|
||||
html: false
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
type: string
|
||||
settings:
|
||||
link_to_entity: true
|
||||
plugin_id: term_name
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
exclude: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: true
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_alter_empty: true
|
||||
click_sort_column: value
|
||||
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
|
||||
convert_spaces: false
|
||||
filters: { }
|
||||
sorts: { }
|
||||
title: test_taxonomy_glossary
|
||||
header: { }
|
||||
footer: { }
|
||||
empty: { }
|
||||
relationships: { }
|
||||
arguments:
|
||||
name:
|
||||
id: name
|
||||
table: taxonomy_term_field_data
|
||||
field: name
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
default_action: ignore
|
||||
exception:
|
||||
value: all
|
||||
title_enable: false
|
||||
title: All
|
||||
title_enable: false
|
||||
title: ''
|
||||
default_argument_type: fixed
|
||||
default_argument_options:
|
||||
argument: ''
|
||||
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: { }
|
||||
glossary: true
|
||||
limit: 1
|
||||
case: none
|
||||
path_case: none
|
||||
transform_dash: false
|
||||
break_phrase: false
|
||||
add_table: false
|
||||
require_value: false
|
||||
entity_type: taxonomy_term
|
||||
entity_field: name
|
||||
plugin_id: string
|
||||
display_extenders: { }
|
||||
cache_metadata:
|
||||
max-age: -1
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url
|
||||
- url.query_args
|
||||
tags: { }
|
||||
page_1:
|
||||
display_plugin: page
|
||||
id: page_1
|
||||
display_title: Page
|
||||
position: 1
|
||||
display_options:
|
||||
display_extenders: { }
|
||||
path: test_taxonomy_glossary
|
||||
cache_metadata:
|
||||
max-age: -1
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url
|
||||
- url.query_args
|
||||
tags: { }
|
||||
+1
-1
@@ -151,7 +151,7 @@ display:
|
||||
plugin_id: field
|
||||
filters:
|
||||
status:
|
||||
value: true
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
plugin_id: boolean
|
||||
|
||||
+31
@@ -77,3 +77,34 @@ display:
|
||||
operator: '='
|
||||
value: 'not an existing name'
|
||||
path: test_tokens_empty
|
||||
page_3:
|
||||
display_plugin: page
|
||||
id: page_3
|
||||
display_title: Page
|
||||
position: 1
|
||||
display_options:
|
||||
defaults:
|
||||
title: false
|
||||
pager: false
|
||||
header: false
|
||||
pager:
|
||||
type: mini
|
||||
options:
|
||||
items_per_page: 2
|
||||
title: 'Test token page with minipager'
|
||||
path: test_tokens_minipager
|
||||
display_extenders: { }
|
||||
header:
|
||||
area:
|
||||
id: area
|
||||
table: views
|
||||
field: area
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
empty: false
|
||||
tokenize: false
|
||||
content:
|
||||
value: "Total rows: [view:total-rows] - Page count: [view:page-count]"
|
||||
format: basic_html
|
||||
plugin_id: text
|
||||
|
||||
@@ -7,8 +7,8 @@ package: Testing
|
||||
dependencies:
|
||||
- views
|
||||
|
||||
# Information added by Drupal.org packaging script on 2016-08-03
|
||||
version: '8.1.8'
|
||||
# Information added by Drupal.org packaging script on 2017-08-16
|
||||
version: '8.3.7'
|
||||
core: '8.x'
|
||||
project: 'drupal'
|
||||
datestamp: 1470233790
|
||||
datestamp: 1502903957
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\views_test_data\Controller;
|
||||
|
||||
/**
|
||||
* Controller class for views_test_data callbacks.
|
||||
*/
|
||||
class ViewsTestDataController {
|
||||
|
||||
/**
|
||||
* Renders an error form page.
|
||||
*
|
||||
* This contains a form that will contain an error and an embedded view with
|
||||
* an exposed form.
|
||||
*/
|
||||
public function errorFormPage() {
|
||||
$build = [];
|
||||
$build['view'] = [
|
||||
'#type' => 'view',
|
||||
'#name' => 'test_exposed_form_buttons',
|
||||
];
|
||||
$build['error_form'] = \Drupal::formBuilder()->getForm('Drupal\views_test_data\Form\ViewsTestDataErrorForm');
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
}
|
||||
+3
-3
@@ -21,13 +21,13 @@ class ViewsTestDataElementEmbedForm extends FormBase {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$form['view'] = array(
|
||||
$form['view'] = [
|
||||
'#type' => 'view',
|
||||
'#name' => 'test_view_embed',
|
||||
'#display_id' => 'embed_1',
|
||||
'#arguments' => array(25),
|
||||
'#arguments' => [25],
|
||||
'#embed' => TRUE,
|
||||
);
|
||||
];
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
+3
-3
@@ -21,13 +21,13 @@ class ViewsTestDataElementForm extends FormBase {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$form['view'] = array(
|
||||
$form['view'] = [
|
||||
'#type' => 'view',
|
||||
'#name' => 'test_view_embed',
|
||||
'#display_id' => 'default',
|
||||
'#arguments' => array(25),
|
||||
'#arguments' => [25],
|
||||
'#embed' => FALSE,
|
||||
);
|
||||
];
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\views_test_data\Form;
|
||||
|
||||
use Drupal\Core\Form\FormInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Implements a test form that has a validation error.
|
||||
*/
|
||||
class ViewsTestDataErrorForm implements FormInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'views_test_data_error_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$form['text'] = [
|
||||
'#type' => 'textfield',
|
||||
];
|
||||
$form['submit'] = [
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Submit'),
|
||||
];
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateForm(array &$form, FormStateInterface $form_state) {
|
||||
$form_state->setErrorByName('text', t('Form validation error'));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -19,7 +19,7 @@ class StaticTest extends AccessPluginBase {
|
||||
|
||||
protected function defineOptions() {
|
||||
$options = parent::defineOptions();
|
||||
$options['access'] = array('default' => FALSE);
|
||||
$options['access'] = ['default' => FALSE];
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
+5
-5
@@ -27,8 +27,8 @@ class TestExample extends AreaPluginBase {
|
||||
*/
|
||||
public function defineOptions() {
|
||||
$options = parent::defineOptions();
|
||||
$options['string'] = array('default' => '');
|
||||
$options['custom_access'] = array('default' => TRUE);
|
||||
$options['string'] = ['default' => ''];
|
||||
$options['custom_access'] = ['default' => TRUE];
|
||||
|
||||
return $options;
|
||||
}
|
||||
@@ -46,11 +46,11 @@ class TestExample extends AreaPluginBase {
|
||||
*/
|
||||
public function render($empty = FALSE) {
|
||||
if (!$empty || !empty($this->options['empty'])) {
|
||||
return array(
|
||||
return [
|
||||
'#markup' => $this->globalTokenReplace($this->options['string']),
|
||||
);
|
||||
];
|
||||
}
|
||||
return array();
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-1
@@ -19,7 +19,7 @@ class ArgumentDefaultTest extends ArgumentDefaultPluginBase {
|
||||
*/
|
||||
protected function defineOptions() {
|
||||
$options = parent::defineOptions();
|
||||
$options['value'] = array('default' => '');
|
||||
$options['value'] = ['default' => ''];
|
||||
|
||||
return $options;
|
||||
}
|
||||
@@ -28,6 +28,7 @@ class ArgumentDefaultTest extends ArgumentDefaultPluginBase {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getArgument() {
|
||||
$this->view->element['#cache']['tags'][] = 'example_tag';
|
||||
return $this->options['value'];
|
||||
}
|
||||
|
||||
|
||||
+9
-9
@@ -39,7 +39,7 @@ class DisplayTest extends DisplayPluginBase {
|
||||
*/
|
||||
protected function defineOptions() {
|
||||
$options = parent::defineOptions();
|
||||
$options['test_option'] = array('default' => '');
|
||||
$options['test_option'] = ['default' => ''];
|
||||
|
||||
return $options;
|
||||
}
|
||||
@@ -50,21 +50,21 @@ class DisplayTest extends DisplayPluginBase {
|
||||
public function optionsSummary(&$categories, &$options) {
|
||||
parent::optionsSummary($categories, $options);
|
||||
|
||||
$categories['display_test'] = array(
|
||||
$categories['display_test'] = [
|
||||
'title' => $this->t('Display test settings'),
|
||||
'column' => 'second',
|
||||
'build' => array(
|
||||
'build' => [
|
||||
'#weight' => -100,
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
|
||||
$test_option = $this->getOption('test_option') ?: $this->t('Empty');
|
||||
|
||||
$options['test_option'] = array(
|
||||
$options['test_option'] = [
|
||||
'category' => 'display_test',
|
||||
'title' => $this->t('Test option'),
|
||||
'value' => views_ui_truncate($test_option, 24),
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,12 +76,12 @@ class DisplayTest extends DisplayPluginBase {
|
||||
switch ($form_state->get('section')) {
|
||||
case 'test_option':
|
||||
$form['#title'] .= $this->t('Test option');
|
||||
$form['test_option'] = array(
|
||||
$form['test_option'] = [
|
||||
'#title' => $this->t('Test option'),
|
||||
'#type' => 'textfield',
|
||||
'#description' => $this->t('This is a textfield for test_option.'),
|
||||
'#default_value' => $this->getOption('test_option'),
|
||||
);
|
||||
];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+9
-9
@@ -39,19 +39,19 @@ class DisplayExtenderTest extends DisplayExtenderPluginBase {
|
||||
public function optionsSummary(&$categories, &$options) {
|
||||
parent::optionsSummary($categories, $options);
|
||||
|
||||
$categories['display_extender_test'] = array(
|
||||
$categories['display_extender_test'] = [
|
||||
'title' => $this->t('Display extender test settings'),
|
||||
'column' => 'second',
|
||||
'build' => array(
|
||||
'build' => [
|
||||
'#weight' => -100,
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
|
||||
$options['test_extender_test_option'] = array(
|
||||
$options['test_extender_test_option'] = [
|
||||
'category' => 'display_extender_test',
|
||||
'title' => $this->t('Test option'),
|
||||
'value' => views_ui_truncate($this->options['test_extender_test_option'], 24),
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,12 +61,12 @@ class DisplayExtenderTest extends DisplayExtenderPluginBase {
|
||||
switch ($form_state->get('section')) {
|
||||
case 'test_extender_test_option':
|
||||
$form['#title'] .= $this->t('Test option');
|
||||
$form['test_extender_test_option'] = array(
|
||||
$form['test_extender_test_option'] = [
|
||||
'#title' => $this->t('Test option'),
|
||||
'#type' => 'textfield',
|
||||
'#description' => $this->t('This is a textfield for test_option.'),
|
||||
'#default_value' => $this->options['test_extender_test_option'],
|
||||
);
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ class DisplayExtenderTest extends DisplayExtenderPluginBase {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defaultableSections(&$sections, $section = NULL) {
|
||||
$sections['test_extender_test_option'] = array('test_extender_test_option');
|
||||
$sections['test_extender_test_option'] = ['test_extender_test_option'];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\views_test_data\Plugin\views\filter;
|
||||
|
||||
use Drupal\views\Plugin\views\filter\BooleanOperator;
|
||||
|
||||
/**
|
||||
* Filter to test queryOpBoolean() with default operator.
|
||||
*
|
||||
* @ingroup views_filter_handlers
|
||||
*
|
||||
* @ViewsFilter("boolean_default")
|
||||
*/
|
||||
class FilterBooleanOperatorDefaultTest extends BooleanOperator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
$this->ensureMyTable();
|
||||
$field = "$this->tableAlias.$this->realField";
|
||||
$this->queryOpBoolean($field);
|
||||
}
|
||||
|
||||
}
|
||||
+3
-3
@@ -18,7 +18,7 @@ class FilterTest extends FilterPluginBase {
|
||||
protected function defineOptions() {
|
||||
$options = parent::defineOptions();
|
||||
|
||||
$options['test_enable'] = array('default' => TRUE);
|
||||
$options['test_enable'] = ['default' => TRUE];
|
||||
return $options;
|
||||
}
|
||||
|
||||
@@ -30,11 +30,11 @@ class FilterTest extends FilterPluginBase {
|
||||
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
|
||||
parent::buildOptionsForm($form, $form_state);
|
||||
|
||||
$form['test_enable'] = array(
|
||||
$form['test_enable'] = [
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Controls whether the filter plugin should be active'),
|
||||
'#default_value' => $this->options['test_enable'],
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+14
-14
@@ -18,17 +18,17 @@ use Drupal\views\ViewExecutable;
|
||||
* )
|
||||
*/
|
||||
class QueryTest extends QueryPluginBase {
|
||||
protected $conditions = array();
|
||||
protected $fields = array();
|
||||
protected $allItems = array();
|
||||
protected $orderBy = array();
|
||||
protected $conditions = [];
|
||||
protected $fields = [];
|
||||
protected $allItems = [];
|
||||
protected $orderBy = [];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function defineOptions() {
|
||||
$options = parent::defineOptions();
|
||||
$options['test_setting'] = array('default' => '');
|
||||
$options['test_setting'] = ['default' => ''];
|
||||
|
||||
return $options;
|
||||
}
|
||||
@@ -39,11 +39,11 @@ class QueryTest extends QueryPluginBase {
|
||||
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
|
||||
parent::buildOptionsForm($form, $form_state);
|
||||
|
||||
$form['test_setting'] = array(
|
||||
$form['test_setting'] = [
|
||||
'#title' => $this->t('Test setting'),
|
||||
'#type' => 'textfield',
|
||||
'#default_value' => $this->options['test_setting'],
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,21 +57,21 @@ class QueryTest extends QueryPluginBase {
|
||||
}
|
||||
|
||||
public function addWhere($group, $field, $value = NULL, $operator = NULL) {
|
||||
$this->conditions[] = array(
|
||||
$this->conditions[] = [
|
||||
'field' => $field,
|
||||
'value' => $value,
|
||||
'operator' => $operator
|
||||
);
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
public function addField($table, $field, $alias = '', $params = array()) {
|
||||
public function addField($table, $field, $alias = '', $params = []) {
|
||||
$this->fields[$field] = $field;
|
||||
return $field;
|
||||
}
|
||||
|
||||
public function addOrderBy($table, $field = NULL, $order = 'ASC', $alias = '', $params = array()) {
|
||||
$this->orderBy = array('field' => $field, 'order' => $order);
|
||||
public function addOrderBy($table, $field = NULL, $order = 'ASC', $alias = '', $params = []) {
|
||||
$this->orderBy = ['field' => $field, 'order' => $order];
|
||||
}
|
||||
|
||||
|
||||
@@ -90,13 +90,13 @@ class QueryTest extends QueryPluginBase {
|
||||
// @todo You could add a string representation of the query.
|
||||
$this->view->build_info['query'] = "";
|
||||
$this->view->build_info['count_query'] = "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function execute(ViewExecutable $view) {
|
||||
$result = array();
|
||||
$result = [];
|
||||
foreach ($this->allItems as $element) {
|
||||
// Run all conditions on the element, and add it to the result if they
|
||||
// match.
|
||||
|
||||
@@ -32,7 +32,7 @@ class RowTest extends RowPluginBase {
|
||||
*/
|
||||
protected function defineOptions() {
|
||||
$options = parent::defineOptions();
|
||||
$options['test_option'] = array('default' => '');
|
||||
$options['test_option'] = ['default' => ''];
|
||||
|
||||
return $options;
|
||||
}
|
||||
@@ -43,12 +43,12 @@ class RowTest extends RowPluginBase {
|
||||
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
|
||||
parent::buildOptionsForm($form, $form_state);
|
||||
|
||||
$form['test_option'] = array(
|
||||
$form['test_option'] = [
|
||||
'#title' => $this->t('Test option'),
|
||||
'#type' => 'textfield',
|
||||
'#description' => $this->t('This is a textfield for test_option.'),
|
||||
'#default_value' => $this->options['test_option'],
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+8
-8
@@ -24,26 +24,26 @@ class MappingTest extends Mapping {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function defineMapping() {
|
||||
return array(
|
||||
'title_field' => array(
|
||||
return [
|
||||
'title_field' => [
|
||||
'#title' => $this->t('Title field'),
|
||||
'#description' => $this->t('Choose the field with the custom title.'),
|
||||
'#toggle' => TRUE,
|
||||
'#required' => TRUE,
|
||||
),
|
||||
'name_field' => array(
|
||||
],
|
||||
'name_field' => [
|
||||
'#title' => $this->t('Name field'),
|
||||
'#description' => $this->t('Choose the field with the custom name.'),
|
||||
),
|
||||
'numeric_field' => array(
|
||||
],
|
||||
'numeric_field' => [
|
||||
'#title' => $this->t('Numeric field'),
|
||||
'#description' => $this->t('Select one or more numeric fields.'),
|
||||
'#multiple' => TRUE,
|
||||
'#toggle' => TRUE,
|
||||
'#filter' => 'filterNumericFields',
|
||||
'#required' => TRUE,
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-3
@@ -20,9 +20,7 @@ use Drupal\views\Plugin\views\style\StylePluginBase;
|
||||
class StyleTemplateTest extends StylePluginBase {
|
||||
|
||||
/**
|
||||
* Can the style plugin use row plugins.
|
||||
*
|
||||
* @var bool
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $usesRowPlugin = TRUE;
|
||||
|
||||
|
||||
+4
-6
@@ -29,9 +29,7 @@ class StyleTest extends StylePluginBase {
|
||||
public $output;
|
||||
|
||||
/**
|
||||
* Can the style plugin use row plugins.
|
||||
*
|
||||
* @var bool
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $usesRowPlugin = TRUE;
|
||||
|
||||
@@ -40,7 +38,7 @@ class StyleTest extends StylePluginBase {
|
||||
*/
|
||||
protected function defineOptions() {
|
||||
$options = parent::defineOptions();
|
||||
$options['test_option'] = array('default' => '');
|
||||
$options['test_option'] = ['default' => ''];
|
||||
|
||||
return $options;
|
||||
}
|
||||
@@ -51,12 +49,12 @@ class StyleTest extends StylePluginBase {
|
||||
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
|
||||
parent::buildOptionsForm($form, $form_state);
|
||||
|
||||
$form['test_option'] = array(
|
||||
$form['test_option'] = [
|
||||
'#title' => $this->t('Test option'),
|
||||
'#type' => 'textfield',
|
||||
'#description' => $this->t('This is a textfield for test_option.'),
|
||||
'#default_value' => $this->options['test_option'],
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,8 +7,8 @@ package: Testing
|
||||
dependencies:
|
||||
- views
|
||||
|
||||
# Information added by Drupal.org packaging script on 2016-08-03
|
||||
version: '8.1.8'
|
||||
# Information added by Drupal.org packaging script on 2017-08-16
|
||||
version: '8.3.7'
|
||||
core: '8.x'
|
||||
project: 'drupal'
|
||||
datestamp: 1470233790
|
||||
datestamp: 1502903957
|
||||
|
||||
@@ -17,7 +17,7 @@ function views_test_data_schema() {
|
||||
*/
|
||||
function views_test_data_install() {
|
||||
// Add the marquee tag to possible html elements to test the field handler.
|
||||
$values = array(
|
||||
$values = [
|
||||
'div' => 'DIV',
|
||||
'span' => 'SPAN',
|
||||
'h1' => 'H1',
|
||||
@@ -30,6 +30,6 @@ function views_test_data_install() {
|
||||
'strong' => 'STRONG',
|
||||
'em' => 'EM',
|
||||
'marquee' => 'MARQUEE'
|
||||
);
|
||||
];
|
||||
\Drupal::configFactory()->getEditable('views.settings')->set('field_rewrite_elements', $values)->save();
|
||||
}
|
||||
|
||||
@@ -66,13 +66,13 @@ function views_test_data_preprocess_views_view_table(&$variables) {
|
||||
* - view: The view object.
|
||||
*/
|
||||
function template_preprocess_views_view_mapping_test(&$variables) {
|
||||
$variables['element'] = array();
|
||||
$variables['element'] = [];
|
||||
|
||||
foreach ($variables['rows'] as $delta => $row) {
|
||||
$fields = array();
|
||||
$fields = [];
|
||||
foreach ($variables['options']['mapping'] as $type => $field_names) {
|
||||
if (!is_array($field_names)) {
|
||||
$field_names = array($field_names);
|
||||
$field_names = [$field_names];
|
||||
}
|
||||
foreach ($field_names as $field_name) {
|
||||
if ($value = $variables['view']->style_plugin->getField($delta, $field_name)) {
|
||||
@@ -87,26 +87,26 @@ function template_preprocess_views_view_mapping_test(&$variables) {
|
||||
}
|
||||
|
||||
// Build a container for the row.
|
||||
$variables['element'][$delta] = array(
|
||||
$variables['element'][$delta] = [
|
||||
'#type' => 'container',
|
||||
'#attributes' => array(
|
||||
'class' => array(
|
||||
'#attributes' => [
|
||||
'class' => [
|
||||
'views-row-mapping-test',
|
||||
),
|
||||
),
|
||||
);
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// Add each field to the row.
|
||||
foreach ($fields as $key => $render) {
|
||||
$variables['element'][$delta][$key] = array(
|
||||
$variables['element'][$delta][$key] = [
|
||||
'#children' => $render,
|
||||
'#type' => 'container',
|
||||
'#attributes' => array(
|
||||
'class' => array(
|
||||
'#attributes' => [
|
||||
'class' => [
|
||||
$key,
|
||||
),
|
||||
),
|
||||
);
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,3 +19,11 @@ views_test_data.form_multiple:
|
||||
_controller: '\Drupal\views_test_data\Controller\ViewsTestFormMultipleController::testPage'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
views_test_data.error_form_page:
|
||||
path: '/views_test_data_error_form_page'
|
||||
defaults:
|
||||
_title: 'Test Views Form Exposed Errors'
|
||||
_controller: '\Drupal\views_test_data\Controller\ViewsTestDataController::errorFormPage'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
@@ -39,7 +39,7 @@ function views_test_data_views_data_alter() {
|
||||
function views_test_data_views_analyze(ViewExecutable $view) {
|
||||
\Drupal::state()->set('views_hook_test_views_analyze', TRUE);
|
||||
|
||||
$ret = array();
|
||||
$ret = [];
|
||||
|
||||
$ret[] = Analyzer::formatMessage(t('Test ok message'), 'ok');
|
||||
$ret[] = Analyzer::formatMessage(t('Test warning message'), 'warning');
|
||||
|
||||
+2
-2
@@ -22,10 +22,10 @@ function views_test_data_views_query_substitutions(ViewExecutable $view) {
|
||||
function views_test_data_views_form_substitutions() {
|
||||
\Drupal::state()->set('views_hook_test_views_form_substitutions', TRUE);
|
||||
$render = ['#markup' => '<em>unescaped</em>'];
|
||||
return array(
|
||||
return [
|
||||
'<!--will-be-escaped-->' => '<em>escaped</em>',
|
||||
'<!--will-be-not-escaped-->' => \Drupal::service('renderer')->renderPlain($render),
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,8 +7,8 @@ package: Testing
|
||||
dependencies:
|
||||
- views
|
||||
|
||||
# Information added by Drupal.org packaging script on 2016-08-03
|
||||
version: '8.1.8'
|
||||
# Information added by Drupal.org packaging script on 2017-08-16
|
||||
version: '8.3.7'
|
||||
core: '8.x'
|
||||
project: 'drupal'
|
||||
datestamp: 1470233790
|
||||
datestamp: 1502903957
|
||||
|
||||
@@ -8,8 +8,8 @@ dependencies:
|
||||
- views
|
||||
- language
|
||||
|
||||
# Information added by Drupal.org packaging script on 2016-08-03
|
||||
version: '8.1.8'
|
||||
# Information added by Drupal.org packaging script on 2017-08-16
|
||||
version: '8.3.7'
|
||||
core: '8.x'
|
||||
project: 'drupal'
|
||||
datestamp: 1470233790
|
||||
datestamp: 1502903957
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional;
|
||||
|
||||
use Drupal\comment\CommentInterface;
|
||||
use Drupal\comment\Tests\CommentTestTrait;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
|
||||
use Drupal\views\Views;
|
||||
use Drupal\comment\Entity\Comment;
|
||||
use Drupal\taxonomy\Entity\Vocabulary;
|
||||
use Drupal\taxonomy\Entity\Term;
|
||||
|
||||
/**
|
||||
* Tests the default views provided by views.
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class DefaultViewsTest extends ViewTestBase {
|
||||
|
||||
use CommentTestTrait;
|
||||
use EntityReferenceTestTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['views', 'node', 'search', 'comment', 'taxonomy', 'block', 'user'];
|
||||
|
||||
/**
|
||||
* An array of argument arrays to use for default views.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $viewArgMap = [
|
||||
'backlinks' => [1],
|
||||
'taxonomy_term' => [1],
|
||||
'glossary' => ['all'],
|
||||
];
|
||||
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
|
||||
// Create Basic page node type.
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
|
||||
$vocabulary = Vocabulary::create([
|
||||
'name' => $this->randomMachineName(),
|
||||
'description' => $this->randomMachineName(),
|
||||
'vid' => Unicode::strtolower($this->randomMachineName()),
|
||||
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
||||
'help' => '',
|
||||
'nodes' => ['page' => 'page'],
|
||||
'weight' => mt_rand(0, 10),
|
||||
]);
|
||||
$vocabulary->save();
|
||||
|
||||
// Create a field.
|
||||
$field_name = Unicode::strtolower($this->randomMachineName());
|
||||
|
||||
$handler_settings = [
|
||||
'target_bundles' => [
|
||||
$vocabulary->id() => $vocabulary->id(),
|
||||
],
|
||||
'auto_create' => TRUE,
|
||||
];
|
||||
$this->createEntityReferenceField('node', 'page', $field_name, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
|
||||
|
||||
// Create a time in the past for the archive.
|
||||
$time = REQUEST_TIME - 3600;
|
||||
|
||||
$this->addDefaultCommentField('node', 'page');
|
||||
|
||||
for ($i = 0; $i <= 10; $i++) {
|
||||
$user = $this->drupalCreateUser();
|
||||
$term = $this->createTerm($vocabulary);
|
||||
|
||||
$values = ['created' => $time, 'type' => 'page'];
|
||||
$values[$field_name][]['target_id'] = $term->id();
|
||||
|
||||
// Make every other node promoted.
|
||||
if ($i % 2) {
|
||||
$values['promote'] = TRUE;
|
||||
}
|
||||
$values['body'][]['value'] = \Drupal::l('Node ' . 1, new Url('entity.node.canonical', ['node' => 1]));
|
||||
|
||||
$node = $this->drupalCreateNode($values);
|
||||
|
||||
$comment = [
|
||||
'uid' => $user->id(),
|
||||
'status' => CommentInterface::PUBLISHED,
|
||||
'entity_id' => $node->id(),
|
||||
'entity_type' => 'node',
|
||||
'field_name' => 'comment'
|
||||
];
|
||||
Comment::create($comment)->save();
|
||||
}
|
||||
|
||||
// Some views, such as the "Who's Online" view, only return results if at
|
||||
// least one user is logged in.
|
||||
$account = $this->drupalCreateUser([]);
|
||||
$this->drupalLogin($account);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that all Default views work as expected.
|
||||
*/
|
||||
public function testDefaultViews() {
|
||||
// Get all default views.
|
||||
$controller = $this->container->get('entity.manager')->getStorage('view');
|
||||
$views = $controller->loadMultiple();
|
||||
|
||||
foreach ($views as $name => $view_storage) {
|
||||
$view = $view_storage->getExecutable();
|
||||
$view->initDisplay();
|
||||
foreach ($view->storage->get('display') as $display_id => $display) {
|
||||
$view->setDisplay($display_id);
|
||||
|
||||
// Add any args if needed.
|
||||
if (array_key_exists($name, $this->viewArgMap)) {
|
||||
$view->preExecute($this->viewArgMap[$name]);
|
||||
}
|
||||
|
||||
$this->assert(TRUE, format_string('View @view will be executed.', ['@view' => $view->storage->id()]));
|
||||
$view->execute();
|
||||
|
||||
$tokens = ['@name' => $name, '@display_id' => $display_id];
|
||||
$this->assertTrue($view->executed, format_string('@name:@display_id has been executed.', $tokens));
|
||||
|
||||
$count = count($view->result);
|
||||
$this->assertTrue($count > 0, format_string('@count results returned', ['@count' => $count]));
|
||||
$view->destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new term with random properties in vocabulary $vid.
|
||||
*/
|
||||
public function createTerm($vocabulary) {
|
||||
$filter_formats = filter_formats();
|
||||
$format = array_pop($filter_formats);
|
||||
$term = Term::create([
|
||||
'name' => $this->randomMachineName(),
|
||||
'description' => $this->randomMachineName(),
|
||||
// Use the first available text format.
|
||||
'format' => $format->id(),
|
||||
'vid' => $vocabulary->id(),
|
||||
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
||||
]);
|
||||
$term->save();
|
||||
return $term;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the archive view.
|
||||
*/
|
||||
public function testArchiveView() {
|
||||
// Create additional nodes compared to the one in the setup method.
|
||||
// Create two nodes in the same month, and one in each following month.
|
||||
$node = [
|
||||
'created' => 280299600, // Sun, 19 Nov 1978 05:00:00 GMT
|
||||
];
|
||||
$this->drupalCreateNode($node);
|
||||
$this->drupalCreateNode($node);
|
||||
$node = [
|
||||
'created' => 282891600, // Tue, 19 Dec 1978 05:00:00 GMT
|
||||
];
|
||||
$this->drupalCreateNode($node);
|
||||
$node = [
|
||||
'created' => 285570000, // Fri, 19 Jan 1979 05:00:00 GMT
|
||||
];
|
||||
$this->drupalCreateNode($node);
|
||||
|
||||
$view = Views::getView('archive');
|
||||
$view->setDisplay('page_1');
|
||||
$this->executeView($view);
|
||||
$columns = ['nid', 'created_year_month', 'num_records'];
|
||||
$column_map = array_combine($columns, $columns);
|
||||
// Create time of additional nodes created in the setup method.
|
||||
$created_year_month = date('Ym', REQUEST_TIME - 3600);
|
||||
$expected_result = [
|
||||
[
|
||||
'nid' => 1,
|
||||
'created_year_month' => $created_year_month,
|
||||
'num_records' => 11,
|
||||
],
|
||||
[
|
||||
'nid' => 15,
|
||||
'created_year_month' => 197901,
|
||||
'num_records' => 1,
|
||||
],
|
||||
[
|
||||
'nid' => 14,
|
||||
'created_year_month' => 197812,
|
||||
'num_records' => 1,
|
||||
],
|
||||
[
|
||||
'nid' => 12,
|
||||
'created_year_month' => 197811,
|
||||
'num_records' => 2,
|
||||
],
|
||||
];
|
||||
$this->assertIdenticalResultset($view, $expected_result, $column_map);
|
||||
|
||||
$view->storage->setStatus(TRUE);
|
||||
$view->save();
|
||||
\Drupal::service('router.builder')->rebuild();
|
||||
|
||||
$this->drupalGet('archive');
|
||||
$this->assertResponse(200);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Entity;
|
||||
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
|
||||
/**
|
||||
* Tests views base field access.
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class BaseFieldAccessTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_entity_test_protected_access'];
|
||||
|
||||
/**
|
||||
* Modules to enable
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = [
|
||||
'views', 'views_test_config', 'entity_test', 'node', 'views_entity_test',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
/** @var \Drupal\Core\Entity\EntityDefinitionUpdateManager $update_manager */
|
||||
$update_manager = $this->container->get('entity.definition_update_manager');
|
||||
\Drupal::entityManager()->clearCachedDefinitions();
|
||||
$update_manager->applyUpdates();
|
||||
ViewTestData::createTestViews(get_class($this), ['comment_test_views']);
|
||||
\Drupal::state()->set('entity_test.views_data', [
|
||||
'entity_test' => [
|
||||
'test_text_access' => [
|
||||
'field' => [
|
||||
'id' => 'standard',
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
$entity_1 = EntityTest::create([
|
||||
'test_text_access' => 'no access value',
|
||||
]);
|
||||
$entity_1->save();
|
||||
$entity_2 = EntityTest::create([
|
||||
'test_text_access' => 'ok to see this one',
|
||||
]);
|
||||
$entity_2->save();
|
||||
$this->drupalLogin($this->drupalCreateUser(['access content']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test access to protected base fields.
|
||||
*/
|
||||
public function testProtectedField() {
|
||||
$this->drupalGet('test-entity-protected-access');
|
||||
$this->assertText('ok to see this one');
|
||||
$this->assertNoText('no access value');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Entity;
|
||||
|
||||
use Drupal\comment\Tests\CommentTestTrait;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\user\Entity\User;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
use Drupal\views\Views;
|
||||
use Drupal\comment\Entity\Comment;
|
||||
|
||||
/**
|
||||
* Tests the field plugin base integration with the entity system.
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class FieldEntityTest extends ViewTestBase {
|
||||
|
||||
use CommentTestTrait;
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_field_get_entity'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node', 'comment'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp(FALSE);
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page']);
|
||||
$this->addDefaultCommentField('node', 'page');
|
||||
|
||||
ViewTestData::createTestViews(get_class($this), ['views_test_config']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getEntity method.
|
||||
*/
|
||||
public function testGetEntity() {
|
||||
// The view is a view of comments, their nodes and their authors, so there
|
||||
// are three layers of entities.
|
||||
|
||||
$account = User::create(['name' => $this->randomMachineName(), 'bundle' => 'user']);
|
||||
$account->save();
|
||||
|
||||
$node = Node::create([
|
||||
'uid' => $account->id(),
|
||||
'type' => 'page',
|
||||
'title' => $this->randomString(),
|
||||
]);
|
||||
$node->save();
|
||||
$comment = Comment::create([
|
||||
'uid' => $account->id(),
|
||||
'entity_id' => $node->id(),
|
||||
'entity_type' => 'node',
|
||||
'field_name' => 'comment'
|
||||
]);
|
||||
$comment->save();
|
||||
|
||||
$user = $this->drupalCreateUser(['access comments']);
|
||||
$this->drupalLogin($user);
|
||||
|
||||
$view = Views::getView('test_field_get_entity');
|
||||
$this->executeView($view);
|
||||
$row = $view->result[0];
|
||||
|
||||
// Tests entities on the base level.
|
||||
$entity = $view->field['cid']->getEntity($row);
|
||||
$this->assertEqual($entity->id(), $comment->id(), 'Make sure the right comment entity got loaded.');
|
||||
// Tests entities as relationship on first level.
|
||||
$entity = $view->field['nid']->getEntity($row);
|
||||
$this->assertEqual($entity->id(), $node->id(), 'Make sure the right node entity got loaded.');
|
||||
// Tests entities as relationships on second level.
|
||||
$entity = $view->field['uid']->getEntity($row);
|
||||
$this->assertEqual($entity->id(), $account->id(), 'Make sure the right user entity got loaded.');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Entity;
|
||||
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Symfony\Component\CssSelector\CssSelectorConverter;
|
||||
|
||||
/**
|
||||
* Tests the rendering of fields (base fields) and their translations.
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class FieldEntityTranslationTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['language', 'locale', 'content_translation', 'node'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $testViews = ['test_entity_field_renderers'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$node_type = NodeType::create([
|
||||
'type' => 'article',
|
||||
'label' => 'Article',
|
||||
]);
|
||||
$node_type->save();
|
||||
|
||||
/** @var \Drupal\content_translation\ContentTranslationManagerInterface $content_translation_manager */
|
||||
$content_translation_manager = \Drupal::service('content_translation.manager');
|
||||
|
||||
$content_translation_manager->setEnabled('node', 'article', TRUE);
|
||||
|
||||
$language = ConfigurableLanguage::create([
|
||||
'id' => 'es',
|
||||
'label' => 'Spanish',
|
||||
]);
|
||||
$language->save();
|
||||
// Rebuild the container to setup the language path processors.
|
||||
$this->rebuildContainer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that different translation mechanisms can be used for base fields.
|
||||
*/
|
||||
public function testTranslationRows() {
|
||||
$node = Node::create([
|
||||
'type' => 'article',
|
||||
'title' => 'example EN',
|
||||
'sticky' => FALSE,
|
||||
]);
|
||||
$node->save();
|
||||
|
||||
$translation = $node->addTranslation('es');
|
||||
$translation->title->value = 'example ES';
|
||||
$translation->sticky->value = TRUE;
|
||||
$translation->save();
|
||||
|
||||
$this->drupalGet('test_entity_field_renderers/entity_translation');
|
||||
$this->assertRows([
|
||||
[
|
||||
'title' => 'example EN',
|
||||
'sticky' => 'Off',
|
||||
],
|
||||
[
|
||||
'title' => 'example ES',
|
||||
'sticky' => 'On',
|
||||
],
|
||||
]);
|
||||
|
||||
$this->drupalGet('test_entity_field_renderers/entity_default');
|
||||
$this->assertRows([
|
||||
[
|
||||
'title' => 'example EN',
|
||||
'sticky' => 'Off',
|
||||
],
|
||||
[
|
||||
'title' => 'example EN',
|
||||
'sticky' => 'Off',
|
||||
],
|
||||
]);
|
||||
|
||||
$this->drupalGet('test_entity_field_renderers/site_default');
|
||||
$this->assertRows([
|
||||
[
|
||||
'title' => 'example EN',
|
||||
'sticky' => 'Off',
|
||||
],
|
||||
[
|
||||
'title' => 'example EN',
|
||||
'sticky' => 'Off',
|
||||
],
|
||||
]);
|
||||
|
||||
$this->drupalGet('test_entity_field_renderers/language_interface');
|
||||
$this->assertRows([
|
||||
[
|
||||
'title' => 'example EN',
|
||||
'sticky' => 'Off',
|
||||
],
|
||||
[
|
||||
'title' => 'example EN',
|
||||
'sticky' => 'Off',
|
||||
],
|
||||
]);
|
||||
|
||||
$this->drupalGet('test_entity_field_renderers/language_interface', ['language' => new Language(['id' => 'es'])]);
|
||||
$this->assertRows([
|
||||
[
|
||||
'title' => 'example ES',
|
||||
'sticky' => 'On',
|
||||
],
|
||||
[
|
||||
'title' => 'example ES',
|
||||
'sticky' => 'On',
|
||||
],
|
||||
]);
|
||||
|
||||
$this->drupalGet('test_entity_field_renderers/en');
|
||||
$this->assertRows([
|
||||
[
|
||||
'title' => 'example EN',
|
||||
'sticky' => 'Off',
|
||||
],
|
||||
[
|
||||
'title' => 'example EN',
|
||||
'sticky' => 'Off',
|
||||
],
|
||||
]);
|
||||
|
||||
$this->drupalGet('test_entity_field_renderers/es');
|
||||
$this->assertRows([
|
||||
[
|
||||
'title' => 'example ES',
|
||||
'sticky' => 'On',
|
||||
],
|
||||
[
|
||||
'title' => 'example ES',
|
||||
'sticky' => 'On',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the rendered results are working as expected.
|
||||
*
|
||||
* @param array $expected
|
||||
* The expected rows of the result.
|
||||
*/
|
||||
protected function assertRows($expected = []) {
|
||||
$actual = [];
|
||||
$rows = $this->cssSelect('div.views-row');
|
||||
foreach ($rows as $row) {
|
||||
$actual[] = [
|
||||
'title' => $row->find('xpath', (new CssSelectorConverter())->toXPath('.views-field-title span.field-content a'))->getText(),
|
||||
'sticky' => $row->find('xpath', (new CssSelectorConverter())->toXPath('.views-field-sticky span.field-content'))->getText(),
|
||||
];
|
||||
}
|
||||
$this->assertEqual($actual, $expected);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Entity;
|
||||
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the generic entity bundle filter.
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class FilterEntityBundleTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_entity_type_filter'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node'];
|
||||
|
||||
/**
|
||||
* Entity bundle data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $entityBundles;
|
||||
|
||||
/**
|
||||
* An array of entities.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $entities = [];
|
||||
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp(FALSE);
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'test_bundle']);
|
||||
$this->drupalCreateContentType(['type' => 'test_bundle_2']);
|
||||
|
||||
ViewTestData::createTestViews(get_class($this), ['views_test_config']);
|
||||
|
||||
$this->entityBundles = $this->container->get('entity_type.bundle.info')->getBundleInfo('node');
|
||||
|
||||
$this->entities['count'] = 0;
|
||||
|
||||
foreach ($this->entityBundles as $key => $info) {
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$entity = Node::create([
|
||||
'title' => $this->randomString(),
|
||||
'uid' => 1,
|
||||
'type' => $key,
|
||||
]);
|
||||
$entity->save();
|
||||
$this->entities[$key][$entity->id()] = $entity;
|
||||
$this->entities['count']++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the generic bundle filter.
|
||||
*/
|
||||
public function testFilterEntity() {
|
||||
$view = Views::getView('test_entity_type_filter');
|
||||
|
||||
// Tests \Drupal\views\Plugin\views\filter\Bundle::calculateDependencies().
|
||||
$expected = [
|
||||
'config' => [
|
||||
'node.type.test_bundle',
|
||||
'node.type.test_bundle_2',
|
||||
],
|
||||
'module' => [
|
||||
'node'
|
||||
],
|
||||
];
|
||||
$this->assertIdentical($expected, $view->getDependencies());
|
||||
|
||||
$this->executeView($view);
|
||||
|
||||
// Test we have all the results, with all types selected.
|
||||
$this->assertEqual(count($view->result), $this->entities['count']);
|
||||
|
||||
// Test the valueOptions of the filter handler.
|
||||
$expected = [];
|
||||
|
||||
foreach ($this->entityBundles as $key => $info) {
|
||||
$expected[$key] = $info['label'];
|
||||
}
|
||||
$this->assertIdentical($view->filter['type']->getValueOptions(), $expected);
|
||||
|
||||
$view->destroy();
|
||||
|
||||
// Test each bundle type.
|
||||
foreach ($this->entityBundles as $key => $info) {
|
||||
// Test each bundle type.
|
||||
$view->initDisplay();
|
||||
$filters = $view->display_handler->getOption('filters');
|
||||
$filters['type']['value'] = [$key => $key];
|
||||
$view->display_handler->setOption('filters', $filters);
|
||||
$this->executeView($view);
|
||||
|
||||
$this->assertEqual(count($view->result), count($this->entities[$key]));
|
||||
|
||||
$view->destroy();
|
||||
}
|
||||
|
||||
// Test an invalid bundle type to make sure we have no results.
|
||||
$view->initDisplay();
|
||||
$filters = $view->display_handler->getOption('filters');
|
||||
$filters['type']['value'] = ['type_3' => 'type_3'];
|
||||
$view->display_handler->setOption('filters', $filters);
|
||||
$this->executeView($view);
|
||||
|
||||
$this->assertEqual(count($view->result), 0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Entity;
|
||||
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\language_test\Entity\NoLanguageEntityTest;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests the view creation of non-translatable entities.
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class ViewNonTranslatableEntityTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = [
|
||||
'entity_test',
|
||||
'content_translation',
|
||||
'language_test',
|
||||
'views_ui',
|
||||
];
|
||||
|
||||
/**
|
||||
* Tests displaying a view of non-translatable entities.
|
||||
*/
|
||||
public function testViewNoTranslatableEntity() {
|
||||
// Add a new language.
|
||||
ConfigurableLanguage::createFromLangcode('sr')->save();
|
||||
|
||||
// Create a non-translatable entity.
|
||||
$no_language_entity = NoLanguageEntityTest::create();
|
||||
$no_language_entity->save();
|
||||
|
||||
// Visit the view page and assert it is displayed properly.
|
||||
$this->drupalGet('no-entity-translation-view');
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('No Entity Translation View');
|
||||
$this->assertText($no_language_entity->uuid());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional;
|
||||
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\views\Tests\AssertViewsCacheTagsTrait;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests glossary functionality of views.
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class GlossaryTest extends ViewTestBase {
|
||||
|
||||
use AssertViewsCacheTagsTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node'];
|
||||
|
||||
/**
|
||||
* Tests the default glossary view.
|
||||
*/
|
||||
public function testGlossaryView() {
|
||||
// Create a content type and add some nodes, with a non-random title.
|
||||
$type = $this->drupalCreateContentType();
|
||||
$nodes_per_char = [
|
||||
'd' => 1,
|
||||
'r' => 4,
|
||||
'u' => 10,
|
||||
'p' => 2,
|
||||
'a' => 3,
|
||||
'l' => 6,
|
||||
];
|
||||
$nodes_by_char = [];
|
||||
foreach ($nodes_per_char as $char => $count) {
|
||||
$setting = [
|
||||
'type' => $type->id()
|
||||
];
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$node = $setting;
|
||||
$node['title'] = $char . $this->randomString(3);
|
||||
$node = $this->drupalCreateNode($node);
|
||||
$nodes_by_char[$char][] = $node;
|
||||
}
|
||||
}
|
||||
|
||||
// Execute glossary view
|
||||
$view = Views::getView('glossary');
|
||||
$view->setDisplay('attachment_1');
|
||||
$view->executeDisplay('attachment_1');
|
||||
|
||||
// Check that the amount of nodes per char.
|
||||
foreach ($view->result as $item) {
|
||||
$this->assertEqual($nodes_per_char[$item->title_truncated], $item->num_records);
|
||||
}
|
||||
|
||||
// Enable the glossary to be displayed.
|
||||
$view->storage->enable()->save();
|
||||
$this->container->get('router.builder')->rebuildIfNeeded();
|
||||
$url = Url::fromRoute('view.glossary.page_1');
|
||||
|
||||
// Verify cache tags.
|
||||
$this->assertPageCacheContextsAndTags(
|
||||
$url,
|
||||
[
|
||||
'timezone',
|
||||
'languages:' . LanguageInterface::TYPE_CONTENT,
|
||||
'languages:' . LanguageInterface::TYPE_INTERFACE,
|
||||
'theme',
|
||||
'url',
|
||||
'user.node_grants:view',
|
||||
'user.permissions',
|
||||
'route',
|
||||
],
|
||||
[
|
||||
'config:views.view.glossary',
|
||||
// Listed for letter 'a'
|
||||
'node:' . $nodes_by_char['a'][0]->id(), 'node:' . $nodes_by_char['a'][1]->id(), 'node:' . $nodes_by_char['a'][2]->id(),
|
||||
// Link for letter 'd'.
|
||||
'node:1',
|
||||
// Link for letter 'p'.
|
||||
'node:16',
|
||||
// Link for letter 'r'.
|
||||
'node:2',
|
||||
// Link for letter 'l'.
|
||||
'node:21',
|
||||
// Link for letter 'u'.
|
||||
'node:6',
|
||||
'node_list',
|
||||
'user:0',
|
||||
'user_list',
|
||||
'http_response',
|
||||
'rendered',
|
||||
// FinishResponseSubscriber adds this cache tag to responses that have
|
||||
// the 'user.permissions' cache context for anonymous users.
|
||||
'config:user.role.anonymous',
|
||||
]
|
||||
);
|
||||
|
||||
// Check the actual page response.
|
||||
$this->drupalGet($url);
|
||||
$this->assertResponse(200);
|
||||
foreach ($nodes_per_char as $char => $count) {
|
||||
$href = Url::fromRoute('view.glossary.page_1', ['arg_0' => $char])->toString();
|
||||
$label = Unicode::strtoupper($char);
|
||||
// Get the summary link for a certain character. Filter by label and href
|
||||
// to ensure that both of them are correct.
|
||||
$result = $this->xpath('//a[contains(@href, :href) and normalize-space(text())=:label]/..', [':href' => $href, ':label' => $label]);
|
||||
$this->assertTrue(count($result));
|
||||
// The rendered output looks like "<a href=''>X</a> | (count)" so let's
|
||||
// figure out the int.
|
||||
$result_count = explode(' ', trim(str_replace(['|', '(', ')'], '', $result[0]->getText())))[1];
|
||||
$this->assertEqual($result_count, $count, 'The expected number got rendered.');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Handler;
|
||||
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the http_status_code area handler.
|
||||
*
|
||||
* @group views
|
||||
* @see \Drupal\views\Plugin\views\area\HTTPStatusCode
|
||||
*/
|
||||
class AreaHTTPStatusCodeTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_http_status_code'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node'];
|
||||
|
||||
/**
|
||||
* Tests the area handler.
|
||||
*/
|
||||
public function testHTTPStatusCodeHandler() {
|
||||
$this->drupalGet('test-http-status-code');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Change the HTTP status code to 418.
|
||||
$view = Views::getView('test_http_status_code');
|
||||
$display = &$view->storage->getDisplay('default');
|
||||
$display['display_options']['empty']['http_status_code']['status_code'] = 418;
|
||||
$view->save();
|
||||
|
||||
// Test that the HTTP response is "I'm a teapot".
|
||||
$this->drupalGet('test-http-status-code');
|
||||
$this->assertResponse(418);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Handler;
|
||||
|
||||
use Drupal\Component\Utility\Xss;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the plugin base of the area handler.
|
||||
*
|
||||
* @group views
|
||||
* @see \Drupal\views\Plugin\views\area\AreaPluginBase
|
||||
* @see \Drupal\views_test\Plugin\views\area\TestExample
|
||||
*/
|
||||
class AreaTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_example_area', 'test_example_area_access'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node', 'views_ui'];
|
||||
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$this->enableViewsTestModule();
|
||||
}
|
||||
|
||||
protected function viewsData() {
|
||||
$data = parent::viewsData();
|
||||
$data['views']['test_example'] = [
|
||||
'title' => 'Test Example area',
|
||||
'help' => 'A area handler which just exists for tests.',
|
||||
'area' => [
|
||||
'id' => 'test_example'
|
||||
]
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests the generic UI of a area handler.
|
||||
*/
|
||||
public function testUI() {
|
||||
$admin_user = $this->drupalCreateUser(['administer views', 'administer site configuration']);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
$types = ['header', 'footer', 'empty'];
|
||||
$labels = [];
|
||||
foreach ($types as $type) {
|
||||
$edit_path = 'admin/structure/views/nojs/handler/test_example_area/default/' . $type . '/test_example';
|
||||
|
||||
// First setup an empty label.
|
||||
$this->drupalPostForm($edit_path, [], t('Apply'));
|
||||
$this->assertText('Test Example area');
|
||||
|
||||
// Then setup a no empty label.
|
||||
$labels[$type] = $this->randomMachineName();
|
||||
$this->drupalPostForm($edit_path, ['options[admin_label]' => $labels[$type]], t('Apply'));
|
||||
// Make sure that the new label appears on the site.
|
||||
$this->assertText($labels[$type]);
|
||||
|
||||
// Test that the settings (empty/admin_label) are accessible.
|
||||
$this->drupalGet($edit_path);
|
||||
$this->assertField('options[admin_label]');
|
||||
if ($type !== 'empty') {
|
||||
$this->assertField('options[empty]');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the rendering of an area.
|
||||
*/
|
||||
public function testRenderArea() {
|
||||
$view = Views::getView('test_example_area');
|
||||
$view->initHandlers();
|
||||
|
||||
// Insert a random string with XSS injection in the test area plugin.
|
||||
// Ensure that the string is rendered for the header, footer, and empty
|
||||
// text with the markup properly escaped.
|
||||
$header_string = '<script type="text/javascript">alert("boo");</script><p>' . $this->randomMachineName() . '</p>';
|
||||
$footer_string = '<script type="text/javascript">alert("boo");</script><p>' . $this->randomMachineName() . '</p>';
|
||||
$empty_string = '<script type="text/javascript">alert("boo");</script><p>' . $this->randomMachineName() . '</p>';
|
||||
|
||||
$view->header['test_example']->options['string'] = $header_string;
|
||||
$view->header['test_example']->options['empty'] = TRUE;
|
||||
|
||||
$view->footer['test_example']->options['string'] = $footer_string;
|
||||
$view->footer['test_example']->options['empty'] = TRUE;
|
||||
|
||||
$view->empty['test_example']->options['string'] = $empty_string;
|
||||
|
||||
// Check whether the strings exist in the output and are sanitized.
|
||||
$output = $view->preview();
|
||||
$output = $this->container->get('renderer')->renderRoot($output);
|
||||
$this->assertTrue(strpos($output, Xss::filterAdmin($header_string)) !== FALSE, 'Views header exists in the output and is sanitized');
|
||||
$this->assertTrue(strpos($output, Xss::filterAdmin($footer_string)) !== FALSE, 'Views footer exists in the output and is sanitized');
|
||||
$this->assertTrue(strpos($output, Xss::filterAdmin($empty_string)) !== FALSE, 'Views empty exists in the output and is sanitized');
|
||||
$this->assertTrue(strpos($output, '<script') === FALSE, 'Script tags were escaped');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the access for an area.
|
||||
*/
|
||||
public function testAreaAccess() {
|
||||
// Test with access denied for the area handler.
|
||||
$view = Views::getView('test_example_area_access');
|
||||
$view->initDisplay();
|
||||
$view->initHandlers();
|
||||
$handlers = $view->display_handler->getHandlers('empty');
|
||||
$this->assertEqual(0, count($handlers));
|
||||
|
||||
$output = $view->preview();
|
||||
$output = \Drupal::service('renderer')->renderRoot($output);
|
||||
// The area output should not be present since access was denied.
|
||||
$this->assertFalse(strpos($output, 'a custom string') !== FALSE);
|
||||
$view->destroy();
|
||||
|
||||
// Test with access granted for the area handler.
|
||||
$view = Views::getView('test_example_area_access');
|
||||
$view->initDisplay();
|
||||
$view->display_handler->overrideOption('empty', [
|
||||
'test_example' => [
|
||||
'field' => 'test_example',
|
||||
'id' => 'test_example',
|
||||
'table' => 'views',
|
||||
'plugin_id' => 'test_example',
|
||||
'string' => 'a custom string',
|
||||
'custom_access' => TRUE,
|
||||
],
|
||||
]);
|
||||
$view->initHandlers();
|
||||
$handlers = $view->display_handler->getHandlers('empty');
|
||||
|
||||
$output = $view->preview();
|
||||
$output = \Drupal::service('renderer')->renderRoot($output);
|
||||
$this->assertTrue(strpos($output, 'a custom string') !== FALSE);
|
||||
$this->assertEqual(1, count($handlers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests global tokens.
|
||||
*/
|
||||
public function testRenderAreaToken() {
|
||||
$admin_user = $this->drupalCreateUser(['administer views', 'administer site configuration']);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
$view = Views::getView('test_example_area');
|
||||
$view->initHandlers();
|
||||
|
||||
$this->drupalGet('admin/structure/views/nojs/handler/test_example_area/default/empty/test_example');
|
||||
|
||||
// Test that the list is token present.
|
||||
$element = $this->xpath('//ul[@class="global-tokens"]');
|
||||
$this->assertTrue($element, 'Token list found on the options form.');
|
||||
|
||||
$empty_handler = &$view->empty['test_example'];
|
||||
|
||||
// Test the list of available tokens.
|
||||
$available = $empty_handler->getAvailableGlobalTokens();
|
||||
foreach (['site', 'view'] as $type) {
|
||||
$this->assertTrue(!empty($available[$type]) && is_array($available[$type]));
|
||||
// Test that each item exists in the list.
|
||||
foreach ($available[$type] as $token => $info) {
|
||||
$this->assertText("[$type:$token]");
|
||||
}
|
||||
}
|
||||
|
||||
// Test the rendered output of a token.
|
||||
$empty_handler->options['string'] = '[site:name]';
|
||||
|
||||
// Test we have the site:name token in the output.
|
||||
$output = $view->preview();
|
||||
$output = $this->container->get('renderer')->renderRoot($output);
|
||||
$expected = \Drupal::token()->replace('[site:name]');
|
||||
$this->assertTrue(strpos($output, $expected) !== FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests overriding the view title using the area title handler.
|
||||
*/
|
||||
public function testTitleArea() {
|
||||
$view = Views::getView('frontpage');
|
||||
$view->initDisplay('page_1');
|
||||
|
||||
// Add the title area handler to the empty area.
|
||||
$view->displayHandlers->get('page_1')->overrideOption('empty', [
|
||||
'title' => [
|
||||
'id' => 'title',
|
||||
'table' => 'views',
|
||||
'field' => 'title',
|
||||
'admin_label' => '',
|
||||
'empty' => '0',
|
||||
'title' => 'Overridden title',
|
||||
'plugin_id' => 'title',
|
||||
],
|
||||
]);
|
||||
|
||||
$view->storage->enable()->save();
|
||||
|
||||
$this->drupalGet('node');
|
||||
$this->assertText('Overridden title', 'Overridden title found.');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Handler;
|
||||
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Entity\View;
|
||||
|
||||
/**
|
||||
* Tests the title area handler with a web test.
|
||||
*
|
||||
* @group views
|
||||
* @see \Drupal\views\Plugin\views\area\Title
|
||||
*/
|
||||
class AreaTitleWebTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_area_title'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$this->enableViewsTestModule();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the title area handler.
|
||||
*/
|
||||
public function testTitleText() {
|
||||
// Confirm that the view has the normal title before making the view return
|
||||
// no result.
|
||||
$this->drupalGet('test-area-title');
|
||||
$this->assertTitle('test_title_header | Drupal');
|
||||
|
||||
// Change the view to return no result.
|
||||
/** @var \Drupal\views\Entity\View $view */
|
||||
$view = View::load('test_area_title');
|
||||
$display =& $view->getDisplay('default');
|
||||
$display['display_options']['filters']['name'] = [
|
||||
'field' => 'name',
|
||||
'id' => 'name',
|
||||
'table' => 'views_test_data',
|
||||
'relationship' => 'none',
|
||||
'plugin_id' => 'string',
|
||||
// Add a value which does not exist. The dataset is defined in
|
||||
// \Drupal\views\Tests\ViewTestData::dataSet().
|
||||
'value' => 'Euler',
|
||||
];
|
||||
$view->save();
|
||||
|
||||
$this->drupalGet('test-area-title');
|
||||
$this->assertTitle('test_title_empty | Drupal');
|
||||
|
||||
// Change the view to return a result instead.
|
||||
/** @var \Drupal\views\Entity\View $view */
|
||||
$view = View::load('test_area_title');
|
||||
$display =& $view->getDisplay('default');
|
||||
$display['display_options']['filters']['name'] = [
|
||||
'field' => 'name',
|
||||
'id' => 'name',
|
||||
'table' => 'views_test_data',
|
||||
'relationship' => 'none',
|
||||
'plugin_id' => 'string',
|
||||
// Change to a value which does exist. The dataset is defined in
|
||||
// \Drupal\views\Tests\ViewTestData::dataSet().
|
||||
'value' => 'Ringo',
|
||||
];
|
||||
$view->save();
|
||||
|
||||
$this->drupalGet('test-area-title');
|
||||
$this->assertTitle('test_title_header | Drupal');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Handler;
|
||||
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the core Drupal\views\Plugin\views\argument\StringArgument handler.
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class ArgumentStringTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_glossary'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node'];
|
||||
|
||||
/**
|
||||
* Tests the glossary feature.
|
||||
*/
|
||||
public function testGlossary() {
|
||||
// Setup some nodes, one with a, two with b and three with c.
|
||||
$counter = 1;
|
||||
foreach (['a', 'b', 'c'] as $char) {
|
||||
for ($i = 0; $i < $counter; $i++) {
|
||||
$edit = [
|
||||
'title' => $char . $this->randomMachineName(),
|
||||
];
|
||||
$this->drupalCreateNode($edit);
|
||||
}
|
||||
}
|
||||
|
||||
$view = Views::getView('test_glossary');
|
||||
$this->executeView($view);
|
||||
|
||||
$count_field = 'nid';
|
||||
foreach ($view->result as &$row) {
|
||||
if (strpos($view->field['title']->getValue($row), 'a') === 0) {
|
||||
$this->assertEqual(1, $row->{$count_field});
|
||||
}
|
||||
if (strpos($view->field['title']->getValue($row), 'b') === 0) {
|
||||
$this->assertEqual(2, $row->{$count_field});
|
||||
}
|
||||
if (strpos($view->field['title']->getValue($row), 'c') === 0) {
|
||||
$this->assertEqual(3, $row->{$count_field});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Handler;
|
||||
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
|
||||
/**
|
||||
* Tests the dropbutton field handler.
|
||||
*
|
||||
* @group views
|
||||
* @see \Drupal\system\Plugin\views\field\Dropbutton
|
||||
*/
|
||||
class FieldDropButtonTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_dropbutton'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$admin_user = $this->drupalCreateUser(['access content overview', 'administer nodes', 'bypass node access']);
|
||||
$this->drupalLogin($admin_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests dropbutton field.
|
||||
*/
|
||||
public function testDropbutton() {
|
||||
// Create some test nodes.
|
||||
$nodes = [];
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$nodes[] = $this->drupalCreateNode();
|
||||
}
|
||||
|
||||
$this->drupalGet('test-dropbutton');
|
||||
foreach ($nodes as $node) {
|
||||
$result = $this->xpath('//ul[contains(@class, dropbutton)]/li/a[contains(@href, :path) and text()=:title]', [':path' => '/node/' . $node->id(), ':title' => $node->label()]);
|
||||
$this->assertEqual(count($result), 1, 'Just one node title link was found.');
|
||||
$result = $this->xpath('//ul[contains(@class, dropbutton)]/li/a[contains(@href, :path) and text()=:title]', [':path' => '/node/' . $node->id(), ':title' => 'Custom Text']);
|
||||
$this->assertEqual(count($result), 1, 'Just one custom link was found.');
|
||||
}
|
||||
|
||||
// Check if the dropbutton.js library is available.
|
||||
$this->drupalGet('admin/content');
|
||||
$this->assertRaw('dropbutton.js');
|
||||
// Check if the dropbutton.js library is available on a cached page to
|
||||
// ensure that bubbleable metadata is not lost in the views render workflow.
|
||||
$this->drupalGet('admin/content');
|
||||
$this->assertRaw('dropbutton.js');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Handler;
|
||||
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
|
||||
/**
|
||||
* Tests the core Drupal\views\Plugin\views\field\EntityOperations handler.
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class FieldEntityOperationsTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_entity_operations'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node', 'language', 'views_ui'];
|
||||
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
// Create Article content type.
|
||||
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests entity operations field.
|
||||
*/
|
||||
public function testEntityOperations() {
|
||||
// Add languages and refresh the container so the entity manager will have
|
||||
// fresh data.
|
||||
ConfigurableLanguage::createFromLangcode('hu')->save();
|
||||
ConfigurableLanguage::createFromLangcode('es')->save();
|
||||
$this->rebuildContainer();
|
||||
|
||||
// Create some test entities. Every other entity is Hungarian while all
|
||||
// have a Spanish translation.
|
||||
$entities = [];
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$entity = Node::create([
|
||||
'title' => $this->randomString(),
|
||||
'type' => 'article',
|
||||
'langcode' => $i % 2 === 0 ? 'hu' : 'en',
|
||||
]);
|
||||
$entity->save();
|
||||
$translation = $entity->addTranslation('es');
|
||||
$translation->set('title', $entity->getTitle() . ' in Spanish');
|
||||
$translation->save();
|
||||
$entities[$i] = $entity;
|
||||
}
|
||||
|
||||
$admin_user = $this->drupalCreateUser(['access administration pages', 'administer nodes', 'bypass node access']);
|
||||
$this->drupalLogin($this->rootUser);
|
||||
$this->drupalGet('test-entity-operations');
|
||||
/** @var $entity \Drupal\entity_test\Entity\EntityTest */
|
||||
foreach ($entities as $entity) {
|
||||
/** @var \Drupal\Core\Language\LanguageInterface $language */
|
||||
foreach ($entity->getTranslationLanguages() as $language) {
|
||||
$entity = $entity->getTranslation($language->getId());
|
||||
$operations = \Drupal::entityManager()->getListBuilder('node')->getOperations($entity);
|
||||
$this->assertTrue(count($operations) > 0, 'There are operations.');
|
||||
foreach ($operations as $operation) {
|
||||
$expected_destination = Url::fromUri('internal:/test-entity-operations')->toString();
|
||||
$result = $this->xpath('//ul[contains(@class, dropbutton)]/li/a[@href=:path and text()=:title]', [':path' => $operation['url']->toString() . '?destination=' . $expected_destination, ':title' => (string) $operation['title']]);
|
||||
$this->assertEqual(count($result), 1, t('Found entity @operation link with destination parameter.', ['@operation' => $operation['title']]));
|
||||
// Entities which were created in Hungarian should link to the Hungarian
|
||||
// edit form, others to the English one (which has no path prefix here).
|
||||
$base_path = \Drupal::request()->getBasePath();
|
||||
$parts = explode('/', str_replace($base_path, '', $operation['url']->toString()));
|
||||
$expected_prefix = ($language->getId() != 'en' ? $language->getId() : 'node');
|
||||
$this->assertEqual($parts[1], $expected_prefix, 'Entity operation links to the correct language for the entity.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test that we can't enable click sorting on the operation field.
|
||||
$this->drupalGet('admin/structure/views/nojs/display/test_entity_operations/page_2/style_options');
|
||||
$this->assertField('style_options[info][title][sortable]');
|
||||
$this->assertNoField('style_options[info][operations][sortable]');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Handler;
|
||||
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\Core\Render\RenderContext;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Views;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
|
||||
/**
|
||||
* Tests the "Display all values in the same row" setting.
|
||||
*
|
||||
* @see \Drupal\views\Plugin\views\field\EntityField
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class FieldGroupRowsTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_group_rows', 'test_ungroup_rows'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node', 'field_test'];
|
||||
|
||||
/**
|
||||
* Field that will be created to test the group/ungroup rows functionality
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $fieldName = 'field_group_rows';
|
||||
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
// Create content type with unlimited text field.
|
||||
$node_type = $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
|
||||
// Create the unlimited text field.
|
||||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => $this->fieldName,
|
||||
'entity_type' => 'node',
|
||||
'type' => 'text',
|
||||
'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
|
||||
]);
|
||||
$field_storage->save();
|
||||
|
||||
// Create an instance of the text field on the content type.
|
||||
$field = [
|
||||
'field_storage' => $field_storage,
|
||||
'bundle' => $node_type->id(),
|
||||
];
|
||||
FieldConfig::create($field)->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Testing the "Grouped rows" functionality.
|
||||
*/
|
||||
public function testGroupRows() {
|
||||
/** @var \Drupal\Core\Render\RendererInterface $renderer */
|
||||
$renderer = \Drupal::service('renderer');
|
||||
|
||||
$edit = [
|
||||
'title' => $this->randomMachineName(),
|
||||
$this->fieldName => ['a', 'b', 'c'],
|
||||
];
|
||||
$this->drupalCreateNode($edit);
|
||||
|
||||
$view = Views::getView('test_group_rows');
|
||||
|
||||
// Test grouped rows.
|
||||
$this->executeView($view);
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
|
||||
return $view->field[$this->fieldName]->advancedRender($view->result[0]);
|
||||
});
|
||||
$this->assertEqual($output, 'a, b, c');
|
||||
|
||||
// Change the group_rows checkbox to false.
|
||||
$view = Views::getView('test_group_rows');
|
||||
$view->setHandlerOption('default', 'field', $this->fieldName, 'group_rows', FALSE);
|
||||
|
||||
// Test ungrouped rows.
|
||||
$this->executeView($view);
|
||||
$view->render();
|
||||
|
||||
$view->row_index = 0;
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
|
||||
return $view->field[$this->fieldName]->advancedRender($view->result[0]);
|
||||
});
|
||||
$this->assertEqual($output, 'a');
|
||||
$view->row_index = 1;
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
|
||||
return $view->field[$this->fieldName]->advancedRender($view->result[1]);
|
||||
});
|
||||
$this->assertEqual($output, 'b');
|
||||
$view->row_index = 2;
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
|
||||
return $view->field[$this->fieldName]->advancedRender($view->result[2]);
|
||||
});
|
||||
$this->assertEqual($output, 'c');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Handler;
|
||||
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
|
||||
/**
|
||||
* Tests the "Display all values in the same row" setting.
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class FieldGroupRowsWebTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_group_rows', 'test_ungroup_rows'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node'];
|
||||
|
||||
/**
|
||||
* The page node type.
|
||||
*
|
||||
* @var \Drupal\node\NodeTypeInterface
|
||||
*/
|
||||
protected $nodeType;
|
||||
|
||||
/**
|
||||
* 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($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
// Create content type with unlimited text field.
|
||||
$this->nodeType = $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
|
||||
// Create the unlimited text field.
|
||||
$this->fieldName = 'field_views_testing_group_rows';
|
||||
$this->fieldStorage = FieldStorageConfig::create([
|
||||
'field_name' => $this->fieldName,
|
||||
'entity_type' => 'node',
|
||||
'type' => 'text',
|
||||
'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
|
||||
]);
|
||||
$this->fieldStorage->save();
|
||||
|
||||
// Create an instance of the text field on the content type.
|
||||
$this->field = FieldConfig::create([
|
||||
'field_storage' => $this->fieldStorage,
|
||||
'bundle' => $this->nodeType->id(),
|
||||
]);
|
||||
$this->field->save();
|
||||
|
||||
$edit = [
|
||||
'title' => $this->randomMachineName(),
|
||||
$this->fieldName => ['a', 'b', 'c'],
|
||||
];
|
||||
$this->drupalCreateNode($edit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Testing when "Display all values in the same row" is checked.
|
||||
*/
|
||||
public function testGroupRows() {
|
||||
$this->drupalGet('test-group-rows');
|
||||
$result = $this->cssSelect('div.views-field-field-views-testing-group- div');
|
||||
|
||||
$rendered_value = [];
|
||||
foreach ($result as $row) {
|
||||
$rendered_value[] = $row->getText();
|
||||
}
|
||||
$this->assertEqual(['a, b, c'], $rendered_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Testing when "Display all values in the same row" is unchecked.
|
||||
*/
|
||||
public function testUngroupedRows() {
|
||||
$this->drupalGet('test-ungroup-rows');
|
||||
$result = $this->cssSelect('div.views-field-field-views-testing-group- div');
|
||||
$rendered_value = [];
|
||||
foreach ($result as $row) {
|
||||
$rendered_value[] = $row->getText();
|
||||
}
|
||||
$this->assertEqual(['a', 'b', 'c'], $rendered_value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,656 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Handler;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Component\Utility\UrlHelper;
|
||||
use Drupal\Core\Render\RenderContext;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests fields from within a UI.
|
||||
*
|
||||
* @group views
|
||||
* @see \Drupal\views\Plugin\views\field\FieldPluginBase
|
||||
*/
|
||||
class FieldWebTest extends ViewTestBase {
|
||||
|
||||
use AssertPageCacheContextsAndTagsTrait;
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_view', 'test_field_classes', 'test_field_output', 'test_click_sort'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['node'];
|
||||
|
||||
/**
|
||||
* Maps between the key in the expected result and the query result.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $columnMap = [
|
||||
'views_test_data_name' => 'name',
|
||||
];
|
||||
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$this->enableViewsTestModule();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function viewsData() {
|
||||
$data = parent::viewsData();
|
||||
$data['views_test_data']['job']['field']['id'] = 'test_field';
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the click sorting functionality.
|
||||
*/
|
||||
public function testClickSorting() {
|
||||
$this->drupalGet('test_click_sort');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Only the id and name should be click sortable, but not the name.
|
||||
$this->assertLinkByHref(\Drupal::url('<none>', [], ['query' => ['order' => 'id', 'sort' => 'asc']]));
|
||||
$this->assertLinkByHref(\Drupal::url('<none>', [], ['query' => ['order' => 'name', 'sort' => 'desc']]));
|
||||
$this->assertNoLinkByHref(\Drupal::url('<none>', [], ['query' => ['order' => 'created']]));
|
||||
|
||||
// Check that the view returns the click sorting cache contexts.
|
||||
$expected_contexts = [
|
||||
'languages:language_interface',
|
||||
'theme',
|
||||
'url.query_args',
|
||||
];
|
||||
$this->assertCacheContexts($expected_contexts);
|
||||
|
||||
// Clicking a click sort should change the order.
|
||||
$this->clickLink(t('ID'));
|
||||
$this->assertLinkByHref(\Drupal::url('<none>', [], ['query' => ['order' => 'id', 'sort' => 'desc']]));
|
||||
// Check that the output has the expected order (asc).
|
||||
$ids = $this->clickSortLoadIdsFromOutput();
|
||||
$this->assertEqual($ids, range(1, 5));
|
||||
|
||||
$this->clickLink(t('ID Sort descending'));
|
||||
// Check that the output has the expected order (desc).
|
||||
$ids = $this->clickSortLoadIdsFromOutput();
|
||||
$this->assertEqual($ids, range(5, 1, -1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Small helper function to get all ids in the output.
|
||||
*
|
||||
* @return array
|
||||
* A list of beatle ids.
|
||||
*/
|
||||
protected function clickSortLoadIdsFromOutput() {
|
||||
$fields = $this->xpath("//td[contains(@class, 'views-field-id')]");
|
||||
$ids = [];
|
||||
foreach ($fields as $field) {
|
||||
$ids[] = (int) $field->getText();
|
||||
}
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assertion helper which checks whether a string is part of another string.
|
||||
*
|
||||
* @param string $haystack
|
||||
* The value to search in.
|
||||
* @param string $needle
|
||||
* The value to search for.
|
||||
* @param string $message
|
||||
* The message to display along with the assertion.
|
||||
* @param string $group
|
||||
* The type of assertion - examples are "Browser", "PHP".
|
||||
* @return bool
|
||||
* TRUE if the assertion succeeded, FALSE otherwise.
|
||||
*/
|
||||
protected function assertSubString($haystack, $needle, $message = '', $group = 'Other') {
|
||||
return $this->assertTrue(strpos($haystack, $needle) !== FALSE, $message, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assertion helper which checks whether a string is not part of another string.
|
||||
*
|
||||
* @param string $haystack
|
||||
* The value to search in.
|
||||
* @param string $needle
|
||||
* The value to search for.
|
||||
* @param string $message
|
||||
* The message to display along with the assertion.
|
||||
* @param string $group
|
||||
* The type of assertion - examples are "Browser", "PHP".
|
||||
* @return bool
|
||||
* TRUE if the assertion succeeded, FALSE otherwise.
|
||||
*/
|
||||
protected function assertNotSubString($haystack, $needle, $message = '', $group = 'Other') {
|
||||
return $this->assertTrue(strpos($haystack, $needle) === FALSE, $message, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a content and return the html element.
|
||||
*
|
||||
* @param string $content
|
||||
* The html to parse.
|
||||
*
|
||||
* @return array
|
||||
* An array containing simplexml objects.
|
||||
*/
|
||||
protected function parseContent($content) {
|
||||
$htmlDom = new \DOMDocument();
|
||||
@$htmlDom->loadHTML('<?xml encoding="UTF-8">' . $content);
|
||||
$elements = simplexml_import_dom($htmlDom);
|
||||
|
||||
return $elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs an xpath search on a certain content.
|
||||
*
|
||||
* The search is relative to the root element of the $content variable.
|
||||
*
|
||||
* @param string $content
|
||||
* The html to parse.
|
||||
* @param string $xpath
|
||||
* The xpath string to use in the search.
|
||||
* @param array $arguments
|
||||
* Some arguments for the xpath.
|
||||
*
|
||||
* @return array|false
|
||||
* The return value of the xpath search. For details on the xpath string
|
||||
* format and return values see the SimpleXML documentation,
|
||||
* http://php.net/manual/function.simplexml-element-xpath.php.
|
||||
*/
|
||||
protected function xpathContent($content, $xpath, array $arguments = []) {
|
||||
if ($elements = $this->parseContent($content)) {
|
||||
$xpath = $this->buildXPathQuery($xpath, $arguments);
|
||||
$result = $elements->xpath($xpath);
|
||||
// Some combinations of PHP / libxml versions return an empty array
|
||||
// instead of the documented FALSE. Forcefully convert any falsish values
|
||||
// to an empty array to allow foreach(...) constructions.
|
||||
return $result ? $result : [];
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests rewriting the output to a link.
|
||||
*/
|
||||
public function testAlterUrl() {
|
||||
/** @var \Drupal\Core\Render\RendererInterface $renderer */
|
||||
$renderer = \Drupal::service('renderer');
|
||||
|
||||
$view = Views::getView('test_view');
|
||||
$view->setDisplay();
|
||||
$view->initHandlers();
|
||||
$this->executeView($view);
|
||||
$row = $view->result[0];
|
||||
$id_field = $view->field['id'];
|
||||
|
||||
// Setup the general settings required to build a link.
|
||||
$id_field->options['alter']['make_link'] = TRUE;
|
||||
$id_field->options['alter']['path'] = $path = $this->randomMachineName();
|
||||
|
||||
// Tests that the suffix/prefix appears on the output.
|
||||
$id_field->options['alter']['prefix'] = $prefix = $this->randomMachineName();
|
||||
$id_field->options['alter']['suffix'] = $suffix = $this->randomMachineName();
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) {
|
||||
return $id_field->theme($row);
|
||||
});
|
||||
$this->assertSubString($output, $prefix);
|
||||
$this->assertSubString($output, $suffix);
|
||||
unset($id_field->options['alter']['prefix']);
|
||||
unset($id_field->options['alter']['suffix']);
|
||||
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) {
|
||||
return $id_field->theme($row);
|
||||
});
|
||||
$this->assertSubString($output, $path, 'Make sure that the path is part of the output');
|
||||
|
||||
// Some generic test code adapted from the UrlTest class, which tests
|
||||
// mostly the different options for the path.
|
||||
foreach ([FALSE, TRUE] as $absolute) {
|
||||
$alter = &$id_field->options['alter'];
|
||||
$alter['path'] = 'node/123';
|
||||
|
||||
$expected_result = \Drupal::url('entity.node.canonical', ['node' => '123'], ['absolute' => $absolute]);
|
||||
$alter['absolute'] = $absolute;
|
||||
$result = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) {
|
||||
return $id_field->theme($row);
|
||||
});
|
||||
$this->assertSubString($result, $expected_result);
|
||||
|
||||
$expected_result = \Drupal::url('entity.node.canonical', ['node' => '123'], ['fragment' => 'foo', 'absolute' => $absolute]);
|
||||
$alter['path'] = 'node/123#foo';
|
||||
$result = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) {
|
||||
return $id_field->theme($row);
|
||||
});
|
||||
$this->assertSubString($result, $expected_result);
|
||||
|
||||
$expected_result = \Drupal::url('entity.node.canonical', ['node' => '123'], ['query' => ['foo' => NULL], 'absolute' => $absolute]);
|
||||
$alter['path'] = 'node/123?foo';
|
||||
$result = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) {
|
||||
return $id_field->theme($row);
|
||||
});
|
||||
$this->assertSubString($result, $expected_result);
|
||||
|
||||
$expected_result = \Drupal::url('entity.node.canonical', ['node' => '123'], ['query' => ['foo' => 'bar', 'bar' => 'baz'], 'absolute' => $absolute]);
|
||||
$alter['path'] = 'node/123?foo=bar&bar=baz';
|
||||
$result = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) {
|
||||
return $id_field->theme($row);
|
||||
});
|
||||
$this->assertSubString(Html::decodeEntities($result), Html::decodeEntities($expected_result));
|
||||
|
||||
// @todo The route-based URL generator strips out NULL attributes.
|
||||
// $expected_result = \Drupal::url('entity.node.canonical', ['node' => '123'], ['query' => ['foo' => NULL], 'fragment' => 'bar', 'absolute' => $absolute]);
|
||||
$expected_result = Url::fromUserInput('/node/123', ['query' => ['foo' => NULL], 'fragment' => 'bar', 'absolute' => $absolute])->toString();
|
||||
$alter['path'] = 'node/123?foo#bar';
|
||||
$result = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) {
|
||||
return $id_field->theme($row);
|
||||
});
|
||||
$this->assertSubString(Html::decodeEntities($result), Html::decodeEntities($expected_result));
|
||||
|
||||
$expected_result = \Drupal::url('<front>', [], ['absolute' => $absolute]);
|
||||
$alter['path'] = '<front>';
|
||||
$result = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) {
|
||||
return $id_field->theme($row);
|
||||
});
|
||||
$this->assertSubString($result, $expected_result);
|
||||
}
|
||||
|
||||
// Tests the replace spaces with dashes feature.
|
||||
$id_field->options['alter']['replace_spaces'] = TRUE;
|
||||
$id_field->options['alter']['path'] = $path = $this->randomMachineName() . ' ' . $this->randomMachineName();
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) {
|
||||
return $id_field->theme($row);
|
||||
});
|
||||
$this->assertSubString($output, str_replace(' ', '-', $path));
|
||||
$id_field->options['alter']['replace_spaces'] = FALSE;
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) {
|
||||
return $id_field->theme($row);
|
||||
});
|
||||
// The url has a space in it, so to check we have to decode the url output.
|
||||
$this->assertSubString(urldecode($output), $path);
|
||||
|
||||
// Tests the external flag.
|
||||
// Switch on the external flag should output an external url as well.
|
||||
$id_field->options['alter']['external'] = TRUE;
|
||||
$id_field->options['alter']['path'] = $path = 'www.drupal.org';
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) {
|
||||
return $id_field->theme($row);
|
||||
});
|
||||
$this->assertSubString($output, 'http://www.drupal.org');
|
||||
|
||||
// Setup a not external url, which shouldn't lead to an external url.
|
||||
$id_field->options['alter']['external'] = FALSE;
|
||||
$id_field->options['alter']['path'] = $path = 'www.drupal.org';
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) {
|
||||
return $id_field->theme($row);
|
||||
});
|
||||
$this->assertNotSubString($output, 'http://www.drupal.org');
|
||||
|
||||
// Tests the transforming of the case setting.
|
||||
$id_field->options['alter']['path'] = $path = $this->randomMachineName();
|
||||
$id_field->options['alter']['path_case'] = 'none';
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) {
|
||||
return $id_field->theme($row);
|
||||
});
|
||||
$this->assertSubString($output, $path);
|
||||
|
||||
// Switch to uppercase and lowercase.
|
||||
$id_field->options['alter']['path_case'] = 'upper';
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) {
|
||||
return $id_field->theme($row);
|
||||
});
|
||||
$this->assertSubString($output, strtoupper($path));
|
||||
$id_field->options['alter']['path_case'] = 'lower';
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) {
|
||||
return $id_field->theme($row);
|
||||
});
|
||||
$this->assertSubString($output, strtolower($path));
|
||||
|
||||
// Switch to ucfirst and ucwords.
|
||||
$id_field->options['alter']['path_case'] = 'ucfirst';
|
||||
$id_field->options['alter']['path'] = 'drupal has a great community';
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) {
|
||||
return $id_field->theme($row);
|
||||
});
|
||||
$this->assertSubString($output, UrlHelper::encodePath('Drupal has a great community'));
|
||||
|
||||
$id_field->options['alter']['path_case'] = 'ucwords';
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) {
|
||||
return $id_field->theme($row);
|
||||
});
|
||||
$this->assertSubString($output, UrlHelper::encodePath('Drupal Has A Great Community'));
|
||||
unset($id_field->options['alter']['path_case']);
|
||||
|
||||
// Tests the linkclass setting and see whether it actually exists in the
|
||||
// output.
|
||||
$id_field->options['alter']['link_class'] = $class = $this->randomMachineName();
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) {
|
||||
return $id_field->theme($row);
|
||||
});
|
||||
$elements = $this->xpathContent($output, '//a[contains(@class, :class)]', [':class' => $class]);
|
||||
$this->assertTrue($elements);
|
||||
// @fixme link_class, alt, rel cannot be unset, which should be fixed.
|
||||
$id_field->options['alter']['link_class'] = '';
|
||||
|
||||
// Tests the alt setting.
|
||||
$id_field->options['alter']['alt'] = $rel = $this->randomMachineName();
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) {
|
||||
return $id_field->theme($row);
|
||||
});
|
||||
$elements = $this->xpathContent($output, '//a[contains(@title, :alt)]', [':alt' => $rel]);
|
||||
$this->assertTrue($elements);
|
||||
$id_field->options['alter']['alt'] = '';
|
||||
|
||||
// Tests the rel setting.
|
||||
$id_field->options['alter']['rel'] = $rel = $this->randomMachineName();
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) {
|
||||
return $id_field->theme($row);
|
||||
});
|
||||
$elements = $this->xpathContent($output, '//a[contains(@rel, :rel)]', [':rel' => $rel]);
|
||||
$this->assertTrue($elements);
|
||||
$id_field->options['alter']['rel'] = '';
|
||||
|
||||
// Tests the target setting.
|
||||
$id_field->options['alter']['target'] = $target = $this->randomMachineName();
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) {
|
||||
return $id_field->theme($row);
|
||||
});
|
||||
$elements = $this->xpathContent($output, '//a[contains(@target, :target)]', [':target' => $target]);
|
||||
$this->assertTrue($elements);
|
||||
unset($id_field->options['alter']['target']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the field/label/wrapper classes.
|
||||
*/
|
||||
public function testFieldClasses() {
|
||||
/** @var \Drupal\Core\Render\RendererInterface $renderer */
|
||||
$renderer = $this->container->get('renderer');
|
||||
$view = Views::getView('test_field_classes');
|
||||
$view->initHandlers();
|
||||
|
||||
// Tests whether the default field classes are added.
|
||||
$id_field = $view->field['id'];
|
||||
|
||||
$id_field->options['element_default_classes'] = FALSE;
|
||||
// Setup some kind of label by default.
|
||||
$id_field->options['label'] = $this->randomMachineName();
|
||||
$output = $view->preview();
|
||||
$output = $renderer->renderRoot($output);
|
||||
$this->assertFalse($this->xpathContent($output, '//div[contains(@class, :class)]', [':class' => 'field-content']));
|
||||
$this->assertFalse($this->xpathContent($output, '//div[contains(@class, :class)]', [':class' => 'field__label']));
|
||||
|
||||
$id_field->options['element_default_classes'] = TRUE;
|
||||
$output = $view->preview();
|
||||
$output = $renderer->renderRoot($output);
|
||||
// Per default the label and the element of the field are spans.
|
||||
$this->assertTrue($this->xpathContent($output, '//span[contains(@class, :class)]', [':class' => 'field-content']));
|
||||
$this->assertTrue($this->xpathContent($output, '//span[contains(@class, :class)]', [':class' => 'views-label']));
|
||||
$this->assertTrue($this->xpathContent($output, '//div[contains(@class, :class)]', [':class' => 'views-field']));
|
||||
|
||||
// Tests the element wrapper classes/element.
|
||||
$random_class = $this->randomMachineName();
|
||||
|
||||
// Set some common wrapper element types and see whether they appear with and without a custom class set.
|
||||
foreach (['h1', 'span', 'p', 'div'] as $element_type) {
|
||||
$id_field->options['element_wrapper_type'] = $element_type;
|
||||
|
||||
// Set a custom wrapper element css class.
|
||||
$id_field->options['element_wrapper_class'] = $random_class;
|
||||
$output = $view->preview();
|
||||
$output = $renderer->renderRoot($output);
|
||||
$this->assertTrue($this->xpathContent($output, "//{$element_type}[contains(@class, :class)]", [':class' => $random_class]));
|
||||
|
||||
// Set no custom css class.
|
||||
$id_field->options['element_wrapper_class'] = '';
|
||||
$output = $view->preview();
|
||||
$output = $renderer->renderRoot($output);
|
||||
$this->assertFalse($this->xpathContent($output, "//{$element_type}[contains(@class, :class)]", [':class' => $random_class]));
|
||||
$this->assertTrue($this->xpathContent($output, "//li[contains(@class, views-row)]/{$element_type}"));
|
||||
}
|
||||
|
||||
// Tests the label class/element.
|
||||
|
||||
// Set some common label element types and see whether they appear with and without a custom class set.
|
||||
foreach (['h1', 'span', 'p', 'div'] as $element_type) {
|
||||
$id_field->options['element_label_type'] = $element_type;
|
||||
|
||||
// Set a custom label element css class.
|
||||
$id_field->options['element_label_class'] = $random_class;
|
||||
$output = $view->preview();
|
||||
$output = $renderer->renderRoot($output);
|
||||
$this->assertTrue($this->xpathContent($output, "//li[contains(@class, views-row)]//{$element_type}[contains(@class, :class)]", [':class' => $random_class]));
|
||||
|
||||
// Set no custom css class.
|
||||
$id_field->options['element_label_class'] = '';
|
||||
$output = $view->preview();
|
||||
$output = $renderer->renderRoot($output);
|
||||
$this->assertFalse($this->xpathContent($output, "//li[contains(@class, views-row)]//{$element_type}[contains(@class, :class)]", [':class' => $random_class]));
|
||||
$this->assertTrue($this->xpathContent($output, "//li[contains(@class, views-row)]//{$element_type}"));
|
||||
}
|
||||
|
||||
// Tests the element classes/element.
|
||||
|
||||
// Set some common element element types and see whether they appear with and without a custom class set.
|
||||
foreach (['h1', 'span', 'p', 'div'] as $element_type) {
|
||||
$id_field->options['element_type'] = $element_type;
|
||||
|
||||
// Set a custom label element css class.
|
||||
$id_field->options['element_class'] = $random_class;
|
||||
$output = $view->preview();
|
||||
$output = $renderer->renderRoot($output);
|
||||
$this->assertTrue($this->xpathContent($output, "//li[contains(@class, views-row)]//div[contains(@class, views-field)]//{$element_type}[contains(@class, :class)]", [':class' => $random_class]));
|
||||
|
||||
// Set no custom css class.
|
||||
$id_field->options['element_class'] = '';
|
||||
$output = $view->preview();
|
||||
$output = $renderer->renderRoot($output);
|
||||
$this->assertFalse($this->xpathContent($output, "//li[contains(@class, views-row)]//div[contains(@class, views-field)]//{$element_type}[contains(@class, :class)]", [':class' => $random_class]));
|
||||
$this->assertTrue($this->xpathContent($output, "//li[contains(@class, views-row)]//div[contains(@class, views-field)]//{$element_type}"));
|
||||
}
|
||||
|
||||
// Tests the available html elements.
|
||||
$element_types = $id_field->getElements();
|
||||
$expected_elements = [
|
||||
'',
|
||||
0,
|
||||
'div',
|
||||
'span',
|
||||
'h1',
|
||||
'h2',
|
||||
'h3',
|
||||
'h4',
|
||||
'h5',
|
||||
'h6',
|
||||
'p',
|
||||
'strong',
|
||||
'em',
|
||||
'marquee'
|
||||
];
|
||||
|
||||
$this->assertEqual(array_keys($element_types), $expected_elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests trimming/read-more/ellipses.
|
||||
*/
|
||||
public function testTextRendering() {
|
||||
/** @var \Drupal\Core\Render\RendererInterface $renderer */
|
||||
$renderer = \Drupal::service('renderer');
|
||||
|
||||
$view = Views::getView('test_field_output');
|
||||
$view->initHandlers();
|
||||
$name_field = $view->field['name'];
|
||||
|
||||
// Tests stripping of html elements.
|
||||
$this->executeView($view);
|
||||
$random_text = $this->randomMachineName();
|
||||
$name_field->options['alter']['alter_text'] = TRUE;
|
||||
$name_field->options['alter']['text'] = $html_text = '<div class="views-test">' . $random_text . '</div>';
|
||||
$row = $view->result[0];
|
||||
|
||||
$name_field->options['alter']['strip_tags'] = TRUE;
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($name_field, $row) {
|
||||
return $name_field->advancedRender($row);
|
||||
});
|
||||
$this->assertSubString($output, $random_text, 'Find text without html if stripping of views field output is enabled.');
|
||||
$this->assertNotSubString($output, $html_text, 'Find no text with the html if stripping of views field output is enabled.');
|
||||
|
||||
// Tests preserving of html tags.
|
||||
$name_field->options['alter']['preserve_tags'] = '<div>';
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($name_field, $row) {
|
||||
return $name_field->advancedRender($row);
|
||||
});
|
||||
$this->assertSubString($output, $random_text, 'Find text without html if stripping of views field output is enabled but a div is allowed.');
|
||||
$this->assertSubString($output, $html_text, 'Find text with the html if stripping of views field output is enabled but a div is allowed.');
|
||||
|
||||
$name_field->options['alter']['strip_tags'] = FALSE;
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($name_field, $row) {
|
||||
return $name_field->advancedRender($row);
|
||||
});
|
||||
$this->assertSubString($output, $random_text, 'Find text without html if stripping of views field output is disabled.');
|
||||
$this->assertSubString($output, $html_text, 'Find text with the html if stripping of views field output is disabled.');
|
||||
|
||||
// Tests for removing whitespace and the beginning and the end.
|
||||
$name_field->options['alter']['alter_text'] = FALSE;
|
||||
$views_test_data_name = $row->views_test_data_name;
|
||||
$row->views_test_data_name = ' ' . $views_test_data_name . ' ';
|
||||
$name_field->options['alter']['trim_whitespace'] = TRUE;
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($name_field, $row) {
|
||||
return $name_field->advancedRender($row);
|
||||
});
|
||||
|
||||
$this->assertSubString($output, $views_test_data_name, 'Make sure the trimmed text can be found if trimming is enabled.');
|
||||
$this->assertNotSubString($output, $row->views_test_data_name, 'Make sure the untrimmed text can be found if trimming is enabled.');
|
||||
|
||||
$name_field->options['alter']['trim_whitespace'] = FALSE;
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($name_field, $row) {
|
||||
return $name_field->advancedRender($row);
|
||||
});
|
||||
$this->assertSubString($output, $views_test_data_name, 'Make sure the trimmed text can be found if trimming is disabled.');
|
||||
$this->assertSubString($output, $row->views_test_data_name, 'Make sure the untrimmed text can be found if trimming is disabled.');
|
||||
|
||||
// Tests for trimming to a maximum length.
|
||||
$name_field->options['alter']['trim'] = TRUE;
|
||||
$name_field->options['alter']['word_boundary'] = FALSE;
|
||||
|
||||
// Tests for simple trimming by string length.
|
||||
$row->views_test_data_name = $this->randomMachineName(8);
|
||||
$name_field->options['alter']['max_length'] = 5;
|
||||
$trimmed_name = Unicode::substr($row->views_test_data_name, 0, 5);
|
||||
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($name_field, $row) {
|
||||
return $name_field->advancedRender($row);
|
||||
});
|
||||
$this->assertSubString($output, $trimmed_name, format_string('Make sure the trimmed output (@trimmed) appears in the rendered output (@output).', ['@trimmed' => $trimmed_name, '@output' => $output]));
|
||||
$this->assertNotSubString($output, $row->views_test_data_name, format_string("Make sure the untrimmed value (@untrimmed) shouldn't appear in the rendered output (@output).", ['@untrimmed' => $row->views_test_data_name, '@output' => $output]));
|
||||
|
||||
$name_field->options['alter']['max_length'] = 9;
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($name_field, $row) {
|
||||
return $name_field->advancedRender($row);
|
||||
});
|
||||
$this->assertSubString($output, $trimmed_name, format_string('Make sure the untrimmed (@untrimmed) output appears in the rendered output (@output).', ['@trimmed' => $trimmed_name, '@output' => $output]));
|
||||
|
||||
// Take word_boundary into account for the tests.
|
||||
$name_field->options['alter']['max_length'] = 5;
|
||||
$name_field->options['alter']['word_boundary'] = TRUE;
|
||||
$random_text_2 = $this->randomMachineName(2);
|
||||
$random_text_4 = $this->randomMachineName(4);
|
||||
$random_text_8 = $this->randomMachineName(8);
|
||||
$tuples = [
|
||||
// Create one string which doesn't fit at all into the limit.
|
||||
[
|
||||
'value' => $random_text_8,
|
||||
'trimmed_value' => '',
|
||||
'trimmed' => TRUE
|
||||
],
|
||||
// Create one string with two words which doesn't fit both into the limit.
|
||||
[
|
||||
'value' => $random_text_8 . ' ' . $random_text_8,
|
||||
'trimmed_value' => '',
|
||||
'trimmed' => TRUE
|
||||
],
|
||||
// Create one string which contains of two words, of which only the first
|
||||
// fits into the limit.
|
||||
[
|
||||
'value' => $random_text_4 . ' ' . $random_text_8,
|
||||
'trimmed_value' => $random_text_4,
|
||||
'trimmed' => TRUE
|
||||
],
|
||||
// Create one string which contains of two words, of which both fits into
|
||||
// the limit.
|
||||
[
|
||||
'value' => $random_text_2 . ' ' . $random_text_2,
|
||||
'trimmed_value' => $random_text_2 . ' ' . $random_text_2,
|
||||
'trimmed' => FALSE
|
||||
]
|
||||
];
|
||||
|
||||
foreach ($tuples as $tuple) {
|
||||
$row->views_test_data_name = $tuple['value'];
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($name_field, $row) {
|
||||
return $name_field->advancedRender($row);
|
||||
});
|
||||
|
||||
if ($tuple['trimmed']) {
|
||||
$this->assertNotSubString($output, $tuple['value'], format_string('The untrimmed value (@untrimmed) should not appear in the trimmed output (@output).', ['@untrimmed' => $tuple['value'], '@output' => $output]));
|
||||
}
|
||||
if (!empty($tuple['trimmed_value'])) {
|
||||
$this->assertSubString($output, $tuple['trimmed_value'], format_string('The trimmed value (@trimmed) should appear in the trimmed output (@output).', ['@trimmed' => $tuple['trimmed_value'], '@output' => $output]));
|
||||
}
|
||||
}
|
||||
|
||||
// Tests for displaying a readmore link when the output got trimmed.
|
||||
$row->views_test_data_name = $this->randomMachineName(8);
|
||||
$name_field->options['alter']['max_length'] = 5;
|
||||
$name_field->options['alter']['more_link'] = TRUE;
|
||||
$name_field->options['alter']['more_link_text'] = $more_text = $this->randomMachineName();
|
||||
$name_field->options['alter']['more_link_path'] = $more_path = $this->randomMachineName();
|
||||
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($name_field, $row) {
|
||||
return $name_field->advancedRender($row);
|
||||
});
|
||||
$this->assertSubString($output, $more_text, 'Make sure a read more text is displayed if the output got trimmed');
|
||||
$this->assertTrue($this->xpathContent($output, '//a[contains(@href, :path)]', [':path' => $more_path]), 'Make sure the read more link points to the right destination.');
|
||||
|
||||
$name_field->options['alter']['more_link'] = FALSE;
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($name_field, $row) {
|
||||
return $name_field->advancedRender($row);
|
||||
});
|
||||
$this->assertNotSubString($output, $more_text, 'Make sure no read more text appears.');
|
||||
$this->assertFalse($this->xpathContent($output, '//a[contains(@href, :path)]', [':path' => $more_path]), 'Make sure no read more link appears.');
|
||||
|
||||
// Check for the ellipses.
|
||||
$row->views_test_data_name = $this->randomMachineName(8);
|
||||
$name_field->options['alter']['max_length'] = 5;
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($name_field, $row) {
|
||||
return $name_field->advancedRender($row);
|
||||
});
|
||||
$this->assertSubString($output, '…', 'An ellipsis should appear if the output is trimmed');
|
||||
$name_field->options['alter']['max_length'] = 10;
|
||||
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($name_field, $row) {
|
||||
return $name_field->advancedRender($row);
|
||||
});
|
||||
$this->assertNotSubString($output, '…', 'No ellipsis should appear if the output is not trimmed');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,319 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Handler;
|
||||
|
||||
use Drupal\config\Tests\SchemaCheckTestTrait;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the core Drupal\views\Plugin\views\filter\Date handler.
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class FilterDateTest extends ViewTestBase {
|
||||
use SchemaCheckTestTrait;
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_filter_date_between'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node', 'views_ui', 'datetime'];
|
||||
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
// Add a date field so we can test datetime handling.
|
||||
NodeType::create([
|
||||
'type' => 'page',
|
||||
'name' => 'Page',
|
||||
])->save();
|
||||
|
||||
// Setup a field storage and field, but also change the views data for the
|
||||
// entity_test entity type.
|
||||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => 'field_date',
|
||||
'type' => 'datetime',
|
||||
'entity_type' => 'node',
|
||||
]);
|
||||
$field_storage->save();
|
||||
|
||||
$field = FieldConfig::create([
|
||||
'field_name' => 'field_date',
|
||||
'entity_type' => 'node',
|
||||
'bundle' => 'page',
|
||||
]);
|
||||
$field->save();
|
||||
|
||||
// Add some basic test nodes.
|
||||
$this->nodes = [];
|
||||
$this->nodes[] = $this->drupalCreateNode(['created' => 100000, 'field_date' => 10000]);
|
||||
$this->nodes[] = $this->drupalCreateNode(['created' => 200000, 'field_date' => 20000]);
|
||||
$this->nodes[] = $this->drupalCreateNode(['created' => 300000, 'field_date' => 30000]);
|
||||
$this->nodes[] = $this->drupalCreateNode(['created' => time() + 86400, 'field_date' => time() + 86400]);
|
||||
|
||||
$this->map = [
|
||||
'nid' => 'nid',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs other test methods.
|
||||
*/
|
||||
public function testDateFilter() {
|
||||
$this->_testOffset();
|
||||
$this->_testBetween();
|
||||
$this->_testUiValidation();
|
||||
$this->_testFilterDateUI();
|
||||
$this->_testFilterDatetimeUI();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the general offset functionality.
|
||||
*/
|
||||
protected function _testOffset() {
|
||||
$view = Views::getView('test_filter_date_between');
|
||||
|
||||
// Test offset for simple operator.
|
||||
$view->initHandlers();
|
||||
$view->filter['created']->operator = '>';
|
||||
$view->filter['created']->value['type'] = 'offset';
|
||||
$view->filter['created']->value['value'] = '+1 hour';
|
||||
$view->executeDisplay('default');
|
||||
$expected_result = [
|
||||
['nid' => $this->nodes[3]->id()],
|
||||
];
|
||||
$this->assertIdenticalResultset($view, $expected_result, $this->map);
|
||||
$view->destroy();
|
||||
|
||||
// Test offset for between operator.
|
||||
$view->initHandlers();
|
||||
$view->filter['created']->operator = 'between';
|
||||
$view->filter['created']->value['type'] = 'offset';
|
||||
$view->filter['created']->value['max'] = '+2 days';
|
||||
$view->filter['created']->value['min'] = '+1 hour';
|
||||
$view->executeDisplay('default');
|
||||
$expected_result = [
|
||||
['nid' => $this->nodes[3]->id()],
|
||||
];
|
||||
$this->assertIdenticalResultset($view, $expected_result, $this->map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the filter operator between/not between.
|
||||
*/
|
||||
protected function _testBetween() {
|
||||
$view = Views::getView('test_filter_date_between');
|
||||
|
||||
// Test between with min and max.
|
||||
$view->initHandlers();
|
||||
$view->filter['created']->operator = 'between';
|
||||
$view->filter['created']->value['min'] = format_date(150000, 'custom', 'Y-m-d H:i:s');
|
||||
$view->filter['created']->value['max'] = format_date(200000, 'custom', 'Y-m-d H:i:s');
|
||||
$view->executeDisplay('default');
|
||||
$expected_result = [
|
||||
['nid' => $this->nodes[1]->id()],
|
||||
];
|
||||
$this->assertIdenticalResultset($view, $expected_result, $this->map);
|
||||
$view->destroy();
|
||||
|
||||
// Test between with just max.
|
||||
$view->initHandlers();
|
||||
$view->filter['created']->operator = 'between';
|
||||
$view->filter['created']->value['max'] = format_date(200000, 'custom', 'Y-m-d H:i:s');
|
||||
$view->executeDisplay('default');
|
||||
$expected_result = [
|
||||
['nid' => $this->nodes[0]->id()],
|
||||
['nid' => $this->nodes[1]->id()],
|
||||
];
|
||||
$this->assertIdenticalResultset($view, $expected_result, $this->map);
|
||||
$view->destroy();
|
||||
|
||||
// Test not between with min and max.
|
||||
$view->initHandlers();
|
||||
$view->filter['created']->operator = 'not between';
|
||||
$view->filter['created']->value['min'] = format_date(100000, 'custom', 'Y-m-d H:i:s');
|
||||
$view->filter['created']->value['max'] = format_date(200000, 'custom', 'Y-m-d H:i:s');
|
||||
|
||||
$view->executeDisplay('default');
|
||||
$expected_result = [
|
||||
['nid' => $this->nodes[2]->id()],
|
||||
['nid' => $this->nodes[3]->id()],
|
||||
];
|
||||
$this->assertIdenticalResultset($view, $expected_result, $this->map);
|
||||
$view->destroy();
|
||||
|
||||
// Test not between with just max.
|
||||
$view->initHandlers();
|
||||
$view->filter['created']->operator = 'not between';
|
||||
$view->filter['created']->value['max'] = format_date(200000, 'custom', 'Y-m-d H:i:s');
|
||||
$view->executeDisplay('default');
|
||||
$expected_result = [
|
||||
['nid' => $this->nodes[2]->id()],
|
||||
['nid' => $this->nodes[3]->id()],
|
||||
];
|
||||
$this->assertIdenticalResultset($view, $expected_result, $this->map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure the validation callbacks works.
|
||||
*/
|
||||
protected function _testUiValidation() {
|
||||
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer views', 'administer site configuration']));
|
||||
|
||||
$this->drupalGet('admin/structure/views/view/test_filter_date_between/edit');
|
||||
$this->drupalGet('admin/structure/views/nojs/handler/test_filter_date_between/default/filter/created');
|
||||
|
||||
$edit = [];
|
||||
// Generate a definitive wrong value, which should be checked by validation.
|
||||
$edit['options[value][value]'] = $this->randomString() . '-------';
|
||||
$this->drupalPostForm(NULL, $edit, t('Apply'));
|
||||
$this->assertText(t('Invalid date format.'), 'Make sure that validation is run and the invalidate date format is identified.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test date filter UI.
|
||||
*/
|
||||
protected function _testFilterDateUI() {
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer views']));
|
||||
$this->drupalGet('admin/structure/views/nojs/handler/test_filter_date_between/default/filter/created');
|
||||
$this->drupalPostForm(NULL, [], t('Expose filter'));
|
||||
$this->drupalPostForm(NULL, [], t('Grouped filters'));
|
||||
|
||||
$edit = [];
|
||||
$edit['options[group_info][group_items][1][title]'] = 'simple-offset';
|
||||
$edit['options[group_info][group_items][1][operator]'] = '>';
|
||||
$edit['options[group_info][group_items][1][value][type]'] = 'offset';
|
||||
$edit['options[group_info][group_items][1][value][value]'] = '+1 hour';
|
||||
$edit['options[group_info][group_items][2][title]'] = 'between-offset';
|
||||
$edit['options[group_info][group_items][2][operator]'] = 'between';
|
||||
$edit['options[group_info][group_items][2][value][type]'] = 'offset';
|
||||
$edit['options[group_info][group_items][2][value][min]'] = '+1 hour';
|
||||
$edit['options[group_info][group_items][2][value][max]'] = '+2 days';
|
||||
$edit['options[group_info][group_items][3][title]'] = 'between-date';
|
||||
$edit['options[group_info][group_items][3][operator]'] = 'between';
|
||||
$edit['options[group_info][group_items][3][value][min]'] = format_date(150000, 'custom', 'Y-m-d H:i:s');
|
||||
$edit['options[group_info][group_items][3][value][max]'] = format_date(250000, 'custom', 'Y-m-d H:i:s');
|
||||
|
||||
$this->drupalPostForm(NULL, $edit, t('Apply'));
|
||||
|
||||
$this->drupalGet('admin/structure/views/nojs/handler/test_filter_date_between/default/filter/created');
|
||||
foreach ($edit as $name => $value) {
|
||||
$this->assertFieldByName($name, $value);
|
||||
if (strpos($name, '[value][type]')) {
|
||||
$radio = $this->cssSelect('input[name="' . $name . '"][checked="checked"][type="radio"]');
|
||||
$this->assertEqual($radio[0]->getAttribute('value'), $value);
|
||||
}
|
||||
}
|
||||
|
||||
$this->drupalPostForm('admin/structure/views/view/test_filter_date_between', [], t('Save'));
|
||||
$this->assertConfigSchemaByName('views.view.test_filter_date_between');
|
||||
|
||||
// Test that the exposed filter works as expected.
|
||||
$path = 'test_filter_date_between-path';
|
||||
$this->drupalPostForm('admin/structure/views/view/test_filter_date_between/edit', [], 'Add Page');
|
||||
$this->drupalPostForm('admin/structure/views/nojs/display/test_filter_date_between/page_1/path', ['path' => $path], 'Apply');
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
|
||||
$this->drupalGet($path);
|
||||
$this->drupalPostForm(NULL, [], 'Apply');
|
||||
$results = $this->cssSelect('.view-content .field-content');
|
||||
$this->assertEqual(count($results), 4);
|
||||
$this->drupalPostForm(NULL, ['created' => '1'], 'Apply');
|
||||
$results = $this->cssSelect('.view-content .field-content');
|
||||
$this->assertEqual(count($results), 1);
|
||||
$this->assertEqual($results[0]->getText(), $this->nodes[3]->id());
|
||||
$this->drupalPostForm(NULL, ['created' => '2'], 'Apply');
|
||||
$results = $this->cssSelect('.view-content .field-content');
|
||||
$this->assertEqual(count($results), 1);
|
||||
$this->assertEqual($results[0]->getText(), $this->nodes[3]->id());
|
||||
$this->drupalPostForm(NULL, ['created' => '3'], 'Apply');
|
||||
$results = $this->cssSelect('.view-content .field-content');
|
||||
$this->assertEqual(count($results), 1);
|
||||
$this->assertEqual($results[0]->getText(), $this->nodes[1]->id());
|
||||
|
||||
// Change the filter to a single filter to test the schema when the operator
|
||||
// is not exposed.
|
||||
$this->drupalPostForm('admin/structure/views/nojs/handler/test_filter_date_between/default/filter/created', [], t('Single filter'));
|
||||
$edit = [];
|
||||
$edit['options[operator]'] = '>';
|
||||
$edit['options[value][type]'] = 'date';
|
||||
$edit['options[value][value]'] = format_date(350000, 'custom', 'Y-m-d H:i:s');
|
||||
$this->drupalPostForm(NULL, $edit, t('Apply'));
|
||||
$this->drupalPostForm('admin/structure/views/view/test_filter_date_between', [], t('Save'));
|
||||
$this->assertConfigSchemaByName('views.view.test_filter_date_between');
|
||||
|
||||
// Test that the filter works as expected.
|
||||
$this->drupalGet($path);
|
||||
$results = $this->cssSelect('.view-content .field-content');
|
||||
$this->assertEqual(count($results), 1);
|
||||
$this->assertEqual($results[0]->getText(), $this->nodes[3]->id());
|
||||
$this->drupalPostForm(NULL, ['created' => format_date(250000, 'custom', 'Y-m-d H:i:s')], 'Apply');
|
||||
$results = $this->cssSelect('.view-content .field-content');
|
||||
$this->assertEqual(count($results), 2);
|
||||
$this->assertEqual($results[0]->getText(), $this->nodes[2]->id());
|
||||
$this->assertEqual($results[1]->getText(), $this->nodes[3]->id());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test datetime grouped filter UI.
|
||||
*/
|
||||
protected function _testFilterDatetimeUI() {
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer views']));
|
||||
$this->drupalPostForm('admin/structure/views/nojs/add-handler/test_filter_date_between/default/filter', ['name[node__field_date.field_date_value]' => 'node__field_date.field_date_value'], t('Add and configure filter criteria'));
|
||||
|
||||
$this->drupalPostForm(NULL, [], t('Expose filter'));
|
||||
$this->drupalPostForm(NULL, [], t('Grouped filters'));
|
||||
|
||||
$edit = [];
|
||||
$edit['options[group_info][group_items][1][title]'] = 'simple-offset';
|
||||
$edit['options[group_info][group_items][1][operator]'] = '>';
|
||||
$edit['options[group_info][group_items][1][value][type]'] = 'offset';
|
||||
$edit['options[group_info][group_items][1][value][value]'] = '+1 hour';
|
||||
$edit['options[group_info][group_items][2][title]'] = 'between-offset';
|
||||
$edit['options[group_info][group_items][2][operator]'] = 'between';
|
||||
$edit['options[group_info][group_items][2][value][type]'] = 'offset';
|
||||
$edit['options[group_info][group_items][2][value][min]'] = '+1 hour';
|
||||
$edit['options[group_info][group_items][2][value][max]'] = '+2 days';
|
||||
$edit['options[group_info][group_items][3][title]'] = 'between-date';
|
||||
$edit['options[group_info][group_items][3][operator]'] = 'between';
|
||||
$edit['options[group_info][group_items][3][value][min]'] = format_date(150000, 'custom', 'Y-m-d H:i:s');
|
||||
$edit['options[group_info][group_items][3][value][max]'] = format_date(250000, 'custom', 'Y-m-d H:i:s');
|
||||
|
||||
$this->drupalPostForm(NULL, $edit, t('Apply'));
|
||||
|
||||
$this->drupalPostForm('admin/structure/views/view/test_filter_date_between', [], t('Save'));
|
||||
$this->assertConfigSchemaByName('views.view.test_filter_date_between');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the exposed date filter is displayed without errors.
|
||||
*/
|
||||
public function testExposedFilter() {
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer views']));
|
||||
$this->drupalPostForm('admin/structure/views/nojs/handler/test_filter_date_between/default/filter/created', [], t('Expose filter'));
|
||||
$this->drupalPostForm('admin/structure/views/view/test_filter_date_between/edit', [], t('Add Page'));
|
||||
$edit = [
|
||||
'path' => 'exposed-date-filter',
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/views/nojs/display/test_filter_date_between/page_1/path', $edit, t('Apply'));
|
||||
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
|
||||
$this->drupalGet('exposed-date-filter');
|
||||
$this->assertField('created');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Handler;
|
||||
|
||||
use Drupal\comment\Tests\CommentTestTrait;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\ViewExecutable;
|
||||
use Drupal\views\Plugin\views\HandlerBase;
|
||||
use Drupal\views\Plugin\views\filter\InOperator;
|
||||
use Drupal\views\Entity\View;
|
||||
|
||||
/**
|
||||
* Tests instances of all handlers.
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class HandlerAllTest extends ViewTestBase {
|
||||
|
||||
use CommentTestTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = [
|
||||
'aggregator',
|
||||
'book',
|
||||
'block',
|
||||
'comment',
|
||||
'contact',
|
||||
'field',
|
||||
'filter',
|
||||
'file',
|
||||
'forum',
|
||||
'history',
|
||||
'language',
|
||||
'locale',
|
||||
'node',
|
||||
'search',
|
||||
'statistics',
|
||||
'taxonomy',
|
||||
'user',
|
||||
];
|
||||
|
||||
/**
|
||||
* Tests most of the handlers.
|
||||
*/
|
||||
public function testHandlers() {
|
||||
$this->drupalCreateContentType(['type' => 'article']);
|
||||
$this->addDefaultCommentField('node', 'article');
|
||||
|
||||
$object_types = array_keys(ViewExecutable::getHandlerTypes());
|
||||
foreach ($this->container->get('views.views_data')->get() as $base_table => $info) {
|
||||
if (!isset($info['table']['base'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$view = View::create(['base_table' => $base_table]);
|
||||
$view = $view->getExecutable();
|
||||
|
||||
// @todo The groupwise relationship is currently broken.
|
||||
$exclude[] = 'taxonomy_term_field_data:tid_representative';
|
||||
$exclude[] = 'users_field_data:uid_representative';
|
||||
|
||||
// Go through all fields and there through all handler types.
|
||||
foreach ($info as $field => $field_info) {
|
||||
// Table is a reserved key for the metainformation.
|
||||
if ($field != 'table' && !in_array("$base_table:$field", $exclude)) {
|
||||
$item = [
|
||||
'table' => $base_table,
|
||||
'field' => $field,
|
||||
];
|
||||
foreach ($object_types as $type) {
|
||||
if (isset($field_info[$type]['id'])) {
|
||||
$options = [];
|
||||
if ($type == 'filter') {
|
||||
$handler = $this->container->get("plugin.manager.views.$type")->getHandler($item);
|
||||
// Set the value to use for the filter based on the filter type.
|
||||
if ($handler instanceof InOperator) {
|
||||
$options['value'] = [1];
|
||||
}
|
||||
else {
|
||||
$options['value'] = 1;
|
||||
}
|
||||
}
|
||||
$view->addHandler('default', $type, $base_table, $field, $options);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Go through each step individually to see whether some parts are
|
||||
// failing.
|
||||
$view->build();
|
||||
$view->preExecute();
|
||||
$view->execute();
|
||||
$view->render();
|
||||
|
||||
// Make sure all handlers extend the HandlerBase.
|
||||
foreach ($object_types as $type) {
|
||||
if (isset($view->{$type})) {
|
||||
foreach ($view->{$type} as $handler) {
|
||||
$this->assertTrue($handler instanceof HandlerBase, format_string(
|
||||
'@type handler of class %class is an instance of HandlerBase',
|
||||
[
|
||||
'@type' => $type,
|
||||
'%class' => get_class($handler),
|
||||
]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,400 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Handler;
|
||||
|
||||
use Drupal\comment\Tests\CommentTestTrait;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Entity\View;
|
||||
use Drupal\views\ViewExecutable;
|
||||
use Drupal\views\Plugin\views\HandlerBase;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests abstract handler definitions.
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class HandlerTest extends ViewTestBase {
|
||||
|
||||
use CommentTestTrait;
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_view', 'test_view_handler_weight', 'test_handler_relationships', 'test_handler_test_access', 'test_filter_in_operator_ui'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['views_ui', 'comment', 'node'];
|
||||
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
$this->drupalCreateContentType(['type' => 'page']);
|
||||
$this->addDefaultCommentField('node', 'page');
|
||||
$this->enableViewsTestModule();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function viewsData() {
|
||||
$data = parent::viewsData();
|
||||
// Override the name handler to be able to call placeholder() from outside.
|
||||
$data['views_test_data']['name']['field']['id'] = 'test_field';
|
||||
|
||||
// Setup one field with an access callback and one with an access callback
|
||||
// and arguments.
|
||||
$data['views_test_data']['access_callback'] = $data['views_test_data']['id'];
|
||||
$data['views_test_data']['access_callback_arguments'] = $data['views_test_data']['id'];
|
||||
foreach (ViewExecutable::getHandlerTypes() as $type => $info) {
|
||||
if (isset($data['views_test_data']['access_callback'][$type]['id'])) {
|
||||
$data['views_test_data']['access_callback'][$type]['access callback'] = 'views_test_data_handler_test_access_callback';
|
||||
|
||||
$data['views_test_data']['access_callback_arguments'][$type]['access callback'] = 'views_test_data_handler_test_access_callback_argument';
|
||||
$data['views_test_data']['access_callback_arguments'][$type]['access arguments'] = [TRUE];
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the breakString method.
|
||||
*/
|
||||
public function testBreakString() {
|
||||
// Check defaults.
|
||||
$this->assertEqual((object) ['value' => [], 'operator' => NULL], HandlerBase::breakString(''));
|
||||
|
||||
// Test ors
|
||||
$handler = HandlerBase::breakString('word1 word2+word');
|
||||
$this->assertEqualValue(['word1', 'word2', 'word'], $handler);
|
||||
$this->assertEqual('or', $handler->operator);
|
||||
$handler = HandlerBase::breakString('word1+word2+word');
|
||||
$this->assertEqualValue(['word1', 'word2', 'word'], $handler);
|
||||
$this->assertEqual('or', $handler->operator);
|
||||
$handler = HandlerBase::breakString('word1 word2 word');
|
||||
$this->assertEqualValue(['word1', 'word2', 'word'], $handler);
|
||||
$this->assertEqual('or', $handler->operator);
|
||||
$handler = HandlerBase::breakString('word-1+word-2+word');
|
||||
$this->assertEqualValue(['word-1', 'word-2', 'word'], $handler);
|
||||
$this->assertEqual('or', $handler->operator);
|
||||
$handler = HandlerBase::breakString('wõrd1+wõrd2+wõrd');
|
||||
$this->assertEqualValue(['wõrd1', 'wõrd2', 'wõrd'], $handler);
|
||||
$this->assertEqual('or', $handler->operator);
|
||||
|
||||
// Test ands.
|
||||
$handler = HandlerBase::breakString('word1,word2,word');
|
||||
$this->assertEqualValue(['word1', 'word2', 'word'], $handler);
|
||||
$this->assertEqual('and', $handler->operator);
|
||||
$handler = HandlerBase::breakString('word1 word2,word');
|
||||
$this->assertEqualValue(['word1 word2', 'word'], $handler);
|
||||
$this->assertEqual('and', $handler->operator);
|
||||
$handler = HandlerBase::breakString('word1,word2 word');
|
||||
$this->assertEqualValue(['word1', 'word2 word'], $handler);
|
||||
$this->assertEqual('and', $handler->operator);
|
||||
$handler = HandlerBase::breakString('word-1,word-2,word');
|
||||
$this->assertEqualValue(['word-1', 'word-2', 'word'], $handler);
|
||||
$this->assertEqual('and', $handler->operator);
|
||||
$handler = HandlerBase::breakString('wõrd1,wõrd2,wõrd');
|
||||
$this->assertEqualValue(['wõrd1', 'wõrd2', 'wõrd'], $handler);
|
||||
$this->assertEqual('and', $handler->operator);
|
||||
|
||||
// Test a single word
|
||||
$handler = HandlerBase::breakString('word');
|
||||
$this->assertEqualValue(['word'], $handler);
|
||||
$this->assertEqual('and', $handler->operator);
|
||||
|
||||
$s1 = $this->randomMachineName();
|
||||
// Generate three random numbers which can be used below;
|
||||
$n1 = rand(0, 100);
|
||||
$n2 = rand(0, 100);
|
||||
$n3 = rand(0, 100);
|
||||
|
||||
// Test "or"s.
|
||||
$handlerBase = HandlerBase::breakString("$s1 $n2+$n3");
|
||||
$this->assertEqualValue([$s1, $n2, $n3], $handlerBase);
|
||||
$this->assertEqual('or', $handlerBase->operator);
|
||||
|
||||
$handlerBase = HandlerBase::breakString("$s1+$n2+$n3");
|
||||
$this->assertEqualValue([$s1, $n2, $n3], $handlerBase);
|
||||
$this->assertEqual('or', $handlerBase->operator);
|
||||
|
||||
$handlerBase = HandlerBase::breakString("$s1 $n2 $n3");
|
||||
$this->assertEqualValue([$s1, $n2, $n3], $handlerBase);
|
||||
$this->assertEqual('or', $handlerBase->operator);
|
||||
|
||||
$handlerBase = HandlerBase::breakString("$s1 $n2++$n3");
|
||||
$this->assertEqualValue([$s1, $n2, $n3], $handlerBase);
|
||||
$this->assertEqual('or', $handlerBase->operator);
|
||||
|
||||
// Test "and"s.
|
||||
$handlerBase = HandlerBase::breakString("$s1,$n2,$n3");
|
||||
$this->assertEqualValue([$s1, $n2, $n3], $handlerBase);
|
||||
$this->assertEqual('and', $handlerBase->operator);
|
||||
|
||||
$handlerBase = HandlerBase::breakString("$s1,,$n2,$n3");
|
||||
$this->assertEqualValue([$s1, $n2, $n3], $handlerBase);
|
||||
$this->assertEqual('and', $handlerBase->operator);
|
||||
|
||||
// Enforce int values.
|
||||
$handlerBase = HandlerBase::breakString("$n1,$n2,$n3", TRUE);
|
||||
$this->assertEqualValue([$n1, $n2, $n3], $handlerBase);
|
||||
$this->assertEqual('and', $handlerBase->operator);
|
||||
|
||||
$handlerBase = HandlerBase::breakString("$n1+$n2+$n3", TRUE);
|
||||
$this->assertEqualValue([$n1, $n2, $n3], $handlerBase);
|
||||
$this->assertEqual('or', $handlerBase->operator);
|
||||
|
||||
$handlerBase = HandlerBase::breakString("$s1,$n2,$n3", TRUE);
|
||||
$this->assertEqualValue([(int) $s1, $n2, $n3], $handlerBase);
|
||||
$this->assertEqual('and', $handlerBase->operator);
|
||||
|
||||
$handlerBase = HandlerBase::breakString("$s1+$n2+$n3", TRUE);
|
||||
$this->assertEqualValue([(int) $s1, $n2, $n3], $handlerBase);
|
||||
$this->assertEqual('or', $handlerBase->operator);
|
||||
|
||||
// Generate three random decimals which can be used below;
|
||||
$d1 = rand(0, 10) / 10;
|
||||
$d2 = rand(0, 10) / 10;
|
||||
$d3 = rand(0, 10) / 10;
|
||||
|
||||
// Test "or"s.
|
||||
$handlerBase = HandlerBase::breakString("$s1 $d1+$d2");
|
||||
$this->assertEqualValue([$s1, $d1, $d2], $handlerBase);
|
||||
$this->assertEqual('or', $handlerBase->operator);
|
||||
|
||||
$handlerBase = HandlerBase::breakString("$s1+$d1+$d3");
|
||||
$this->assertEqualValue([$s1, $d1, $d3], $handlerBase);
|
||||
$this->assertEqual('or', $handlerBase->operator);
|
||||
|
||||
$handlerBase = HandlerBase::breakString("$s1 $d2 $d3");
|
||||
$this->assertEqualValue([$s1, $d2, $d3], $handlerBase);
|
||||
$this->assertEqual('or', $handlerBase->operator);
|
||||
|
||||
$handlerBase = HandlerBase::breakString("$s1 $d2++$d3");
|
||||
$this->assertEqualValue([$s1, $d2, $d3], $handlerBase);
|
||||
$this->assertEqual('or', $handlerBase->operator);
|
||||
|
||||
// Test "and"s.
|
||||
$handlerBase = HandlerBase::breakString("$s1,$d2,$d3");
|
||||
$this->assertEqualValue([$s1, $d2, $d3], $handlerBase);
|
||||
$this->assertEqual('and', $handlerBase->operator);
|
||||
|
||||
$handlerBase = HandlerBase::breakString("$s1,,$d2,$d3");
|
||||
$this->assertEqualValue([$s1, $d2, $d3], $handlerBase);
|
||||
$this->assertEqual('and', $handlerBase->operator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the order of handlers is the same before and after saving.
|
||||
*/
|
||||
public function testHandlerWeights() {
|
||||
$handler_types = ['fields', 'filters', 'sorts'];
|
||||
|
||||
$view = Views::getView('test_view_handler_weight');
|
||||
$view->initDisplay();
|
||||
|
||||
// Store the order of handlers before saving the view.
|
||||
$original_order = [];
|
||||
foreach ($handler_types as $type) {
|
||||
$original_order[$type] = array_keys($view->display_handler->getOption($type));
|
||||
}
|
||||
|
||||
// Save the view and see if our filters are in the same order.
|
||||
$view->save();
|
||||
$view = views::getView('test_view_handler_weight');
|
||||
$view->initDisplay();
|
||||
|
||||
foreach ($handler_types as $type) {
|
||||
$loaded_order = array_keys($view->display_handler->getOption($type));
|
||||
$this->assertIdentical($original_order[$type], $loaded_order);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if a value is the same as the value on a certain handler.
|
||||
*
|
||||
* @param $expected
|
||||
* The expected value to check.
|
||||
* @param \Drupal\views\Plugin\views\ViewsHandlerInterface $handler
|
||||
* The handler that has the $handler->value property to compare with first.
|
||||
* @param string $message
|
||||
* The message to display along with the assertion.
|
||||
* @param string $group
|
||||
* The type of assertion - examples are "Browser", "PHP".
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the assertion succeeded, FALSE otherwise.
|
||||
*/
|
||||
protected function assertEqualValue($expected, $handler, $message = '', $group = 'Other') {
|
||||
if (empty($message)) {
|
||||
$message = t('Comparing @first and @second', ['@first' => implode(',', $expected), '@second' => implode(',', $handler->value)]);
|
||||
}
|
||||
|
||||
return $this->assert($expected == $handler->value, $message, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the relationship ui for field/filter/argument/relationship.
|
||||
*/
|
||||
public function testRelationshipUI() {
|
||||
$views_admin = $this->drupalCreateUser(['administer views']);
|
||||
$this->drupalLogin($views_admin);
|
||||
|
||||
// Make sure the link to the field options exists.
|
||||
$handler_options_path = 'admin/structure/views/nojs/handler/test_handler_relationships/default/field/title';
|
||||
$view_edit_path = 'admin/structure/views/view/test_handler_relationships/edit';
|
||||
$this->drupalGet($view_edit_path);
|
||||
$this->assertLinkByHref($handler_options_path);
|
||||
|
||||
// The test view has a relationship to node_revision so the field should
|
||||
// show a relationship selection.
|
||||
|
||||
$this->drupalGet($handler_options_path);
|
||||
$relationship_name = 'options[relationship]';
|
||||
$this->assertFieldByName($relationship_name);
|
||||
|
||||
// Check for available options.
|
||||
$fields = $this->getSession()->getPage()->findAll('named_exact', ['field', $relationship_name]);
|
||||
$options = [];
|
||||
foreach ($fields as $field) {
|
||||
$items = $field->findAll('css', 'option');
|
||||
foreach ($items as $item) {
|
||||
$options[] = $item->getAttribute('value');
|
||||
}
|
||||
}
|
||||
$expected_options = ['none', 'nid'];
|
||||
$this->assertEqual($options, $expected_options);
|
||||
|
||||
// Remove the relationship and make sure no relationship option appears.
|
||||
$this->drupalPostForm('admin/structure/views/nojs/handler/test_handler_relationships/default/relationship/nid', [], t('Remove'));
|
||||
$this->drupalGet($handler_options_path);
|
||||
$this->assertNoFieldByName($relationship_name, NULL, 'Make sure that no relationship option is available');
|
||||
|
||||
// Create a view of comments with node relationship.
|
||||
View::create(['base_table' => 'comment_field_data', 'id' => 'test_get_entity_type'])->save();
|
||||
$this->drupalPostForm('admin/structure/views/nojs/add-handler/test_get_entity_type/default/relationship', ['name[comment_field_data.node]' => 'comment_field_data.node'], t('Add and configure relationships'));
|
||||
$this->drupalPostForm(NULL, [], t('Apply'));
|
||||
// Add a content type filter.
|
||||
$this->drupalPostForm('admin/structure/views/nojs/add-handler/test_get_entity_type/default/filter', ['name[node_field_data.type]' => 'node_field_data.type'], t('Add and configure filter criteria'));
|
||||
$this->assertOptionSelected('edit-options-relationship', 'node');
|
||||
$this->drupalPostForm(NULL, ['options[value][page]' => 'page'], t('Apply'));
|
||||
// Check content type filter options.
|
||||
$this->drupalGet('admin/structure/views/nojs/handler/test_get_entity_type/default/filter/type');
|
||||
$this->assertOptionSelected('edit-options-relationship', 'node');
|
||||
$this->assertFieldChecked('edit-options-value-page');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the relationship method on the base class.
|
||||
*/
|
||||
public function testSetRelationship() {
|
||||
$view = Views::getView('test_handler_relationships');
|
||||
$view->setDisplay();
|
||||
// Setup a broken relationship.
|
||||
$view->addHandler('default', 'relationship', $this->randomMachineName(), $this->randomMachineName(), [], 'broken_relationship');
|
||||
// Setup a valid relationship.
|
||||
$view->addHandler('default', 'relationship', 'comment_field_data', 'node', ['relationship' => 'cid'], 'valid_relationship');
|
||||
$view->initHandlers();
|
||||
$field = $view->field['title'];
|
||||
|
||||
$field->options['relationship'] = NULL;
|
||||
$field->setRelationship();
|
||||
$this->assertFalse($field->relationship, 'Make sure that an empty relationship does not create a relationship on the field.');
|
||||
|
||||
$field->options['relationship'] = $this->randomMachineName();
|
||||
$field->setRelationship();
|
||||
$this->assertFalse($field->relationship, 'Make sure that a random relationship does not create a relationship on the field.');
|
||||
|
||||
$field->options['relationship'] = 'broken_relationship';
|
||||
$field->setRelationship();
|
||||
$this->assertFalse($field->relationship, 'Make sure that a broken relationship does not create a relationship on the field.');
|
||||
|
||||
$field->options['relationship'] = 'valid_relationship';
|
||||
$field->setRelationship();
|
||||
$this->assertFalse(!empty($field->relationship), 'Make sure that the relationship alias was not set without building a views query before.');
|
||||
|
||||
// Remove the invalid relationship.
|
||||
unset($view->relationship['broken_relationship']);
|
||||
|
||||
$view->build();
|
||||
$field->setRelationship();
|
||||
$this->assertEqual($field->relationship, $view->relationship['valid_relationship']->alias, 'Make sure that a valid relationship does create the right relationship query alias.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the placeholder function.
|
||||
*
|
||||
* @see \Drupal\views\Plugin\views\HandlerBase::placeholder()
|
||||
*/
|
||||
public function testPlaceholder() {
|
||||
$view = Views::getView('test_view');
|
||||
$view->initHandlers();
|
||||
$view->initQuery();
|
||||
|
||||
$handler = $view->field['name'];
|
||||
$table = $handler->table;
|
||||
$field = $handler->field;
|
||||
$string = ':' . $table . '_' . $field;
|
||||
|
||||
// Make sure the placeholder variables are like expected.
|
||||
$this->assertEqual($handler->getPlaceholder(), $string);
|
||||
$this->assertEqual($handler->getPlaceholder(), $string . 1);
|
||||
$this->assertEqual($handler->getPlaceholder(), $string . 2);
|
||||
|
||||
// Set another table/field combination and make sure there are new
|
||||
// placeholders.
|
||||
$table = $handler->table = $this->randomMachineName();
|
||||
$field = $handler->field = $this->randomMachineName();
|
||||
$string = ':' . $table . '_' . $field;
|
||||
|
||||
// Make sure the placeholder variables are like expected.
|
||||
$this->assertEqual($handler->getPlaceholder(), $string);
|
||||
$this->assertEqual($handler->getPlaceholder(), $string . 1);
|
||||
$this->assertEqual($handler->getPlaceholder(), $string . 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests access to a handler.
|
||||
*
|
||||
* @see views_test_data_handler_test_access_callback
|
||||
*/
|
||||
public function testAccess() {
|
||||
$view = Views::getView('test_handler_test_access');
|
||||
$views_data = $this->viewsData();
|
||||
$views_data = $views_data['views_test_data'];
|
||||
|
||||
// Enable access to callback only field and deny for callback + arguments.
|
||||
$this->config('views_test_data.tests')->set('handler_access_callback', TRUE)->save();
|
||||
$this->config('views_test_data.tests')->set('handler_access_callback_argument', FALSE)->save();
|
||||
$view->initDisplay();
|
||||
$view->initHandlers();
|
||||
|
||||
foreach ($views_data['access_callback'] as $type => $info) {
|
||||
if (!in_array($type, ['title', 'help'])) {
|
||||
$this->assertTrue($view->field['access_callback'] instanceof HandlerBase, 'Make sure the user got access to the access_callback field ');
|
||||
$this->assertFalse(isset($view->field['access_callback_arguments']), 'Make sure the user got no access to the access_callback_arguments field ');
|
||||
}
|
||||
}
|
||||
|
||||
// Enable access to the callback + argument handlers and deny for callback.
|
||||
$this->config('views_test_data.tests')->set('handler_access_callback', FALSE)->save();
|
||||
$this->config('views_test_data.tests')->set('handler_access_callback_argument', TRUE)->save();
|
||||
$view->destroy();
|
||||
$view->initDisplay();
|
||||
$view->initHandlers();
|
||||
|
||||
foreach ($views_data['access_callback'] as $type => $info) {
|
||||
if (!in_array($type, ['title', 'help'])) {
|
||||
$this->assertFalse(isset($view->field['access_callback']), 'Make sure the user got no access to the access_callback field ');
|
||||
$this->assertTrue($view->field['access_callback_arguments'] instanceof HandlerBase, 'Make sure the user got access to the access_callback_arguments field ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Plugin;
|
||||
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests pluggable access for views.
|
||||
*
|
||||
* @group views
|
||||
* @todo It probably make sense to split the test up by one for role/perm/none
|
||||
* and the two generic ones.
|
||||
*/
|
||||
class AccessTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_access_none', 'test_access_static', 'test_access_dynamic'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static $modules = ['node'];
|
||||
|
||||
/**
|
||||
* Web user for testing.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $webUser;
|
||||
|
||||
/**
|
||||
* Normal user for testing.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $normalUser;
|
||||
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$this->enableViewsTestModule();
|
||||
|
||||
ViewTestData::createTestViews(get_class($this), ['views_test_data']);
|
||||
|
||||
$this->webUser = $this->drupalCreateUser();
|
||||
|
||||
$normal_role = $this->drupalCreateRole([]);
|
||||
$this->normalUser = $this->drupalCreateUser(['views_test_data test permission']);
|
||||
$this->normalUser->addRole($normal_role);
|
||||
// @todo when all the plugin information is cached make a reset function and
|
||||
// call it here.
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests none access plugin.
|
||||
*/
|
||||
public function testAccessNone() {
|
||||
$view = Views::getView('test_access_none');
|
||||
$view->setDisplay();
|
||||
|
||||
$this->assertTrue($view->display_handler->access($this->webUser));
|
||||
$this->assertTrue($view->display_handler->access($this->normalUser));
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Test abstract access plugin.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests static access check.
|
||||
*
|
||||
* @see \Drupal\views_test\Plugin\views\access\StaticTest
|
||||
*/
|
||||
public function testStaticAccessPlugin() {
|
||||
$view = Views::getView('test_access_static');
|
||||
$view->setDisplay();
|
||||
|
||||
$access_plugin = $view->display_handler->getPlugin('access');
|
||||
|
||||
$this->assertFalse($access_plugin->access($this->normalUser));
|
||||
$this->drupalGet('test_access_static');
|
||||
$this->assertResponse(403);
|
||||
|
||||
$display = &$view->storage->getDisplay('default');
|
||||
$display['display_options']['access']['options']['access'] = TRUE;
|
||||
$access_plugin->options['access'] = TRUE;
|
||||
$view->save();
|
||||
// Saving a view will cause the router to be rebuilt when the kernel
|
||||
// termination event fires. Simulate that here.
|
||||
$this->container->get('router.builder')->rebuildIfNeeded();
|
||||
|
||||
$this->assertTrue($access_plugin->access($this->normalUser));
|
||||
|
||||
$this->drupalGet('test_access_static');
|
||||
$this->assertResponse(200);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Plugin;
|
||||
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Views;
|
||||
use Drupal\views_test_data\Plugin\views\argument_default\ArgumentDefaultTest as ArgumentDefaultTestPlugin;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
|
||||
/**
|
||||
* Tests pluggable argument_default for views.
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class ArgumentDefaultTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = [
|
||||
'test_view',
|
||||
'test_argument_default_fixed',
|
||||
'test_argument_default_current_user',
|
||||
'test_argument_default_node',
|
||||
'test_argument_default_query_param',
|
||||
];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node', 'views_ui', 'block'];
|
||||
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$this->enableViewsTestModule();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the argument default test plugin.
|
||||
*
|
||||
* @see \Drupal\views_test_data\Plugin\views\argument_default\ArgumentDefaultTest
|
||||
*/
|
||||
public function testArgumentDefaultPlugin() {
|
||||
$view = Views::getView('test_view');
|
||||
|
||||
// Add a new argument and set the test plugin for the argument_default.
|
||||
$options = [
|
||||
'default_argument_type' => 'argument_default_test',
|
||||
'default_argument_options' => [
|
||||
'value' => 'John'
|
||||
],
|
||||
'default_action' => 'default'
|
||||
];
|
||||
$id = $view->addHandler('default', 'argument', 'views_test_data', 'name', $options);
|
||||
$view->initHandlers();
|
||||
$plugin = $view->argument[$id]->getPlugin('argument_default');
|
||||
$this->assertTrue($plugin instanceof ArgumentDefaultTestPlugin, 'The correct argument default plugin is used.');
|
||||
|
||||
// Check that the value of the default argument is as expected.
|
||||
$this->assertEqual($view->argument[$id]->getDefaultArgument(), 'John', 'The correct argument default value is returned.');
|
||||
// Don't pass in a value for the default argument and make sure the query
|
||||
// just returns John.
|
||||
$this->executeView($view);
|
||||
$this->assertEqual($view->argument[$id]->getValue(), 'John', 'The correct argument value is used.');
|
||||
$expected_result = [['name' => 'John']];
|
||||
$this->assertIdenticalResultset($view, $expected_result, ['views_test_data_name' => 'name']);
|
||||
|
||||
// Pass in value as argument to be sure that not the default value is used.
|
||||
$view->destroy();
|
||||
$this->executeView($view, ['George']);
|
||||
$this->assertEqual($view->argument[$id]->getValue(), 'George', 'The correct argument value is used.');
|
||||
$expected_result = [['name' => 'George']];
|
||||
$this->assertIdenticalResultset($view, $expected_result, ['views_test_data_name' => 'name']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests the use of a default argument plugin that provides no options.
|
||||
*/
|
||||
public function testArgumentDefaultNoOptions() {
|
||||
$admin_user = $this->drupalCreateUser(['administer views', 'administer site configuration']);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// The current_user plugin has no options form, and should pass validation.
|
||||
$argument_type = 'current_user';
|
||||
$edit = [
|
||||
'options[default_argument_type]' => $argument_type,
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/views/nojs/handler/test_argument_default_current_user/default/argument/uid', $edit, t('Apply'));
|
||||
|
||||
// Note, the undefined index error has two spaces after it.
|
||||
$error = [
|
||||
'%type' => 'Notice',
|
||||
'@message' => 'Undefined index: ' . $argument_type,
|
||||
'%function' => 'views_handler_argument->validateOptionsForm()',
|
||||
];
|
||||
$message = t('%type: @message in %function', $error);
|
||||
$this->assertNoRaw($message, format_string('Did not find error message: @message.', ['@message' => $message]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests fixed default argument.
|
||||
*/
|
||||
public function testArgumentDefaultFixed() {
|
||||
$random = $this->randomMachineName();
|
||||
$view = Views::getView('test_argument_default_fixed');
|
||||
$view->setDisplay();
|
||||
$options = $view->display_handler->getOption('arguments');
|
||||
$options['null']['default_argument_options']['argument'] = $random;
|
||||
$view->display_handler->overrideOption('arguments', $options);
|
||||
$view->initHandlers();
|
||||
|
||||
$this->assertEqual($view->argument['null']->getDefaultArgument(), $random, 'Fixed argument should be used by default.');
|
||||
|
||||
// Make sure that a normal argument provided is used
|
||||
$random_string = $this->randomMachineName();
|
||||
$view->executeDisplay('default', [$random_string]);
|
||||
|
||||
$this->assertEqual($view->args[0], $random_string, 'Provided argument should be used.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Test php default argument.
|
||||
*/
|
||||
//function testArgumentDefaultPhp() {}
|
||||
|
||||
/**
|
||||
* Test node default argument.
|
||||
*/
|
||||
public function testArgumentDefaultNode() {
|
||||
// Create a user that has permission to place a view block.
|
||||
$permissions = [
|
||||
'administer views',
|
||||
'administer blocks',
|
||||
'bypass node access',
|
||||
'access user profiles',
|
||||
'view all revisions',
|
||||
];
|
||||
$views_admin = $this->drupalCreateUser($permissions);
|
||||
$this->drupalLogin($views_admin);
|
||||
|
||||
// Create nodes where should show themselves again as view block.
|
||||
$node_type = NodeType::create(['type' => 'page', 'label' => 'Page']);
|
||||
$node_type->save();
|
||||
$node1 = Node::create(['title' => 'Test node 1', 'type' => 'page']);
|
||||
$node1->save();
|
||||
$node2 = Node::create(['title' => 'Test node 2', 'type' => 'page']);
|
||||
$node2->save();
|
||||
|
||||
// Place the block, visit the pages that display the block, and check that
|
||||
// the nodes we expect appear in the respective pages.
|
||||
$id = 'view-block-id';
|
||||
$this->drupalPlaceBlock("views_block:test_argument_default_node-block_1", ['id' => $id]);
|
||||
$xpath = '//*[@id="block-' . $id . '"]';
|
||||
$this->drupalGet('node/' . $node1->id());
|
||||
$this->assertTrue(strpos($this->xpath($xpath)[0]->getText(), $node1->getTitle()));
|
||||
$this->drupalGet('node/' . $node2->id());
|
||||
$this->assertTrue(strpos($this->xpath($xpath)[0]->getText(), $node2->getTitle()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the query parameter default argument.
|
||||
*/
|
||||
public function testArgumentDefaultQueryParameter() {
|
||||
$view = Views::getView('test_argument_default_query_param');
|
||||
|
||||
$request = Request::create(Url::fromUri('internal:/whatever', ['absolute' => TRUE])->toString());
|
||||
|
||||
// Check the query parameter default argument fallback value.
|
||||
$view->setRequest($request);
|
||||
$view->initHandlers();
|
||||
$this->assertEqual($view->argument['type']->getDefaultArgument(), 'all');
|
||||
|
||||
// Check the query parameter default argument with a value.
|
||||
$request->query->add(['the_node_type' => 'page']);
|
||||
$view->setRequest($request);
|
||||
$view->initHandlers();
|
||||
$this->assertEqual($view->argument['type']->getDefaultArgument(), 'page');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Plugin;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\ViewExecutable;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests tag cache plugin.
|
||||
*
|
||||
* @group views
|
||||
* @see \Drupal\views\Plugin\views\cache\Tag
|
||||
*/
|
||||
class CacheTagTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_tag_cache'];
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node'];
|
||||
|
||||
/**
|
||||
* The node storage.
|
||||
*
|
||||
* @var \Drupal\node\NodeStorage
|
||||
*/
|
||||
protected $nodeStorage;
|
||||
|
||||
/**
|
||||
* The node view builder.
|
||||
*
|
||||
* @var \Drupal\node\NodeViewBuilder
|
||||
*/
|
||||
protected $nodeViewBuilder;
|
||||
|
||||
/**
|
||||
* The user view builder.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityViewBuilder
|
||||
*/
|
||||
protected $userViewBuilder;
|
||||
|
||||
/**
|
||||
* An array of page nodes.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface[]
|
||||
*/
|
||||
protected $pages;
|
||||
|
||||
/**
|
||||
* An article node.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface
|
||||
*/
|
||||
protected $article;
|
||||
|
||||
/**
|
||||
* A test user.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
|
||||
|
||||
$this->nodeStorage = $this->container->get('entity.manager')->getStorage('node');
|
||||
$this->nodeViewBuilder = $this->container->get('entity.manager')->getViewBuilder('node');
|
||||
$this->userViewBuilder = $this->container->get('entity.manager')->getViewBuilder('user');
|
||||
|
||||
for ($i = 1; $i <= 5; $i++) {
|
||||
$this->pages[] = $this->drupalCreateNode(['title' => "Test $i", 'type' => 'page']);
|
||||
}
|
||||
$this->article = $this->drupalCreateNode(['title' => "Test article", 'type' => 'article']);
|
||||
$this->user = $this->drupalCreateUser();
|
||||
|
||||
// Mark the current request safe, in order to make render cache working, see
|
||||
// \Drupal\Core\Render\RenderCache::get.
|
||||
\Drupal::request()->setMethod('GET');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the render cache for a given view.
|
||||
*
|
||||
* @param \Drupal\views\ViewExecutable $view
|
||||
* The view.
|
||||
*
|
||||
* @return array|false
|
||||
* The render cache result or FALSE if not existent.
|
||||
*/
|
||||
protected function getRenderCache(ViewExecutable $view) {
|
||||
/** @var \Drupal\Core\Render\RenderCacheInterface $render_cache */
|
||||
$render_cache = \Drupal::service('render_cache');
|
||||
$view->element = ['#cache' => []];
|
||||
$build = $view->buildRenderable();
|
||||
$build['#cache']['contexts'] = Cache::mergeContexts($build['#cache']['contexts'], $this->container->getParameter('renderer.config')['required_cache_contexts']);
|
||||
|
||||
return $render_cache->get($build);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the tag cache plugin.
|
||||
*/
|
||||
public function testTagCaching() {
|
||||
/** @var \Drupal\Core\Render\RendererInterface $renderer */
|
||||
$renderer = \Drupal::service('renderer');
|
||||
$view = Views::getView('test_tag_cache');
|
||||
$build = $view->buildRenderable();
|
||||
$renderer->renderPlain($build);
|
||||
|
||||
// Saving the view should invalidate the tags.
|
||||
$cache_plugin = $view->display_handler->getPlugin('cache');
|
||||
$this->assertTrue($cache_plugin->cacheGet('results'), 'Results cache found.');
|
||||
$this->assertTrue($this->getRenderCache($view), 'Output cache found.');
|
||||
|
||||
$view->storage->save();
|
||||
|
||||
$this->assertFalse($cache_plugin->cacheGet('results'), 'Results cache empty after the view is saved.');
|
||||
$this->assertFalse($this->getRenderCache($view), 'Output cache empty after the view is saved.');
|
||||
|
||||
$view->destroy();
|
||||
$build = $view->buildRenderable();
|
||||
$renderer->renderPlain($build);
|
||||
|
||||
// Test invalidating the nodes in this view invalidates the cache.
|
||||
$cache_plugin = $view->display_handler->getPlugin('cache');
|
||||
$this->assertTrue($cache_plugin->cacheGet('results'), 'Results cache found.');
|
||||
$this->assertTrue($this->getRenderCache($view), 'Output cache found.');
|
||||
|
||||
$this->nodeViewBuilder->resetCache($this->pages);
|
||||
|
||||
$this->assertFalse($cache_plugin->cacheGet('results'), 'Results cache empty after resetCache is called with pages.');
|
||||
$this->assertFalse($this->getRenderCache($view), 'Output cache empty after resetCache is called with pages.');
|
||||
|
||||
$view->destroy();
|
||||
$build = $view->buildRenderable();
|
||||
$renderer->renderPlain($build);
|
||||
|
||||
// Test saving a node in this view invalidates the cache.
|
||||
$cache_plugin = $view->display_handler->getPlugin('cache');
|
||||
$this->assertTrue($cache_plugin->cacheGet('results'), 'Results cache found.');
|
||||
$this->assertTrue($this->getRenderCache($view), 'Output cache found.');
|
||||
|
||||
$node = reset($this->pages);
|
||||
$node->save();
|
||||
|
||||
$this->assertFalse($cache_plugin->cacheGet('results'), 'Results cache empty after a page node is saved.');
|
||||
$this->assertFalse($this->getRenderCache($view), 'Output cache empty after a page node is saved.');
|
||||
|
||||
$view->destroy();
|
||||
$build = $view->buildRenderable();
|
||||
$renderer->renderPlain($build);
|
||||
|
||||
// Test saving a node not in this view invalidates the cache too.
|
||||
$cache_plugin = $view->display_handler->getPlugin('cache');
|
||||
$this->assertTrue($cache_plugin->cacheGet('results'), 'Results cache found.');
|
||||
$this->assertTrue($this->getRenderCache($view), 'Output cache found.');
|
||||
|
||||
$this->article->save();
|
||||
|
||||
$this->assertFalse($cache_plugin->cacheGet('results'), 'Results cache empty after an article node is saved.');
|
||||
$this->assertFalse($this->getRenderCache($view), 'Output cache empty after an article node is saved.');
|
||||
|
||||
$view->destroy();
|
||||
$build = $view->buildRenderable();
|
||||
$renderer->renderPlain($build);
|
||||
|
||||
// Test that invalidating a tag for a user, does not invalidate the cache,
|
||||
// as the user entity type will not be contained in the views cache tags.
|
||||
$cache_plugin = $view->display_handler->getPlugin('cache');
|
||||
$this->assertTrue($cache_plugin->cacheGet('results'), 'Results cache found.');
|
||||
$this->assertTrue($this->getRenderCache($view), 'Output cache found.');
|
||||
|
||||
$this->userViewBuilder->resetCache([$this->user]);
|
||||
|
||||
$cache_plugin = $view->display_handler->getPlugin('cache');
|
||||
$this->assertTrue($cache_plugin->cacheGet('results'), 'Results cache found after a user is invalidated.');
|
||||
$this->assertTrue($this->getRenderCache($view), 'Output cache found after a user is invalidated.');
|
||||
|
||||
$view->destroy();
|
||||
// Invalidate the views cache tags in order to invalidate the render
|
||||
// caching.
|
||||
\Drupal::service('cache_tags.invalidator')->invalidateTags($view->storage->getCacheTagsToInvalidate());
|
||||
$build = $view->buildRenderable();
|
||||
$renderer->renderPlain($build);
|
||||
|
||||
// Test the cacheFlush method invalidates the cache.
|
||||
$cache_plugin = $view->display_handler->getPlugin('cache');
|
||||
$this->assertTrue($cache_plugin->cacheGet('results'), 'Results cache found.');
|
||||
$this->assertTrue($this->getRenderCache($view), 'Output cache found.');
|
||||
|
||||
$cache_plugin->cacheFlush();
|
||||
|
||||
$cache_plugin = $view->display_handler->getPlugin('cache');
|
||||
$this->assertFalse($cache_plugin->cacheGet('results'), 'Results cache empty after the cacheFlush() method is called.');
|
||||
$this->assertFalse($this->getRenderCache($view), 'Output cache empty after the cacheFlush() method is called.');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Plugin;
|
||||
|
||||
use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Plugin\views\display\DisplayPluginBase;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests pluggable caching for views via a web test.
|
||||
*
|
||||
* @group views
|
||||
* @see views_plugin_cache
|
||||
*/
|
||||
class CacheWebTest extends ViewTestBase {
|
||||
|
||||
use AssertPageCacheContextsAndTagsTrait;
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_display'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['taxonomy'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$this->enableViewsTestModule();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the output caching on an actual page.
|
||||
*/
|
||||
public function testCacheOutputOnPage() {
|
||||
$view = Views::getView('test_display');
|
||||
$view->storage->setStatus(TRUE);
|
||||
$view->setDisplay('page_1');
|
||||
$view->display_handler->overrideOption('cache', [
|
||||
'type' => 'time',
|
||||
'options' => [
|
||||
'results_lifespan' => '3600',
|
||||
'output_lifespan' => '3600'
|
||||
]
|
||||
]);
|
||||
$view->save();
|
||||
$this->container->get('router.builder')->rebuildIfNeeded();
|
||||
|
||||
/** @var \Drupal\Core\Render\RenderCacheInterface $render_cache */
|
||||
$render_cache = \Drupal::service('render_cache');
|
||||
$cache_element = DisplayPluginBase::buildBasicRenderable('test_display', 'page_1');
|
||||
$cache_element['#cache'] += ['contexts' => $this->container->getParameter('renderer.config')['required_cache_contexts']];
|
||||
$this->assertFalse($render_cache->get($cache_element));
|
||||
|
||||
$this->drupalGet('test-display');
|
||||
$this->assertResponse(200);
|
||||
$this->assertTrue($render_cache->get($cache_element));
|
||||
$cache_tags = [
|
||||
'config:user.role.anonymous',
|
||||
'config:views.view.test_display',
|
||||
'node_list',
|
||||
'rendered'
|
||||
];
|
||||
$this->assertCacheTags($cache_tags);
|
||||
|
||||
$this->drupalGet('test-display');
|
||||
$this->assertResponse(200);
|
||||
$this->assertTrue($render_cache->get($cache_element));
|
||||
$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,153 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Plugin;
|
||||
|
||||
use Drupal\Core\Plugin\Context\ContextDefinitionInterface;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
|
||||
|
||||
/**
|
||||
* A test for contextual filters exposed as block context.
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class ContextualFiltersBlockContextTest extends ViewTestBase {
|
||||
|
||||
use AssertPageCacheContextsAndTagsTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['block', 'block_test_views', 'views_ui', 'node'];
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_view_block_with_context'];
|
||||
|
||||
/**
|
||||
* Test node type.
|
||||
*
|
||||
* @var \Drupal\node\NodeTypeInterface
|
||||
*/
|
||||
protected $nodeType;
|
||||
|
||||
/**
|
||||
* Test nodes.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface[]
|
||||
*/
|
||||
protected $nodes;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
ViewTestData::createTestViews(get_class($this), ['block_test_views']);
|
||||
$this->enableViewsTestModule();
|
||||
|
||||
$this->nodeType = $this->container->get('entity_type.manager')
|
||||
->getStorage('node_type')
|
||||
->create([
|
||||
'name' => 'Test node type',
|
||||
'type' => 'test',
|
||||
]);
|
||||
$this->nodeType->save();
|
||||
|
||||
$this->nodes[0] = $this->container->get('entity_type.manager')
|
||||
->getStorage('node')
|
||||
->create(['type' => $this->nodeType->id(), 'title' => 'First test node']);
|
||||
$this->nodes[0]->save();
|
||||
|
||||
$this->nodes[1] = $this->container->get('entity_type.manager')
|
||||
->getStorage('node')
|
||||
->create(['type' => $this->nodeType->id(), 'title' => 'Second test node']);
|
||||
$this->nodes[1]->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests exposed context.
|
||||
*/
|
||||
public function testBlockContext() {
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer views', 'administer blocks']));
|
||||
|
||||
// Check if context was correctly propagated to the block.
|
||||
$definition = $this->container->get('plugin.manager.block')
|
||||
->getDefinition('views_block:test_view_block_with_context-block_1');
|
||||
$this->assertTrue($definition['context']['nid'] instanceof ContextDefinitionInterface);
|
||||
/** @var \Drupal\Core\Plugin\Context\ContextDefinitionInterface $context */
|
||||
$context = $definition['context']['nid'];
|
||||
$this->assertEqual($context->getDataType(), 'entity:node', 'Context definition data type is correct.');
|
||||
$this->assertEqual($context->getLabel(), 'Content: ID', 'Context definition label is correct.');
|
||||
$this->assertFalse($context->isRequired(), 'Context is not required.');
|
||||
|
||||
// Place test block via block UI to check if contexts are correctly exposed.
|
||||
$this->drupalGet(
|
||||
'admin/structure/block/add/views_block:test_view_block_with_context-block_1/classy',
|
||||
['query' => ['region' => 'content']]
|
||||
);
|
||||
$edit = [
|
||||
'settings[context_mapping][nid]' => '@node.node_route_context:node',
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, 'Save block');
|
||||
|
||||
// Check if mapping saved correctly.
|
||||
/** @var \Drupal\block\BlockInterface $block */
|
||||
$block = $this->container->get('entity_type.manager')
|
||||
->getStorage('block')
|
||||
->load('views_block__test_view_block_with_context_block_1');
|
||||
$expected_settings = [
|
||||
'id' => 'views_block:test_view_block_with_context-block_1',
|
||||
'label' => '',
|
||||
'provider' => 'views',
|
||||
'label_display' => 'visible',
|
||||
'views_label' => '',
|
||||
'items_per_page' => 'none',
|
||||
'context_mapping' => ['nid' => '@node.node_route_context:node']
|
||||
];
|
||||
$this->assertEqual($block->getPlugin()->getConfiguration(), $expected_settings, 'Block settings are correct.');
|
||||
|
||||
// Make sure view behaves as expected.
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertText('Test view: No results found.');
|
||||
|
||||
$this->drupalGet($this->nodes[0]->toUrl());
|
||||
$this->assertText('Test view row: First test node');
|
||||
|
||||
$this->drupalGet($this->nodes[1]->toUrl());
|
||||
$this->assertText('Test view row: Second test node');
|
||||
|
||||
// Check the second block which should expose two integer contexts, one
|
||||
// based on the numeric plugin and the other based on numeric validation.
|
||||
$definition = $this->container->get('plugin.manager.block')
|
||||
->getDefinition('views_block:test_view_block_with_context-block_2');
|
||||
$this->assertTrue($definition['context']['created'] instanceof ContextDefinitionInterface);
|
||||
/** @var \Drupal\Core\Plugin\Context\ContextDefinitionInterface $context */
|
||||
$context = $definition['context']['created'];
|
||||
$this->assertEqual($context->getDataType(), 'integer', 'Context definition data type is correct.');
|
||||
$this->assertEqual($context->getLabel(), 'Content: Authored on', 'Context definition label is correct.');
|
||||
$this->assertFalse($context->isRequired(), 'Context is not required.');
|
||||
|
||||
$this->assertTrue($definition['context']['vid'] instanceof ContextDefinitionInterface);
|
||||
/** @var \Drupal\Core\Plugin\Context\ContextDefinitionInterface $context */
|
||||
$context = $definition['context']['vid'];
|
||||
$this->assertEqual($context->getDataType(), 'integer', 'Context definition data type is correct.');
|
||||
$this->assertEqual($context->getLabel(), 'Content: Revision ID', 'Context definition label is correct.');
|
||||
$this->assertFalse($context->isRequired(), 'Context is not required.');
|
||||
|
||||
$this->assertTrue($definition['context']['title'] instanceof ContextDefinitionInterface);
|
||||
/** @var \Drupal\Core\Plugin\Context\ContextDefinitionInterface $context */
|
||||
$context = $definition['context']['title'];
|
||||
$this->assertEqual($context->getDataType(), 'string', 'Context definition data type is correct.');
|
||||
$this->assertEqual($context->getLabel(), 'Content: Title', 'Context definition label is correct.');
|
||||
$this->assertFalse($context->isRequired(), 'Context is not required.');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Plugin;
|
||||
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
|
||||
/**
|
||||
* Tests the ability to disable and enable view displays.
|
||||
*
|
||||
* @group views
|
||||
* @see \Drupal\views\Plugin\views\display\Feed
|
||||
*/
|
||||
class DisabledDisplayTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_disabled_display'];
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
|
||||
$admin_user = $this->drupalCreateUser(['administer site configuration']);
|
||||
$this->drupalLogin($admin_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that views displays can be disabled.
|
||||
*
|
||||
* This method only checks the page displays via a HTTP request, but should
|
||||
* the .enabled property disappear from the schema both the load and save
|
||||
* calls will start failing.
|
||||
*/
|
||||
public function testDisabledDisplays() {
|
||||
// The displays defined in this view.
|
||||
$display_ids = ['attachment_1', 'block_1', 'embed_1', 'feed_1', 'page_2'];
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page']);
|
||||
$this->drupalCreateNode();
|
||||
|
||||
// Load the test view and initialize its displays.
|
||||
$view = $this->container->get('entity.manager')->getStorage('view')->load('test_disabled_display');
|
||||
$view->getExecutable()->setDisplay();
|
||||
|
||||
// Enabled page display should return content.
|
||||
$this->drupalGet('test-disabled-display');
|
||||
$result = $this->xpath('//h1[@class="page-title"]');
|
||||
$this->assertEqual($result[0]->getText(), 'test_disabled_display', 'The enabled page_1 display is accessible.');
|
||||
|
||||
// Disabled page view should 404.
|
||||
$this->drupalGet('test-disabled-display-2');
|
||||
$this->assertResponse(404);
|
||||
|
||||
// Enable each disabled display and save the view.
|
||||
foreach ($display_ids as $display_id) {
|
||||
$view->getExecutable()->displayHandlers->get($display_id)->setOption('enabled', TRUE);
|
||||
$view->save();
|
||||
$enabled = $view->getExecutable()->displayHandlers->get($display_id)->isEnabled();
|
||||
$this->assertTrue($enabled, 'Display ' . $display_id . ' is now enabled');
|
||||
}
|
||||
|
||||
\Drupal::service('router.builder')->rebuildIfNeeded();
|
||||
|
||||
// Check that the originally disabled page_2 display is now enabled.
|
||||
$this->drupalGet('test-disabled-display-2');
|
||||
$result = $this->xpath('//h1[@class="page-title"]');
|
||||
$this->assertEqual($result[0]->getText(), 'test_disabled_display', 'The enabled page_2 display is accessible.');
|
||||
|
||||
// Disable each disabled display and save the view.
|
||||
foreach ($display_ids as $display_id) {
|
||||
$view->getExecutable()->displayHandlers->get($display_id)->setOption('enabled', FALSE);
|
||||
$view->save();
|
||||
$enabled = $view->getExecutable()->displayHandlers->get($display_id)->isEnabled();
|
||||
$this->assertFalse($enabled, 'Display ' . $display_id . ' is now disabled');
|
||||
}
|
||||
|
||||
\Drupal::service('router.builder')->rebuild();
|
||||
|
||||
// Check that the page_1 display still works.
|
||||
$this->drupalGet('test-disabled-display');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Check that the page_2 display is now disabled again.
|
||||
$this->drupalGet('test-disabled-display-2');
|
||||
$this->assertResponse(404);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Plugin;
|
||||
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the attachment display plugin.
|
||||
*
|
||||
* @group views
|
||||
* @see \Drupal\views\Plugin\views\display\Attachment
|
||||
*/
|
||||
class DisplayAttachmentTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_display_attachment', 'test_attached_disabled'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['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 attachment plugin.
|
||||
*/
|
||||
public function testAttachment() {
|
||||
$this->drupalGet('test-display-attachment');
|
||||
|
||||
$result = $this->xpath('//div[contains(@class, "view-content")]');
|
||||
$this->assertEqual(count($result), 2, 'Both actual view and the attachment is rendered.');
|
||||
|
||||
$result = $this->xpath('//div[contains(@class, "attachment-after")]');
|
||||
$this->assertEqual(count($result), 0, 'The attachment is not rendered after the actual view.');
|
||||
|
||||
$result = $this->xpath('//div[contains(@class, "attachment-before")]');
|
||||
$this->assertEqual(count($result), 1, 'The attachment is rendered before the actual view.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that nothing is output when the attachment displays are disabled.
|
||||
*/
|
||||
public function testDisabledAttachments() {
|
||||
$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('attachment_1', $attached_displays), 'The attachment_1 display is attached to the page display.');
|
||||
$this->assertTrue(in_array('attachment_2', $attached_displays), 'The attachment_2 display is attached to the page display.');
|
||||
|
||||
// Check that the attachments are output on the page display.
|
||||
$this->drupalGet('test-attached-disabled');
|
||||
|
||||
$result = $this->xpath('//div[contains(@class, "view-content")]');
|
||||
$this->assertEqual(count($result), 3, 'The page view and the attachments are rendered.');
|
||||
|
||||
$result = $this->xpath('//div[contains(@class, "attachment-before")]');
|
||||
$this->assertEqual(count($result), 1, 'The attachment is rendered before the page view.');
|
||||
|
||||
$result = $this->xpath('//div[contains(@class, "attachment-after")]');
|
||||
$this->assertEqual(count($result), 1, 'The attachment is rendered after the page view.');
|
||||
|
||||
// Disable the attachment_1 display.
|
||||
$view->displayHandlers->get('attachment_1')->setOption('enabled', FALSE);
|
||||
$view->save();
|
||||
|
||||
// Test that the before attachment is not displayed.
|
||||
$this->drupalGet('/test-attached-disabled');
|
||||
$result = $this->xpath('//div[contains(@class, "view-content")]');
|
||||
$this->assertEqual(count($result), 2, 'The page view and only one attachment are rendered.');
|
||||
|
||||
$result = $this->xpath('//div[contains(@class, "attachment-before")]');
|
||||
$this->assertEqual(count($result), 0, 'The attachment_1 is not rendered.');
|
||||
|
||||
// Disable the attachment_2 display.
|
||||
$view->displayHandlers->get('attachment_2')->setOption('enabled', FALSE);
|
||||
$view->save();
|
||||
|
||||
// Test that the after attachment is not displayed.
|
||||
$this->drupalGet('/test-attached-disabled');
|
||||
$result = $this->xpath('//div[contains(@class, "view-content")]');
|
||||
$this->assertEqual(count($result), 1, 'The page view is rendered without attachments.');
|
||||
|
||||
$result = $this->xpath('//div[contains(@class, "attachment-after")]');
|
||||
$this->assertEqual(count($result), 0, 'The attachment_2 is not rendered.');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Plugin;
|
||||
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the entity reference display plugin.
|
||||
*
|
||||
* @group views
|
||||
*
|
||||
* @see \Drupal\views\Plugin\views\display\EntityReference
|
||||
*/
|
||||
class DisplayEntityReferenceTest extends ViewTestBase {
|
||||
|
||||
use EntityReferenceTestTrait;
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_display_entity_reference'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['entity_test', 'field', 'views_ui'];
|
||||
|
||||
/**
|
||||
* The used field name in the test.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $fieldName;
|
||||
|
||||
/**
|
||||
* The used entity reference field name in the test.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $entityRefFieldName;
|
||||
|
||||
/**
|
||||
* The field storage.
|
||||
*
|
||||
* @var \Drupal\field\Entity\FieldStorageConfig
|
||||
*/
|
||||
protected $fieldStorage;
|
||||
|
||||
/**
|
||||
* The field config.
|
||||
*
|
||||
* @var \Drupal\field\Entity\FieldConfig
|
||||
*/
|
||||
protected $field;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$this->drupalLogin($this->drupalCreateUser(['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();
|
||||
|
||||
// Add an entity reference field to reference the same base table.
|
||||
$this->entityRefFieldName = 'field_test_entity_ref_entity_ref';
|
||||
$this->createEntityReferenceField('entity_test', 'entity_test', $this->entityRefFieldName, NULL, 'entity_test');
|
||||
|
||||
// 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();
|
||||
}
|
||||
EntityTest::create([
|
||||
'bundle' => 'entity_test',
|
||||
'name' => 'name',
|
||||
$this->fieldName => 'tex',
|
||||
])->save();
|
||||
EntityTest::create([
|
||||
'bundle' => 'entity_test',
|
||||
'name' => 'name',
|
||||
$this->fieldName => 'TEX',
|
||||
])->save();
|
||||
EntityTest::create([
|
||||
'bundle' => 'entity_test',
|
||||
'name' => 'name',
|
||||
$this->fieldName => 'sometext',
|
||||
])->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');
|
||||
$view->destroy();
|
||||
|
||||
// Test the 'CONTAINS' match_operator.
|
||||
$view = Views::getView('test_display_entity_reference');
|
||||
$view->setDisplay('entity_reference_1');
|
||||
$options = [
|
||||
'match' => 'tex',
|
||||
'match_operator' => 'CONTAINS',
|
||||
'limit' => 0,
|
||||
'ids' => NULL,
|
||||
];
|
||||
$view->display_handler->setOption('entity_reference_options', $options);
|
||||
$this->executeView($view);
|
||||
$this->assertEqual(count($view->result), 13, 'Search returned thirteen rows');
|
||||
$view->destroy();
|
||||
|
||||
// Test the 'STARTS_WITH' match_operator.
|
||||
$view = Views::getView('test_display_entity_reference');
|
||||
$view->setDisplay('entity_reference_1');
|
||||
$options = [
|
||||
'match' => 'tex',
|
||||
'match_operator' => 'STARTS_WITH',
|
||||
'limit' => 0,
|
||||
'ids' => NULL,
|
||||
];
|
||||
$view->display_handler->setOption('entity_reference_options', $options);
|
||||
$this->executeView($view);
|
||||
$this->assertEqual(count($view->result), 12, 'Search returned twelve rows');
|
||||
$view->destroy();
|
||||
|
||||
// Test the '=' match_operator.
|
||||
$view = Views::getView('test_display_entity_reference');
|
||||
$view->setDisplay('entity_reference_1');
|
||||
$options = [
|
||||
'match' => 'tex',
|
||||
'match_operator' => '=',
|
||||
'limit' => 0,
|
||||
'ids' => NULL,
|
||||
];
|
||||
$view->display_handler->setOption('entity_reference_options', $options);
|
||||
$this->executeView($view);
|
||||
$this->assertEqual(count($view->result), 2, 'Search returned two rows');
|
||||
$view->destroy();
|
||||
|
||||
// Add a relationship and a field using that relationship.
|
||||
$this->drupalPostForm('admin/structure/views/nojs/add-handler/test_display_entity_reference/default/relationship', ['name[entity_test.user_id]' => TRUE], t('Add and configure relationships'));
|
||||
$this->drupalPostForm(NULL, [], t('Apply'));
|
||||
|
||||
$this->drupalPostForm('admin/structure/views/nojs/add-handler/test_display_entity_reference/default/field', ['name[users_field_data.uid]' => TRUE], t('Add and configure fields'));
|
||||
$this->drupalPostForm(NULL, [], t('Apply'));
|
||||
|
||||
// Add the new field to the search fields.
|
||||
$this->drupalPostForm('admin/structure/views/nojs/display/test_display_entity_reference/entity_reference_1/style_options', ['style_options[search_fields][uid]' => 'uid'], t('Apply'));
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
|
||||
// Test that the search still works with the ralated field.
|
||||
$view = Views::getView('test_display_entity_reference');
|
||||
$view->setDisplay('entity_reference_1');
|
||||
|
||||
// Add the required settings to test a search operation.
|
||||
$options = [
|
||||
'match' => '2',
|
||||
'match_operator' => 'CONTAINS',
|
||||
'limit' => 0,
|
||||
'ids' => NULL,
|
||||
];
|
||||
$view->display_handler->setOption('entity_reference_options', $options);
|
||||
|
||||
$this->executeView($view);
|
||||
|
||||
// Run validation when using a relationship to the same base table.
|
||||
$this->assertEqual(count($view->result), 2, 'Search returned two rows');
|
||||
$view->destroy();
|
||||
|
||||
$this->drupalPostForm('admin/structure/views/nojs/add-handler/test_display_entity_reference/default/relationship', ['name[entity_test__field_test_entity_ref_entity_ref.field_test_entity_ref_entity_ref]' => TRUE], t('Add and configure relationships'));
|
||||
$this->drupalPostForm(NULL, [], t('Apply'));
|
||||
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
|
||||
// Test that the search still works with the related field.
|
||||
$view = Views::getView('test_display_entity_reference');
|
||||
$view->setDisplay('entity_reference_1');
|
||||
|
||||
// Add IDs to trigger validation.
|
||||
$options = [
|
||||
'match' => '1',
|
||||
'match_operator' => 'CONTAINS',
|
||||
'limit' => 0,
|
||||
'ids' => [1, 2],
|
||||
];
|
||||
$view->display_handler->setOption('entity_reference_options', $options);
|
||||
|
||||
$this->executeView($view);
|
||||
|
||||
$this->assertEqual(count($view->result), 2, 'Search returned two rows');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Plugin;
|
||||
|
||||
use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the views page display plugin as webtest.
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class DisplayPageWebTest extends ViewTestBase {
|
||||
|
||||
use AssertPageCacheContextsAndTagsTrait;
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_page_display', 'test_page_display_arguments', 'test_page_display_menu', 'test_page_display_path'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['menu_ui', 'block', 'views_ui'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$this->enableViewsTestModule();
|
||||
$this->drupalPlaceBlock('local_tasks_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests arguments.
|
||||
*/
|
||||
public function testArguments() {
|
||||
$this->drupalGet('test_route_without_arguments');
|
||||
$this->assertResponse(200);
|
||||
$result = $this->xpath('//span[@class="field-content"]');
|
||||
$this->assertEqual(count($result), 5, 'All entries was returned');
|
||||
|
||||
$this->drupalGet('test_route_without_arguments/1');
|
||||
$this->assertResponse(404);
|
||||
|
||||
$this->drupalGet('test_route_with_argument/1');
|
||||
$this->assertResponse(200);
|
||||
$this->assertCacheContexts(['languages:language_interface', 'route', 'theme', 'url']);
|
||||
$result = $this->xpath('//span[@class="field-content"]');
|
||||
$this->assertEqual(count($result), 1, 'Ensure that just the filtered entry was returned.');
|
||||
$this->assertEqual($result[0]->getText(), 1, 'The passed ID was returned.');
|
||||
|
||||
$this->drupalGet('test_route_with_suffix/1/suffix');
|
||||
$this->assertResponse(200);
|
||||
$result = $this->xpath('//span[@class="field-content"]');
|
||||
$this->assertEqual(count($result), 1, 'Ensure that just the filtered entry was returned.');
|
||||
$this->assertEqual($result[0]->getText(), 1, 'The passed ID was returned.');
|
||||
|
||||
$this->drupalGet('test_route_with_suffix_and_argument/1/suffix/2');
|
||||
$this->assertResponse(200);
|
||||
$result = $this->xpath('//span[@class="field-content"]');
|
||||
$this->assertEqual(count($result), 0, 'No result was returned.');
|
||||
|
||||
$this->drupalGet('test_route_with_suffix_and_argument/1/suffix/1');
|
||||
$this->assertResponse(200);
|
||||
$result = $this->xpath('//span[@class="field-content"]');
|
||||
$this->assertEqual(count($result), 1, 'Ensure that just the filtered entry was returned.');
|
||||
$this->assertEqual($result[0]->getText(), 1, 'The passed ID was returned.');
|
||||
|
||||
$this->drupalGet('test_route_with_long_argument/1');
|
||||
$this->assertResponse(200);
|
||||
$result = $this->xpath('//span[@class="field-content"]');
|
||||
$this->assertEqual(count($result), 1, 'Ensure that just the filtered entry was returned.');
|
||||
$this->assertEqual($result[0]->getText(), 1, 'The passed ID was returned.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests menu settings of page displays.
|
||||
*/
|
||||
public function testPageDisplayMenu() {
|
||||
// Check local tasks.
|
||||
$this->drupalGet('test_page_display_menu');
|
||||
$this->assertResponse(200);
|
||||
$element = $this->xpath('//ul[contains(@class, :ul_class)]//a[contains(@class, :a_class)]/child::text()', [
|
||||
':ul_class' => 'tabs primary',
|
||||
':a_class' => 'is-active',
|
||||
]);
|
||||
$this->assertEqual($element[0]->getText(), t('Test default tab'));
|
||||
$this->assertTitle(t('Test default page | Drupal'));
|
||||
|
||||
$this->drupalGet('test_page_display_menu/default');
|
||||
$this->assertResponse(404);
|
||||
|
||||
$this->drupalGet('test_page_display_menu/local');
|
||||
$this->assertResponse(200);
|
||||
$element = $this->xpath('//ul[contains(@class, :ul_class)]//a[contains(@class, :a_class)]/child::text()', [
|
||||
':ul_class' => 'tabs primary',
|
||||
':a_class' => 'is-active',
|
||||
]);
|
||||
$this->assertEqual($element[0]->getText(), t('Test local tab'));
|
||||
$this->assertTitle(t('Test local page | Drupal'));
|
||||
|
||||
// Check an ordinary menu link.
|
||||
$admin_user = $this->drupalCreateUser(['administer menu']);
|
||||
$this->drupalLogin($admin_user);
|
||||
$this->drupalPlaceBlock('system_menu_block:tools');
|
||||
$this->drupalGet('<front>');
|
||||
|
||||
$menu_link = $this->cssSelect('nav.block-menu ul.menu a');
|
||||
$this->assertEqual($menu_link[0]->getText(), 'Test menu link');
|
||||
|
||||
// Update the menu link.
|
||||
$this->drupalPostForm("admin/structure/menu/link/views_view:views.test_page_display_menu.page_3/edit", [
|
||||
'title' => 'New title',
|
||||
], t('Save'));
|
||||
|
||||
$this->drupalGet('<front>');
|
||||
$menu_link = $this->cssSelect('nav.block-menu ul.menu a');
|
||||
$this->assertEqual($menu_link[0]->getText(), 'New title');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the title is not displayed in the output.
|
||||
*/
|
||||
public function testTitleOutput() {
|
||||
$this->drupalGet('test_page_display_200');
|
||||
|
||||
$view = Views::getView('test_page_display');
|
||||
$xpath = $this->cssSelect('div.view:contains("' . $view->getTitle() . '")');
|
||||
$this->assertFalse($xpath, 'The view title was not displayed in the view markup.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the views page path functionality.
|
||||
*/
|
||||
public function testPagePaths() {
|
||||
$this->drupalLogin($this->rootUser);
|
||||
$this->assertPagePath('0');
|
||||
$this->assertPagePath('9999');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that we can successfully change a view page display path.
|
||||
*
|
||||
* @param string $path
|
||||
* Path that will be set as the view page display path.
|
||||
*
|
||||
* @return bool
|
||||
* Assertion result.
|
||||
*/
|
||||
public function assertPagePath($path) {
|
||||
$view = Views::getView('test_page_display_path');
|
||||
$view->initDisplay('page_1');
|
||||
$view->displayHandlers->get('page_1')->overrideOption('path', $path);
|
||||
$view->save();
|
||||
$this->container->get('router.builder')->rebuild();
|
||||
// Check if we successfully changed the path.
|
||||
$this->drupalGet($path);
|
||||
$success = $this->assertResponse(200);
|
||||
// Check if we don't get any error on the view edit page.
|
||||
$this->drupalGet('admin/structure/views/view/test_page_display_path');
|
||||
return $success && $this->assertResponse(200);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,364 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Plugin;
|
||||
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Views;
|
||||
use Drupal\views_test_data\Plugin\views\display\DisplayTest as DisplayTestPlugin;
|
||||
|
||||
/**
|
||||
* Tests the basic display plugin.
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class DisplayTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_filter_groups', 'test_get_attach_displays', 'test_view', 'test_display_more', 'test_display_invalid', 'test_display_empty', 'test_exposed_relationship_admin_ui'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['views_ui', 'node', 'block'];
|
||||
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp();
|
||||
|
||||
$this->enableViewsTestModule();
|
||||
|
||||
$this->adminUser = $this->drupalCreateUser(['administer views']);
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Create 10 nodes.
|
||||
for ($i = 0; $i <= 10; $i++) {
|
||||
$this->drupalCreateNode(['promote' => TRUE]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the display test plugin.
|
||||
*
|
||||
* @see \Drupal\views_test_data\Plugin\views\display\DisplayTest
|
||||
*/
|
||||
public function testDisplayPlugin() {
|
||||
/** @var \Drupal\Core\Render\RendererInterface $renderer */
|
||||
$renderer = $this->container->get('renderer');
|
||||
$view = Views::getView('test_view');
|
||||
|
||||
// Add a new 'display_test' display and test it's there.
|
||||
$view->storage->addDisplay('display_test');
|
||||
$displays = $view->storage->get('display');
|
||||
|
||||
$this->assertTrue(isset($displays['display_test_1']), 'Added display has been assigned to "display_test_1"');
|
||||
|
||||
// Check the display options are like expected.
|
||||
$options = [
|
||||
'display_options' => [],
|
||||
'display_plugin' => 'display_test',
|
||||
'id' => 'display_test_1',
|
||||
'display_title' => 'Display test',
|
||||
'position' => 1,
|
||||
];
|
||||
$this->assertEqual($displays['display_test_1'], $options);
|
||||
|
||||
// Add another one to ensure that position is counted up.
|
||||
$view->storage->addDisplay('display_test');
|
||||
$displays = $view->storage->get('display');
|
||||
$options = [
|
||||
'display_options' => [],
|
||||
'display_plugin' => 'display_test',
|
||||
'id' => 'display_test_2',
|
||||
'display_title' => 'Display test 2',
|
||||
'position' => 2,
|
||||
];
|
||||
$this->assertEqual($displays['display_test_2'], $options);
|
||||
|
||||
// Move the second display before the first one in order to test custom
|
||||
// sorting.
|
||||
$displays['display_test_1']['position'] = 2;
|
||||
$displays['display_test_2']['position'] = 1;
|
||||
$view->storage->set('display', $displays);
|
||||
$view->save();
|
||||
|
||||
$view->setDisplay('display_test_1');
|
||||
|
||||
$this->assertTrue($view->display_handler instanceof DisplayTestPlugin, 'The correct display handler instance is on the view object.');
|
||||
|
||||
// Check the test option.
|
||||
$this->assertIdentical($view->display_handler->getOption('test_option'), '');
|
||||
|
||||
$style = $view->display_handler->getOption('style');
|
||||
$style['type'] = 'test_style';
|
||||
$view->display_handler->setOption('style', $style);
|
||||
$view->initDisplay();
|
||||
$view->initStyle();
|
||||
$view->style_plugin->setUsesRowPlugin(FALSE);
|
||||
|
||||
$output = $view->preview();
|
||||
$output = $renderer->renderRoot($output);
|
||||
|
||||
$this->assertTrue(strpos($output, '<h1></h1>') !== FALSE, 'An empty value for test_option found in output.');
|
||||
|
||||
// Change this option and check the title of out output.
|
||||
$view->display_handler->overrideOption('test_option', 'Test option title');
|
||||
$view->save();
|
||||
|
||||
$output = $view->preview();
|
||||
$output = $renderer->renderRoot($output);
|
||||
|
||||
// Test we have our custom <h1> tag in the output of the view.
|
||||
$this->assertTrue(strpos($output, '<h1>Test option title</h1>') !== FALSE, 'The test_option value found in display output title.');
|
||||
|
||||
// Test that the display category/summary is in the UI.
|
||||
$this->drupalGet('admin/structure/views/view/test_view/edit/display_test_1');
|
||||
$this->assertText('Display test settings');
|
||||
// Ensure that the order is as expected.
|
||||
$result = $this->xpath('//ul[@id="views-display-menu-tabs"]/li/a/child::text()');
|
||||
$this->assertEqual($result[0]->getText(), 'Display test 2');
|
||||
$this->assertEqual($result[1]->getText(), 'Display test');
|
||||
|
||||
$this->clickLink('Test option title');
|
||||
|
||||
$test_option = $this->randomString();
|
||||
$this->drupalPostForm(NULL, ['test_option' => $test_option], t('Apply'));
|
||||
|
||||
// Check the new value has been saved by checking the UI summary text.
|
||||
$this->drupalGet('admin/structure/views/view/test_view/edit/display_test_1');
|
||||
$this->assertLink($test_option);
|
||||
|
||||
// Test the enable/disable status of a display.
|
||||
$view->display_handler->setOption('enabled', FALSE);
|
||||
$this->assertFalse($view->display_handler->isEnabled(), 'Make sure that isEnabled returns FALSE on a disabled display.');
|
||||
$view->display_handler->setOption('enabled', TRUE);
|
||||
$this->assertTrue($view->display_handler->isEnabled(), 'Make sure that isEnabled returns TRUE on a disabled display.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the overriding of filter_groups.
|
||||
*/
|
||||
public function testFilterGroupsOverriding() {
|
||||
$view = Views::getView('test_filter_groups');
|
||||
$view->initDisplay();
|
||||
|
||||
// mark is as overridden, yes FALSE, means overridden.
|
||||
$view->displayHandlers->get('page')->setOverride('filter_groups', FALSE);
|
||||
$this->assertFalse($view->displayHandlers->get('page')->isDefaulted('filter_groups'), "Make sure that 'filter_groups' is marked as overridden.");
|
||||
$this->assertFalse($view->displayHandlers->get('page')->isDefaulted('filters'), "Make sure that 'filters'' is marked as overridden.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getAttachedDisplays method.
|
||||
*/
|
||||
public function testGetAttachedDisplays() {
|
||||
$view = Views::getView('test_get_attach_displays');
|
||||
|
||||
// Both the feed_1 and the feed_2 display are attached to the page display.
|
||||
$view->setDisplay('page_1');
|
||||
$this->assertEqual($view->display_handler->getAttachedDisplays(), ['feed_1', 'feed_2']);
|
||||
|
||||
$view->setDisplay('feed_1');
|
||||
$this->assertEqual($view->display_handler->getAttachedDisplays(), []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the readmore validation.
|
||||
*/
|
||||
public function testReadMoreNoDisplay() {
|
||||
$view = Views::getView('test_display_more');
|
||||
// Confirm that the view validates when there is a page display.
|
||||
$errors = $view->validate();
|
||||
$this->assertTrue(empty($errors), 'More link validation has no errors.');
|
||||
|
||||
// Confirm that the view does not validate when the page display is disabled.
|
||||
$view->setDisplay('page_1');
|
||||
$view->display_handler->setOption('enabled', FALSE);
|
||||
$view->setDisplay('default');
|
||||
$errors = $view->validate();
|
||||
$this->assertTrue(!empty($errors), 'More link validation has some errors.');
|
||||
$this->assertEqual($errors['default'][0], 'Display "Master" uses a "more" link but there are no displays it can link to. You need to specify a custom URL.', 'More link validation has the right error.');
|
||||
|
||||
// Confirm that the view does not validate when the page display does not exist.
|
||||
$view = Views::getView('test_view');
|
||||
$view->setDisplay('default');
|
||||
$view->display_handler->setOption('use_more', 1);
|
||||
$errors = $view->validate();
|
||||
$this->assertTrue(!empty($errors), 'More link validation has some errors.');
|
||||
$this->assertEqual($errors['default'][0], 'Display "Master" uses a "more" link but there are no displays it can link to. You need to specify a custom URL.', 'More link validation has the right error.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests invalid display plugins.
|
||||
*/
|
||||
public function testInvalidDisplayPlugins() {
|
||||
$this->drupalGet('test_display_invalid');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Change the page plugin id to an invalid one. Bypass the entity system
|
||||
// so no menu rebuild was executed (so the path is still available).
|
||||
$config = $this->config('views.view.test_display_invalid');
|
||||
$config->set('display.page_1.display_plugin', 'invalid');
|
||||
$config->save();
|
||||
|
||||
$this->drupalGet('test_display_invalid');
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('The "invalid" plugin does not exist.');
|
||||
|
||||
// Rebuild the router, and ensure that the path is not accessible anymore.
|
||||
views_invalidate_cache();
|
||||
\Drupal::service('router.builder')->rebuildIfNeeded();
|
||||
|
||||
$this->drupalGet('test_display_invalid');
|
||||
$this->assertResponse(404);
|
||||
|
||||
// Change the display plugin ID back to the correct ID.
|
||||
$config = $this->config('views.view.test_display_invalid');
|
||||
$config->set('display.page_1.display_plugin', 'page');
|
||||
$config->save();
|
||||
|
||||
// Place the block display.
|
||||
$block = $this->drupalPlaceBlock('views_block:test_display_invalid-block_1', ['label' => 'Invalid display']);
|
||||
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertResponse(200);
|
||||
$result = $this->xpath('//div[@id = :id]', [':id' => 'block-' . $block->id()]);
|
||||
$this->assertEquals(1, count($result));
|
||||
|
||||
// Change the block plugin ID to an invalid one.
|
||||
$config = $this->config('views.view.test_display_invalid');
|
||||
$config->set('display.block_1.display_plugin', 'invalid');
|
||||
$config->save();
|
||||
|
||||
// Test the page is still displayed, the block not present, and has the
|
||||
// plugin warning message.
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('The "invalid" plugin does not exist.');
|
||||
$result = $this->xpath('//div[@id = :id]', [':id' => 'block-' . $block->id()]);
|
||||
$this->assertEquals(0, count($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests display validation when a required relationship is missing.
|
||||
*/
|
||||
public function testMissingRelationship() {
|
||||
$view = Views::getView('test_exposed_relationship_admin_ui');
|
||||
|
||||
// Remove the relationship that is not used by other handlers.
|
||||
$view->removeHandler('default', 'relationship', 'uid_1');
|
||||
$errors = $view->validate();
|
||||
// Check that no error message is shown.
|
||||
$this->assertTrue(empty($errors['default']), 'No errors found when removing unused relationship.');
|
||||
|
||||
// Unset cached relationships (see DisplayPluginBase::getHandlers())
|
||||
unset($view->display_handler->handlers['relationship']);
|
||||
|
||||
// Remove the relationship used by other handlers.
|
||||
$view->removeHandler('default', 'relationship', 'uid');
|
||||
// Validate display
|
||||
$errors = $view->validate();
|
||||
// Check that the error messages are shown.
|
||||
$this->assertTrue(count($errors['default']) == 2, 'Error messages found for required relationship');
|
||||
$this->assertEqual($errors['default'][0], t('The %handler_type %handler uses a relationship that has been removed.', ['%handler_type' => 'field', '%handler' => 'User: Last login']));
|
||||
$this->assertEqual($errors['default'][1], t('The %handler_type %handler uses a relationship that has been removed.', ['%handler_type' => 'field', '%handler' => 'User: Created']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the outputIsEmpty method on the display.
|
||||
*/
|
||||
public function testOutputIsEmpty() {
|
||||
$view = Views::getView('test_display_empty');
|
||||
$this->executeView($view);
|
||||
$this->assertTrue(count($view->result) > 0, 'Ensure the result of the view is not empty.');
|
||||
$this->assertFalse($view->display_handler->outputIsEmpty(), 'Ensure the view output is marked as not empty.');
|
||||
$view->destroy();
|
||||
|
||||
// Add a filter, so the view result is empty.
|
||||
$view->setDisplay('default');
|
||||
$item = [
|
||||
'table' => 'views_test_data',
|
||||
'field' => 'id',
|
||||
'id' => 'id',
|
||||
'value' => ['value' => 7297]
|
||||
];
|
||||
$view->setHandler('default', 'filter', 'id', $item);
|
||||
$this->executeView($view);
|
||||
$this->assertFalse(count($view->result), 'Ensure the result of the view is empty.');
|
||||
$this->assertFalse($view->display_handler->outputIsEmpty(), 'Ensure the view output is marked as not empty, because the empty text still appears.');
|
||||
$view->destroy();
|
||||
|
||||
// Remove the empty area, but mark the header area to still appear.
|
||||
$view->removeHandler('default', 'empty', 'area');
|
||||
$item = $view->getHandler('default', 'header', 'area');
|
||||
$item['empty'] = TRUE;
|
||||
$view->setHandler('default', 'header', 'area', $item);
|
||||
$this->executeView($view);
|
||||
$this->assertFalse(count($view->result), 'Ensure the result of the view is empty.');
|
||||
$this->assertFalse($view->display_handler->outputIsEmpty(), 'Ensure the view output is marked as not empty, because the header text still appears.');
|
||||
$view->destroy();
|
||||
|
||||
// Hide the header on empty results.
|
||||
$item = $view->getHandler('default', 'header', 'area');
|
||||
$item['empty'] = FALSE;
|
||||
$view->setHandler('default', 'header', 'area', $item);
|
||||
$this->executeView($view);
|
||||
$this->assertFalse(count($view->result), 'Ensure the result of the view is empty.');
|
||||
$this->assertTrue($view->display_handler->outputIsEmpty(), 'Ensure the view output is marked as empty.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test translation rendering settings based on entity translatability.
|
||||
*/
|
||||
public function testTranslationSetting() {
|
||||
\Drupal::service('module_installer')->install(['file']);
|
||||
\Drupal::service('router.builder')->rebuild();
|
||||
|
||||
// By default there should be no language settings.
|
||||
$this->checkTranslationSetting();
|
||||
\Drupal::service('module_installer')->install(['language']);
|
||||
|
||||
// Enabling the language module should not make a difference.
|
||||
$this->checkTranslationSetting();
|
||||
|
||||
// Making the site multilingual should let translatable entity types support
|
||||
// translation rendering.
|
||||
ConfigurableLanguage::createFromLangcode('it')->save();
|
||||
$this->checkTranslationSetting(TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts a node and a file based view for the translation setting.
|
||||
*
|
||||
* The file based view should never expose that setting. The node based view
|
||||
* should if the site is multilingual.
|
||||
*
|
||||
* @param bool $expected_node_translatability
|
||||
* Whether the node based view should be expected to support translation
|
||||
* settings.
|
||||
*/
|
||||
protected function checkTranslationSetting($expected_node_translatability = FALSE) {
|
||||
$not_supported_text = 'The view is not based on a translatable entity type or the site is not multilingual.';
|
||||
$supported_text = 'All content that supports translations will be displayed in the selected language.';
|
||||
|
||||
$this->drupalGet('admin/structure/views/nojs/display/content/page_1/rendering_language');
|
||||
if ($expected_node_translatability) {
|
||||
$this->assertNoText($not_supported_text);
|
||||
$this->assertText($supported_text);
|
||||
}
|
||||
else {
|
||||
$this->assertText($not_supported_text);
|
||||
$this->assertNoText($supported_text);
|
||||
}
|
||||
|
||||
$this->drupalGet('admin/structure/views/nojs/display/files/page_1/rendering_language');
|
||||
$this->assertText($not_supported_text);
|
||||
$this->assertNoText($supported_text);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,403 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Plugin;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\ViewExecutable;
|
||||
use Drupal\views\Views;
|
||||
use Drupal\views\Entity\View;
|
||||
|
||||
/**
|
||||
* Tests exposed forms functionality.
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class ExposedFormTest extends ViewTestBase {
|
||||
|
||||
use AssertPageCacheContextsAndTagsTrait;
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_exposed_form_buttons', 'test_exposed_block', 'test_exposed_form_sort_items_per_page'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node', 'views_ui', 'block', 'entity_test'];
|
||||
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$this->enableViewsTestModule();
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'article']);
|
||||
|
||||
// Create some random nodes.
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$this->drupalCreateNode(['type' => 'article']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the submit button.
|
||||
*/
|
||||
public function testSubmitButton() {
|
||||
// Test the submit button value defaults to 'Apply'.
|
||||
$this->drupalGet('test_exposed_form_buttons');
|
||||
$this->assertResponse(200);
|
||||
$this->helperButtonHasLabel('edit-submit-test-exposed-form-buttons', t('Apply'));
|
||||
|
||||
// Rename the label of the submit button.
|
||||
$view = Views::getView('test_exposed_form_buttons');
|
||||
$view->setDisplay();
|
||||
|
||||
$exposed_form = $view->display_handler->getOption('exposed_form');
|
||||
$exposed_form['options']['submit_button'] = $expected_label = $this->randomMachineName();
|
||||
$view->display_handler->setOption('exposed_form', $exposed_form);
|
||||
$view->save();
|
||||
|
||||
// Make sure the submit button label changed.
|
||||
$this->drupalGet('test_exposed_form_buttons');
|
||||
$this->helperButtonHasLabel('edit-submit-test-exposed-form-buttons', $expected_label);
|
||||
|
||||
// Make sure an empty label uses the default 'Apply' button value too.
|
||||
$view = Views::getView('test_exposed_form_buttons');
|
||||
$view->setDisplay();
|
||||
|
||||
$exposed_form = $view->display_handler->getOption('exposed_form');
|
||||
$exposed_form['options']['submit_button'] = '';
|
||||
$view->display_handler->setOption('exposed_form', $exposed_form);
|
||||
$view->save();
|
||||
|
||||
// Make sure the submit button label shows 'Apply'.
|
||||
$this->drupalGet('test_exposed_form_buttons');
|
||||
$this->helperButtonHasLabel('edit-submit-test-exposed-form-buttons', t('Apply'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the exposed form with a non-standard identifier.
|
||||
*/
|
||||
public function testExposedIdentifier() {
|
||||
// Alter the identifier of the filter to a random string.
|
||||
$view = Views::getView('test_exposed_form_buttons');
|
||||
$view->setDisplay();
|
||||
$identifier = 'new_identifier';
|
||||
$view->displayHandlers->get('default')->overrideOption('filters', [
|
||||
'type' => [
|
||||
'exposed' => TRUE,
|
||||
'field' => 'type',
|
||||
'id' => 'type',
|
||||
'table' => 'node_field_data',
|
||||
'plugin_id' => 'in_operator',
|
||||
'entity_type' => 'node',
|
||||
'entity_field' => 'type',
|
||||
'expose' => [
|
||||
'identifier' => $identifier,
|
||||
'label' => 'Content: Type',
|
||||
'operator_id' => 'type_op',
|
||||
'reduce' => FALSE,
|
||||
'description' => 'Exposed overridden description'
|
||||
],
|
||||
]
|
||||
]);
|
||||
$view->save();
|
||||
$this->drupalGet('test_exposed_form_buttons', ['query' => [$identifier => 'article']]);
|
||||
$this->assertFieldById(Html::getId('edit-' . $identifier), 'article', "Article type filter set with new identifier.");
|
||||
|
||||
// Alter the identifier of the filter to a random string containing
|
||||
// restricted characters.
|
||||
$view = Views::getView('test_exposed_form_buttons');
|
||||
$view->setDisplay();
|
||||
$identifier = 'bad identifier';
|
||||
$view->displayHandlers->get('default')->overrideOption('filters', [
|
||||
'type' => [
|
||||
'exposed' => TRUE,
|
||||
'field' => 'type',
|
||||
'id' => 'type',
|
||||
'table' => 'node_field_data',
|
||||
'plugin_id' => 'in_operator',
|
||||
'entity_type' => 'node',
|
||||
'entity_field' => 'type',
|
||||
'expose' => [
|
||||
'identifier' => $identifier,
|
||||
'label' => 'Content: Type',
|
||||
'operator_id' => 'type_op',
|
||||
'reduce' => FALSE,
|
||||
'description' => 'Exposed overridden description'
|
||||
],
|
||||
]
|
||||
]);
|
||||
$this->executeView($view);
|
||||
|
||||
$errors = $view->validate();
|
||||
$expected = [
|
||||
'default' => ['This identifier has illegal characters.'],
|
||||
'page_1' => ['This identifier has illegal characters.'],
|
||||
];
|
||||
$this->assertEqual($errors, $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the reset button works on an exposed form.
|
||||
*/
|
||||
public function testResetButton() {
|
||||
// Test the button is hidden when there is no exposed input.
|
||||
$this->drupalGet('test_exposed_form_buttons');
|
||||
$this->assertNoField('edit-reset');
|
||||
|
||||
$this->drupalGet('test_exposed_form_buttons', ['query' => ['type' => 'article']]);
|
||||
// Test that the type has been set.
|
||||
$this->assertFieldById('edit-type', 'article', 'Article type filter set.');
|
||||
|
||||
// Test the reset works.
|
||||
$this->drupalGet('test_exposed_form_buttons', ['query' => ['op' => 'Reset']]);
|
||||
$this->assertResponse(200);
|
||||
// Test the type has been reset.
|
||||
$this->assertFieldById('edit-type', 'All', 'Article type filter has been reset.');
|
||||
|
||||
// Test the button is hidden after reset.
|
||||
$this->assertNoField('edit-reset');
|
||||
|
||||
// Test the reset works with type set.
|
||||
$this->drupalGet('test_exposed_form_buttons', ['query' => ['type' => 'article', 'op' => 'Reset']]);
|
||||
$this->assertResponse(200);
|
||||
$this->assertFieldById('edit-type', 'All', 'Article type filter has been reset.');
|
||||
|
||||
// Test the button is hidden after reset.
|
||||
$this->assertNoField('edit-reset');
|
||||
|
||||
// Rename the label of the reset button.
|
||||
$view = Views::getView('test_exposed_form_buttons');
|
||||
$view->setDisplay();
|
||||
|
||||
$exposed_form = $view->display_handler->getOption('exposed_form');
|
||||
$exposed_form['options']['reset_button_label'] = $expected_label = $this->randomMachineName();
|
||||
$exposed_form['options']['reset_button'] = TRUE;
|
||||
$view->display_handler->setOption('exposed_form', $exposed_form);
|
||||
$view->save();
|
||||
|
||||
// Look whether the reset button label changed.
|
||||
$this->drupalGet('test_exposed_form_buttons', ['query' => ['type' => 'article']]);
|
||||
$this->assertResponse(200);
|
||||
|
||||
$this->helperButtonHasLabel('edit-reset', $expected_label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests overriding the default render option with checkboxes.
|
||||
*/
|
||||
public function testExposedFormRenderCheckboxes() {
|
||||
// Make sure we have at least two options for node type.
|
||||
$this->drupalCreateContentType(['type' => 'page']);
|
||||
$this->drupalCreateNode(['type' => 'page']);
|
||||
|
||||
// Use a test theme to convert multi-select elements into checkboxes.
|
||||
\Drupal::service('theme_handler')->install(['views_test_checkboxes_theme']);
|
||||
$this->config('system.theme')
|
||||
->set('default', 'views_test_checkboxes_theme')
|
||||
->save();
|
||||
|
||||
// Set the "type" filter to multi-select.
|
||||
$view = Views::getView('test_exposed_form_buttons');
|
||||
$filter = $view->getHandler('page_1', 'filter', 'type');
|
||||
$filter['expose']['multiple'] = TRUE;
|
||||
$view->setHandler('page_1', 'filter', 'type', $filter);
|
||||
|
||||
// Only display 5 items per page so we can test that paging works.
|
||||
$display = &$view->storage->getDisplay('default');
|
||||
$display['display_options']['pager']['options']['items_per_page'] = 5;
|
||||
|
||||
$view->save();
|
||||
$this->drupalGet('test_exposed_form_buttons');
|
||||
|
||||
$actual = $this->xpath('//form//input[@type="checkbox" and @name="type[article]"]');
|
||||
$this->assertEqual(count($actual), 1, 'Article option renders as a checkbox.');
|
||||
$actual = $this->xpath('//form//input[@type="checkbox" and @name="type[page]"]');
|
||||
$this->assertEqual(count($actual), 1, 'Page option renders as a checkbox');
|
||||
|
||||
// Ensure that all results are displayed.
|
||||
$rows = $this->xpath("//div[contains(@class, 'views-row')]");
|
||||
$this->assertEqual(count($rows), 5, '5 rows are displayed by default on the first page when no options are checked.');
|
||||
|
||||
$this->clickLink('Page 2');
|
||||
$rows = $this->xpath("//div[contains(@class, 'views-row')]");
|
||||
$this->assertEqual(count($rows), 1, '1 row is displayed by default on the second page when no options are checked.');
|
||||
$this->assertNoText('An illegal choice has been detected. Please contact the site administrator.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the exposed block functionality.
|
||||
*/
|
||||
public function testExposedBlock() {
|
||||
$this->drupalCreateContentType(['type' => 'page']);
|
||||
$view = Views::getView('test_exposed_block');
|
||||
$view->setDisplay('page_1');
|
||||
$block = $this->drupalPlaceBlock('views_exposed_filter_block:test_exposed_block-page_1');
|
||||
$this->drupalGet('test_exposed_block');
|
||||
|
||||
// Test there is an exposed form in a block.
|
||||
$xpath = $this->buildXPathQuery('//div[@id=:id]/form/@id', [':id' => Html::getUniqueId('block-' . $block->id())]);
|
||||
$result = $this->xpath($xpath);
|
||||
$this->assertEquals(1, count($result));
|
||||
|
||||
// Test there is not an exposed form in the view page content area.
|
||||
$xpath = $this->buildXPathQuery('//div[@class="view-content"]/form/@id', [':id' => Html::getUniqueId('block-' . $block->id())]);
|
||||
$this->assertNoFieldByXpath($xpath, $this->getExpectedExposedFormId($view), 'No exposed form found in views content region.');
|
||||
|
||||
// Test there is only one views exposed form on the page.
|
||||
$elements = $this->xpath('//form[@id=:id]', [':id' => $this->getExpectedExposedFormId($view)]);
|
||||
$this->assertEqual(count($elements), 1, 'One exposed form block found.');
|
||||
|
||||
// Test that the correct option is selected after form submission.
|
||||
$this->assertCacheContext('url');
|
||||
$this->assertOptionSelected('edit-type', 'All');
|
||||
foreach (['All', 'article', 'page'] as $argument) {
|
||||
$this->drupalGet('test_exposed_block', ['query' => ['type' => $argument]]);
|
||||
$this->assertCacheContext('url');
|
||||
$this->assertOptionSelected('edit-type', $argument);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the input required exposed form type.
|
||||
*/
|
||||
public function testInputRequired() {
|
||||
$view = View::load('test_exposed_form_buttons');
|
||||
$display = &$view->getDisplay('default');
|
||||
$display['display_options']['exposed_form']['type'] = 'input_required';
|
||||
$view->save();
|
||||
|
||||
$this->drupalGet('test_exposed_form_buttons');
|
||||
$this->assertResponse(200);
|
||||
$this->helperButtonHasLabel('edit-submit-test-exposed-form-buttons', t('Apply'));
|
||||
|
||||
// Ensure that no results are displayed.
|
||||
$rows = $this->xpath("//div[contains(@class, 'views-row')]");
|
||||
$this->assertEqual(count($rows), 0, 'No rows are displayed by default when no input is provided.');
|
||||
|
||||
$this->drupalGet('test_exposed_form_buttons', ['query' => ['type' => 'article']]);
|
||||
|
||||
// Ensure that results are displayed.
|
||||
$rows = $this->xpath("//div[contains(@class, 'views-row')]");
|
||||
$this->assertEqual(count($rows), 5, 'All rows are displayed by default when input is provided.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the "on demand text" for the input required exposed form type.
|
||||
*/
|
||||
public function testTextInputRequired() {
|
||||
$view = Views::getView('test_exposed_form_buttons');
|
||||
$display = &$view->storage->getDisplay('default');
|
||||
$display['display_options']['exposed_form']['type'] = 'input_required';
|
||||
// Set up the "on demand text".
|
||||
// @see https://www.drupal.org/node/535868
|
||||
$on_demand_text = 'Select any filter and click Apply to see results.';
|
||||
$display['display_options']['exposed_form']['options']['text_input_required'] = $on_demand_text;
|
||||
$display['display_options']['exposed_form']['options']['text_input_required_format'] = filter_default_format();
|
||||
$view->save();
|
||||
|
||||
// Ensure that the "on demand text" is displayed when no exposed filters are
|
||||
// applied.
|
||||
$this->drupalGet('test_exposed_form_buttons');
|
||||
$this->assertText('Select any filter and click Apply to see results.');
|
||||
|
||||
// Ensure that the "on demand text" is not displayed when an exposed filter
|
||||
// is applied.
|
||||
$this->drupalGet('test_exposed_form_buttons', ['query' => ['type' => 'article']]);
|
||||
$this->assertNoText($on_demand_text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests exposed forms with exposed sort and items per page.
|
||||
*/
|
||||
public function testExposedSortAndItemsPerPage() {
|
||||
for ($i = 0; $i < 50; $i++) {
|
||||
$entity = EntityTest::create([
|
||||
]);
|
||||
$entity->save();
|
||||
}
|
||||
$contexts = [
|
||||
'languages:language_interface',
|
||||
'entity_test_view_grants',
|
||||
'theme',
|
||||
'url.query_args',
|
||||
'languages:language_content'
|
||||
];
|
||||
|
||||
$this->drupalGet('test_exposed_form_sort_items_per_page');
|
||||
$this->assertCacheContexts($contexts);
|
||||
$this->assertIds(range(1, 10, 1));
|
||||
|
||||
$this->drupalGet('test_exposed_form_sort_items_per_page', ['query' => ['sort_order' => 'DESC']]);
|
||||
$this->assertCacheContexts($contexts);
|
||||
$this->assertIds(range(50, 41, 1));
|
||||
|
||||
$this->drupalGet('test_exposed_form_sort_items_per_page', ['query' => ['sort_order' => 'DESC', 'items_per_page' => 25]]);
|
||||
$this->assertCacheContexts($contexts);
|
||||
$this->assertIds(range(50, 26, 1));
|
||||
|
||||
$this->drupalGet('test_exposed_form_sort_items_per_page', ['query' => ['sort_order' => 'DESC', 'items_per_page' => 25, 'offset' => 10]]);
|
||||
$this->assertCacheContexts($contexts);
|
||||
$this->assertIds(range(40, 16, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the specified ids are the ones displayed in the view output.
|
||||
*
|
||||
* @param int[] $ids
|
||||
* The ids to check.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if ids match, FALSE otherwise.
|
||||
*/
|
||||
protected function assertIds(array $ids) {
|
||||
$elements = $this->cssSelect('div.view-test-exposed-form-sort-items-per-page div.views-row span.field-content');
|
||||
$actual_ids = [];
|
||||
foreach ($elements as $element) {
|
||||
$actual_ids[] = (int) $element->getText();
|
||||
}
|
||||
|
||||
return $this->assertIdentical($ids, $actual_ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a views exposed form ID.
|
||||
*
|
||||
* @param \Drupal\views\ViewExecutable $view
|
||||
* The view to create an ID for.
|
||||
*
|
||||
* @return string
|
||||
* The form ID.
|
||||
*/
|
||||
protected function getExpectedExposedFormId(ViewExecutable $view) {
|
||||
return Html::cleanCssIdentifier('views-exposed-form-' . $view->storage->id() . '-' . $view->current_display);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a view which is rendered after a form with a validation error.
|
||||
*/
|
||||
public function testFormErrorWithExposedForm() {
|
||||
$this->drupalGet('views_test_data_error_form_page');
|
||||
$this->assertResponse(200);
|
||||
$form = $this->cssSelect('form.views-exposed-form');
|
||||
$this->assertTrue($form, 'The exposed form element was found.');
|
||||
$this->assertRaw(t('Apply'), 'Ensure the exposed form is rendered before submitting the normal form.');
|
||||
$this->assertRaw('<div class="views-row">', 'Views result shown.');
|
||||
|
||||
$this->drupalPostForm(NULL, [], t('Submit'));
|
||||
$this->assertResponse(200);
|
||||
$form = $this->cssSelect('form.views-exposed-form');
|
||||
$this->assertTrue($form, 'The exposed form element was found.');
|
||||
$this->assertRaw(t('Apply'), 'Ensure the exposed form is rendered after submitting the normal form.');
|
||||
$this->assertRaw('<div class="views-row">', 'Views result shown.');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Plugin;
|
||||
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Views;
|
||||
use Drupal\views_test_data\Plugin\views\filter\FilterTest as FilterPlugin;
|
||||
|
||||
/**
|
||||
* Tests general filter plugin functionality.
|
||||
*
|
||||
* @group views
|
||||
* @see \Drupal\views\Plugin\views\filter\FilterPluginBase
|
||||
*/
|
||||
class FilterTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_filter', 'test_filter_in_operator_ui'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['views_ui', 'node'];
|
||||
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$this->enableViewsTestModule();
|
||||
|
||||
$this->adminUser = $this->drupalCreateUser(['administer views']);
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Page']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function viewsData() {
|
||||
$data = parent::viewsData();
|
||||
$data['views_test_data']['name']['filter']['id'] = 'test_filter';
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test query of the row plugin.
|
||||
*/
|
||||
public function testFilterQuery() {
|
||||
// Check that we can find the test filter plugin.
|
||||
$plugin = $this->container->get('plugin.manager.views.filter')->createInstance('test_filter');
|
||||
$this->assertTrue($plugin instanceof FilterPlugin, 'Test filter plugin found.');
|
||||
|
||||
$view = Views::getView('test_filter');
|
||||
$view->initDisplay();
|
||||
|
||||
// Change the filtering.
|
||||
$view->displayHandlers->get('default')->overrideOption('filters', [
|
||||
'test_filter' => [
|
||||
'id' => 'test_filter',
|
||||
'table' => 'views_test_data',
|
||||
'field' => 'name',
|
||||
'operator' => '=',
|
||||
'value' => 'John',
|
||||
'group' => 0,
|
||||
],
|
||||
]);
|
||||
|
||||
$this->executeView($view);
|
||||
|
||||
// Make sure the query have where data.
|
||||
$this->assertTrue(!empty($view->query->where));
|
||||
|
||||
// Check the data added.
|
||||
$where = $view->query->where;
|
||||
$this->assertIdentical($where[0]['conditions'][0]['field'], 'views_test_data.name', 'Where condition field matches');
|
||||
$this->assertIdentical($where[0]['conditions'][0]['value'], 'John', 'Where condition value matches');
|
||||
$this->assertIdentical($where[0]['conditions'][0]['operator'], '=', 'Where condition operator matches');
|
||||
|
||||
$this->executeView($view);
|
||||
|
||||
// Check that our operator and value match on the filter.
|
||||
$this->assertIdentical($view->filter['test_filter']->operator, '=');
|
||||
$this->assertIdentical($view->filter['test_filter']->value, 'John');
|
||||
|
||||
// Check that we have a single element, as a result of applying the '= John'
|
||||
// filter.
|
||||
$this->assertEqual(count($view->result), 1, format_string('Results were returned. @count results.', ['@count' => count($view->result)]));
|
||||
|
||||
$view->destroy();
|
||||
|
||||
$view->initDisplay();
|
||||
|
||||
// Change the filtering.
|
||||
$view->displayHandlers->get('default')->overrideOption('filters', [
|
||||
'test_filter' => [
|
||||
'id' => 'test_filter',
|
||||
'table' => 'views_test_data',
|
||||
'field' => 'name',
|
||||
'operator' => '<>',
|
||||
'value' => 'John',
|
||||
'group' => 0,
|
||||
],
|
||||
]);
|
||||
|
||||
$this->executeView($view);
|
||||
|
||||
// Check that our operator and value match on the filter.
|
||||
$this->assertIdentical($view->filter['test_filter']->operator, '<>');
|
||||
$this->assertIdentical($view->filter['test_filter']->value, 'John');
|
||||
|
||||
// Check if we have the other elements in the dataset, as a result of
|
||||
// applying the '<> John' filter.
|
||||
$this->assertEqual(count($view->result), 4, format_string('Results were returned. @count results.', ['@count' => count($view->result)]));
|
||||
|
||||
$view->destroy();
|
||||
$view->initDisplay();
|
||||
|
||||
// Set the test_enable option to FALSE. The 'where' clause should not be
|
||||
// added to the query.
|
||||
$view->displayHandlers->get('default')->overrideOption('filters', [
|
||||
'test_filter' => [
|
||||
'id' => 'test_filter',
|
||||
'table' => 'views_test_data',
|
||||
'field' => 'name',
|
||||
'operator' => '<>',
|
||||
'value' => 'John',
|
||||
'group' => 0,
|
||||
// Disable this option, so nothing should be added to the query.
|
||||
'test_enable' => FALSE,
|
||||
],
|
||||
]);
|
||||
|
||||
// Execute the view again.
|
||||
$this->executeView($view);
|
||||
|
||||
// Check if we have all 5 results.
|
||||
$this->assertEqual(count($view->result), 5, format_string('All @count results returned', ['@count' => count($view->displayHandlers)]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test no error message is displayed when all options are selected in an
|
||||
* exposed filter.
|
||||
*/
|
||||
public function testInOperatorSelectAllOptions() {
|
||||
$view = Views::getView('test_filter_in_operator_ui');
|
||||
$row['row[type]'] = 'fields';
|
||||
$this->drupalPostForm('admin/structure/views/nojs/display/test_filter_in_operator_ui/default/row', $row, t('Apply'));
|
||||
$field['name[node_field_data.nid]'] = TRUE;
|
||||
$this->drupalPostForm('admin/structure/views/nojs/add-handler/test_filter_in_operator_ui/default/field', $field, t('Add and configure fields'));
|
||||
$this->drupalPostForm('admin/structure/views/nojs/handler/test_filter_in_operator_ui/default/field/nid', [], t('Apply'));
|
||||
$edit['options[value][all]'] = TRUE;
|
||||
$edit['options[value][article]'] = TRUE;
|
||||
$edit['options[value][page]'] = TRUE;
|
||||
$this->drupalPostForm('admin/structure/views/nojs/handler/test_filter_in_operator_ui/default/filter/type', $edit, t('Apply'));
|
||||
$this->drupalPostForm('admin/structure/views/view/test_filter_in_operator_ui/edit/default', [], t('Save'));
|
||||
$this->drupalPostForm(NULL, [], t('Update preview'));
|
||||
$this->assertNoText('An illegal choice has been detected.');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Plugin;
|
||||
|
||||
use Drupal\menu_link_content\Entity\MenuLinkContent;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
|
||||
/**
|
||||
* Tests the menu links created in views.
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class MenuLinkTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_menu_link'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['views', 'views_ui', 'user', 'node', 'menu_ui', 'block'];
|
||||
|
||||
/**
|
||||
* A user with permission to administer views, menus and view content.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$this->enableViewsTestModule();
|
||||
|
||||
$this->adminUser = $this->drupalCreateUser(['administer views', 'administer menu']);
|
||||
$this->drupalPlaceBlock('system_menu_block:main');
|
||||
$this->drupalCreateContentType(['type' => 'page']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that menu links using menu_link_content as parent are visible.
|
||||
*/
|
||||
public function testHierarchicalMenuLinkVisibility() {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
$node = $this->drupalCreateNode(['type' => 'page']);
|
||||
|
||||
// Create a primary level menu link to the node.
|
||||
$link = MenuLinkContent::create([
|
||||
'title' => 'Primary level node',
|
||||
'menu_name' => 'main',
|
||||
'bundle' => 'menu_link_content',
|
||||
'parent' => '',
|
||||
'link' => [['uri' => 'entity:node/' . $node->id()]],
|
||||
]);
|
||||
$link->save();
|
||||
|
||||
$parent_menu_value = 'main:menu_link_content:' . $link->uuid();
|
||||
|
||||
// Alter the view's menu link in view page to use the menu link from the
|
||||
// node as parent.
|
||||
$this->drupalPostForm("admin/structure/views/nojs/display/test_menu_link/page_1/menu", [
|
||||
'menu[type]' => 'normal',
|
||||
'menu[title]' => 'Secondary level view page',
|
||||
'menu[parent]' => $parent_menu_value,
|
||||
], 'Apply');
|
||||
|
||||
// Save view which has pending changes.
|
||||
$this->drupalPostForm(NULL, [], 'Save');
|
||||
|
||||
// Test if the node as parent menu item is selected in our views settings.
|
||||
$this->drupalGet('admin/structure/views/nojs/display/test_menu_link/page_1/menu');
|
||||
$this->assertOptionSelected('edit-menu-parent', $parent_menu_value);
|
||||
|
||||
$this->drupalGet('');
|
||||
|
||||
// Test if the primary menu item (node) is visible, and the secondary menu
|
||||
// item (view) is hidden.
|
||||
$this->assertText('Primary level node');
|
||||
$this->assertNoText('Secondary level view page');
|
||||
|
||||
// Go to the node page and ensure that both the first and second level items
|
||||
// are visible.
|
||||
$this->drupalGet($node->urlInfo());
|
||||
$this->assertText('Primary level node');
|
||||
$this->assertText('Secondary level view page');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Plugin;
|
||||
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the mini pager plugin.
|
||||
*
|
||||
* @group views
|
||||
* @see \Drupal\views\Plugin\views\pager\Mini
|
||||
*/
|
||||
class MiniPagerTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_mini_pager'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node'];
|
||||
|
||||
/**
|
||||
* Nodes used by the test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $nodes;
|
||||
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page']);
|
||||
// Create a bunch of test nodes.
|
||||
for ($i = 0; $i < 20; $i++) {
|
||||
$this->nodes[] = $this->drupalCreateNode();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the rendering of mini pagers.
|
||||
*/
|
||||
public function testMiniPagerRender() {
|
||||
$this->drupalGet('test_mini_pager');
|
||||
$this->assertText('›› test', 'The next link appears on the first page.');
|
||||
$this->assertText('Page 1', 'The current page info shows the first page.');
|
||||
$this->assertNoText('‹‹ test', 'The previous link does not appear on the first page.');
|
||||
$this->assertText($this->nodes[0]->label());
|
||||
$this->assertText($this->nodes[1]->label());
|
||||
$this->assertText($this->nodes[2]->label());
|
||||
|
||||
$this->drupalGet('test_mini_pager', ['query' => ['page' => 1]]);
|
||||
$this->assertText('‹‹ test', 'The previous link appears.');
|
||||
$this->assertText('Page 2', 'The current page info shows the second page.');
|
||||
$this->assertText('›› test', 'The next link appears.');
|
||||
$this->assertText($this->nodes[3]->label());
|
||||
$this->assertText($this->nodes[4]->label());
|
||||
$this->assertText($this->nodes[5]->label());
|
||||
|
||||
$this->drupalGet('test_mini_pager', ['query' => ['page' => 6]]);
|
||||
$this->assertNoText('›› test', 'The next link appears on the last page.');
|
||||
$this->assertText('Page 7', 'The current page info shows the last page.');
|
||||
$this->assertText('‹‹ test', 'The previous link does not appear on the last page.');
|
||||
$this->assertText($this->nodes[18]->label());
|
||||
$this->assertText($this->nodes[19]->label());
|
||||
|
||||
// Test @total value in result summary
|
||||
$view = Views::getView('test_mini_pager');
|
||||
$view->setDisplay('page_4');
|
||||
$this->executeView($view);
|
||||
$this->assertIdentical($view->get_total_rows, TRUE, 'The query was set to calculate the total number of rows.');
|
||||
$this->assertEqual(count($this->nodes), $view->total_rows, 'The total row count is equal to the number of nodes.');
|
||||
|
||||
$this->drupalGet('test_mini_pager_total', ['query' => ['page' => 1]]);
|
||||
$this->assertText('of ' . count($this->nodes), 'The first page shows the total row count.');
|
||||
$this->drupalGet('test_mini_pager_total', ['query' => ['page' => 6]]);
|
||||
$this->assertText('of ' . count($this->nodes), 'The last page shows the total row count.');
|
||||
|
||||
// Test a mini pager with just one item per page.
|
||||
$this->drupalGet('test_mini_pager_one');
|
||||
$this->assertText('››');
|
||||
$this->assertText('Page 1');
|
||||
$this->assertText($this->nodes[0]->label());
|
||||
|
||||
$this->drupalGet('test_mini_pager_one', ['query' => ['page' => 1]]);
|
||||
$this->assertText('‹‹');
|
||||
$this->assertText('Page 2');
|
||||
$this->assertText('››');
|
||||
$this->assertText($this->nodes[1]->label());
|
||||
|
||||
$this->drupalGet('test_mini_pager_one', ['query' => ['page' => 19]]);
|
||||
$this->assertNoText('››');
|
||||
$this->assertText('Page 20');
|
||||
$this->assertText('‹‹');
|
||||
$this->assertText($this->nodes[19]->label());
|
||||
|
||||
$this->drupalGet('test_mini_pager_all');
|
||||
$this->assertNoText('‹‹ test', 'The previous link does not appear on the page.');
|
||||
$this->assertNoText('Page 1', 'The current page info shows the only page.');
|
||||
$this->assertNoText('test ››', 'The next link does not appear on the page.');
|
||||
$result = $this->xpath('//div[contains(@class, "views-row")]');
|
||||
$this->assertEqual(count($result), count($this->nodes), 'All rows appear on the page.');
|
||||
|
||||
// Remove all items beside 1, so there should be no links shown.
|
||||
for ($i = 0; $i < 19; $i++) {
|
||||
$this->nodes[$i]->delete();
|
||||
}
|
||||
|
||||
$this->drupalGet('test_mini_pager');
|
||||
$this->assertNoText('‹‹ test', 'The previous link does not appear on the page.');
|
||||
$this->assertNoText('Page 1', 'The current page info shows the only page.');
|
||||
$this->assertNoText('‹‹ test', 'The previous link does not appear on the page.');
|
||||
$this->assertText($this->nodes[19]->label());
|
||||
|
||||
$view = Views::getView('test_mini_pager');
|
||||
$this->executeView($view);
|
||||
$this->assertIdentical($view->get_total_rows, NULL, 'The query was not forced to calculate the total number of results.');
|
||||
$this->assertIdentical($view->total_rows, 1, 'The pager calculated the total number of rows.');
|
||||
|
||||
// Remove the last node as well and ensure that no "Page 1" is shown.
|
||||
$this->nodes[19]->delete();
|
||||
$this->drupalGet('test_mini_pager');
|
||||
$this->assertNoText('‹‹ test', 'The previous link does not appear on the page.');
|
||||
$this->assertNoText('Page 1', 'The current page info shows the only page.');
|
||||
$this->assertNoText('‹‹ test', 'The previous link does not appear on the page.');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Plugin;
|
||||
|
||||
use Drupal\Component\Gettext\PoHeader;
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
|
||||
/**
|
||||
* Tests the creation of numeric fields.
|
||||
*
|
||||
* @group field
|
||||
*/
|
||||
class NumericFormatPluralTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['views_ui', 'file', 'language', 'locale'];
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['numeric_test'];
|
||||
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$web_user = $this->drupalCreateUser(['administer views', 'administer languages']);
|
||||
$this->drupalLogin($web_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test plural formatting setting on a numeric views handler.
|
||||
*/
|
||||
public function testNumericFormatPlural() {
|
||||
// Create a file.
|
||||
$file = $this->createFile();
|
||||
|
||||
// Assert that the starting configuration is correct.
|
||||
$config = $this->config('views.view.numeric_test');
|
||||
$field_config_prefix = 'display.default.display_options.fields.count.';
|
||||
$this->assertEqual($config->get($field_config_prefix . 'format_plural'), TRUE);
|
||||
$this->assertEqual($config->get($field_config_prefix . 'format_plural_string'), '1' . LOCALE_PLURAL_DELIMITER . '@count');
|
||||
|
||||
// Assert that the value is displayed.
|
||||
$this->drupalGet('numeric-test');
|
||||
$this->assertRaw('<span class="field-content">0</span>');
|
||||
|
||||
// Assert that the user interface has controls to change it.
|
||||
$this->drupalGet('admin/structure/views/nojs/handler/numeric_test/page_1/field/count');
|
||||
$this->assertFieldByName('options[format_plural_values][0]', '1');
|
||||
$this->assertFieldByName('options[format_plural_values][1]', '@count');
|
||||
|
||||
// Assert that changing the settings will change configuration properly.
|
||||
$edit = ['options[format_plural_values][0]' => '1 time', 'options[format_plural_values][1]' => '@count times'];
|
||||
$this->drupalPostForm(NULL, $edit, t('Apply'));
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
|
||||
$config = $this->config('views.view.numeric_test');
|
||||
$field_config_prefix = 'display.default.display_options.fields.count.';
|
||||
$this->assertEqual($config->get($field_config_prefix . 'format_plural'), TRUE);
|
||||
$this->assertEqual($config->get($field_config_prefix . 'format_plural_string'), '1 time' . LOCALE_PLURAL_DELIMITER . '@count times');
|
||||
|
||||
// Assert that the value is displayed with some sample values.
|
||||
$numbers = [0, 1, 2, 3, 4, 42];
|
||||
foreach ($numbers as $i => $number) {
|
||||
\Drupal::service('file.usage')->add($file, 'views_ui', 'dummy', $i, $number);
|
||||
}
|
||||
$this->drupalGet('numeric-test');
|
||||
foreach ($numbers as $i => $number) {
|
||||
$this->assertRaw('<span class="field-content">' . $number . ($number == 1 ? ' time' : ' times') . '</span>');
|
||||
}
|
||||
|
||||
// Add Slovenian and set its plural formula to test multiple plural forms.
|
||||
$edit = ['predefined_langcode' => 'sl'];
|
||||
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
|
||||
$formula = 'nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);';
|
||||
$header = new PoHeader();
|
||||
list($nplurals, $formula) = $header->parsePluralForms($formula);
|
||||
\Drupal::service('locale.plural.formula')->setPluralFormula('sl', $nplurals, $formula);
|
||||
|
||||
// Change the view to Slovenian.
|
||||
$config = $this->config('views.view.numeric_test');
|
||||
$config->set('langcode', 'sl')->save();
|
||||
|
||||
// Assert that the user interface has controls with more inputs now.
|
||||
$this->drupalGet('admin/structure/views/nojs/handler/numeric_test/page_1/field/count');
|
||||
$this->assertFieldByName('options[format_plural_values][0]', '1 time');
|
||||
$this->assertFieldByName('options[format_plural_values][1]', '@count times');
|
||||
$this->assertFieldByName('options[format_plural_values][2]', '');
|
||||
$this->assertFieldByName('options[format_plural_values][3]', '');
|
||||
|
||||
// Assert that changing the settings will change configuration properly.
|
||||
$edit = [
|
||||
'options[format_plural_values][0]' => '@count time0',
|
||||
'options[format_plural_values][1]' => '@count time1',
|
||||
'options[format_plural_values][2]' => '@count time2',
|
||||
'options[format_plural_values][3]' => '@count time3',
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, t('Apply'));
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
$config = $this->config('views.view.numeric_test');
|
||||
$field_config_prefix = 'display.default.display_options.fields.count.';
|
||||
$this->assertEqual($config->get($field_config_prefix . 'format_plural'), TRUE);
|
||||
$this->assertEqual($config->get($field_config_prefix . 'format_plural_string'), implode(LOCALE_PLURAL_DELIMITER, array_values($edit)));
|
||||
|
||||
// The view should now use the new plural configuration.
|
||||
$this->drupalGet('sl/numeric-test');
|
||||
$this->assertRaw('<span class="field-content">0 time3</span>');
|
||||
$this->assertRaw('<span class="field-content">1 time0</span>');
|
||||
$this->assertRaw('<span class="field-content">2 time1</span>');
|
||||
$this->assertRaw('<span class="field-content">3 time2</span>');
|
||||
$this->assertRaw('<span class="field-content">4 time2</span>');
|
||||
$this->assertRaw('<span class="field-content">42 time3</span>');
|
||||
|
||||
// Add an English configuration translation with English plurals.
|
||||
$english = \Drupal::languageManager()->getLanguageConfigOverride('en', 'views.view.numeric_test');
|
||||
$english->set('display.default.display_options.fields.count.format_plural_string', '1 time' . LOCALE_PLURAL_DELIMITER . '@count times')->save();
|
||||
|
||||
// The view displayed in English should use the English translation.
|
||||
$this->drupalGet('numeric-test');
|
||||
$this->assertRaw('<span class="field-content">0 times</span>');
|
||||
$this->assertRaw('<span class="field-content">1 time</span>');
|
||||
$this->assertRaw('<span class="field-content">2 times</span>');
|
||||
$this->assertRaw('<span class="field-content">3 times</span>');
|
||||
$this->assertRaw('<span class="field-content">4 times</span>');
|
||||
$this->assertRaw('<span class="field-content">42 times</span>');
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and saves a test file.
|
||||
*
|
||||
* @return \Drupal\Core\Entity\EntityInterface
|
||||
* A file entity.
|
||||
*/
|
||||
protected function createFile() {
|
||||
// Create a new file entity.
|
||||
$file = File::create([
|
||||
'uid' => 1,
|
||||
'filename' => 'druplicon.txt',
|
||||
'uri' => 'public://druplicon.txt',
|
||||
'filemime' => 'text/plain',
|
||||
'created' => 1,
|
||||
'changed' => 1,
|
||||
'status' => FILE_STATUS_PERMANENT,
|
||||
]);
|
||||
file_put_contents($file->getFileUri(), 'hello world');
|
||||
|
||||
// Save it, inserting a new record.
|
||||
$file->save();
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,454 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Functional\Plugin;
|
||||
|
||||
use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Views;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
|
||||
/**
|
||||
* Tests the pluggable pager system.
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class PagerTest extends ViewTestBase {
|
||||
|
||||
use AssertPageCacheContextsAndTagsTrait;
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_store_pager_settings', 'test_pager_none', 'test_pager_some', 'test_pager_full', 'test_view_pager_full_zero_items_per_page', 'test_view', 'content'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node', 'views_ui'];
|
||||
|
||||
/**
|
||||
* String translation storage object.
|
||||
*
|
||||
* @var \Drupal\locale\StringStorageInterface
|
||||
*/
|
||||
protected $localeStorage;
|
||||
|
||||
/**
|
||||
* Pagers was sometimes not stored.
|
||||
*
|
||||
* @see https://www.drupal.org/node/652712
|
||||
*/
|
||||
public function testStorePagerSettings() {
|
||||
// Show the master display so the override selection is shown.
|
||||
\Drupal::configFactory()->getEditable('views.settings')->set('ui.show.master_display', TRUE)->save();
|
||||
|
||||
$admin_user = $this->drupalCreateUser(['administer views', 'administer site configuration']);
|
||||
$this->drupalLogin($admin_user);
|
||||
// Test behavior described in
|
||||
// https://www.drupal.org/node/652712#comment-2354918.
|
||||
|
||||
$this->drupalGet('admin/structure/views/view/test_view/edit');
|
||||
|
||||
$edit = [
|
||||
'pager[type]' => 'full',
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/views/nojs/display/test_view/default/pager', $edit, t('Apply'));
|
||||
$edit = [
|
||||
'pager_options[items_per_page]' => 20,
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/views/nojs/display/test_view/default/pager_options', $edit, t('Apply'));
|
||||
$this->assertText('20 items');
|
||||
|
||||
// Change type and check whether the type is new type is stored.
|
||||
$edit = [
|
||||
'pager[type]' => 'mini',
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/views/nojs/display/test_view/default/pager', $edit, t('Apply'));
|
||||
$this->drupalGet('admin/structure/views/view/test_view/edit');
|
||||
$this->assertText('Mini', 'Changed pager plugin, should change some text');
|
||||
|
||||
// Test behavior described in
|
||||
// https://www.drupal.org/node/652712#comment-2354400.
|
||||
$view = Views::getView('test_store_pager_settings');
|
||||
// Make it editable in the admin interface.
|
||||
$view->save();
|
||||
|
||||
$this->drupalGet('admin/structure/views/view/test_store_pager_settings/edit');
|
||||
|
||||
$edit = [
|
||||
'pager[type]' => 'full',
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/views/nojs/display/test_store_pager_settings/default/pager', $edit, t('Apply'));
|
||||
$this->drupalGet('admin/structure/views/view/test_store_pager_settings/edit');
|
||||
$this->assertText('Full');
|
||||
|
||||
$edit = [
|
||||
'pager_options[items_per_page]' => 20,
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/views/nojs/display/test_store_pager_settings/default/pager_options', $edit, t('Apply'));
|
||||
$this->assertText('20 items');
|
||||
|
||||
// add new display and test the settings again, by override it.
|
||||
$edit = [ ];
|
||||
// Add a display and override the pager settings.
|
||||
$this->drupalPostForm('admin/structure/views/view/test_store_pager_settings/edit', $edit, t('Add Page'));
|
||||
$edit = [
|
||||
'override[dropdown]' => 'page_1',
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/views/nojs/display/test_store_pager_settings/page_1/pager', $edit, t('Apply'));
|
||||
|
||||
$edit = [
|
||||
'pager[type]' => 'mini',
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/views/nojs/display/test_store_pager_settings/page_1/pager', $edit, t('Apply'));
|
||||
$this->drupalGet('admin/structure/views/view/test_store_pager_settings/edit/page_1');
|
||||
$this->assertText('Mini', 'Changed pager plugin, should change some text');
|
||||
|
||||
$edit = [
|
||||
'pager_options[items_per_page]' => 10,
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/views/nojs/display/test_store_pager_settings/default/pager_options', $edit, t('Apply'));
|
||||
$this->assertText('10 items', 'The default value has been changed.');
|
||||
$this->drupalGet('admin/structure/views/view/test_store_pager_settings/edit/page_1');
|
||||
$this->assertText('20 items', 'The original value remains unchanged.');
|
||||
|
||||
// Test that the override element is only displayed on pager plugin selection form.
|
||||
$this->drupalGet('admin/structure/views/nojs/display/test_store_pager_settings/page_1/pager');
|
||||
$this->assertFieldByName('override[dropdown]', 'page_1', 'The override element is displayed on plugin selection form.');
|
||||
$this->drupalGet('admin/structure/views/nojs/display/test_store_pager_settings/page_1/pager_options');
|
||||
$this->assertNoFieldByName('override[dropdown]', NULL, 'The override element is not displayed on plugin settings form.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the none-pager-query.
|
||||
*/
|
||||
public function testNoLimit() {
|
||||
// Create 11 nodes and make sure that everyone is returned.
|
||||
// We create 11 nodes, because the default pager plugin had 10 items per page.
|
||||
$this->drupalCreateContentType(['type' => 'page']);
|
||||
for ($i = 0; $i < 11; $i++) {
|
||||
$this->drupalCreateNode();
|
||||
}
|
||||
$view = Views::getView('test_pager_none');
|
||||
$this->executeView($view);
|
||||
$this->assertEqual(count($view->result), 11, 'Make sure that every item is returned in the result');
|
||||
|
||||
// Setup and test a offset.
|
||||
$view = Views::getView('test_pager_none');
|
||||
$view->setDisplay();
|
||||
$pager = [
|
||||
'type' => 'none',
|
||||
'options' => [
|
||||
'offset' => 3,
|
||||
],
|
||||
];
|
||||
$view->display_handler->setOption('pager', $pager);
|
||||
$this->executeView($view);
|
||||
|
||||
$this->assertEqual(count($view->result), 8, 'Make sure that every item beside the first three is returned in the result');
|
||||
|
||||
// Check some public functions.
|
||||
$this->assertFalse($view->pager->usePager());
|
||||
$this->assertFalse($view->pager->useCountQuery());
|
||||
$this->assertEqual($view->pager->getItemsPerPage(), 0);
|
||||
}
|
||||
|
||||
public function testViewTotalRowsWithoutPager() {
|
||||
$this->drupalCreateContentType(['type' => 'page']);
|
||||
for ($i = 0; $i < 23; $i++) {
|
||||
$this->drupalCreateNode();
|
||||
}
|
||||
|
||||
$view = Views::getView('test_pager_none');
|
||||
$view->get_total_rows = TRUE;
|
||||
$this->executeView($view);
|
||||
|
||||
$this->assertEqual($view->total_rows, 23, "'total_rows' is calculated when pager type is 'none' and 'get_total_rows' is TRUE.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the some pager plugin.
|
||||
*/
|
||||
public function testLimit() {
|
||||
// Create 11 nodes and make sure that everyone is returned.
|
||||
// We create 11 nodes, because the default pager plugin had 10 items per page.
|
||||
$this->drupalCreateContentType(['type' => 'page']);
|
||||
for ($i = 0; $i < 11; $i++) {
|
||||
$this->drupalCreateNode();
|
||||
}
|
||||
|
||||
$view = Views::getView('test_pager_some');
|
||||
$this->executeView($view);
|
||||
$this->assertEqual(count($view->result), 5, 'Make sure that only a certain count of items is returned');
|
||||
|
||||
// Setup and test a offset.
|
||||
$view = Views::getView('test_pager_some');
|
||||
$view->setDisplay();
|
||||
$pager = [
|
||||
'type' => 'none',
|
||||
'options' => [
|
||||
'offset' => 8,
|
||||
'items_per_page' => 5,
|
||||
],
|
||||
];
|
||||
$view->display_handler->setOption('pager', $pager);
|
||||
$this->executeView($view);
|
||||
$this->assertEqual(count($view->result), 3, 'Make sure that only a certain count of items is returned');
|
||||
|
||||
// Check some public functions.
|
||||
$this->assertFalse($view->pager->usePager());
|
||||
$this->assertFalse($view->pager->useCountQuery());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the normal pager.
|
||||
*/
|
||||
public function testNormalPager() {
|
||||
// Create 11 nodes and make sure that everyone is returned.
|
||||
// We create 11 nodes, because the default pager plugin had 10 items per page.
|
||||
$this->drupalCreateContentType(['type' => 'page']);
|
||||
for ($i = 0; $i < 11; $i++) {
|
||||
$this->drupalCreateNode();
|
||||
}
|
||||
|
||||
$view = Views::getView('test_pager_full');
|
||||
$this->executeView($view);
|
||||
$this->assertEqual(count($view->result), 5, 'Make sure that only a certain count of items is returned');
|
||||
|
||||
// Setup and test a offset.
|
||||
$view = Views::getView('test_pager_full');
|
||||
$view->setDisplay();
|
||||
$pager = [
|
||||
'type' => 'full',
|
||||
'options' => [
|
||||
'offset' => 8,
|
||||
'items_per_page' => 5,
|
||||
],
|
||||
];
|
||||
$view->display_handler->setOption('pager', $pager);
|
||||
$this->executeView($view);
|
||||
$this->assertEqual(count($view->result), 3, 'Make sure that only a certain count of items is returned');
|
||||
|
||||
// Test items per page = 0
|
||||
$view = Views::getView('test_view_pager_full_zero_items_per_page');
|
||||
$this->executeView($view);
|
||||
|
||||
$this->assertEqual(count($view->result), 11, 'All items are return');
|
||||
|
||||
// TODO test number of pages.
|
||||
|
||||
// Test items per page = 0.
|
||||
// Setup and test a offset.
|
||||
$view = Views::getView('test_pager_full');
|
||||
$view->setDisplay();
|
||||
$pager = [
|
||||
'type' => 'full',
|
||||
'options' => [
|
||||
'offset' => 0,
|
||||
'items_per_page' => 0,
|
||||
],
|
||||
];
|
||||
|
||||
$view->display_handler->setOption('pager', $pager);
|
||||
$this->executeView($view);
|
||||
$this->assertEqual($view->pager->getItemsPerPage(), 0);
|
||||
$this->assertEqual(count($view->result), 11);
|
||||
|
||||
// Test pager cache contexts.
|
||||
$this->drupalGet('test_pager_full');
|
||||
$this->assertCacheContexts(['languages:language_interface', 'theme', 'timezone', 'url.query_args', 'user.node_grants:view']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests rendering with NULL pager.
|
||||
*/
|
||||
public function testRenderNullPager() {
|
||||
// Create 11 nodes and make sure that everyone is returned.
|
||||
// We create 11 nodes, because the default pager plugin had 10 items per page.
|
||||
$this->drupalCreateContentType(['type' => 'page']);
|
||||
for ($i = 0; $i < 11; $i++) {
|
||||
$this->drupalCreateNode();
|
||||
}
|
||||
$view = Views::getView('test_pager_full');
|
||||
$this->executeView($view);
|
||||
// Force the value again here.
|
||||
$view->setAjaxEnabled(TRUE);
|
||||
$view->pager = NULL;
|
||||
$output = $view->render();
|
||||
$output = \Drupal::service('renderer')->renderRoot($output);
|
||||
$this->assertEqual(preg_match('/<ul class="pager">/', $output), 0, 'The pager is not rendered.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the api functions on the view object.
|
||||
*/
|
||||
public function testPagerApi() {
|
||||
$view = Views::getView('test_pager_full');
|
||||
$view->setDisplay();
|
||||
// On the first round don't initialize the pager.
|
||||
|
||||
$this->assertEqual($view->getItemsPerPage(), NULL, 'If the pager is not initialized and no manual override there is no items per page.');
|
||||
$rand_number = rand(1, 5);
|
||||
$view->setItemsPerPage($rand_number);
|
||||
$this->assertEqual($view->getItemsPerPage(), $rand_number, 'Make sure getItemsPerPage uses the settings of setItemsPerPage.');
|
||||
|
||||
$this->assertEqual($view->getOffset(), NULL, 'If the pager is not initialized and no manual override there is no offset.');
|
||||
$rand_number = rand(1, 5);
|
||||
$view->setOffset($rand_number);
|
||||
$this->assertEqual($view->getOffset(), $rand_number, 'Make sure getOffset uses the settings of setOffset.');
|
||||
|
||||
$this->assertEqual($view->getCurrentPage(), NULL, 'If the pager is not initialized and no manual override there is no current page.');
|
||||
$rand_number = rand(1, 5);
|
||||
$view->setCurrentPage($rand_number);
|
||||
$this->assertEqual($view->getCurrentPage(), $rand_number, 'Make sure getCurrentPage uses the settings of set_current_page.');
|
||||
|
||||
$view->destroy();
|
||||
|
||||
// On this round enable the pager.
|
||||
$view->initDisplay();
|
||||
$view->initQuery();
|
||||
$view->initPager();
|
||||
|
||||
$this->assertEqual($view->getItemsPerPage(), 5, 'Per default the view has 5 items per page.');
|
||||
$rand_number = rand(1, 5);
|
||||
$view->setItemsPerPage($rand_number);
|
||||
$rand_number = rand(6, 11);
|
||||
$view->pager->setItemsPerPage($rand_number);
|
||||
$this->assertEqual($view->getItemsPerPage(), $rand_number, 'Make sure getItemsPerPage uses the settings of setItemsPerPage.');
|
||||
|
||||
$this->assertEqual($view->getOffset(), 0, 'Per default a view has a 0 offset.');
|
||||
$rand_number = rand(1, 5);
|
||||
$view->setOffset($rand_number);
|
||||
$rand_number = rand(6, 11);
|
||||
$view->pager->setOffset($rand_number);
|
||||
$this->assertEqual($view->getOffset(), $rand_number, 'Make sure getOffset uses the settings of setOffset.');
|
||||
|
||||
$this->assertEqual($view->getCurrentPage(), 0, 'Per default the current page is 0.');
|
||||
$rand_number = rand(1, 5);
|
||||
$view->setCurrentPage($rand_number);
|
||||
$rand_number = rand(6, 11);
|
||||
$view->pager->setCurrentPage($rand_number);
|
||||
$this->assertEqual($view->getCurrentPage(), $rand_number, 'Make sure getCurrentPage uses the settings of set_current_page.');
|
||||
|
||||
// Set an invalid page and make sure the method takes care about it.
|
||||
$view->setCurrentPage(-1);
|
||||
$this->assertEqual($view->getCurrentPage(), 0, 'Make sure setCurrentPage always sets a valid page number.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests translating the pager using config_translation.
|
||||
*/
|
||||
public function testPagerConfigTranslation() {
|
||||
$view = Views::getView('content');
|
||||
$display = &$view->storage->getDisplay('default');
|
||||
$display['display_options']['pager']['options']['items_per_page'] = 5;
|
||||
$view->save();
|
||||
|
||||
// Enable locale, config_translation and language module.
|
||||
$this->container->get('module_installer')->install(['locale', 'language', 'config_translation']);
|
||||
$this->resetAll();
|
||||
|
||||
$admin_user = $this->drupalCreateUser(['access content overview', 'administer nodes', 'bypass node access', 'translate configuration']);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
$langcode = 'nl';
|
||||
|
||||
// Add a default locale storage for this test.
|
||||
$this->localeStorage = $this->container->get('locale.storage');
|
||||
|
||||
// Add Dutch language programmatically.
|
||||
ConfigurableLanguage::createFromLangcode($langcode)->save();
|
||||
|
||||
$edit = [
|
||||
'translation[config_names][views.view.content][display][default][display_options][pager][options][tags][first]' => '« Eerste',
|
||||
'translation[config_names][views.view.content][display][default][display_options][pager][options][tags][previous]' => '‹ Vorige',
|
||||
'translation[config_names][views.view.content][display][default][display_options][pager][options][tags][next]' => 'Volgende ›',
|
||||
'translation[config_names][views.view.content][display][default][display_options][pager][options][tags][last]' => 'Laatste »',
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/views/view/content/translate/nl/edit', $edit, t('Save translation'));
|
||||
|
||||
// We create 11 nodes, this will give us 3 pages.
|
||||
$this->drupalCreateContentType(['type' => 'page']);
|
||||
for ($i = 0; $i < 11; $i++) {
|
||||
$this->drupalCreateNode();
|
||||
}
|
||||
|
||||
// Go to the second page so we see both previous and next buttons.
|
||||
$this->drupalGet('nl/admin/content', ['query' => ['page' => 1]]);
|
||||
// Translation mapping..
|
||||
$labels = [
|
||||
'« First' => '« Eerste',
|
||||
'‹ Previous' => '‹ Vorige',
|
||||
'Next ›' => 'Volgende ›',
|
||||
'Last »' => 'Laatste »',
|
||||
];
|
||||
foreach ($labels as $label => $translation) {
|
||||
// Check if we can find the translation.
|
||||
$this->assertRaw($translation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests translating the pager using locale.
|
||||
*/
|
||||
public function testPagerLocale() {
|
||||
// Enable locale and language module.
|
||||
$this->container->get('module_installer')->install(['locale', 'language']);
|
||||
$this->resetAll();
|
||||
$langcode = 'nl';
|
||||
|
||||
// Add a default locale storage for this test.
|
||||
$this->localeStorage = $this->container->get('locale.storage');
|
||||
|
||||
// Add Dutch language programmatically.
|
||||
ConfigurableLanguage::createFromLangcode($langcode)->save();
|
||||
|
||||
// Labels that need translations.
|
||||
$labels = [
|
||||
'« First' => '« Eerste',
|
||||
'‹ Previous' => '‹ Vorige',
|
||||
'Next ›' => 'Volgende ›',
|
||||
'Last »' => 'Laatste »',
|
||||
];
|
||||
foreach ($labels as $label => $translation) {
|
||||
// Create source string.
|
||||
$source = $this->localeStorage->createString(
|
||||
[
|
||||
'source' => $label
|
||||
]
|
||||
);
|
||||
$source->save();
|
||||
$this->createTranslation($source, $translation, $langcode);
|
||||
}
|
||||
|
||||
// We create 11 nodes, this will give us 3 pages.
|
||||
$this->drupalCreateContentType(['type' => 'page']);
|
||||
for ($i = 0; $i < 11; $i++) {
|
||||
$this->drupalCreateNode();
|
||||
}
|
||||
|
||||
// Go to the second page so we see both previous and next buttons.
|
||||
$this->drupalGet('nl/test_pager_full', ['query' => ['page' => 1]]);
|
||||
foreach ($labels as $label => $translation) {
|
||||
// Check if we can find the translation.
|
||||
$this->assertRaw($translation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates single translation for source string.
|
||||
*/
|
||||
protected function createTranslation($source, $translation, $langcode) {
|
||||
$values = [
|
||||
'lid' => $source->lid,
|
||||
'language' => $langcode,
|
||||
'translation' => $translation,
|
||||
];
|
||||
return $this->localeStorage->createTranslation($values)->save();
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user