Initial Drupal 11 with DDEV setup
This commit is contained in:
@ -0,0 +1,7 @@
|
||||
name: "Content Block module tests"
|
||||
type: module
|
||||
description: "Support module for content block related testing."
|
||||
package: Testing
|
||||
version: VERSION
|
||||
dependencies:
|
||||
- drupal:block_content
|
||||
@ -0,0 +1,6 @@
|
||||
block_content_test.block_content_view:
|
||||
path: '/block-content/{block_content}'
|
||||
defaults:
|
||||
_entity_view: 'block_content'
|
||||
requirements:
|
||||
_entity_access: 'block_content.view'
|
||||
@ -0,0 +1,26 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- block_content
|
||||
theme:
|
||||
- stark
|
||||
id: foobar_gorilla
|
||||
theme: stark
|
||||
region: content
|
||||
weight: 0
|
||||
provider: null
|
||||
plugin: 'block_content:fb5e8434-3617-4a1d-a252-8273e95ec30e'
|
||||
settings:
|
||||
id: 'block_content:fb5e8434-3617-4a1d-a252-8273e95ec30e'
|
||||
label: 'Foobar Gorilla'
|
||||
label_display: visible
|
||||
provider: block_content
|
||||
status: true
|
||||
info: ''
|
||||
view_mode: full
|
||||
visibility:
|
||||
request_path:
|
||||
id: request_path
|
||||
negate: false
|
||||
pages: ''
|
||||
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\block_content_test\Hook;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\Core\Hook\Attribute\Hook;
|
||||
|
||||
/**
|
||||
* Hook implementations for block_content_test.
|
||||
*/
|
||||
class BlockContentTestHooks {
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_view().
|
||||
*/
|
||||
#[Hook('block_content_view')]
|
||||
public function blockContentView(array &$build, BlockContent $block_content, $view_mode): void {
|
||||
// Add extra content.
|
||||
$build['extra_content'] = ['#markup' => '<blink>Wow</blink>'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_presave().
|
||||
*/
|
||||
#[Hook('block_content_presave')]
|
||||
public function blockContentPresave(BlockContent $block_content): void {
|
||||
if ($block_content->label() == 'testing_block_content_presave') {
|
||||
$block_content->setInfo($block_content->label() . '_presave');
|
||||
}
|
||||
// Determine changes.
|
||||
if ($block_content->getOriginal() && $block_content->getOriginal()->label() == 'test_changes') {
|
||||
if ($block_content->getOriginal()->label() != $block_content->label()) {
|
||||
$block_content->setInfo($block_content->label() . '_presave');
|
||||
// Drupal 1.0 release.
|
||||
$block_content->changed = 979534800;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_update().
|
||||
*/
|
||||
#[Hook('block_content_update')]
|
||||
public function blockContentUpdate(BlockContent $block_content): void {
|
||||
// Determine changes on update.
|
||||
if ($block_content->getOriginal() && $block_content->getOriginal()->label() == 'test_changes') {
|
||||
if ($block_content->getOriginal()->label() != $block_content->label()) {
|
||||
$block_content->setInfo($block_content->label() . '_update');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_insert().
|
||||
*
|
||||
* This tests saving a block_content on block_content insert.
|
||||
*
|
||||
* @see \Drupal\block_content\Tests\BlockContentSaveTest::testBlockContentSaveOnInsert()
|
||||
*/
|
||||
#[Hook('block_content_insert')]
|
||||
public function blockContentInsert(BlockContent $block_content): void {
|
||||
// Set the block_content title to the block_content ID and save.
|
||||
if ($block_content->label() == 'new') {
|
||||
$block_content->setInfo('BlockContent ' . $block_content->id());
|
||||
$block_content->setNewRevision(FALSE);
|
||||
$block_content->save();
|
||||
}
|
||||
if ($block_content->label() == 'fail_creation') {
|
||||
throw new \Exception('Test exception for rollback.');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\block_content_test\Plugin\EntityReferenceSelection;
|
||||
|
||||
use Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection;
|
||||
|
||||
/**
|
||||
* Test EntityReferenceSelection with conditions on the 'reusable' field.
|
||||
*/
|
||||
class TestSelection extends DefaultSelection {
|
||||
|
||||
/**
|
||||
* The condition type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $conditionType;
|
||||
|
||||
/**
|
||||
* Whether to set the condition for reusable or non-reusable blocks.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $isReusable;
|
||||
|
||||
/**
|
||||
* Sets the test mode.
|
||||
*
|
||||
* @param string $condition_type
|
||||
* The condition type.
|
||||
* @param bool $is_reusable
|
||||
* Whether to set the condition for reusable or non-reusable blocks.
|
||||
*/
|
||||
public function setTestMode($condition_type = NULL, $is_reusable = NULL) {
|
||||
$this->conditionType = $condition_type;
|
||||
$this->isReusable = $is_reusable;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') {
|
||||
$query = parent::buildEntityQuery($match, $match_operator);
|
||||
if ($this->conditionType) {
|
||||
/** @var \Drupal\Core\Database\Query\ConditionInterface $add_condition */
|
||||
$add_condition = NULL;
|
||||
switch ($this->conditionType) {
|
||||
case 'base':
|
||||
$add_condition = $query;
|
||||
break;
|
||||
|
||||
case 'group':
|
||||
$group = $query->andConditionGroup()
|
||||
->exists('type');
|
||||
$add_condition = $group;
|
||||
$query->condition($group);
|
||||
break;
|
||||
|
||||
case "nested_group":
|
||||
$query->exists('type');
|
||||
$sub_group = $query->andConditionGroup()
|
||||
->exists('type');
|
||||
$add_condition = $sub_group;
|
||||
$group = $query->andConditionGroup()
|
||||
->exists('type')
|
||||
->condition($sub_group);
|
||||
$query->condition($group);
|
||||
break;
|
||||
}
|
||||
if ($this->isReusable) {
|
||||
$add_condition->condition('reusable', 1);
|
||||
}
|
||||
else {
|
||||
$add_condition->condition('reusable', 0);
|
||||
}
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
name: 'Block Content test views'
|
||||
type: module
|
||||
description: 'Provides default views for views block_content tests.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
dependencies:
|
||||
- drupal:block_content
|
||||
- drupal:views
|
||||
@ -0,0 +1,234 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- block_content
|
||||
id: test_block_content_redirect_destination
|
||||
label: 'Redirect destination'
|
||||
module: views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: block_content_field_data
|
||||
base_field: id
|
||||
display:
|
||||
default:
|
||||
display_plugin: default
|
||||
id: default
|
||||
display_title: Default
|
||||
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: table
|
||||
options:
|
||||
grouping: { }
|
||||
class: ''
|
||||
row_class: ''
|
||||
default_row_class: true
|
||||
override: true
|
||||
sticky: false
|
||||
caption: ''
|
||||
summary: ''
|
||||
description: ''
|
||||
columns:
|
||||
info: info
|
||||
info:
|
||||
info:
|
||||
sortable: false
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
default: '-1'
|
||||
empty_table: false
|
||||
row:
|
||||
type: 'entity:block_content'
|
||||
fields:
|
||||
info:
|
||||
table: block_content_field_data
|
||||
field: info
|
||||
id: info
|
||||
entity_type: null
|
||||
entity_field: info
|
||||
plugin_id: field
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: ''
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
text: ''
|
||||
make_link: false
|
||||
path: ''
|
||||
absolute: false
|
||||
external: false
|
||||
replace_spaces: false
|
||||
path_case: none
|
||||
trim_whitespace: false
|
||||
alt: ''
|
||||
rel: ''
|
||||
link_class: ''
|
||||
prefix: ''
|
||||
suffix: ''
|
||||
target: ''
|
||||
nl2br: false
|
||||
max_length: 0
|
||||
word_boundary: true
|
||||
ellipsis: true
|
||||
more_link: false
|
||||
more_link_text: ''
|
||||
more_link_path: ''
|
||||
strip_tags: false
|
||||
trim: false
|
||||
preserve_tags: ''
|
||||
html: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: true
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
click_sort_column: value
|
||||
type: string
|
||||
settings: { }
|
||||
group_column: value
|
||||
group_columns: { }
|
||||
group_rows: true
|
||||
delta_limit: 0
|
||||
delta_offset: 0
|
||||
delta_reversed: false
|
||||
delta_first_last: false
|
||||
multi_type: separator
|
||||
separator: ', '
|
||||
field_api_classes: false
|
||||
operations:
|
||||
id: operations
|
||||
table: block_content
|
||||
field: operations
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: 'Operations links'
|
||||
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
|
||||
entity_type: block_content
|
||||
plugin_id: entity_operations
|
||||
filters: { }
|
||||
sorts: { }
|
||||
title: 'Redirect destination'
|
||||
header: { }
|
||||
footer: { }
|
||||
empty: { }
|
||||
relationships: { }
|
||||
arguments: { }
|
||||
display_extenders: { }
|
||||
cache_metadata:
|
||||
max-age: 0
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url.query_args
|
||||
tags: { }
|
||||
page_1:
|
||||
display_plugin: page
|
||||
id: page_1
|
||||
display_title: Page
|
||||
position: 1
|
||||
display_options:
|
||||
display_extenders: { }
|
||||
path: /admin/content/redirect_destination
|
||||
cache_metadata:
|
||||
max-age: 0
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url.query_args
|
||||
tags: { }
|
||||
@ -0,0 +1,66 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- block_content
|
||||
id: test_block_content_revision_id
|
||||
label: test_block_content_revision_id
|
||||
module: views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: block_content_field_revision
|
||||
base_field: revision_id
|
||||
display:
|
||||
default:
|
||||
display_options:
|
||||
relationships:
|
||||
id:
|
||||
id: id
|
||||
table: block_content_field_revision
|
||||
field: id
|
||||
required: true
|
||||
plugin_id: standard
|
||||
fields:
|
||||
revision_id:
|
||||
id: revision_id
|
||||
table: block_content_field_revision
|
||||
field: revision_id
|
||||
plugin_id: field
|
||||
entity_type: block_content
|
||||
entity_field: revision_id
|
||||
id_1:
|
||||
id: id_1
|
||||
table: block_content_field_revision
|
||||
field: id
|
||||
plugin_id: field
|
||||
entity_type: block_content
|
||||
entity_field: id
|
||||
id:
|
||||
id: id
|
||||
table: block_content_field_data
|
||||
field: id
|
||||
relationship: id
|
||||
plugin_id: field
|
||||
entity_type: block_content
|
||||
entity_field: id
|
||||
arguments:
|
||||
id:
|
||||
id: id
|
||||
table: block_content_field_revision
|
||||
field: id
|
||||
plugin_id: numeric
|
||||
entity_type: block_content
|
||||
entity_field: id
|
||||
sorts:
|
||||
revision_id:
|
||||
id: revision_id
|
||||
table: block_content_field_revision
|
||||
field: revision_id
|
||||
order: ASC
|
||||
plugin_id: field
|
||||
entity_type: block_content
|
||||
entity_field: revision_id
|
||||
display_plugin: default
|
||||
display_title: Default
|
||||
id: default
|
||||
position: 0
|
||||
@ -0,0 +1,69 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- block_content
|
||||
id: test_block_content_revision_revision_id
|
||||
label: test_block_content_revision_revision_id
|
||||
module: views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: block_content_field_revision
|
||||
base_field: revision_id
|
||||
display:
|
||||
default:
|
||||
display_options:
|
||||
relationships:
|
||||
revision_id:
|
||||
id: revision_id
|
||||
table: block_content_field_revision
|
||||
field: revision_id
|
||||
required: true
|
||||
entity_type: block_content
|
||||
entity_field: revision_id
|
||||
plugin_id: standard
|
||||
fields:
|
||||
revision_id:
|
||||
id: revision_id
|
||||
table: block_content_field_revision
|
||||
field: revision_id
|
||||
plugin_id: field
|
||||
entity_type: block_content
|
||||
entity_field: revision_id
|
||||
id_1:
|
||||
id: id_1
|
||||
table: block_content_field_revision
|
||||
field: id
|
||||
plugin_id: field
|
||||
entity_type: block_content
|
||||
entity_field: id
|
||||
id:
|
||||
id: id
|
||||
table: block_content_field_data
|
||||
field: id
|
||||
relationship: revision_id
|
||||
plugin_id: field
|
||||
entity_type: block_content
|
||||
entity_field: id
|
||||
arguments:
|
||||
id:
|
||||
id: id
|
||||
table: block_content_field_revision
|
||||
field: id
|
||||
plugin_id: block_content_id
|
||||
entity_type: block_content
|
||||
entity_field: id
|
||||
sorts:
|
||||
revision_id:
|
||||
id: revision_id
|
||||
table: block_content_field_revision
|
||||
field: revision_id
|
||||
order: ASC
|
||||
plugin_id: field
|
||||
entity_type: block_content
|
||||
entity_field: revision_id
|
||||
display_extenders: { }
|
||||
display_plugin: default
|
||||
display_title: Default
|
||||
id: default
|
||||
position: 0
|
||||
@ -0,0 +1,322 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- block_content
|
||||
- user
|
||||
id: test_block_content_revision_user
|
||||
label: 'Test block content revision user'
|
||||
module: views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: block_content_field_data
|
||||
base_field: id
|
||||
display:
|
||||
default:
|
||||
display_plugin: default
|
||||
id: default
|
||||
display_title: Default
|
||||
position: 0
|
||||
display_options:
|
||||
access:
|
||||
type: perm
|
||||
options:
|
||||
perm: 'access content'
|
||||
cache:
|
||||
type: tag
|
||||
options: { }
|
||||
query:
|
||||
type: views_query
|
||||
options:
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
replica: false
|
||||
query_comment: ''
|
||||
query_tags: { }
|
||||
exposed_form:
|
||||
type: basic
|
||||
options:
|
||||
submit_button: Apply
|
||||
reset_button: false
|
||||
reset_button_label: Reset
|
||||
exposed_sorts_label: 'Sort by'
|
||||
expose_sort_order: true
|
||||
sort_asc_label: Asc
|
||||
sort_desc_label: Desc
|
||||
pager:
|
||||
type: none
|
||||
options:
|
||||
offset: 0
|
||||
style:
|
||||
type: default
|
||||
options:
|
||||
grouping: { }
|
||||
row_class: ''
|
||||
default_row_class: true
|
||||
uses_fields: false
|
||||
row:
|
||||
type: fields
|
||||
options:
|
||||
inline: { }
|
||||
separator: ''
|
||||
hide_empty: false
|
||||
default_field_elements: true
|
||||
fields:
|
||||
id:
|
||||
id: id
|
||||
table: block_content_field_revision
|
||||
field: id
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: ''
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
text: ''
|
||||
make_link: false
|
||||
path: ''
|
||||
absolute: false
|
||||
external: false
|
||||
replace_spaces: false
|
||||
path_case: none
|
||||
trim_whitespace: false
|
||||
alt: ''
|
||||
rel: ''
|
||||
link_class: ''
|
||||
prefix: ''
|
||||
suffix: ''
|
||||
target: ''
|
||||
nl2br: false
|
||||
max_length: 0
|
||||
word_boundary: true
|
||||
ellipsis: true
|
||||
more_link: false
|
||||
more_link_text: ''
|
||||
more_link_path: ''
|
||||
strip_tags: false
|
||||
trim: false
|
||||
preserve_tags: ''
|
||||
html: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: false
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
click_sort_column: value
|
||||
type: number_integer
|
||||
settings:
|
||||
thousand_separator: ''
|
||||
prefix_suffix: false
|
||||
group_column: value
|
||||
group_columns: { }
|
||||
group_rows: true
|
||||
delta_limit: 0
|
||||
delta_offset: 0
|
||||
delta_reversed: false
|
||||
delta_first_last: false
|
||||
multi_type: separator
|
||||
separator: ', '
|
||||
field_api_classes: false
|
||||
entity_type: block_content
|
||||
entity_field: id
|
||||
plugin_id: field
|
||||
revision_id:
|
||||
id: revision_id
|
||||
table: block_content_field_revision
|
||||
field: revision_id
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: ''
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
text: ''
|
||||
make_link: false
|
||||
path: ''
|
||||
absolute: false
|
||||
external: false
|
||||
replace_spaces: false
|
||||
path_case: none
|
||||
trim_whitespace: false
|
||||
alt: ''
|
||||
rel: ''
|
||||
link_class: ''
|
||||
prefix: ''
|
||||
suffix: ''
|
||||
target: ''
|
||||
nl2br: false
|
||||
max_length: 0
|
||||
word_boundary: true
|
||||
ellipsis: true
|
||||
more_link: false
|
||||
more_link_text: ''
|
||||
more_link_path: ''
|
||||
strip_tags: false
|
||||
trim: false
|
||||
preserve_tags: ''
|
||||
html: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: false
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
click_sort_column: value
|
||||
type: number_integer
|
||||
settings:
|
||||
thousand_separator: ''
|
||||
prefix_suffix: false
|
||||
group_column: value
|
||||
group_columns: { }
|
||||
group_rows: true
|
||||
delta_limit: 0
|
||||
delta_offset: 0
|
||||
delta_reversed: false
|
||||
delta_first_last: false
|
||||
multi_type: separator
|
||||
separator: ', '
|
||||
field_api_classes: false
|
||||
entity_type: block_content
|
||||
entity_field: revision_id
|
||||
plugin_id: field
|
||||
revision_user:
|
||||
id: revision_user
|
||||
table: block_content_revision
|
||||
field: revision_user
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: ''
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
text: ''
|
||||
make_link: false
|
||||
path: ''
|
||||
absolute: false
|
||||
external: false
|
||||
replace_spaces: false
|
||||
path_case: none
|
||||
trim_whitespace: false
|
||||
alt: ''
|
||||
rel: ''
|
||||
link_class: ''
|
||||
prefix: ''
|
||||
suffix: ''
|
||||
target: ''
|
||||
nl2br: false
|
||||
max_length: 0
|
||||
word_boundary: true
|
||||
ellipsis: true
|
||||
more_link: false
|
||||
more_link_text: ''
|
||||
more_link_path: ''
|
||||
strip_tags: false
|
||||
trim: false
|
||||
preserve_tags: ''
|
||||
html: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: false
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
click_sort_column: 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: block_content
|
||||
entity_field: revision_user
|
||||
plugin_id: field
|
||||
filters:
|
||||
revision_user:
|
||||
id: revision_user
|
||||
table: block_content_revision
|
||||
field: revision_user
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: in
|
||||
value: { }
|
||||
group: 1
|
||||
exposed: true
|
||||
expose:
|
||||
operator_id: revision_user_op
|
||||
label: 'Revision user'
|
||||
description: ''
|
||||
use_operator: false
|
||||
operator: revision_user_op
|
||||
operator_limit_selection: false
|
||||
operator_list: { }
|
||||
identifier: revision_user
|
||||
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: { }
|
||||
entity_type: block_content
|
||||
entity_field: revision_user
|
||||
plugin_id: user_name
|
||||
sorts: { }
|
||||
header: { }
|
||||
footer: { }
|
||||
empty: { }
|
||||
relationships: { }
|
||||
arguments: { }
|
||||
display_extenders: { }
|
||||
filter_groups:
|
||||
operator: AND
|
||||
groups: { }
|
||||
cache_metadata:
|
||||
max-age: -1
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url
|
||||
- 'user.block_content_grants:view'
|
||||
- user.permissions
|
||||
tags: { }
|
||||
@ -0,0 +1,190 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- block_content
|
||||
id: test_block_content_view
|
||||
label: test_block_content_view
|
||||
module: views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: block_content_field_data
|
||||
base_field: id
|
||||
display:
|
||||
default:
|
||||
display_plugin: default
|
||||
id: default
|
||||
display_title: Default
|
||||
position: null
|
||||
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: 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: fields
|
||||
fields:
|
||||
id:
|
||||
id: id
|
||||
table: block_content_field_data
|
||||
field: id
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: Id
|
||||
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
|
||||
plugin_id: field
|
||||
entity_type: block_content
|
||||
entity_field: id
|
||||
sorts:
|
||||
id:
|
||||
id: id
|
||||
table: block_content_field_data
|
||||
field: id
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
order: ASC
|
||||
exposed: false
|
||||
expose:
|
||||
label: ''
|
||||
entity_type: block_content
|
||||
entity_field: id
|
||||
plugin_id: standard
|
||||
title: test_block_content_view
|
||||
header: { }
|
||||
footer: { }
|
||||
empty: { }
|
||||
relationships: { }
|
||||
display_extenders: { }
|
||||
arguments:
|
||||
type:
|
||||
id: type
|
||||
table: block_content_field_data
|
||||
field: type
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
default_action: 'not found'
|
||||
exception:
|
||||
value: all
|
||||
title_enable: false
|
||||
title: All
|
||||
title_enable: false
|
||||
title: ''
|
||||
default_argument_type: fixed
|
||||
default_argument_options:
|
||||
argument: ''
|
||||
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: false
|
||||
limit: 0
|
||||
case: none
|
||||
path_case: none
|
||||
transform_dash: false
|
||||
break_phrase: false
|
||||
entity_type: block_content
|
||||
entity_field: type
|
||||
plugin_id: string
|
||||
page_1:
|
||||
display_plugin: page
|
||||
id: page_1
|
||||
display_title: Page
|
||||
position: null
|
||||
display_options:
|
||||
path: test-block_content-view
|
||||
display_extenders: { }
|
||||
@ -0,0 +1,338 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- block_content
|
||||
id: test_field_filters
|
||||
label: 'Test field filters'
|
||||
module: views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: block_content_field_data
|
||||
base_field: id
|
||||
display:
|
||||
default:
|
||||
display_plugin: default
|
||||
id: default
|
||||
display_title: Default
|
||||
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: none
|
||||
options:
|
||||
items_per_page: 0
|
||||
offset: 0
|
||||
style:
|
||||
type: default
|
||||
row:
|
||||
type: 'entity:block_content'
|
||||
options:
|
||||
relationship: none
|
||||
view_mode: default
|
||||
fields:
|
||||
info:
|
||||
id: info
|
||||
table: block_content_field_data
|
||||
field: info
|
||||
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
|
||||
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
|
||||
entity_type: block_content
|
||||
type: string
|
||||
settings:
|
||||
link_to_entity: true
|
||||
entity_field: title
|
||||
plugin_id: field
|
||||
filters:
|
||||
info:
|
||||
id: info
|
||||
table: block_content_field_data
|
||||
field: info
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: contains
|
||||
value: Paris
|
||||
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: string
|
||||
entity_type: block_content
|
||||
entity_field: info
|
||||
sorts:
|
||||
changed:
|
||||
id: changed
|
||||
table: block_content_field_data
|
||||
field: changed
|
||||
order: DESC
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
exposed: false
|
||||
expose:
|
||||
label: ''
|
||||
granularity: second
|
||||
plugin_id: date
|
||||
entity_type: block_content
|
||||
entity_field: changed
|
||||
title: 'Test field filters'
|
||||
header: { }
|
||||
footer: { }
|
||||
empty: { }
|
||||
relationships: { }
|
||||
arguments: { }
|
||||
rendering_language: '***LANGUAGE_entity_translation***'
|
||||
display_extenders: { }
|
||||
page_bf:
|
||||
display_plugin: page
|
||||
id: page_bf
|
||||
display_title: 'Body filter page'
|
||||
position: 1
|
||||
display_options:
|
||||
path: test-body-filter
|
||||
display_description: ''
|
||||
title: 'Test body filters'
|
||||
defaults:
|
||||
title: false
|
||||
filters: false
|
||||
filter_groups: false
|
||||
filters:
|
||||
body_value:
|
||||
id: body_value
|
||||
table: block_content__body
|
||||
field: body_value
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: contains
|
||||
value: Comida
|
||||
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: string
|
||||
entity_type: block_content
|
||||
entity_field: body
|
||||
filter_groups:
|
||||
operator: AND
|
||||
groups:
|
||||
1: AND
|
||||
display_extenders: { }
|
||||
page_bfp:
|
||||
display_plugin: page
|
||||
id: page_bfp
|
||||
display_title: 'Body filter page Paris'
|
||||
position: 1
|
||||
display_options:
|
||||
path: test-body-paris
|
||||
display_description: ''
|
||||
title: 'Test body filters'
|
||||
defaults:
|
||||
title: false
|
||||
filters: false
|
||||
filter_groups: false
|
||||
filters:
|
||||
body_value:
|
||||
id: body_value
|
||||
table: block_content__body
|
||||
field: body_value
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: contains
|
||||
value: Paris
|
||||
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: string
|
||||
entity_type: block_content
|
||||
entity_field: body
|
||||
filter_groups:
|
||||
operator: AND
|
||||
groups:
|
||||
1: AND
|
||||
display_extenders: { }
|
||||
page_if:
|
||||
display_plugin: page
|
||||
id: page_if
|
||||
display_title: 'Info filter page'
|
||||
position: 1
|
||||
display_options:
|
||||
path: test-info-filter
|
||||
display_description: ''
|
||||
title: 'Test info filter'
|
||||
defaults:
|
||||
title: false
|
||||
filters: false
|
||||
filter_groups: false
|
||||
filters:
|
||||
info:
|
||||
id: info
|
||||
table: block_content_field_data
|
||||
field: info
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: contains
|
||||
value: Comida
|
||||
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: string
|
||||
entity_type: block_content
|
||||
entity_field: info
|
||||
filter_groups:
|
||||
operator: AND
|
||||
groups:
|
||||
1: AND
|
||||
display_extenders: { }
|
||||
page_ifp:
|
||||
display_plugin: page
|
||||
id: page_ifp
|
||||
display_title: 'Info filter page Paris'
|
||||
position: 1
|
||||
display_options:
|
||||
path: test-info-paris
|
||||
display_description: ''
|
||||
title: 'Test info filter'
|
||||
defaults:
|
||||
title: false
|
||||
display_extenders: { }
|
||||
@ -0,0 +1,27 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- block_content
|
||||
id: test_field_type
|
||||
label: test_field_type
|
||||
module: views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: block_content_field_data
|
||||
base_field: id
|
||||
display:
|
||||
default:
|
||||
display_options:
|
||||
fields:
|
||||
type:
|
||||
field: type
|
||||
id: type
|
||||
table: block_content_field_data
|
||||
plugin_id: field
|
||||
entity_type: block_content
|
||||
entity_field: type
|
||||
display_plugin: default
|
||||
display_title: Default
|
||||
id: default
|
||||
position: 0
|
||||
@ -0,0 +1,5 @@
|
||||
name: 'Block Content Theme Suggestions Test'
|
||||
type: module
|
||||
description: 'Support module for testing.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Support module for testing.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Drupal\block_content\BlockContentInterface;
|
||||
|
||||
/**
|
||||
* Implements hook_preprocess_block().
|
||||
*/
|
||||
function block_content_theme_suggestions_test_preprocess_block(&$variables): void {
|
||||
$block_content = $variables['elements']['content']['#block_content'] ?? NULL;
|
||||
if ($block_content instanceof BlockContentInterface) {
|
||||
$variables['label'] = $block_content->label();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\block_content_theme_suggestions_test\Hook;
|
||||
|
||||
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Hook\Attribute\Hook;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* Hook implementations for block_content_theme_suggestions_test.
|
||||
*/
|
||||
class BlockContentThemeSuggestionsTestHooks {
|
||||
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* Implements hook_entity_extra_field_info().
|
||||
*/
|
||||
#[Hook('entity_extra_field_info')]
|
||||
public function entityExtraFieldInfo(): array {
|
||||
// Add an extra field to the test bundle.
|
||||
$extra['node']['bundle_with_extra_field']['display']['block_content_extra_field_test'] = [
|
||||
'label' => $this->t('Extra field'),
|
||||
'description' => $this->t('Extra field description'),
|
||||
'weight' => 0,
|
||||
];
|
||||
return $extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_node_view().
|
||||
*/
|
||||
#[Hook('node_view')]
|
||||
public function nodeView(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, string $view_mode): void {
|
||||
// Provide content for the extra field in the form of a content block.
|
||||
if ($display->getComponent('block_content_extra_field_test')) {
|
||||
$entity_type_manager = \Drupal::entityTypeManager();
|
||||
// Load a block content entity with a known UUID created by test setup.
|
||||
// @see \Drupal\Tests\block_content\Functional\BlockContentThemeSuggestionsTest::setUp()
|
||||
$block_content = $entity_type_manager->getStorage('block_content')->loadByProperties([
|
||||
'uuid' => 'b22c881a-bcfd-4d0c-a41d-3573327705df',
|
||||
]);
|
||||
$block_content = reset($block_content);
|
||||
$build['block_content_extra_field_test'] = $entity_type_manager->getViewBuilder('block_content')->view($block_content);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_theme().
|
||||
*/
|
||||
#[Hook('theme')]
|
||||
public function theme(): array {
|
||||
// It is necessary to explicitly register the template via hook_theme()
|
||||
// because it is added via a module, not a theme.
|
||||
return [
|
||||
'block__block_content__view_type__basic__full' => [
|
||||
'base hook' => 'block',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
{{ label }}
|
||||
|
||||
<h1>I am a block content template for a specific bundle and view mode!</h1>
|
||||
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Tests\system\Functional\Entity\EntityCacheTagsTestBase;
|
||||
|
||||
/**
|
||||
* Tests the Content Block entity's cache tags.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentCacheTagsTest extends EntityCacheTagsTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block_content'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
$block_content_type = BlockContentType::create([
|
||||
'id' => 'basic',
|
||||
'label' => 'basic',
|
||||
'revision' => FALSE,
|
||||
]);
|
||||
$block_content_type->save();
|
||||
block_content_add_body_field($block_content_type->id());
|
||||
|
||||
// Create a "Llama" content block.
|
||||
$block_content = BlockContent::create([
|
||||
'info' => 'Llama',
|
||||
'type' => 'basic',
|
||||
'body' => [
|
||||
'value' => 'The name "llama" was adopted by European settlers from native Peruvians.',
|
||||
'format' => 'plain_text',
|
||||
],
|
||||
]);
|
||||
$block_content->save();
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see \Drupal\block_content\BlockContentAccessControlHandler::checkAccess()
|
||||
*/
|
||||
protected function getAccessCacheContextsForEntity(EntityInterface $entity): array {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Each comment must have a comment body, which always has a text format.
|
||||
*/
|
||||
protected function getAdditionalCacheTagsForEntity(EntityInterface $entity): array {
|
||||
return ['config:filter.format.plain_text'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the block is cached with the correct contexts and tags.
|
||||
*/
|
||||
public function testBlock(): void {
|
||||
$block = $this->drupalPlaceBlock('block_content:' . $this->entity->uuid());
|
||||
$build = $this->container->get('entity_type.manager')->getViewBuilder('block')->view($block, 'block');
|
||||
|
||||
// Render the block.
|
||||
$this->container->get('renderer')->renderRoot($build);
|
||||
|
||||
// Expected keys, contexts, and tags for the block.
|
||||
// @see \Drupal\block\BlockViewBuilder::viewMultiple()
|
||||
$expected_block_cache_keys = ['entity_view', 'block', $block->id()];
|
||||
$expected_block_cache_tags = Cache::mergeTags(['block_view', 'rendered'], $block->getCacheTags());
|
||||
$expected_block_cache_tags = Cache::mergeTags($expected_block_cache_tags, $block->getPlugin()->getCacheTags());
|
||||
|
||||
// Expected contexts and tags for the BlockContent entity.
|
||||
// @see \Drupal\Core\Entity\EntityViewBuilder::getBuildDefaults().
|
||||
$expected_entity_cache_tags = Cache::mergeTags(['block_content_view'], $this->entity->getCacheTags());
|
||||
$expected_entity_cache_tags = Cache::mergeTags($expected_entity_cache_tags, $this->getAdditionalCacheTagsForEntity($this->entity));
|
||||
|
||||
// Verify that what was render cached matches the above expectations.
|
||||
$this->verifyRenderCache($expected_block_cache_keys, Cache::mergeTags($expected_block_cache_tags, $expected_entity_cache_tags), CacheableMetadata::createFromRenderArray($build));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
/**
|
||||
* Tests views contextual links on block content.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentContextualLinksTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'contextual',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* Tests contextual links.
|
||||
*/
|
||||
public function testBlockContentContextualLinks(): void {
|
||||
$block_content = $this->createBlockContent();
|
||||
|
||||
$block = $this->placeBlock('block_content:' . $block_content->uuid());
|
||||
|
||||
$user = $this->drupalCreateUser([
|
||||
'administer blocks',
|
||||
'access contextual links',
|
||||
]);
|
||||
$this->drupalLogin($user);
|
||||
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertSession()->elementAttributeContains('css', 'div[data-contextual-id]', 'data-contextual-id', 'block:block=' . $block->id() . ':langcode=en|block_content:block_content=' . $block_content->id() . ':');
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,339 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
use Drupal\block_content\BlockContentInterface;
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\Core\Database\Database;
|
||||
|
||||
// cspell:ignore testblock
|
||||
|
||||
/**
|
||||
* Create a block and test saving it.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentCreationTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
* Enable dummy module that implements hook_block_insert() for exceptions and
|
||||
* field_ui to edit display settings.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $modules = ['block_content_test', 'dblog', 'field_ui'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* Permissions to grant admin user.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $permissions = [
|
||||
'administer blocks',
|
||||
'administer block_content display',
|
||||
'access block library',
|
||||
'administer block content',
|
||||
];
|
||||
|
||||
/**
|
||||
* Sets the test up.
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->drupalLogin($this->adminUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a "Basic block" block and verifies its consistency in the database.
|
||||
*/
|
||||
public function testBlockContentCreation(): void {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Create a block.
|
||||
$edit = [];
|
||||
$edit['info[0][value]'] = 'Test Block';
|
||||
$edit['body[0][value]'] = $this->randomMachineName(16);
|
||||
$this->drupalGet('block/add/basic');
|
||||
$this->submitForm($edit, 'Save');
|
||||
|
||||
// Check that the Basic block has been created.
|
||||
$this->assertSession()->pageTextContains('basic ' . $edit['info[0][value]'] . ' has been created.');
|
||||
|
||||
// Check that the view mode setting is hidden because only one exists.
|
||||
$this->assertSession()->fieldNotExists('settings[view_mode]');
|
||||
|
||||
// Check that the block exists in the database.
|
||||
$block = $this->getBlockByLabel($edit['info[0][value]']);
|
||||
$this->assertNotEmpty($block, 'Content Block found in database.');
|
||||
|
||||
// Ensure a user with just the create permission can access the page.
|
||||
$this->drupalLogin($this->drupalCreateUser([
|
||||
'create basic block content',
|
||||
]));
|
||||
$this->drupalGet('block/add/basic');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a "Basic page" block with multiple view modes.
|
||||
*/
|
||||
public function testBlockContentCreationMultipleViewModes(): void {
|
||||
// Add a new view mode and verify if it is selected as expected.
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer display modes']));
|
||||
$this->drupalGet('admin/structure/display-modes/view/add/block_content');
|
||||
$edit = [
|
||||
'id' => 'test_view_mode',
|
||||
'label' => 'Test View Mode',
|
||||
];
|
||||
$this->submitForm($edit, 'Save');
|
||||
$this->assertSession()->pageTextContains('Saved the ' . $edit['label'] . ' view mode.');
|
||||
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Create a block.
|
||||
$edit = [];
|
||||
$edit['info[0][value]'] = 'Test Block';
|
||||
$edit['body[0][value]'] = $this->randomMachineName(16);
|
||||
$this->drupalGet('block/add/basic');
|
||||
$this->submitForm($edit, 'Save and configure');
|
||||
|
||||
// Save our block permanently
|
||||
$this->submitForm(['region' => 'content'], 'Save block');
|
||||
|
||||
// Set test_view_mode as a custom display to be available on the list.
|
||||
$this->drupalGet('admin/structure/block-content/manage/basic/display');
|
||||
$custom_view_mode = [
|
||||
'display_modes_custom[test_view_mode]' => 1,
|
||||
];
|
||||
$this->submitForm($custom_view_mode, 'Save');
|
||||
|
||||
// Go to the configure page and change the view mode.
|
||||
$this->drupalGet('admin/structure/block/manage/stark_testblock');
|
||||
|
||||
// Test the available view mode options.
|
||||
// Verify that the default view mode is available.
|
||||
$this->assertSession()->optionExists('edit-settings-view-mode', 'default');
|
||||
// Verify that the test view mode is available.
|
||||
$this->assertSession()->optionExists('edit-settings-view-mode', 'test_view_mode');
|
||||
|
||||
$view_mode['settings[view_mode]'] = 'test_view_mode';
|
||||
$this->submitForm($view_mode, 'Save block');
|
||||
|
||||
// Check that the view mode setting is shown because more than one exists.
|
||||
$this->drupalGet('admin/structure/block/manage/stark_testblock');
|
||||
$this->assertSession()->fieldExists('settings[view_mode]');
|
||||
|
||||
// Change the view mode.
|
||||
$view_mode['region'] = 'content';
|
||||
$view_mode['settings[view_mode]'] = 'test_view_mode';
|
||||
$this->submitForm($view_mode, 'Save block');
|
||||
|
||||
// Go to the configure page and verify the view mode has changed.
|
||||
$this->drupalGet('admin/structure/block/manage/stark_testblock');
|
||||
$this->assertSession()->fieldValueEquals('settings[view_mode]', 'test_view_mode');
|
||||
|
||||
// Check that the block exists in the database.
|
||||
$block = $this->getBlockByLabel($edit['info[0][value]']);
|
||||
$this->assertNotEmpty($block, 'Content Block found in database.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the redirect workflow of creating a block_content and block.
|
||||
*/
|
||||
public function testBlockContentFormSubmitHandlers(): void {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Create a block and place in block layout.
|
||||
$this->drupalGet('/admin/content/block');
|
||||
$this->clickLink('Add content block');
|
||||
$this->assertSession()->addressEquals('/block/add/basic');
|
||||
$edit = [];
|
||||
$edit['info[0][value]'] = 'Test Block';
|
||||
$edit['body[0][value]'] = $this->randomMachineName(16);
|
||||
$this->submitForm($edit, 'Save and configure');
|
||||
$this->assertSession()->pageTextContains('basic ' . $edit['info[0][value]'] . ' has been created.');
|
||||
$this->assertSession()->pageTextContains('Configure block');
|
||||
|
||||
// Verify when editing a block "Save and configure" does not appear.
|
||||
$this->drupalGet('/admin/content/block/1');
|
||||
$this->assertSession()->buttonNotExists('Save and configure');
|
||||
|
||||
// Create a block but go back to block library.
|
||||
$edit = [];
|
||||
$edit['info[0][value]'] = 'Test Block';
|
||||
$edit['body[0][value]'] = $this->randomMachineName(16);
|
||||
$this->drupalGet('block/add/basic');
|
||||
$this->submitForm($edit, 'Save');
|
||||
// Check that the Basic block has been created.
|
||||
$this->assertSession()->pageTextContains('basic ' . $edit['info[0][value]'] . ' has been created.');
|
||||
$this->assertSession()->addressEquals('/admin/content/block');
|
||||
|
||||
// Check that the user is redirected to the block library on edit.
|
||||
$block = $this->getBlockByLabel($edit['info[0][value]']);
|
||||
$this->drupalGet($block->toUrl('edit-form'));
|
||||
$this->submitForm([
|
||||
'info[0][value]' => 'Test Block Updated',
|
||||
], 'Save');
|
||||
$this->assertSession()->addressEquals('admin/content/block');
|
||||
|
||||
// Test with user who doesn't have permission to place a block.
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer block content']));
|
||||
$this->drupalGet('block/add/basic');
|
||||
$this->assertSession()->buttonNotExists('Save and configure');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a default content block.
|
||||
*
|
||||
* Creates a content block from defaults and ensures that the 'basic block'
|
||||
* type is being used.
|
||||
*/
|
||||
public function testDefaultBlockContentCreation(): void {
|
||||
$edit = [];
|
||||
$edit['info[0][value]'] = $this->randomMachineName(8);
|
||||
$edit['body[0][value]'] = $this->randomMachineName(16);
|
||||
// Don't pass the content block type in the URL so the default is forced.
|
||||
$this->drupalGet('block/add');
|
||||
$this->submitForm($edit, 'Save');
|
||||
|
||||
// Check that the block has been created and that it is a basic block.
|
||||
$this->assertSession()->pageTextContains('basic ' . $edit['info[0][value]'] . ' has been created.');
|
||||
|
||||
// Check that the block exists in the database.
|
||||
$block = $this->getBlockByLabel($edit['info[0][value]']);
|
||||
$this->assertNotEmpty($block, 'Default Content Block found in database.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that a transaction rolls back the failed creation.
|
||||
*/
|
||||
public function testFailedBlockCreation(): void {
|
||||
// Create a block.
|
||||
try {
|
||||
$this->createBlockContent('fail_creation');
|
||||
$this->fail('Expected exception has not been thrown.');
|
||||
}
|
||||
catch (\Exception) {
|
||||
// Expected exception; just continue testing.
|
||||
}
|
||||
|
||||
$connection = Database::getConnection();
|
||||
|
||||
// Check that the block does not exist in the database.
|
||||
$id = $connection->select('block_content_field_data', 'b')
|
||||
->fields('b', ['id'])
|
||||
->condition('info', 'fail_creation')
|
||||
->execute()
|
||||
->fetchField();
|
||||
$this->assertFalse($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests deleting a block.
|
||||
*/
|
||||
public function testBlockDelete(): void {
|
||||
// Create a block.
|
||||
$edit = [];
|
||||
$edit['info[0][value]'] = $this->randomMachineName(8);
|
||||
$body = $this->randomMachineName(16);
|
||||
$edit['body[0][value]'] = $body;
|
||||
$this->drupalGet('block/add/basic');
|
||||
$this->submitForm($edit, 'Save');
|
||||
|
||||
// Place the block.
|
||||
$instance = [
|
||||
'id' => mb_strtolower($edit['info[0][value]']),
|
||||
'settings[label]' => $edit['info[0][value]'],
|
||||
'region' => 'sidebar_first',
|
||||
];
|
||||
$block = BlockContent::load(1);
|
||||
$url = 'admin/structure/block/add/block_content:' . $block->uuid() . '/' . $this->config('system.theme')->get('default');
|
||||
$this->drupalGet($url);
|
||||
$this->submitForm($instance, 'Save block');
|
||||
|
||||
$block = BlockContent::load(1);
|
||||
|
||||
// Test getInstances method.
|
||||
$this->assertCount(1, $block->getInstances());
|
||||
|
||||
// Navigate to home page.
|
||||
$this->drupalGet('');
|
||||
$this->assertSession()->pageTextContains($body);
|
||||
|
||||
// Delete the block.
|
||||
$this->drupalGet('admin/content/block/1/delete');
|
||||
$this->assertSession()->pageTextContains('This will also remove 1 placed block instance.');
|
||||
|
||||
$this->submitForm([], 'Delete');
|
||||
$this->assertSession()->pageTextContains('The content block ' . $edit['info[0][value]'] . ' has been deleted.');
|
||||
|
||||
// Create another block and force the plugin cache to flush.
|
||||
$edit2 = [];
|
||||
$edit2['info[0][value]'] = $this->randomMachineName(8);
|
||||
$body2 = $this->randomMachineName(16);
|
||||
$edit2['body[0][value]'] = $body2;
|
||||
$this->drupalGet('block/add/basic');
|
||||
$this->submitForm($edit2, 'Save');
|
||||
|
||||
$this->assertSession()->responseNotContains('Error message');
|
||||
|
||||
// Create another block with no instances, and test we don't get a
|
||||
// confirmation message about deleting instances.
|
||||
$edit3 = [];
|
||||
$edit3['info[0][value]'] = $this->randomMachineName(8);
|
||||
$body = $this->randomMachineName(16);
|
||||
$edit3['body[0][value]'] = $body;
|
||||
$this->drupalGet('block/add/basic');
|
||||
$this->submitForm($edit3, 'Save');
|
||||
|
||||
// Show the delete confirm form.
|
||||
$this->drupalGet('admin/content/block/3/delete');
|
||||
$this->assertSession()->pageTextNotContains('This will also remove');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests placed content blocks create a dependency in the block placement.
|
||||
*/
|
||||
public function testConfigDependencies(): void {
|
||||
$block = $this->createBlockContent();
|
||||
// Place the block.
|
||||
$block_placement_id = mb_strtolower($block->label());
|
||||
$instance = [
|
||||
'id' => $block_placement_id,
|
||||
'settings[label]' => $block->label(),
|
||||
'region' => 'sidebar_first',
|
||||
];
|
||||
$block = BlockContent::load(1);
|
||||
$url = 'admin/structure/block/add/block_content:' . $block->uuid() . '/' . $this->config('system.theme')->get('default');
|
||||
$this->drupalGet($url);
|
||||
$this->submitForm($instance, 'Save block');
|
||||
|
||||
$dependencies = \Drupal::service('config.manager')->findConfigEntityDependenciesAsEntities('content', [$block->getConfigDependencyName()]);
|
||||
$block_placement = reset($dependencies);
|
||||
$this->assertEquals($block_placement_id, $block_placement->id(), "The block placement config entity has a dependency on the block content entity.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a block based on the label.
|
||||
*/
|
||||
private function getBlockByLabel(string $label): ?BlockContentInterface {
|
||||
$blocks = \Drupal::entityTypeManager()
|
||||
->getStorage('block_content')
|
||||
->loadByProperties(['info' => $label]);
|
||||
if (empty($blocks)) {
|
||||
return NULL;
|
||||
}
|
||||
return reset($blocks);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
|
||||
/**
|
||||
* Tests the listing of content blocks.
|
||||
*
|
||||
* Tests the fallback block content list when Views is disabled.
|
||||
*
|
||||
* @group block_content
|
||||
* @see \Drupal\block\BlockContentListBuilder
|
||||
* @see \Drupal\block_content\Tests\BlockContentListViewsTest
|
||||
*/
|
||||
class BlockContentListTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* A user with 'access block library' permission.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $baseUser1;
|
||||
|
||||
/**
|
||||
* A user with access to create and edit custom basic blocks.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $baseUser2;
|
||||
|
||||
/**
|
||||
* Permissions to grant admin user.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $permissions = [
|
||||
'administer blocks',
|
||||
'access block library',
|
||||
'create basic block content',
|
||||
'edit any basic block content',
|
||||
'delete any basic block content',
|
||||
'translate configuration',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block', 'block_content', 'config_translation'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->baseUser1 = $this->drupalCreateUser(['access block library']);
|
||||
$this->baseUser2 = $this->drupalCreateUser([
|
||||
'access block library',
|
||||
'create basic block content',
|
||||
'edit any basic block content',
|
||||
'delete any basic block content',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the region value when a new block is saved.
|
||||
*/
|
||||
public function testBlockRegionPlacement(): void {
|
||||
$this->drupalLogin($this->drupalCreateUser($this->permissions));
|
||||
$this->drupalGet("admin/structure/block/library/stark", ['query' => ['region' => 'content']]);
|
||||
|
||||
$this->clickLink('Add content block');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$edit = [
|
||||
'info[0][value]' => 'foo',
|
||||
];
|
||||
$this->submitForm($edit, 'Save');
|
||||
$this->assertSession()->fieldValueEquals('region', 'content');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the content block listing page with different permissions.
|
||||
*/
|
||||
public function testListing(): void {
|
||||
// Test with the admin user.
|
||||
$this->drupalLogin($this->drupalCreateUser(['access block library', 'administer block content']));
|
||||
$this->drupalGet('admin/content/block');
|
||||
|
||||
// Test for the page title.
|
||||
$this->assertSession()->titleEquals('Content blocks | Drupal');
|
||||
|
||||
// Test for the table.
|
||||
$this->assertSession()->elementExists('xpath', '//div[@class="layout-content"]//table');
|
||||
|
||||
// Test the table header, two cells should be present.
|
||||
$this->assertSession()->elementsCount('xpath', '//div[@class="layout-content"]//table/thead/tr/th', 2);
|
||||
|
||||
// Test the contents of each th cell.
|
||||
$this->assertSession()->elementTextEquals('xpath', '//div[@class="layout-content"]//table/thead/tr/th[1]', 'Block description');
|
||||
$this->assertSession()->elementTextEquals('xpath', '//div[@class="layout-content"]//table/thead/tr/th[2]', 'Operations');
|
||||
|
||||
$label = 'Antelope';
|
||||
$new_label = 'Albatross';
|
||||
// Add a new entity using the operations link.
|
||||
$this->clickLink('Add content block');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$edit = [];
|
||||
$edit['info[0][value]'] = $label;
|
||||
$edit['body[0][value]'] = $this->randomMachineName(16);
|
||||
$this->submitForm($edit, 'Save');
|
||||
|
||||
// Confirm that once the user returns to the listing, the text of the label
|
||||
// (versus elsewhere on the page).
|
||||
$this->assertSession()->elementTextContains('xpath', '//td', $label);
|
||||
|
||||
// Check the number of table row cells.
|
||||
$this->assertSession()->elementsCount('xpath', '//div[@class="layout-content"]//table/tbody/tr[1]/td', 2);
|
||||
// Check the contents of the row. The first cell contains the label,
|
||||
// and the second contains the operations list.
|
||||
$this->assertSession()->elementTextEquals('xpath', '//div[@class="layout-content"]//table/tbody/tr[1]/td[1]', $label);
|
||||
|
||||
// Edit the entity using the operations link.
|
||||
$blocks = $this->container
|
||||
->get('entity_type.manager')
|
||||
->getStorage('block_content')
|
||||
->loadByProperties(['info' => $label]);
|
||||
$block = reset($blocks);
|
||||
if (!empty($block)) {
|
||||
$this->assertSession()->linkByHrefExists('admin/content/block/' . $block->id());
|
||||
$this->clickLink('Edit');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->assertSession()->titleEquals("Edit content block $label | Drupal");
|
||||
$edit = ['info[0][value]' => $new_label];
|
||||
$this->submitForm($edit, 'Save');
|
||||
}
|
||||
else {
|
||||
$this->fail('Did not find Albatross block in the database.');
|
||||
}
|
||||
|
||||
// Confirm that once the user returns to the listing, the text of the label
|
||||
// (versus elsewhere on the page).
|
||||
$this->assertSession()->elementTextContains('xpath', '//td', $new_label);
|
||||
|
||||
// Delete the added entity using the operations link.
|
||||
$this->assertSession()->linkByHrefExists('admin/content/block/' . $block->id() . '/delete');
|
||||
$this->clickLink('Delete');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->assertSession()->titleEquals("Are you sure you want to delete the content block $new_label? | Drupal");
|
||||
$this->submitForm([], 'Delete');
|
||||
|
||||
// Verify that the text of the label and machine name does not appear in
|
||||
// the list (though it may appear elsewhere on the page).
|
||||
$this->assertSession()->elementTextNotContains('xpath', '//td', $new_label);
|
||||
|
||||
// Confirm that the empty text is displayed.
|
||||
$this->assertSession()->pageTextContains('There are no content blocks yet.');
|
||||
|
||||
$block_content = BlockContent::create([
|
||||
'info' => 'Non-reusable block',
|
||||
'type' => 'basic',
|
||||
'reusable' => FALSE,
|
||||
]);
|
||||
$block_content->save();
|
||||
|
||||
$this->drupalGet('admin/content/block');
|
||||
// Confirm that the empty text is displayed.
|
||||
$this->assertSession()->pageTextContains('There are no content blocks yet.');
|
||||
// Confirm the non-reusable block is not on the page.
|
||||
$this->assertSession()->pageTextNotContains('Non-reusable block');
|
||||
|
||||
$this->drupalLogout();
|
||||
|
||||
// Create test block for other user tests.
|
||||
$test_block = $this->createBlockContent($label);
|
||||
|
||||
// Test as a user with view only permissions.
|
||||
$this->drupalLogin($this->baseUser1);
|
||||
$this->drupalGet('admin/content/block');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->assertSession()->linkNotExists('Add content block');
|
||||
$this->assertSession()->linkByHrefNotExists('admin/content/block/' . $test_block->id());
|
||||
$this->assertSession()->linkByHrefNotExists('admin/content/block/' . $test_block->id() . '/delete');
|
||||
|
||||
$this->drupalLogout();
|
||||
|
||||
// Test as a user with permission to create/edit/delete basic blocks.
|
||||
$this->drupalLogin($this->baseUser2);
|
||||
$this->drupalGet('admin/content/block');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->assertSession()->linkExists('Add content block');
|
||||
$this->assertSession()->linkByHrefExists('admin/content/block/' . $test_block->id());
|
||||
$this->assertSession()->linkByHrefExists('admin/content/block/' . $test_block->id() . '/delete');
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,204 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
|
||||
/**
|
||||
* Tests the Views-powered listing of content blocks.
|
||||
*
|
||||
* @group block_content
|
||||
* @see \Drupal\block\BlockContentListBuilder
|
||||
* @see \Drupal\block_content\Tests\BlockContentListTest
|
||||
*/
|
||||
class BlockContentListViewsTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* A user with 'access block library' permission.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $baseUser1;
|
||||
|
||||
/**
|
||||
* A user with access to create and edit custom basic blocks.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $baseUser2;
|
||||
|
||||
/**
|
||||
* Permissions to grant admin user.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $permissions = [
|
||||
'administer blocks',
|
||||
'access block library',
|
||||
'create basic block content',
|
||||
'edit any basic block content',
|
||||
'delete any basic block content',
|
||||
'translate configuration',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'block',
|
||||
'block_content',
|
||||
'config_translation',
|
||||
'views',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->baseUser1 = $this->drupalCreateUser(['access block library']);
|
||||
$this->baseUser2 = $this->drupalCreateUser([
|
||||
'access block library',
|
||||
'create basic block content',
|
||||
'edit any basic block content',
|
||||
'delete any basic block content',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the content block listing page.
|
||||
*/
|
||||
public function testListing(): void {
|
||||
// Test with an admin user.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalGet('admin/content/block');
|
||||
|
||||
// Test for the page title.
|
||||
$this->assertSession()->titleEquals('Content blocks | Drupal');
|
||||
|
||||
// Test for the exposed filters.
|
||||
$this->assertSession()->fieldExists('info');
|
||||
$this->assertSession()->fieldExists('type');
|
||||
|
||||
// Test for the table.
|
||||
$this->assertSession()->elementExists('xpath', '//div[@class="layout-content"]//table');
|
||||
|
||||
// Test the table header, four cells should be present.
|
||||
$this->assertSession()->elementsCount('xpath', '//div[@class="layout-content"]//table/thead/tr/th', 4);
|
||||
|
||||
// Test the contents of each th cell.
|
||||
$this->assertSession()->elementTextEquals('xpath', '//div[@class="layout-content"]//table/thead/tr/th[1]', 'Block description');
|
||||
$this->assertSession()->elementTextEquals('xpath', '//div[@class="layout-content"]//table/thead/tr/th[2]', 'Block type');
|
||||
$this->assertSession()->elementTextEquals('xpath', '//div[@class="layout-content"]//table/thead/tr/th[3]', 'Updated Sort ascending');
|
||||
$this->assertSession()->elementTextEquals('xpath', '//div[@class="layout-content"]//table/thead/tr/th[4]', 'Operations');
|
||||
|
||||
$label = 'Antelope';
|
||||
$new_label = 'Albatross';
|
||||
// Add a new entity using the operations link.
|
||||
$this->clickLink('Add content block');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$edit = [];
|
||||
$edit['info[0][value]'] = $label;
|
||||
$edit['body[0][value]'] = $this->randomMachineName(16);
|
||||
$this->submitForm($edit, 'Save');
|
||||
|
||||
// Confirm that once the user returns to the listing, the text of the label
|
||||
// (versus elsewhere on the page).
|
||||
$this->assertSession()->elementTextContains('xpath', '//td/a', $label);
|
||||
|
||||
// Check the number of table row cells.
|
||||
$this->assertSession()->elementsCount('xpath', '//div[@class="layout-content"]//table/tbody/tr/td', 4);
|
||||
// Check the contents of each row cell. The first cell contains the label,
|
||||
// the second contains the machine name, and the third contains the
|
||||
// operations list.
|
||||
$this->assertSession()->elementTextEquals('xpath', '//div[@class="layout-content"]//table/tbody/tr/td/a', $label);
|
||||
|
||||
// Edit the entity using the operations link.
|
||||
$blocks = $this->container
|
||||
->get('entity_type.manager')
|
||||
->getStorage('block_content')
|
||||
->loadByProperties(['info' => $label]);
|
||||
$block = reset($blocks);
|
||||
if (!empty($block)) {
|
||||
$this->assertSession()->linkByHrefExists('admin/content/block/' . $block->id());
|
||||
$this->clickLink('Edit');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->assertSession()->titleEquals("Edit content block $label | Drupal");
|
||||
$edit = ['info[0][value]' => $new_label];
|
||||
$this->submitForm($edit, 'Save');
|
||||
}
|
||||
else {
|
||||
$this->fail('Did not find Albatross block in the database.');
|
||||
}
|
||||
|
||||
// Confirm that once the user returns to the listing, the text of the label
|
||||
// (versus elsewhere on the page).
|
||||
$this->assertSession()->elementTextContains('xpath', '//td/a', $new_label);
|
||||
|
||||
// Delete the added entity using the operations link.
|
||||
$this->assertSession()->linkByHrefExists('admin/content/block/' . $block->id() . '/delete');
|
||||
$this->clickLink('Delete');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->assertSession()->titleEquals("Are you sure you want to delete the content block $new_label? | Drupal");
|
||||
$this->submitForm([], 'Delete');
|
||||
|
||||
// Verify that the text of the label and machine name does not appear in
|
||||
// the list (though it may appear elsewhere on the page).
|
||||
$this->assertSession()->elementTextNotContains('xpath', '//td', $new_label);
|
||||
|
||||
// Confirm that the empty text is displayed.
|
||||
$this->assertSession()->pageTextContains('There are no content blocks available.');
|
||||
$this->assertSession()->linkExists('content block');
|
||||
|
||||
$block_content = BlockContent::create([
|
||||
'info' => 'Non-reusable block',
|
||||
'type' => 'basic',
|
||||
'reusable' => FALSE,
|
||||
]);
|
||||
$block_content->save();
|
||||
|
||||
$this->drupalGet('admin/content/block');
|
||||
// Confirm that the empty text is displayed.
|
||||
$this->assertSession()->pageTextContains('There are no content blocks available.');
|
||||
// Confirm the non-reusable block is not on the page.
|
||||
$this->assertSession()->pageTextNotContains('Non-reusable block');
|
||||
|
||||
$this->drupalLogout();
|
||||
|
||||
// Create test block for other user tests.
|
||||
$test_block = $this->createBlockContent($label);
|
||||
|
||||
// Test as a user with view only permissions.
|
||||
$this->drupalLogin($this->baseUser1);
|
||||
$this->drupalGet('admin/content/block');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->assertSession()->linkNotExists('Add content block');
|
||||
$matches = $this->xpath('//td[1]');
|
||||
$actual = $matches[0]->getText();
|
||||
$this->assertEquals($label, $actual, 'Label found for test block.');
|
||||
$this->assertSession()->linkNotExists('Edit');
|
||||
$this->assertSession()->linkNotExists('Delete');
|
||||
$this->assertSession()->linkByHrefNotExists('admin/content/block/' . $test_block->id() . '/delete');
|
||||
|
||||
$this->drupalLogout();
|
||||
|
||||
// Test as a user with permission to create/edit/delete basic blocks.
|
||||
$this->drupalLogin($this->baseUser2);
|
||||
$this->drupalGet('admin/content/block');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->assertSession()->linkExists('Add content block');
|
||||
$matches = $this->xpath('//td/a');
|
||||
$actual = $matches[0]->getText();
|
||||
$this->assertEquals($label, $actual, 'Label found for test block.');
|
||||
$this->assertSession()->linkByHrefExists('admin/content/block/' . $test_block->id());
|
||||
$this->assertSession()->linkByHrefExists('admin/content/block/' . $test_block->id() . '/delete');
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
/**
|
||||
* Create a block and test block access by attempting to view the block.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentPageViewTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block_content_test'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* Checks block edit and fallback functionality.
|
||||
*/
|
||||
public function testPageEdit(): void {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$block = $this->createBlockContent();
|
||||
|
||||
// Attempt to view the block.
|
||||
$this->drupalGet('block-content/' . $block->id());
|
||||
|
||||
// Ensure user was able to view the block.
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertSession()->pageTextContains('This block is broken or missing. You may be missing content or you might need to install the original module.');
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
/**
|
||||
* Block content revision delete form test.
|
||||
*
|
||||
* @group block_content
|
||||
* @coversDefaultClass \Drupal\Core\Entity\Form\RevisionDeleteForm
|
||||
*/
|
||||
class BlockContentRevisionDeleteTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $permissions = [
|
||||
'view any basic block content history',
|
||||
'delete any basic block content revisions',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests revision delete.
|
||||
*/
|
||||
public function testDeleteForm(): void {
|
||||
$entity = $this->createBlockContent(save: FALSE)
|
||||
->setRevisionCreationTime((new \DateTimeImmutable('11 January 2009 4pm'))->getTimestamp())
|
||||
->setRevisionTranslationAffected(TRUE);
|
||||
$entity->setNewRevision();
|
||||
$entity->save();
|
||||
$revisionId = $entity->getRevisionId();
|
||||
|
||||
// Cannot delete latest revision.
|
||||
$this->drupalGet($entity->toUrl('revision-delete-form'));
|
||||
$this->assertSession()->statusCodeEquals(403);
|
||||
|
||||
// Create a new non default revision.
|
||||
$entity
|
||||
->setRevisionCreationTime((new \DateTimeImmutable('11 January 2009 5pm'))->getTimestamp())
|
||||
->setRevisionTranslationAffected(TRUE)
|
||||
->setNewRevision();
|
||||
$entity->isDefaultRevision(FALSE);
|
||||
$entity->save();
|
||||
$nonDefaultRevisionId = $entity->getRevisionId();
|
||||
|
||||
// Reload the default entity.
|
||||
$revision = \Drupal::entityTypeManager()->getStorage('block_content')
|
||||
->loadRevision($revisionId);
|
||||
// Cannot delete default revision.
|
||||
$this->drupalGet($revision->toUrl('revision-delete-form'));
|
||||
$this->assertSession()->statusCodeEquals(403);
|
||||
$this->assertFalse($revision->access('delete revision', $this->adminUser, FALSE));
|
||||
|
||||
// Reload the non default entity.
|
||||
$revision2 = \Drupal::entityTypeManager()->getStorage('block_content')
|
||||
->loadRevision($nonDefaultRevisionId);
|
||||
$this->drupalGet($revision2->toUrl('revision-delete-form'));
|
||||
$this->assertSession()->pageTextContains('Are you sure you want to delete the revision from Sun, 11 Jan 2009 - 17:00?');
|
||||
$this->assertSession()->buttonExists('Delete');
|
||||
$this->assertSession()->linkExists('Cancel');
|
||||
$this->assertTrue($revision2->access('delete revision', $this->adminUser, FALSE));
|
||||
|
||||
$countRevisions = static function (): int {
|
||||
return (int) \Drupal::entityTypeManager()->getStorage('block_content')
|
||||
->getQuery()
|
||||
->accessCheck(FALSE)
|
||||
->allRevisions()
|
||||
->count()
|
||||
->execute();
|
||||
};
|
||||
|
||||
$count = $countRevisions();
|
||||
$this->submitForm([], 'Delete');
|
||||
$this->assertEquals($count - 1, $countRevisions());
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->assertSession()->addressEquals(sprintf('admin/content/block/%s/revisions', $entity->id()));
|
||||
$this->assertSession()->pageTextContains(sprintf('Revision from Sun, 11 Jan 2009 - 17:00 of basic %s has been deleted.', $entity->label()));
|
||||
$this->assertSession()->elementsCount('css', 'table tbody tr', 1);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
/**
|
||||
* Block content revision form test.
|
||||
*
|
||||
* @group block_content
|
||||
* @coversDefaultClass \Drupal\Core\Entity\Form\RevisionRevertForm
|
||||
*/
|
||||
class BlockContentRevisionRevertTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $permissions = [
|
||||
'view any basic block content history',
|
||||
'revert any basic block content revisions',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests revision revert.
|
||||
*/
|
||||
public function testRevertForm(): void {
|
||||
$entity = $this->createBlockContent(save: FALSE)
|
||||
->setRevisionCreationTime((new \DateTimeImmutable('11 January 2009 4pm'))->getTimestamp())
|
||||
->setRevisionTranslationAffected(TRUE);
|
||||
$entity->setNewRevision();
|
||||
$entity->save();
|
||||
$revisionId = $entity->getRevisionId();
|
||||
|
||||
// Cannot revert latest revision.
|
||||
$this->drupalGet($entity->toUrl('revision-revert-form'));
|
||||
$this->assertSession()->statusCodeEquals(403);
|
||||
|
||||
// Create a new non default revision.
|
||||
$entity
|
||||
->setRevisionCreationTime((new \DateTimeImmutable('11 January 2009 5pm'))->getTimestamp())
|
||||
->setRevisionTranslationAffected(TRUE)
|
||||
->setNewRevision();
|
||||
$entity->isDefaultRevision(FALSE);
|
||||
$entity->save();
|
||||
$nonDefaultRevisionId = $entity->getRevisionId();
|
||||
|
||||
// Reload the default entity.
|
||||
$revision = \Drupal::entityTypeManager()->getStorage('block_content')
|
||||
->loadRevision($revisionId);
|
||||
// Cannot revert default revision.
|
||||
$this->drupalGet($revision->toUrl('revision-revert-form'));
|
||||
$this->assertSession()->statusCodeEquals(403);
|
||||
$this->assertFalse($revision->access('revert', $this->adminUser, FALSE));
|
||||
|
||||
// Reload the non default entity.
|
||||
$revision2 = \Drupal::entityTypeManager()->getStorage('block_content')
|
||||
->loadRevision($nonDefaultRevisionId);
|
||||
$this->drupalGet($revision2->toUrl('revision-revert-form'));
|
||||
$this->assertSession()->pageTextContains('Are you sure you want to revert to the revision from Sun, 11 Jan 2009 - 17:00?');
|
||||
$this->assertSession()->buttonExists('Revert');
|
||||
$this->assertSession()->linkExists('Cancel');
|
||||
$this->assertTrue($revision2->access('revert', $this->adminUser, FALSE));
|
||||
|
||||
$countRevisions = static function (): int {
|
||||
return (int) \Drupal::entityTypeManager()->getStorage('block_content')
|
||||
->getQuery()
|
||||
->accessCheck(FALSE)
|
||||
->allRevisions()
|
||||
->count()
|
||||
->execute();
|
||||
};
|
||||
|
||||
$count = $countRevisions();
|
||||
$this->submitForm([], 'Revert');
|
||||
$this->assertEquals($count + 1, $countRevisions());
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->assertSession()->addressEquals(sprintf('admin/content/block/%s/revisions', $entity->id()));
|
||||
$this->assertSession()->pageTextContains(sprintf('basic %s has been reverted to the revision from Sun, 11 Jan 2009 - 17:00.', $entity->label()));
|
||||
// Three rows, from the top: the newly reverted revision, the revision from
|
||||
// 5pm, and the revision from 4pm.
|
||||
$this->assertSession()->elementsCount('css', 'table tbody tr', 3);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
/**
|
||||
* Block content version history test.
|
||||
*
|
||||
* @group block_content
|
||||
* @coversDefaultClass \Drupal\Core\Entity\Controller\VersionHistoryController
|
||||
*/
|
||||
class BlockContentRevisionVersionHistoryTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $permissions = [
|
||||
'view any basic block content history',
|
||||
'revert any basic block content revisions',
|
||||
'delete any basic block content revisions',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->drupalLogin($this->adminUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests version history page.
|
||||
*/
|
||||
public function testVersionHistory(): void {
|
||||
$entity = $this->createBlockContent(save: FALSE);
|
||||
|
||||
$entity
|
||||
->setInfo('first revision')
|
||||
->setRevisionCreationTime((new \DateTimeImmutable('1st June 2020 7am'))->getTimestamp())
|
||||
->setRevisionLogMessage('first revision log')
|
||||
->setRevisionUser($this->drupalCreateUser(name: 'first author'))
|
||||
->setNewRevision();
|
||||
$entity->save();
|
||||
|
||||
$entity
|
||||
->setInfo('second revision')
|
||||
->setRevisionCreationTime((new \DateTimeImmutable('2nd June 2020 8am'))->getTimestamp())
|
||||
->setRevisionLogMessage('second revision log')
|
||||
->setRevisionUser($this->drupalCreateUser(name: 'second author'))
|
||||
->setNewRevision();
|
||||
$entity->save();
|
||||
|
||||
$entity
|
||||
->setInfo('third revision')
|
||||
->setRevisionCreationTime((new \DateTimeImmutable('3rd June 2020 9am'))->getTimestamp())
|
||||
->setRevisionLogMessage('third revision log')
|
||||
->setRevisionUser($this->drupalCreateUser(name: 'third author'))
|
||||
->setNewRevision();
|
||||
$entity->save();
|
||||
|
||||
$this->drupalGet($entity->toUrl('version-history'));
|
||||
$this->assertSession()->elementsCount('css', 'table tbody tr', 3);
|
||||
|
||||
// Order is newest to oldest revision by creation order.
|
||||
$row1 = $this->assertSession()->elementExists('css', 'table tbody tr:nth-child(1)');
|
||||
// Latest revision does not have revert or delete revision operation.
|
||||
$this->assertSession()->elementNotExists('named', ['link', 'Revert'], $row1);
|
||||
$this->assertSession()->elementNotExists('named', ['link', 'Delete'], $row1);
|
||||
$this->assertSession()->elementTextContains('css', 'table tbody tr:nth-child(1)', 'Current revision');
|
||||
$this->assertSession()->elementTextContains('css', 'table tbody tr:nth-child(1)', 'third revision log');
|
||||
$this->assertSession()->elementTextContains('css', 'table tbody tr:nth-child(1)', '3 Jun 2020 - 09:00 by third author');
|
||||
|
||||
$row2 = $this->assertSession()->elementExists('css', 'table tbody tr:nth-child(2)');
|
||||
$this->assertSession()->elementExists('named', ['link', 'Revert'], $row2);
|
||||
$this->assertSession()->elementExists('named', ['link', 'Delete'], $row2);
|
||||
$this->assertSession()->elementTextNotContains('css', 'table tbody tr:nth-child(2)', 'Current revision');
|
||||
$this->assertSession()->elementTextContains('css', 'table tbody tr:nth-child(2)', 'second revision log');
|
||||
$this->assertSession()->elementTextContains('css', 'table tbody tr:nth-child(2)', '2 Jun 2020 - 08:00 by second author');
|
||||
|
||||
$row3 = $this->assertSession()->elementExists('css', 'table tbody tr:nth-child(3)');
|
||||
$this->assertSession()->elementExists('named', ['link', 'Revert'], $row3);
|
||||
$this->assertSession()->elementExists('named', ['link', 'Delete'], $row3);
|
||||
$this->assertSession()->elementTextNotContains('css', 'table tbody tr:nth-child(2)', 'Current revision');
|
||||
$this->assertSession()->elementTextContains('css', 'table tbody tr:nth-child(3)', 'first revision log');
|
||||
$this->assertSession()->elementTextContains('css', 'table tbody tr:nth-child(3)', '1 Jun 2020 - 07:00 by first author');
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
|
||||
/**
|
||||
* Tests $block_content->save() for saving content.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentSaveTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block_content_test'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* Sets the test up.
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalLogin($this->adminUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether content block IDs are saved properly during an import.
|
||||
*/
|
||||
public function testImport(): void {
|
||||
// Content block ID must be a number that is not in the database.
|
||||
$max_id = (int) \Drupal::entityQueryAggregate('block_content')
|
||||
->accessCheck(FALSE)
|
||||
->aggregate('id', 'max')
|
||||
->execute()[0]['id_max'];
|
||||
$test_id = $max_id + mt_rand(1000, 1000000);
|
||||
$info = $this->randomMachineName(8);
|
||||
$block_array = [
|
||||
'info' => $info,
|
||||
'body' => ['value' => $this->randomMachineName(32)],
|
||||
'type' => 'basic',
|
||||
'id' => $test_id,
|
||||
];
|
||||
$block = BlockContent::create($block_array);
|
||||
$block->enforceIsNew(TRUE);
|
||||
$block->save();
|
||||
|
||||
// Verify that block_submit did not wipe the provided id.
|
||||
$this->assertEquals($test_id, $block->id(), 'Block imported using provide id');
|
||||
|
||||
// Test the import saved.
|
||||
$block_by_id = BlockContent::load($test_id);
|
||||
$this->assertNotEmpty($block_by_id, 'Content block load by block ID.');
|
||||
$this->assertSame($block_array['body']['value'], $block_by_id->body->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests determining changes in hook_block_presave().
|
||||
*
|
||||
* Verifies the static block load cache is cleared upon save.
|
||||
*/
|
||||
public function testDeterminingChanges(): void {
|
||||
// Initial creation.
|
||||
$block = $this->createBlockContent('test_changes');
|
||||
// Creating a block should set the changed date to the current time
|
||||
// which is always greater than the time set by hooks we're testing.
|
||||
$this->assertGreaterThan(979534800, $block->getChangedTime(), 'Creating a block sets default "changed" timestamp.');
|
||||
|
||||
// Update the block without applying changes.
|
||||
$block->save();
|
||||
$this->assertEquals('test_changes', $block->label(), 'No changes have been determined.');
|
||||
|
||||
// Apply changes.
|
||||
$block->setInfo('updated');
|
||||
$block->save();
|
||||
|
||||
// The hook implementations block_content_test_block_content_presave() and
|
||||
// block_content_test_block_content_update() determine changes and change
|
||||
// the title as well as programmatically set the 'changed' timestamp.
|
||||
$this->assertEquals('updated_presave_update', $block->label(), 'Changes have been determined.');
|
||||
$this->assertEquals(979534800, $block->getChangedTime(), 'Saving a content block uses "changed" timestamp set in presave hook.');
|
||||
|
||||
// Test the static block load cache to be cleared.
|
||||
$block = BlockContent::load($block->id());
|
||||
$this->assertEquals('updated_presave', $block->label(), 'Static cache has been cleared.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests saving a block on block insert.
|
||||
*
|
||||
* This test ensures that a block has been fully saved when
|
||||
* hook_block_content_insert() is invoked, so that the block can be saved
|
||||
* again in a hook implementation without errors.
|
||||
*
|
||||
* @see block_test_block_insert()
|
||||
*/
|
||||
public function testBlockContentSaveOnInsert(): void {
|
||||
// block_content_test_block_content_insert() triggers a save on insert if
|
||||
// the title equals 'new'.
|
||||
$block = $this->createBlockContent('new');
|
||||
$this->assertEquals('BlockContent ' . $block->id(), $block->label(), 'Content block saved on block insert.');
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Sets up block content types.
|
||||
*/
|
||||
abstract class BlockContentTestBase extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* Profile to use.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $profile = 'testing';
|
||||
|
||||
/**
|
||||
* Admin user.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
/**
|
||||
* Permissions to grant admin user.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $permissions = [
|
||||
'administer blocks',
|
||||
'access block library',
|
||||
'administer block types',
|
||||
'administer block content',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block', 'block_content'];
|
||||
|
||||
/**
|
||||
* Whether or not to auto-create the basic block type during setup.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $autoCreateBasicBlockType = TRUE;
|
||||
|
||||
/**
|
||||
* Sets the test up.
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
if ($this->autoCreateBasicBlockType) {
|
||||
$this->createBlockContentType(['id' => 'basic'], TRUE);
|
||||
}
|
||||
|
||||
$this->adminUser = $this->drupalCreateUser($this->permissions);
|
||||
$this->drupalPlaceBlock('local_actions_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a content block.
|
||||
*
|
||||
* @param bool|string $title
|
||||
* (optional) Title of block. When no value is given uses a random name.
|
||||
* Defaults to FALSE.
|
||||
* @param string $bundle
|
||||
* (optional) Bundle name. Defaults to 'basic'.
|
||||
* @param bool $save
|
||||
* (optional) Whether to save the block. Defaults to TRUE.
|
||||
*
|
||||
* @return \Drupal\block_content\Entity\BlockContent
|
||||
* Created content block.
|
||||
*/
|
||||
protected function createBlockContent($title = FALSE, $bundle = 'basic', $save = TRUE) {
|
||||
$title = $title ?: $this->randomMachineName();
|
||||
$block_content = BlockContent::create([
|
||||
'info' => $title,
|
||||
'type' => $bundle,
|
||||
'langcode' => 'en',
|
||||
]);
|
||||
if ($block_content && $save === TRUE) {
|
||||
$block_content->save();
|
||||
}
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a block type (bundle).
|
||||
*
|
||||
* @param array|string $values
|
||||
* (deprecated) The variable $values as string is deprecated. Provide as an
|
||||
* array as parameter. The value to create the block content type. If
|
||||
* $values is an array it should be like: ['id' => 'foo', 'label' => 'Foo'].
|
||||
* If $values is a string, it will be considered that it represents the
|
||||
* label.
|
||||
* @param bool $create_body
|
||||
* Whether or not to create the body field.
|
||||
*
|
||||
* @return \Drupal\block_content\Entity\BlockContentType
|
||||
* Created block type.
|
||||
*/
|
||||
protected function createBlockContentType($values, $create_body = FALSE) {
|
||||
if (is_string($values)) {
|
||||
@trigger_error('Using the variable $values as string is deprecated in drupal:11.1.0 and is removed from drupal:12.0.0. Provide an array as parameter. See https://www.drupal.org/node/3473739', E_USER_DEPRECATED);
|
||||
}
|
||||
if (is_array($values)) {
|
||||
if (!isset($values['id'])) {
|
||||
do {
|
||||
$id = $this->randomMachineName(8);
|
||||
} while (BlockContentType::load($id));
|
||||
}
|
||||
else {
|
||||
$id = $values['id'];
|
||||
}
|
||||
$values += [
|
||||
'id' => $id,
|
||||
'label' => $id,
|
||||
'revision' => FALSE,
|
||||
];
|
||||
$bundle = BlockContentType::create($values);
|
||||
}
|
||||
else {
|
||||
$bundle = BlockContentType::create([
|
||||
'id' => $values,
|
||||
'label' => $values,
|
||||
'revision' => FALSE,
|
||||
]);
|
||||
}
|
||||
$bundle->save();
|
||||
if ($create_body) {
|
||||
block_content_add_body_field($bundle->id());
|
||||
}
|
||||
return $bundle;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
/**
|
||||
* Tests block content theme suggestions.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentThemeSuggestionsTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* Path prefix for the field UI for the test bundle.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const FIELD_UI_PREFIX = 'admin/structure/types/manage/bundle_with_extra_field';
|
||||
|
||||
/**
|
||||
* The UUID for a block content entity.
|
||||
*/
|
||||
protected string $uuid = 'b22c881a-bcfd-4d0c-a41d-3573327705df';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'field_ui',
|
||||
'layout_builder',
|
||||
'node',
|
||||
'block_content_theme_suggestions_test',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
// Create a block with a known UUID.
|
||||
$block = $this->createBlockContent('Example block!', 'basic', FALSE);
|
||||
$block->set('uuid', $this->uuid);
|
||||
$block->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test suggestions for content blocks.
|
||||
*/
|
||||
public function testBlockContentThemeSuggestionsContent(): void {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalPlaceBlock('block_content:' . $this->uuid);
|
||||
$this->drupalGet('');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->assertSession()->pageTextContains('Example block!');
|
||||
$this->assertSession()->pageTextContainsOnce('I am a block content template for a specific bundle and view mode!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test suggestions for content blocks within extra fields blocks.
|
||||
*/
|
||||
public function testBlockContentThemeSuggestionsExtraField(): void {
|
||||
// Extra field blocks are a block plugin provided by layout builder, so
|
||||
// enable layouts for the test bundle and view a node of that bundle.
|
||||
// A test module injects an extra field referencing a block content entity.
|
||||
// @see block_content_theme_suggestions_test.module
|
||||
// @see \Drupal\block_content_theme_suggestions_test\Hook\BlockContentThemeSuggestionsTestHooks
|
||||
$this->drupalLogin($this->drupalCreateUser([
|
||||
'configure any layout',
|
||||
'administer node display',
|
||||
]));
|
||||
$this->createContentType(['type' => 'bundle_with_extra_field']);
|
||||
$this->drupalGet(static::FIELD_UI_PREFIX . '/display/default');
|
||||
$this->submitForm(['layout[enabled]' => TRUE], 'Save');
|
||||
$node = $this->createNode([
|
||||
'type' => 'bundle_with_extra_field',
|
||||
'title' => 'The first node title',
|
||||
]);
|
||||
$node->save();
|
||||
$this->drupalGet('/node/' . $node->id());
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->assertSession()->pageTextContains('Example block!');
|
||||
$this->assertSession()->pageTextContains('I am a block content template for a specific bundle and view mode!');
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Tests\content_translation\Functional\ContentTranslationUITestBase;
|
||||
|
||||
/**
|
||||
* Tests the block content translation UI.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentTranslationUITest extends ContentTranslationUITestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'language',
|
||||
'content_translation',
|
||||
'block',
|
||||
'field_ui',
|
||||
'block_content',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultCacheContexts = [
|
||||
'languages:language_interface',
|
||||
'session',
|
||||
'theme',
|
||||
'url.path',
|
||||
'url.query_args',
|
||||
'user.permissions',
|
||||
'user.roles:authenticated',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
$this->entityTypeId = 'block_content';
|
||||
$this->bundle = 'basic';
|
||||
$this->testLanguageSelector = FALSE;
|
||||
parent::setUp();
|
||||
$this->doSetup();
|
||||
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setupBundle(): void {
|
||||
// Create the basic bundle since it is provided by standard.
|
||||
$bundle = BlockContentType::create([
|
||||
'id' => $this->bundle,
|
||||
'label' => $this->bundle,
|
||||
'revision' => FALSE,
|
||||
]);
|
||||
$bundle->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTranslatorPermissions() {
|
||||
return array_merge(parent::getTranslatorPermissions(), [
|
||||
'translate any entity',
|
||||
'access administration pages',
|
||||
'administer blocks',
|
||||
'administer block_content fields',
|
||||
'access block library',
|
||||
'create basic block content',
|
||||
'edit any basic block content',
|
||||
'delete any basic block content',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNewEntityValues($langcode) {
|
||||
return ['info' => $this->randomMachineName()] + parent::getNewEntityValues($langcode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an edit array containing the values to be posted.
|
||||
*/
|
||||
protected function getEditValues($values, $langcode, $new = FALSE) {
|
||||
$edit = parent::getEditValues($values, $langcode, $new);
|
||||
foreach ($edit as $property => $value) {
|
||||
if ($property == 'info') {
|
||||
$edit['info[0][value]'] = $value;
|
||||
unset($edit[$property]);
|
||||
}
|
||||
}
|
||||
return $edit;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function doTestBasicTranslation(): void {
|
||||
parent::doTestBasicTranslation();
|
||||
|
||||
// Ensure that a block translation can be created using the same description
|
||||
// as in the original language.
|
||||
$default_langcode = $this->langcodes[0];
|
||||
$values = $this->getNewEntityValues($default_langcode);
|
||||
$storage = \Drupal::entityTypeManager()->getStorage($this->entityTypeId);
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
|
||||
$entity = $storage->create(['type' => 'basic'] + $values);
|
||||
$entity->save();
|
||||
$entity->addTranslation('it', $values);
|
||||
|
||||
try {
|
||||
$entity->save();
|
||||
}
|
||||
catch (\Exception) {
|
||||
$this->fail('Blocks can have translations with the same "info" value.');
|
||||
}
|
||||
|
||||
// Check that the translate operation link is shown.
|
||||
$this->drupalGet('admin/content/block');
|
||||
$this->assertSession()->linkByHrefExists('admin/content/block/' . $entity->id() . '/translations');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function doTestTranslationEdit(): void {
|
||||
$storage = $this->container->get('entity_type.manager')
|
||||
->getStorage($this->entityTypeId);
|
||||
$entity = $storage->load($this->entityId);
|
||||
$languages = $this->container->get('language_manager')->getLanguages();
|
||||
|
||||
foreach ($this->langcodes as $langcode) {
|
||||
// We only want to test the title for non-english translations.
|
||||
if ($langcode != 'en') {
|
||||
$options = ['language' => $languages[$langcode]];
|
||||
$url = $entity->toUrl('edit-form', $options);
|
||||
$this->drupalGet($url);
|
||||
$this->assertSession()->pageTextContains("Edit {$entity->bundle()} {$entity->getTranslation($langcode)->label()} [{$languages[$langcode]->getName()} translation]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,266 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\Tests\system\Functional\Menu\AssertBreadcrumbTrait;
|
||||
|
||||
/**
|
||||
* Ensures that block type functions work correctly.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentTypeTest extends BlockContentTestBase {
|
||||
|
||||
use AssertBreadcrumbTrait;
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['field_ui'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* Permissions to grant admin user.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $permissions = [
|
||||
'administer block content',
|
||||
'administer blocks',
|
||||
'administer block_content fields',
|
||||
'administer block types',
|
||||
'administer block content',
|
||||
'access block library',
|
||||
];
|
||||
|
||||
/**
|
||||
* Whether or not to create an initial block type.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $autoCreateBasicBlockType = FALSE;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the order of the block content types on the add page.
|
||||
*/
|
||||
public function testBlockContentAddPageOrder(): void {
|
||||
$this->createBlockContentType(['id' => 'bundle_1', 'label' => 'Bundle 1']);
|
||||
$this->createBlockContentType(['id' => 'bundle_2', 'label' => 'Aaa Bundle 2']);
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalGet('block/add');
|
||||
$this->assertSession()->pageTextMatches('/Aaa Bundle 2(.*)Bundle 1/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests creating a block type programmatically and via a form.
|
||||
*/
|
||||
public function testBlockContentTypeCreation(): void {
|
||||
// Log in a test user.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Test the page with no block-types.
|
||||
$this->drupalGet('block/add');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->assertSession()->pageTextContains('You have not created any block types yet');
|
||||
$this->clickLink('block type creation page');
|
||||
|
||||
// Create a block type via the user interface.
|
||||
$edit = [
|
||||
'id' => 'foo',
|
||||
'label' => 'title for foo',
|
||||
];
|
||||
$this->submitForm($edit, 'Save and manage fields');
|
||||
|
||||
// Asserts that form submit redirects to the expected manage fields page.
|
||||
$this->assertSession()->addressEquals('admin/structure/block-content/manage/' . $edit['id'] . '/fields');
|
||||
|
||||
$block_type = BlockContentType::load('foo');
|
||||
$this->assertInstanceOf(BlockContentType::class, $block_type);
|
||||
|
||||
$field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions('block_content', 'foo');
|
||||
$this->assertTrue(isset($field_definitions['body']), 'Body field created when using the UI to create block content types.');
|
||||
|
||||
// Check that the block type was created in site default language.
|
||||
$default_langcode = \Drupal::languageManager()->getDefaultLanguage()->getId();
|
||||
$this->assertEquals($block_type->language()->getId(), $default_langcode);
|
||||
|
||||
// Create block types programmatically.
|
||||
$this->createBlockContentType(['id' => 'basic'], TRUE);
|
||||
$field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions('block_content', 'basic');
|
||||
$this->assertTrue(isset($field_definitions['body']), "Body field for 'basic' block type created when using the testing API to create block content types.");
|
||||
|
||||
$this->createBlockContentType(['id' => 'other']);
|
||||
$field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions('block_content', 'other');
|
||||
$this->assertFalse(isset($field_definitions['body']), "Body field for 'other' block type not created when using the testing API to create block content types.");
|
||||
|
||||
$block_type = BlockContentType::load('other');
|
||||
$this->assertInstanceOf(BlockContentType::class, $block_type);
|
||||
|
||||
$this->drupalGet('block/add/' . $block_type->id());
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests editing a block type using the UI.
|
||||
*/
|
||||
public function testBlockContentTypeEditing(): void {
|
||||
$this->drupalPlaceBlock('system_breadcrumb_block');
|
||||
// Now create an initial block-type.
|
||||
$this->createBlockContentType(['id' => 'basic'], TRUE);
|
||||
|
||||
$this->drupalLogin($this->adminUser);
|
||||
// We need two block types to prevent /block/add redirecting.
|
||||
$this->createBlockContentType(['id' => 'other']);
|
||||
|
||||
$field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions('block_content', 'other');
|
||||
$this->assertFalse(isset($field_definitions['body']), 'Body field was not created when using the API to create block content types.');
|
||||
|
||||
// Verify that title and body fields are displayed.
|
||||
$this->drupalGet('block/add/basic');
|
||||
$this->assertSession()->pageTextContains('Block description');
|
||||
$this->assertNotEmpty($this->cssSelect('#edit-body-0-value'), 'Body field was found.');
|
||||
|
||||
// Change the block type name.
|
||||
$edit = [
|
||||
'label' => 'Bar',
|
||||
];
|
||||
$this->drupalGet('admin/structure/block-content/manage/basic');
|
||||
$this->assertSession()->titleEquals('Edit basic block type | Drupal');
|
||||
$this->submitForm($edit, 'Save');
|
||||
$front_page_path = Url::fromRoute('<front>')->toString();
|
||||
$this->assertBreadcrumb('admin/structure/block-content/manage/basic/fields', [
|
||||
$front_page_path => 'Home',
|
||||
'admin/structure/block-content' => 'Block types',
|
||||
'admin/structure/block-content/manage/basic' => 'Edit Bar',
|
||||
]);
|
||||
\Drupal::service('entity_field.manager')->clearCachedFieldDefinitions();
|
||||
|
||||
$this->drupalGet('block/add');
|
||||
$this->assertSession()->pageTextContains('Bar');
|
||||
$this->clickLink('Bar');
|
||||
// Verify that the original machine name was used in the URL.
|
||||
$this->assertSession()->addressEquals(Url::fromRoute('block_content.add_form', ['block_content_type' => 'basic']));
|
||||
|
||||
// Remove the body field.
|
||||
$this->drupalGet('admin/structure/block-content/manage/basic/fields/block_content.basic.body/delete');
|
||||
$this->submitForm([], 'Delete');
|
||||
// Resave the settings for this type.
|
||||
$this->drupalGet('admin/structure/block-content/manage/basic');
|
||||
$this->submitForm([], 'Save');
|
||||
// Check that the body field doesn't exist.
|
||||
$this->drupalGet('block/add/basic');
|
||||
$this->assertEmpty($this->cssSelect('#edit-body-0-value'), 'Body field was not found.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests deleting a block type that still has content.
|
||||
*/
|
||||
public function testBlockContentTypeDeletion(): void {
|
||||
// Now create an initial block-type.
|
||||
$this->createBlockContentType(['id' => 'basic'], TRUE);
|
||||
|
||||
// Create a block type programmatically.
|
||||
$type = $this->createBlockContentType(['id' => 'foo']);
|
||||
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Add a new block of this type.
|
||||
$block = $this->createBlockContent(FALSE, 'foo');
|
||||
// Attempt to delete the block type, which should not be allowed.
|
||||
$this->drupalGet('admin/structure/block-content/manage/' . $type->id() . '/delete');
|
||||
$this->assertSession()->pageTextContains($type->label() . ' is used by 1 content block on your site. You can not remove this block type until you have removed all of the ' . $type->label() . ' blocks.');
|
||||
$this->assertSession()->pageTextNotContains('This action cannot be undone.');
|
||||
|
||||
// Delete the block.
|
||||
$block->delete();
|
||||
// Attempt to delete the block type, which should now be allowed.
|
||||
$this->drupalGet('admin/structure/block-content/manage/' . $type->id() . '/delete');
|
||||
$this->assertSession()->pageTextContains('Are you sure you want to delete the block type ' . $type->id() . '?');
|
||||
$this->assertSession()->pageTextContains('This action cannot be undone.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that redirects work as expected when multiple block types exist.
|
||||
*/
|
||||
public function testsBlockContentAddTypes(): void {
|
||||
// Now create an initial block-type.
|
||||
$this->createBlockContentType(['id' => 'basic'], TRUE);
|
||||
|
||||
$this->drupalLogin($this->adminUser);
|
||||
// Create two block types programmatically.
|
||||
$this->createBlockContentType(['id' => 'foo']);
|
||||
$this->createBlockContentType(['id' => 'bar']);
|
||||
|
||||
// Get the content block storage.
|
||||
$storage = $this->container
|
||||
->get('entity_type.manager')
|
||||
->getStorage('block_content');
|
||||
|
||||
// Install all themes.
|
||||
$themes = ['olivero', 'stark', 'claro'];
|
||||
\Drupal::service('theme_installer')->install($themes);
|
||||
$theme_settings = $this->config('system.theme');
|
||||
foreach ($themes as $default_theme) {
|
||||
// Change the default theme.
|
||||
$theme_settings->set('default', $default_theme)->save();
|
||||
$this->drupalPlaceBlock('local_actions_block');
|
||||
|
||||
// For each installed theme, go to its block page and test the redirects.
|
||||
foreach ($themes as $theme) {
|
||||
// Test that adding a block from the 'place blocks' form sends you to
|
||||
// the block configure form.
|
||||
$path = $theme == $default_theme ? 'admin/structure/block' : "admin/structure/block/list/$theme";
|
||||
$this->drupalGet($path);
|
||||
$this->clickLink('Place block');
|
||||
$this->clickLink('Add content block');
|
||||
$this->clickLink('foo');
|
||||
// Create a new block.
|
||||
$edit = ['info[0][value]' => $this->randomMachineName(8)];
|
||||
$this->submitForm($edit, 'Save and configure');
|
||||
$blocks = $storage->loadByProperties(['info' => $edit['info[0][value]']]);
|
||||
if (!empty($blocks)) {
|
||||
$block = reset($blocks);
|
||||
$this->assertSession()->addressEquals(Url::fromRoute('block.admin_add', ['plugin_id' => 'block_content:' . $block->uuid(), 'theme' => $theme]));
|
||||
$this->submitForm(['region' => 'content'], 'Save block');
|
||||
$this->assertSession()->addressEquals(Url::fromRoute('block.admin_display_theme', ['theme' => $theme], ['query' => ['block-placement' => $theme . '-' . Html::getClass($edit['info[0][value]'])]]));
|
||||
}
|
||||
else {
|
||||
$this->fail('Could not load created block.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test that adding a block from the 'content blocks list' doesn't send you
|
||||
// to the block configure form.
|
||||
$this->drupalGet('admin/content/block');
|
||||
$this->clickLink('Add content block');
|
||||
$this->clickLink('foo');
|
||||
$edit = ['info[0][value]' => $this->randomMachineName(8)];
|
||||
$this->submitForm($edit, 'Save');
|
||||
$blocks = $storage->loadByProperties(['info' => $edit['info[0][value]']]);
|
||||
if (!empty($blocks)) {
|
||||
$this->assertSession()->addressEquals(Url::fromRoute('entity.block_content.collection'));
|
||||
}
|
||||
else {
|
||||
$this->fail('Could not load created block.');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
use Drupal\Tests\system\Functional\Module\GenericModuleTestBase;
|
||||
|
||||
/**
|
||||
* Generic module test for block_content.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class GenericTest extends GenericModuleTestBase {}
|
||||
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
/**
|
||||
* Tests block_content local action links.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class LocalActionTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalLogin($this->adminUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the block_content_add_action link.
|
||||
*/
|
||||
public function testAddContentBlockLink(): void {
|
||||
// Verify that the link takes you straight to the block form if there's only
|
||||
// one type.
|
||||
$this->drupalGet('/admin/content/block');
|
||||
$this->clickLink('Add content block');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->assertSession()->addressEquals('/block/add/basic');
|
||||
|
||||
$type = $this->randomMachineName();
|
||||
$this->createBlockContentType([
|
||||
'id' => $type,
|
||||
'label' => $type,
|
||||
]);
|
||||
|
||||
// Verify that the link takes you to the block add page if there's more than
|
||||
// one type.
|
||||
$this->drupalGet('/admin/content/block');
|
||||
$this->clickLink('Add content block');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->assertSession()->addressEquals('/block/add');
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\Tests\system\Functional\Menu\AssertBreadcrumbTrait;
|
||||
|
||||
/**
|
||||
* Create a block and test block edit functionality.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class PageEditTest extends BlockContentTestBase {
|
||||
|
||||
use AssertBreadcrumbTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
$this->drupalPlaceBlock('system_breadcrumb_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks block edit functionality.
|
||||
*/
|
||||
public function testPageEdit(): void {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
$title_key = 'info[0][value]';
|
||||
$body_key = 'body[0][value]';
|
||||
// Create block to edit.
|
||||
$edit = [];
|
||||
$edit['info[0][value]'] = $this->randomMachineName(8);
|
||||
$edit[$body_key] = $this->randomMachineName(16);
|
||||
$this->drupalGet('block/add/basic');
|
||||
$this->submitForm($edit, 'Save');
|
||||
|
||||
// Check that the block exists in the database.
|
||||
$blocks = \Drupal::entityQuery('block_content')
|
||||
->accessCheck(FALSE)
|
||||
->condition('info', $edit['info[0][value]'])
|
||||
->execute();
|
||||
$block = BlockContent::load(reset($blocks));
|
||||
$this->assertNotEmpty($block, 'Content block found in database.');
|
||||
|
||||
// Load the edit page.
|
||||
$this->drupalGet('admin/content/block/' . $block->id());
|
||||
$this->assertSession()->fieldValueEquals($title_key, $edit[$title_key]);
|
||||
$this->assertSession()->fieldValueEquals($body_key, $edit[$body_key]);
|
||||
|
||||
// Edit the content of the block.
|
||||
$edit = [];
|
||||
$edit[$title_key] = $this->randomMachineName(8);
|
||||
$edit[$body_key] = $this->randomMachineName(16);
|
||||
// Stay on the current page, without reloading.
|
||||
$this->submitForm($edit, 'Save');
|
||||
|
||||
// Edit the same block, creating a new revision.
|
||||
$this->drupalGet("admin/content/block/" . $block->id());
|
||||
$edit = [];
|
||||
$edit['info[0][value]'] = $this->randomMachineName(8);
|
||||
$edit[$body_key] = $this->randomMachineName(16);
|
||||
$edit['revision'] = TRUE;
|
||||
$this->submitForm($edit, 'Save');
|
||||
|
||||
// Ensure that the block revision has been created.
|
||||
$revised_block = BlockContent::load($block->id());
|
||||
$this->assertNotSame($block->getRevisionId(), $revised_block->getRevisionId(), 'A new revision has been created.');
|
||||
|
||||
// Test deleting the block.
|
||||
$this->drupalGet("admin/content/block/" . $revised_block->id());
|
||||
$this->clickLink('Delete');
|
||||
$this->assertSession()->pageTextContains('Are you sure you want to delete the content block ' . $revised_block->label() . '?');
|
||||
|
||||
// Test breadcrumb.
|
||||
$trail = [
|
||||
'' => 'Home',
|
||||
'admin/content/block' => 'Content blocks',
|
||||
'admin/content/block/' . $revised_block->id() => $revised_block->label(),
|
||||
];
|
||||
$this->assertBreadcrumb(
|
||||
'admin/content/block/' . $revised_block->id() . '/delete', $trail
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentJsonAnonTest extends BlockContentResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentJsonBasicAuthTest extends BlockContentResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentJsonCookieTest extends BlockContentResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
}
|
||||
@ -0,0 +1,239 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
|
||||
/**
|
||||
* Resource test base for BlockContent entity.
|
||||
*/
|
||||
abstract class BlockContentResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block_content', 'content_translation'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $entityTypeId = 'block_content';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $patchProtectedFieldNames = [
|
||||
'changed' => NULL,
|
||||
];
|
||||
|
||||
/**
|
||||
* @var \Drupal\block_content\BlockContentInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpAuthorization($method) {
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
case 'PATCH':
|
||||
$this->grantPermissionsToTestedRole(['access block library', 'edit any basic block content']);
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
$this->grantPermissionsToTestedRole(['create basic block content']);
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
$this->grantPermissionsToTestedRole(['delete any basic block content']);
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->grantPermissionsToTestedRole(['administer block content']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
if (!BlockContentType::load('basic')) {
|
||||
$block_content_type = BlockContentType::create([
|
||||
'id' => 'basic',
|
||||
'label' => 'basic',
|
||||
'revision' => TRUE,
|
||||
]);
|
||||
$block_content_type->save();
|
||||
block_content_add_body_field($block_content_type->id());
|
||||
}
|
||||
|
||||
// Create a "Llama" content block.
|
||||
$block_content = BlockContent::create([
|
||||
'info' => 'Llama',
|
||||
'type' => 'basic',
|
||||
'body' => [
|
||||
'value' => 'The name "llama" was adopted by European settlers from native Peruvians.',
|
||||
'format' => 'plain_text',
|
||||
],
|
||||
])
|
||||
->setUnpublished();
|
||||
$block_content->save();
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
return [
|
||||
'id' => [
|
||||
[
|
||||
'value' => 1,
|
||||
],
|
||||
],
|
||||
'uuid' => [
|
||||
[
|
||||
'value' => $this->entity->uuid(),
|
||||
],
|
||||
],
|
||||
'langcode' => [
|
||||
[
|
||||
'value' => 'en',
|
||||
],
|
||||
],
|
||||
'reusable' => [
|
||||
[
|
||||
'value' => TRUE,
|
||||
],
|
||||
],
|
||||
'type' => [
|
||||
[
|
||||
'target_id' => 'basic',
|
||||
'target_type' => 'block_content_type',
|
||||
'target_uuid' => BlockContentType::load('basic')->uuid(),
|
||||
],
|
||||
],
|
||||
'info' => [
|
||||
[
|
||||
'value' => 'Llama',
|
||||
],
|
||||
],
|
||||
'revision_log' => [],
|
||||
'changed' => [
|
||||
[
|
||||
'value' => (new \DateTime())->setTimestamp((int) $this->entity->getChangedTime())
|
||||
->setTimezone(new \DateTimeZone('UTC'))
|
||||
->format(\DateTime::RFC3339),
|
||||
'format' => \DateTime::RFC3339,
|
||||
],
|
||||
],
|
||||
'revision_id' => [
|
||||
[
|
||||
'value' => 1,
|
||||
],
|
||||
],
|
||||
'revision_created' => [
|
||||
[
|
||||
'value' => (new \DateTime())->setTimestamp((int) $this->entity->getRevisionCreationTime())
|
||||
->setTimezone(new \DateTimeZone('UTC'))
|
||||
->format(\DateTime::RFC3339),
|
||||
'format' => \DateTime::RFC3339,
|
||||
],
|
||||
],
|
||||
'revision_user' => [],
|
||||
'revision_translation_affected' => [
|
||||
[
|
||||
'value' => TRUE,
|
||||
],
|
||||
],
|
||||
'default_langcode' => [
|
||||
[
|
||||
'value' => TRUE,
|
||||
],
|
||||
],
|
||||
'body' => [
|
||||
[
|
||||
'value' => 'The name "llama" was adopted by European settlers from native Peruvians.',
|
||||
'format' => 'plain_text',
|
||||
'summary' => NULL,
|
||||
'processed' => "<p>The name "llama" was adopted by European settlers from native Peruvians.</p>\n",
|
||||
],
|
||||
],
|
||||
'status' => [
|
||||
[
|
||||
'value' => FALSE,
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
return [
|
||||
'type' => [
|
||||
[
|
||||
'target_id' => 'basic',
|
||||
],
|
||||
],
|
||||
'info' => [
|
||||
[
|
||||
'value' => 'Drama llama',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedUnauthorizedAccessMessage($method) {
|
||||
if (!$this->resourceConfigStorage->load(static::$resourceConfigId)) {
|
||||
return match ($method) {
|
||||
'GET', 'PATCH' => "The 'edit any basic block content' permission is required.",
|
||||
'POST' => "The following permissions are required: 'create basic block content' OR 'administer block content'.",
|
||||
'DELETE' => "The 'delete any basic block content' permission is required.",
|
||||
default => parent::getExpectedUnauthorizedAccessMessage($method),
|
||||
};
|
||||
}
|
||||
return match ($method) {
|
||||
'GET' => "The 'access block library' permission is required.",
|
||||
'PATCH' => "The 'edit any basic block content' permission is required.",
|
||||
'POST' => "The following permissions are required: 'create basic block content' OR 'administer block content'.",
|
||||
'DELETE' => "The 'delete any basic block content' permission is required.",
|
||||
default => parent::getExpectedUnauthorizedAccessMessage($method),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedUnauthorizedEntityAccessCacheability($is_authenticated) {
|
||||
// @see \Drupal\block_content\BlockContentAccessControlHandler()
|
||||
return parent::getExpectedUnauthorizedEntityAccessCacheability($is_authenticated)
|
||||
->addCacheTags(['block_content:1']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedCacheTags() {
|
||||
return Cache::mergeTags(parent::getExpectedCacheTags(), ['config:filter.format.plain_text']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedCacheContexts() {
|
||||
return Cache::mergeContexts(['url.site'], $this->container->getParameter('renderer.config')['required_cache_contexts']);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentTypeJsonAnonTest extends BlockContentTypeResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentTypeJsonBasicAuthTest extends BlockContentTypeResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentTypeJsonCookieTest extends BlockContentTypeResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\EntityResource\ConfigEntityResourceTestBase;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
|
||||
/**
|
||||
* Resource test base for the BlockContentType entity.
|
||||
*/
|
||||
abstract class BlockContentTypeResourceTestBase extends ConfigEntityResourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block_content'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $entityTypeId = 'block_content_type';
|
||||
|
||||
/**
|
||||
* @var \Drupal\block_content\BlockContentTypeInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpAuthorization($method) {
|
||||
$this->grantPermissionsToTestedRole(['administer block types']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
$block_content_type = BlockContentType::create([
|
||||
'id' => 'pascal',
|
||||
'label' => 'Pascal',
|
||||
'revision' => FALSE,
|
||||
'description' => 'Provides a competitive alternative to the "basic" type',
|
||||
]);
|
||||
|
||||
$block_content_type->save();
|
||||
|
||||
return $block_content_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
return [
|
||||
'dependencies' => [],
|
||||
'description' => 'Provides a competitive alternative to the "basic" type',
|
||||
'id' => 'pascal',
|
||||
'label' => 'Pascal',
|
||||
'langcode' => 'en',
|
||||
'revision' => FALSE,
|
||||
'status' => TRUE,
|
||||
'uuid' => $this->entity->uuid(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
// @todo Update in https://www.drupal.org/node/2300677.
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentTypeXmlAnonTest extends BlockContentTypeResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentTypeXmlBasicAuthTest extends BlockContentTypeResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentTypeXmlCookieTest extends BlockContentTypeResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentXmlAnonTest extends BlockContentResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentXmlBasicAuthTest extends BlockContentResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentXmlCookieTest extends BlockContentResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\Tests\block\Traits\BlockCreationTrait;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests unpublishing of block_content entities.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class UnpublishedBlockTest extends BrowserTestBase {
|
||||
|
||||
use BlockCreationTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block_content'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* Tests unpublishing of block_content entities.
|
||||
*/
|
||||
public function testViewShowsCorrectStates(): void {
|
||||
$block_content = BlockContent::create([
|
||||
'info' => 'Test block',
|
||||
'type' => 'basic',
|
||||
]);
|
||||
$block_content->save();
|
||||
|
||||
$block = $this->placeBlock('block_content:' . $block_content->uuid());
|
||||
|
||||
$this->drupalGet('<front>');
|
||||
$page = $this->getSession()->getPage();
|
||||
$this->assertTrue($page->has('css', '#block-' . $block->id()));
|
||||
|
||||
$block_content->setUnpublished();
|
||||
$block_content->save();
|
||||
|
||||
$this->drupalGet('<front>');
|
||||
$page = $this->getSession()->getPage();
|
||||
$this->assertFalse($page->has('css', '#block-' . $block->id()));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Views;
|
||||
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
|
||||
/**
|
||||
* Tests block_content field filters with translations.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentFieldFilterTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['language'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_field_filters'];
|
||||
|
||||
/**
|
||||
* List of block_content infos by language.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $blockContentInfos = [];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp($import_test_views = TRUE, $modules = ['block_content_test_views']): void {
|
||||
parent::setUp($import_test_views, $modules);
|
||||
|
||||
// Add two new languages.
|
||||
ConfigurableLanguage::createFromLangcode('fr')->save();
|
||||
ConfigurableLanguage::createFromLangcode('es')->save();
|
||||
|
||||
// Make the body field translatable. The info is already translatable by
|
||||
// definition.
|
||||
$field_storage = FieldStorageConfig::loadByName('block_content', 'body');
|
||||
$field_storage->setTranslatable(TRUE);
|
||||
$field_storage->save();
|
||||
|
||||
// Set up block_content infos.
|
||||
$this->blockContentInfos = [
|
||||
'en' => 'Food in Paris',
|
||||
'es' => 'Comida en Paris',
|
||||
'fr' => 'Nourriture en Paris',
|
||||
];
|
||||
|
||||
// Create block_content with translations.
|
||||
$block_content = $this->createBlockContent(['info' => $this->blockContentInfos['en'], 'langcode' => 'en', 'type' => 'basic', 'body' => [['value' => $this->blockContentInfos['en']]]]);
|
||||
foreach (['es', 'fr'] as $langcode) {
|
||||
$translation = $block_content->addTranslation($langcode, ['info' => $this->blockContentInfos[$langcode]]);
|
||||
$translation->body->value = $this->blockContentInfos[$langcode];
|
||||
}
|
||||
$block_content->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests body and info filters.
|
||||
*/
|
||||
public function testFilters(): void {
|
||||
// Test the info filter page, which filters for info contains 'Comida'.
|
||||
// Should show just the Spanish translation, once.
|
||||
$this->assertPageCounts('test-info-filter', ['es' => 1, 'fr' => 0, 'en' => 0], 'Comida info filter');
|
||||
|
||||
// Test the body filter page, which filters for body contains 'Comida'.
|
||||
// Should show just the Spanish translation, once.
|
||||
$this->assertPageCounts('test-body-filter', ['es' => 1, 'fr' => 0, 'en' => 0], 'Comida body filter');
|
||||
|
||||
// Test the info Paris filter page, which filters for info contains
|
||||
// 'Paris'. Should show each translation once.
|
||||
$this->assertPageCounts('test-info-paris', ['es' => 1, 'fr' => 1, 'en' => 1], 'Paris info filter');
|
||||
|
||||
// Test the body Paris filter page, which filters for body contains
|
||||
// 'Paris'. Should show each translation once.
|
||||
$this->assertPageCounts('test-body-paris', ['es' => 1, 'fr' => 1, 'en' => 1], 'Paris body filter');
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the given block_content translation counts are correct.
|
||||
*
|
||||
* @param string $path
|
||||
* Path of the page to test.
|
||||
* @param array $counts
|
||||
* Array whose keys are languages, and values are the number of times
|
||||
* that translation should be shown on the given page.
|
||||
* @param string $message
|
||||
* Message suffix to display.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function assertPageCounts(string $path, array $counts, string $message): void {
|
||||
// Get the text of the page.
|
||||
$this->drupalGet($path);
|
||||
$text = $this->getTextContent();
|
||||
|
||||
foreach ($counts as $langcode => $count) {
|
||||
$this->assertEquals($count, substr_count($text, $this->blockContentInfos[$langcode]), 'Translation ' . $langcode . ' has count ' . $count . ' with ' . $message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Views;
|
||||
|
||||
/**
|
||||
* Tests the block_content integration into views.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentIntegrationTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_block_content_view'];
|
||||
|
||||
/**
|
||||
* Tests basic block_content view with a block_content_type argument.
|
||||
*/
|
||||
public function testBlockContentViewTypeArgument(): void {
|
||||
// Create two content types with three block_contents each.
|
||||
$types = [];
|
||||
$all_ids = [];
|
||||
$block_contents = [];
|
||||
for ($i = 0; $i < 2; $i++) {
|
||||
$type = $this->createBlockContentType();
|
||||
$types[] = $type;
|
||||
|
||||
for ($j = 0; $j < 5; $j++) {
|
||||
// Ensure the right order of the block_contents.
|
||||
$block_content = $this->createBlockContent(['type' => $type->id()]);
|
||||
$block_contents[$type->id()][$block_content->id()] = $block_content;
|
||||
$all_ids[] = $block_content->id();
|
||||
}
|
||||
}
|
||||
|
||||
$this->drupalGet('test-block_content-view');
|
||||
$this->assertSession()->statusCodeEquals(404);
|
||||
|
||||
$this->drupalGet('test-block_content-view/all');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->assertIds($all_ids);
|
||||
/** @var \Drupal\block_content\Entity\BlockContentType[] $types*/
|
||||
foreach ($types as $type) {
|
||||
$this->drupalGet("test-block_content-view/{$type->id()}");
|
||||
$this->assertIds(array_keys($block_contents[$type->id()]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that a list of block_contents appear on the page.
|
||||
*
|
||||
* @param array $expected_ids
|
||||
* An array of block_content IDs.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function assertIds(array $expected_ids = []): void {
|
||||
$result = $this->xpath('//span[@class="field-content"]');
|
||||
$ids = [];
|
||||
foreach ($result as $element) {
|
||||
$ids[] = $element->getText();
|
||||
}
|
||||
$this->assertEquals($expected_ids, $ids);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Views;
|
||||
|
||||
/**
|
||||
* Tests the redirect destination on block content on entity operations.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentRedirectTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_block_content_redirect_destination'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block', 'block_content', 'views'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* Tests the redirect destination when editing block content.
|
||||
*/
|
||||
public function testRedirectDestination(): void {
|
||||
$this->drupalLogin($this->drupalCreateUser(['access block library', 'administer block content']));
|
||||
$this->drupalGet('admin/content/block');
|
||||
|
||||
// Create a content block.
|
||||
$this->clickLink('content block');
|
||||
$edit = [];
|
||||
$edit['info[0][value]'] = 'Test redirect destination';
|
||||
$edit['body[0][value]'] = $this->randomMachineName(16);
|
||||
$this->submitForm($edit, 'Save');
|
||||
|
||||
// Check the block content is present in the view redirect destination.
|
||||
$this->drupalGet('admin/content/redirect_destination');
|
||||
$this->assertSession()->pageTextContains('Test redirect destination');
|
||||
|
||||
// Edit the created block and save.
|
||||
$this->clickLink('Edit');
|
||||
$this->submitForm([], 'Save');
|
||||
$this->assertSession()->addressEquals('admin/content/redirect_destination');
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Views;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
|
||||
/**
|
||||
* Base class for all block_content tests.
|
||||
*/
|
||||
abstract class BlockContentTestBase extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Admin user.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
/**
|
||||
* Permissions to grant admin user.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $permissions = [
|
||||
'administer blocks',
|
||||
'administer block content',
|
||||
'access block library',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'block',
|
||||
'block_content',
|
||||
'block_content_test_views',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp($import_test_views = TRUE, $modules = ['block_content_test_views']): void {
|
||||
parent::setUp($import_test_views, $modules);
|
||||
// Ensure the basic bundle exists. This is provided by the standard profile.
|
||||
$this->createBlockContentType(['id' => 'basic']);
|
||||
|
||||
$this->adminUser = $this->drupalCreateUser($this->permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a content block.
|
||||
*
|
||||
* @param array $values
|
||||
* (optional) The values for the block_content entity.
|
||||
*
|
||||
* @return \Drupal\block_content\Entity\BlockContent
|
||||
* Created content block.
|
||||
*/
|
||||
protected function createBlockContent(array $values = []) {
|
||||
$status = 0;
|
||||
$values += [
|
||||
'info' => $this->randomMachineName(),
|
||||
'type' => 'basic',
|
||||
'langcode' => 'en',
|
||||
];
|
||||
if ($block_content = BlockContent::create($values)) {
|
||||
$status = $block_content->save();
|
||||
}
|
||||
$this->assertEquals(SAVED_NEW, $status, "Created block content {$block_content->label()}.");
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a block type (bundle).
|
||||
*
|
||||
* @param array $values
|
||||
* An array of settings to change from the defaults.
|
||||
*
|
||||
* @return \Drupal\block_content\Entity\BlockContentType
|
||||
* Created block type.
|
||||
*/
|
||||
protected function createBlockContentType(array $values = []) {
|
||||
// Find a non-existent random type name.
|
||||
if (!isset($values['id'])) {
|
||||
do {
|
||||
$id = $this->randomMachineName(8);
|
||||
} while (BlockContentType::load($id));
|
||||
}
|
||||
else {
|
||||
$id = $values['id'];
|
||||
}
|
||||
$values += [
|
||||
'id' => $id,
|
||||
'label' => $id,
|
||||
'revision' => FALSE,
|
||||
];
|
||||
$bundle = BlockContentType::create($values);
|
||||
$status = $bundle->save();
|
||||
block_content_add_body_field($bundle->id());
|
||||
|
||||
$this->assertEquals(SAVED_NEW, $status, sprintf('Created block content type %s.', $bundle->id()));
|
||||
return $bundle;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Views;
|
||||
|
||||
use Drupal\Tests\block_content\Functional\BlockContentTestBase;
|
||||
|
||||
/**
|
||||
* Tests block_content wizard and generic entity integration.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentWizardTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block_content', 'views_ui'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer views']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests creating a 'block_content' entity view.
|
||||
*/
|
||||
public function testViewAddBlockContent(): void {
|
||||
$view = [];
|
||||
$view['label'] = $this->randomMachineName(16);
|
||||
$view['id'] = $this->randomMachineName(16);
|
||||
$view['description'] = $this->randomMachineName(16);
|
||||
$view['page[create]'] = FALSE;
|
||||
$view['show[wizard_key]'] = 'block_content';
|
||||
$this->drupalGet('admin/structure/views/add');
|
||||
$this->submitForm($view, 'Save and edit');
|
||||
|
||||
$view_storage_controller = $this->container->get('entity_type.manager')->getStorage('view');
|
||||
/** @var \Drupal\views\Entity\View $view */
|
||||
$view = $view_storage_controller->load($view['id']);
|
||||
|
||||
$display_options = $view->getDisplay('default')['display_options'];
|
||||
|
||||
$this->assertEquals('block_content', $display_options['filters']['reusable']['entity_type']);
|
||||
$this->assertEquals('reusable', $display_options['filters']['reusable']['entity_field']);
|
||||
$this->assertEquals('boolean', $display_options['filters']['reusable']['plugin_id']);
|
||||
$this->assertEquals('1', $display_options['filters']['reusable']['value']);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,621 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel;
|
||||
|
||||
use Drupal\block_content\BlockContentAccessControlHandler;
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Core\Access\AccessibleInterface;
|
||||
use Drupal\Core\Access\AccessResultAllowed;
|
||||
use Drupal\Core\Access\AccessResultForbidden;
|
||||
use Drupal\Core\Access\AccessResultNeutral;
|
||||
use Drupal\Core\Access\AccessResultReasonInterface;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\Tests\user\Traits\UserCreationTrait;
|
||||
use Drupal\user\Entity\Role;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* Tests the block content entity access handler.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\block_content\BlockContentAccessControlHandler
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentAccessHandlerTest extends KernelTestBase {
|
||||
|
||||
use UserCreationTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'block',
|
||||
'block_content',
|
||||
'system',
|
||||
'user',
|
||||
];
|
||||
|
||||
/**
|
||||
* The BlockContent access controller to test.
|
||||
*
|
||||
* @var \Drupal\block_content\BlockContentAccessControlHandler
|
||||
*/
|
||||
protected $accessControlHandler;
|
||||
|
||||
/**
|
||||
* The BlockContent entity used for testing.
|
||||
*
|
||||
* @var \Drupal\block_content\Entity\BlockContent
|
||||
*/
|
||||
protected $blockEntity;
|
||||
|
||||
/**
|
||||
* The test role.
|
||||
*
|
||||
* @var \Drupal\user\RoleInterface
|
||||
*/
|
||||
protected $role;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->installSchema('user', ['users_data']);
|
||||
$this->installEntitySchema('user');
|
||||
$this->installEntitySchema('block_content');
|
||||
|
||||
// Create a basic block content type.
|
||||
$block_content_type = BlockContentType::create([
|
||||
'id' => 'basic',
|
||||
'label' => 'A basic block type',
|
||||
'description' => "Provides a block type that is basic.",
|
||||
]);
|
||||
$block_content_type->save();
|
||||
|
||||
// Create a square block content type.
|
||||
$block_content_type = BlockContentType::create([
|
||||
'id' => 'square',
|
||||
'label' => 'A square block type',
|
||||
'description' => "Provides a block type that is square.",
|
||||
]);
|
||||
$block_content_type->save();
|
||||
|
||||
$this->blockEntity = BlockContent::create([
|
||||
'info' => 'The Block',
|
||||
'type' => 'square',
|
||||
]);
|
||||
$this->blockEntity->save();
|
||||
|
||||
// Create user 1 test does not have all permissions.
|
||||
User::create([
|
||||
'name' => 'admin',
|
||||
])->save();
|
||||
|
||||
$this->role = Role::create([
|
||||
'id' => 'test',
|
||||
'label' => 'test role',
|
||||
]);
|
||||
$this->role->save();
|
||||
$this->accessControlHandler = new BlockContentAccessControlHandler(\Drupal::entityTypeManager()->getDefinition('block_content'), \Drupal::service('event_dispatcher'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test block content entity access.
|
||||
*
|
||||
* @param string $operation
|
||||
* The entity operation to test.
|
||||
* @param bool $published
|
||||
* Whether the latest revision should be published.
|
||||
* @param bool $reusable
|
||||
* Whether the block content should be reusable. Non-reusable blocks are
|
||||
* typically used in Layout Builder.
|
||||
* @param array $permissions
|
||||
* Permissions to grant to the test user.
|
||||
* @param bool $isLatest
|
||||
* Whether the block content should be the latest revision when checking
|
||||
* access. If FALSE, multiple revisions will be created, and an older
|
||||
* revision will be loaded before checking access.
|
||||
* @param string|null $parent_access
|
||||
* Whether the test user has access to the parent entity, valid values are
|
||||
* class names of classes implementing AccessResultInterface. Set to NULL to
|
||||
* assert parent will not be called.
|
||||
* @param string $expected_access
|
||||
* The expected access for the user and block content. Valid values are
|
||||
* class names of classes implementing AccessResultInterface.
|
||||
* @param string|null $expected_access_message
|
||||
* The expected access message.
|
||||
*
|
||||
* @covers ::checkAccess
|
||||
*
|
||||
* @dataProvider providerTestAccess
|
||||
*
|
||||
* @phpstan-param class-string<\Drupal\Core\Access\AccessResultInterface>|null $parent_access
|
||||
* @phpstan-param class-string<\Drupal\Core\Access\AccessResultInterface> $expected_access
|
||||
*/
|
||||
public function testAccess(string $operation, bool $published, bool $reusable, array $permissions, bool $isLatest, ?string $parent_access, string $expected_access, ?string $expected_access_message = NULL): void {
|
||||
/** @var \Drupal\Core\Entity\RevisionableStorageInterface $entityStorage */
|
||||
$entityStorage = \Drupal::entityTypeManager()->getStorage('block_content');
|
||||
|
||||
$loadRevisionId = NULL;
|
||||
if (!$isLatest) {
|
||||
// Save a historical revision, then setup for a new revision to be saved.
|
||||
$this->blockEntity->save();
|
||||
$loadRevisionId = $this->blockEntity->getRevisionId();
|
||||
$this->blockEntity = $entityStorage->createRevision($this->blockEntity);
|
||||
}
|
||||
|
||||
$published ? $this->blockEntity->setPublished() : $this->blockEntity->setUnpublished();
|
||||
$reusable ? $this->blockEntity->setReusable() : $this->blockEntity->setNonReusable();
|
||||
|
||||
$user = User::create([
|
||||
'name' => 'Someone',
|
||||
'mail' => 'hi@example.com',
|
||||
]);
|
||||
|
||||
if ($permissions) {
|
||||
foreach ($permissions as $permission) {
|
||||
$this->role->grantPermission($permission);
|
||||
}
|
||||
$this->role->save();
|
||||
}
|
||||
$user->addRole($this->role->id())->save();
|
||||
|
||||
if ($parent_access !== NULL) {
|
||||
$parent_entity = $this->prophesize(AccessibleInterface::class);
|
||||
$expected_parent_result = new ($parent_access)();
|
||||
$parent_entity->access($operation, $user, TRUE)
|
||||
->willReturn($expected_parent_result)
|
||||
->shouldBeCalled();
|
||||
|
||||
$this->blockEntity->setAccessDependency($parent_entity->reveal());
|
||||
|
||||
}
|
||||
$this->blockEntity->save();
|
||||
|
||||
// Reload a previous revision.
|
||||
if ($loadRevisionId !== NULL) {
|
||||
$this->blockEntity = $entityStorage->loadRevision($loadRevisionId);
|
||||
}
|
||||
|
||||
$result = $this->accessControlHandler->access($this->blockEntity, $operation, $user, TRUE);
|
||||
$this->assertInstanceOf($expected_access, $result);
|
||||
if ($expected_access_message !== NULL) {
|
||||
$this->assertInstanceOf(AccessResultReasonInterface::class, $result);
|
||||
$this->assertEquals($expected_access_message, $result->getReason());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testAccess().
|
||||
*/
|
||||
public static function providerTestAccess(): array {
|
||||
$cases = [
|
||||
'view:published:reusable' => [
|
||||
'view',
|
||||
TRUE,
|
||||
TRUE,
|
||||
[],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultAllowed::class,
|
||||
],
|
||||
'view:unpublished:reusable' => [
|
||||
'view',
|
||||
FALSE,
|
||||
TRUE,
|
||||
[],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultNeutral::class,
|
||||
],
|
||||
'view:unpublished:reusable:admin' => [
|
||||
'view',
|
||||
FALSE,
|
||||
TRUE,
|
||||
['access block library'],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultAllowed::class,
|
||||
],
|
||||
'view:unpublished:reusable:per-block-editor:basic' => [
|
||||
'view',
|
||||
FALSE,
|
||||
TRUE,
|
||||
['edit any basic block content'],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultNeutral::class,
|
||||
],
|
||||
'view:unpublished:reusable:per-block-editor:square' => [
|
||||
'view',
|
||||
FALSE,
|
||||
TRUE,
|
||||
['access block library', 'edit any basic block content'],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultAllowed::class,
|
||||
],
|
||||
'view:published:reusable:admin' => [
|
||||
'view',
|
||||
TRUE,
|
||||
TRUE,
|
||||
['access block library'],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultAllowed::class,
|
||||
],
|
||||
'view:published:reusable:per-block-editor:basic' => [
|
||||
'view',
|
||||
TRUE,
|
||||
TRUE,
|
||||
['access block library', 'edit any basic block content'],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultAllowed::class,
|
||||
],
|
||||
'view:published:reusable:per-block-editor:square' => [
|
||||
'view',
|
||||
TRUE,
|
||||
TRUE,
|
||||
['access block library', 'edit any square block content'],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultAllowed::class,
|
||||
],
|
||||
'view:published:non_reusable' => [
|
||||
'view',
|
||||
TRUE,
|
||||
FALSE,
|
||||
[],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultForbidden::class,
|
||||
],
|
||||
'view:published:non_reusable:parent_allowed' => [
|
||||
'view',
|
||||
TRUE,
|
||||
FALSE,
|
||||
[],
|
||||
TRUE,
|
||||
AccessResultAllowed::class,
|
||||
AccessResultAllowed::class,
|
||||
],
|
||||
'view:published:non_reusable:parent_neutral' => [
|
||||
'view',
|
||||
TRUE,
|
||||
FALSE,
|
||||
[],
|
||||
TRUE,
|
||||
AccessResultNeutral::class,
|
||||
AccessResultNeutral::class,
|
||||
],
|
||||
'view:published:non_reusable:parent_forbidden' => [
|
||||
'view',
|
||||
TRUE,
|
||||
FALSE,
|
||||
[],
|
||||
TRUE,
|
||||
AccessResultForbidden::class,
|
||||
AccessResultForbidden::class,
|
||||
],
|
||||
];
|
||||
foreach (['update', 'delete'] as $operation) {
|
||||
$label = $operation === 'update' ? 'edit' : 'delete';
|
||||
$cases += [
|
||||
$operation . ':published:reusable' => [
|
||||
$operation,
|
||||
TRUE,
|
||||
TRUE,
|
||||
[],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultNeutral::class,
|
||||
],
|
||||
$operation . ':unpublished:reusable' => [
|
||||
$operation,
|
||||
FALSE,
|
||||
TRUE,
|
||||
[],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultNeutral::class,
|
||||
],
|
||||
$operation . ':unpublished:reusable:admin' => [
|
||||
$operation,
|
||||
FALSE,
|
||||
TRUE,
|
||||
[$label . ' any square block content'],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultAllowed::class,
|
||||
],
|
||||
$operation . ':published:reusable:admin' => [
|
||||
$operation,
|
||||
TRUE,
|
||||
TRUE,
|
||||
[$label . ' any square block content'],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultAllowed::class,
|
||||
],
|
||||
$operation . ':published:non_reusable' => [
|
||||
$operation,
|
||||
TRUE,
|
||||
FALSE,
|
||||
[],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultForbidden::class,
|
||||
],
|
||||
$operation . ':published:non_reusable:parent_allowed' => [
|
||||
$operation,
|
||||
TRUE,
|
||||
FALSE,
|
||||
[],
|
||||
TRUE,
|
||||
AccessResultAllowed::class,
|
||||
AccessResultNeutral::class,
|
||||
],
|
||||
$operation . ':published:non_reusable:parent_neutral' => [
|
||||
$operation,
|
||||
TRUE,
|
||||
FALSE,
|
||||
[],
|
||||
TRUE,
|
||||
AccessResultNeutral::class,
|
||||
AccessResultNeutral::class,
|
||||
],
|
||||
$operation . ':published:non_reusable:parent_forbidden' => [
|
||||
$operation,
|
||||
TRUE,
|
||||
FALSE,
|
||||
[],
|
||||
TRUE,
|
||||
AccessResultForbidden::class,
|
||||
AccessResultForbidden::class,
|
||||
],
|
||||
$operation . ':unpublished:reusable:per-block-editor:basic' => [
|
||||
$operation,
|
||||
FALSE,
|
||||
TRUE,
|
||||
['edit any basic block content'],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultNeutral::class,
|
||||
],
|
||||
$operation . ':published:reusable:per-block-editor:basic' => [
|
||||
$operation,
|
||||
TRUE,
|
||||
TRUE,
|
||||
['edit any basic block content'],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultNeutral::class,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
$cases += [
|
||||
'update:unpublished:reusable:per-block-editor:square' => [
|
||||
'update',
|
||||
FALSE,
|
||||
TRUE,
|
||||
['edit any square block content'],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultAllowed::class,
|
||||
],
|
||||
'update:published:reusable:per-block-editor:square' => [
|
||||
'update',
|
||||
TRUE,
|
||||
TRUE,
|
||||
['edit any square block content'],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultAllowed::class,
|
||||
],
|
||||
];
|
||||
|
||||
$cases += [
|
||||
'delete:unpublished:reusable:per-block-editor:square' => [
|
||||
'delete',
|
||||
FALSE,
|
||||
TRUE,
|
||||
['edit any square block content'],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultNeutral::class,
|
||||
],
|
||||
'delete:published:reusable:per-block-editor:square' => [
|
||||
'delete',
|
||||
TRUE,
|
||||
TRUE,
|
||||
['edit any square block content'],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultNeutral::class,
|
||||
],
|
||||
];
|
||||
|
||||
// View all revisions:
|
||||
$cases['view all revisions:none'] = [
|
||||
'view all revisions',
|
||||
TRUE,
|
||||
TRUE,
|
||||
[],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultNeutral::class,
|
||||
];
|
||||
$cases['view all revisions:view any bundle history'] = [
|
||||
'view all revisions',
|
||||
TRUE,
|
||||
TRUE,
|
||||
['view any square block content history'],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultAllowed::class,
|
||||
];
|
||||
$cases['view all revisions:administer block content'] = [
|
||||
'view all revisions',
|
||||
TRUE,
|
||||
TRUE,
|
||||
['administer block content'],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultAllowed::class,
|
||||
];
|
||||
|
||||
// Revert revisions:
|
||||
$cases['revert:none:latest'] = [
|
||||
'revert',
|
||||
TRUE,
|
||||
TRUE,
|
||||
[],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultForbidden::class,
|
||||
];
|
||||
$cases['revert:none:historical'] = [
|
||||
'revert',
|
||||
TRUE,
|
||||
TRUE,
|
||||
[],
|
||||
FALSE,
|
||||
NULL,
|
||||
AccessResultNeutral::class,
|
||||
];
|
||||
$cases['revert:revert bundle:historical'] = [
|
||||
'revert',
|
||||
TRUE,
|
||||
TRUE,
|
||||
['revert any square block content revisions'],
|
||||
FALSE,
|
||||
NULL,
|
||||
AccessResultAllowed::class,
|
||||
];
|
||||
$cases['revert:administer block content:latest'] = [
|
||||
'revert',
|
||||
TRUE,
|
||||
TRUE,
|
||||
['administer block content'],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultForbidden::class,
|
||||
];
|
||||
$cases['revert:administer block content:historical'] = [
|
||||
'revert',
|
||||
TRUE,
|
||||
TRUE,
|
||||
['administer block content'],
|
||||
FALSE,
|
||||
NULL,
|
||||
AccessResultAllowed::class,
|
||||
];
|
||||
$cases['revert:revert bundle:historical:non reusable'] = [
|
||||
'revert',
|
||||
TRUE,
|
||||
FALSE,
|
||||
['revert any square block content revisions'],
|
||||
FALSE,
|
||||
NULL,
|
||||
AccessResultForbidden::class,
|
||||
'Block content must be reusable to use `revert` operation',
|
||||
];
|
||||
|
||||
// Delete revisions:
|
||||
$cases['delete revision:none:latest'] = [
|
||||
'delete revision',
|
||||
TRUE,
|
||||
TRUE,
|
||||
[],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultForbidden::class,
|
||||
];
|
||||
$cases['delete revision:none:historical'] = [
|
||||
'delete revision',
|
||||
TRUE,
|
||||
TRUE,
|
||||
[],
|
||||
FALSE,
|
||||
NULL,
|
||||
AccessResultNeutral::class,
|
||||
];
|
||||
$cases['delete revision:administer block content:latest'] = [
|
||||
'delete revision',
|
||||
TRUE,
|
||||
TRUE,
|
||||
['administer block content'],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultForbidden::class,
|
||||
];
|
||||
$cases['delete revision:administer block content:historical'] = [
|
||||
'delete revision',
|
||||
TRUE,
|
||||
TRUE,
|
||||
['administer block content'],
|
||||
FALSE,
|
||||
NULL,
|
||||
AccessResultAllowed::class,
|
||||
];
|
||||
$cases['delete revision:delete bundle:latest'] = [
|
||||
'delete revision',
|
||||
TRUE,
|
||||
TRUE,
|
||||
['administer block content'],
|
||||
TRUE,
|
||||
NULL,
|
||||
AccessResultForbidden::class,
|
||||
];
|
||||
$cases['delete revision:delete bundle:historical'] = [
|
||||
'delete revision',
|
||||
TRUE,
|
||||
TRUE,
|
||||
['delete any square block content revisions'],
|
||||
FALSE,
|
||||
NULL,
|
||||
AccessResultAllowed::class,
|
||||
];
|
||||
$cases['delete revision:delete bundle:historical:non reusable'] = [
|
||||
'delete revision',
|
||||
TRUE,
|
||||
FALSE,
|
||||
['delete any square block content revisions'],
|
||||
FALSE,
|
||||
NULL,
|
||||
AccessResultForbidden::class,
|
||||
'Block content must be reusable to use `delete revision` operation',
|
||||
];
|
||||
|
||||
return $cases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests revision log access.
|
||||
*/
|
||||
public function testRevisionLogAccess(): void {
|
||||
$admin = $this->createUser([
|
||||
'administer block content',
|
||||
'access content',
|
||||
]);
|
||||
$editor = $this->createUser([
|
||||
'access content',
|
||||
'access block library',
|
||||
'view any square block content history',
|
||||
]);
|
||||
$viewer = $this->createUser([
|
||||
'access content',
|
||||
]);
|
||||
|
||||
$this->assertTrue($this->blockEntity->get('revision_log')->access('view', $admin));
|
||||
$this->assertTrue($this->blockEntity->get('revision_log')->access('view', $editor));
|
||||
$this->assertFalse($this->blockEntity->get('revision_log')->access('view', $viewer));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Component\Plugin\PluginBase;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\Tests\block\Traits\BlockCreationTrait;
|
||||
|
||||
/**
|
||||
* Tests that deleting a block clears the cached definitions.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentDeletionTest extends KernelTestBase {
|
||||
|
||||
use BlockCreationTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block', 'block_content', 'field', 'system', 'text', 'user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('user');
|
||||
$this->installEntitySchema('block_content');
|
||||
$this->installConfig(['block_content']);
|
||||
$this->container->get('theme_installer')->install(['stark']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests deleting a block_content updates the discovered block plugin.
|
||||
*/
|
||||
public function testDeletingBlockContentShouldClearPluginCache(): void {
|
||||
// Create a block content type.
|
||||
$block_content_type = BlockContentType::create([
|
||||
'id' => 'spiffy',
|
||||
'label' => 'Very spiffy',
|
||||
'description' => "Provides a block type that increases your site's spiffy rating by upto 11%",
|
||||
]);
|
||||
$block_content_type->save();
|
||||
// And a block content entity.
|
||||
$block_content = BlockContent::create([
|
||||
'info' => 'Spiffy prototype',
|
||||
'type' => 'spiffy',
|
||||
]);
|
||||
$block_content->save();
|
||||
|
||||
// Make sure the block content provides a derivative block plugin in the
|
||||
// block repository.
|
||||
/** @var \Drupal\Core\Block\BlockManagerInterface $block_manager */
|
||||
$block_manager = $this->container->get('plugin.manager.block');
|
||||
$plugin_id = 'block_content' . PluginBase::DERIVATIVE_SEPARATOR . $block_content->uuid();
|
||||
$this->assertTrue($block_manager->hasDefinition($plugin_id));
|
||||
|
||||
// Now delete the block content entity.
|
||||
$block_content->delete();
|
||||
// The plugin should no longer exist.
|
||||
$this->assertFalse($block_manager->hasDefinition($plugin_id));
|
||||
|
||||
// Create another block content entity.
|
||||
$block_content = BlockContent::create([
|
||||
'info' => 'Spiffy prototype',
|
||||
'type' => 'spiffy',
|
||||
]);
|
||||
$block_content->save();
|
||||
|
||||
$plugin_id = 'block_content' . PluginBase::DERIVATIVE_SEPARATOR . $block_content->uuid();
|
||||
$block = $this->placeBlock($plugin_id, ['region' => 'content', 'theme' => 'stark']);
|
||||
|
||||
// Delete it via storage.
|
||||
$storage = $this->container->get('entity_type.manager')->getStorage('block_content');
|
||||
$storage->delete([$block_content]);
|
||||
// The plugin should no longer exist.
|
||||
$this->assertFalse($block_manager->hasDefinition($plugin_id));
|
||||
|
||||
$this->assertNull($this->container->get('entity_type.manager')->getStorage('block')->loadUnchanged($block->id()));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\block_content\Plugin\Derivative\BlockContent as DerivativeBlockContent;
|
||||
use Drupal\Component\Plugin\PluginBase;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests block content plugin deriver.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentDeriverTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block', 'block_content', 'system', 'user'];
|
||||
|
||||
/**
|
||||
* The definition array of the base plugin.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $baseDefinition = [
|
||||
'id' => 'block_content',
|
||||
'provider' => 'block_content',
|
||||
'class' => '\Drupal\block_content\Plugin\Block\BlockContentBlock',
|
||||
'deriver' => '\Drupal\block_content\Plugin\Derivative\BlockContent',
|
||||
];
|
||||
|
||||
/**
|
||||
* The block content storage.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
*/
|
||||
protected $blockContentStorage;
|
||||
|
||||
/**
|
||||
* The tested block content derivative class.
|
||||
*
|
||||
* @var \Drupal\block_content\Plugin\Derivative\BlockContent
|
||||
*/
|
||||
protected $blockContentDerivative;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('user');
|
||||
$this->installEntitySchema('block_content');
|
||||
|
||||
$this->blockContentStorage = \Drupal::entityTypeManager()->getStorage('block_content');
|
||||
$this->blockContentDerivative = new DerivativeBlockContent($this->blockContentStorage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that only reusable blocks are derived.
|
||||
*/
|
||||
public function testReusableBlocksOnlyAreDerived(): void {
|
||||
// Create a block content type.
|
||||
$block_content_type = BlockContentType::create([
|
||||
'id' => 'spiffy',
|
||||
'label' => 'Very spiffy',
|
||||
'description' => "Provides a block type that increases your site's spiffy rating by up to 11%",
|
||||
]);
|
||||
$block_content_type->save();
|
||||
// And a block content entity.
|
||||
$block_content = BlockContent::create([
|
||||
'info' => 'Spiffy prototype',
|
||||
'type' => 'spiffy',
|
||||
]);
|
||||
$block_content->save();
|
||||
|
||||
// Ensure the reusable block content is provided as a derivative block
|
||||
// plugin.
|
||||
/** @var \Drupal\Core\Block\BlockManagerInterface $block_manager */
|
||||
$block_manager = $this->container->get('plugin.manager.block');
|
||||
$plugin_id = 'block_content' . PluginBase::DERIVATIVE_SEPARATOR . $block_content->uuid();
|
||||
$this->assertTrue($block_manager->hasDefinition($plugin_id));
|
||||
|
||||
// Set the block not to be reusable.
|
||||
$block_content->setNonReusable();
|
||||
$block_content->save();
|
||||
|
||||
// Ensure the non-reusable block content is not provided a derivative block
|
||||
// plugin.
|
||||
$this->assertFalse($block_manager->hasDefinition($plugin_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the admin labels of derivative definitions.
|
||||
*/
|
||||
public function testGetDerivativeDefinitionsAdminLabels(): void {
|
||||
$blockContentType = BlockContentType::create([
|
||||
'id' => 'basic',
|
||||
'label' => 'Basic Block',
|
||||
]);
|
||||
$blockContentType->save();
|
||||
$blockContentWithLabel = BlockContent::create([
|
||||
'info' => 'Basic prototype',
|
||||
'type' => 'basic',
|
||||
]);
|
||||
$blockContentWithLabel->save();
|
||||
$blockContentNoLabel = BlockContent::create([
|
||||
'type' => 'basic',
|
||||
]);
|
||||
$blockContentNoLabel->save();
|
||||
|
||||
$blockPluginManager = \Drupal::service('plugin.manager.block');
|
||||
$plugin = $blockPluginManager->createInstance('block_content:' . $blockContentWithLabel->uuid());
|
||||
$this->assertEquals('Basic prototype', $plugin->getPluginDefinition()['admin_label']);
|
||||
|
||||
$plugin = $blockPluginManager->createInstance('block_content:' . $blockContentNoLabel->uuid());
|
||||
$this->assertEquals('Basic Block: ' . $blockContentNoLabel->id(), $plugin->getPluginDefinition()['admin_label']);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,195 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\block_content_test\Plugin\EntityReferenceSelection\TestSelection;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests EntityReference selection handlers don't return non-reusable blocks.
|
||||
*
|
||||
* @see block_content_query_entity_reference_alter()
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentEntityReferenceSelectionTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'block',
|
||||
'block_content',
|
||||
'block_content_test',
|
||||
'system',
|
||||
'user',
|
||||
];
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* Test reusable block.
|
||||
*
|
||||
* @var \Drupal\block_content\BlockContentInterface
|
||||
*/
|
||||
protected $blockReusable;
|
||||
|
||||
/**
|
||||
* Test non-reusable block.
|
||||
*
|
||||
* @var \Drupal\block_content\BlockContentInterface
|
||||
*/
|
||||
protected $blockNonReusable;
|
||||
|
||||
/**
|
||||
* Test selection handler.
|
||||
*
|
||||
* @var \Drupal\block_content_test\Plugin\EntityReferenceSelection\TestSelection
|
||||
*/
|
||||
protected $selectionHandler;
|
||||
|
||||
/**
|
||||
* Test block expectations.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $expectations;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('user');
|
||||
$this->installEntitySchema('block_content');
|
||||
|
||||
// Create a block content type.
|
||||
$block_content_type = BlockContentType::create([
|
||||
'id' => 'spiffy',
|
||||
'label' => 'Very spiffy',
|
||||
'description' => "Provides a block type that increases your site's spiffy rating by up to 11%",
|
||||
]);
|
||||
$block_content_type->save();
|
||||
$this->entityTypeManager = $this->container->get('entity_type.manager');
|
||||
|
||||
// And reusable block content entities.
|
||||
$this->blockReusable = BlockContent::create([
|
||||
'info' => 'Reusable Block',
|
||||
'type' => 'spiffy',
|
||||
]);
|
||||
$this->blockReusable->save();
|
||||
$this->blockNonReusable = BlockContent::create([
|
||||
'info' => 'Non-reusable Block',
|
||||
'type' => 'spiffy',
|
||||
'reusable' => FALSE,
|
||||
]);
|
||||
$this->blockNonReusable->save();
|
||||
|
||||
$configuration = [
|
||||
'target_type' => 'block_content',
|
||||
'target_bundles' => ['spiffy' => 'spiffy'],
|
||||
'sort' => ['field' => '_none'],
|
||||
];
|
||||
$this->selectionHandler = new TestSelection($configuration, '', '', $this->container->get('entity_type.manager'), $this->container->get('module_handler'), \Drupal::currentUser(), \Drupal::service('entity_field.manager'), \Drupal::service('entity_type.bundle.info'), \Drupal::service('entity.repository'));
|
||||
|
||||
// Setup the 3 expectation cases.
|
||||
$this->expectations = [
|
||||
'both_blocks' => [
|
||||
'spiffy' => [
|
||||
$this->blockReusable->id() => $this->blockReusable->label(),
|
||||
$this->blockNonReusable->id() => $this->blockNonReusable->label(),
|
||||
],
|
||||
],
|
||||
'block_reusable' => ['spiffy' => [$this->blockReusable->id() => $this->blockReusable->label()]],
|
||||
'block_non_reusable' => ['spiffy' => [$this->blockNonReusable->id() => $this->blockNonReusable->label()]],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests to make sure queries without the expected tags are not altered.
|
||||
*
|
||||
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
|
||||
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
|
||||
*/
|
||||
public function testQueriesNotAltered(): void {
|
||||
// Ensure that queries without all the tags are not altered.
|
||||
$query = $this->entityTypeManager->getStorage('block_content')
|
||||
->getQuery()
|
||||
->accessCheck(FALSE);
|
||||
$this->assertCount(2, $query->execute());
|
||||
|
||||
$query = $this->entityTypeManager->getStorage('block_content')
|
||||
->getQuery()
|
||||
->accessCheck(FALSE);
|
||||
$query->addTag('block_content_access');
|
||||
$this->assertCount(2, $query->execute());
|
||||
|
||||
$query = $this->entityTypeManager->getStorage('block_content')
|
||||
->getQuery()
|
||||
->accessCheck(FALSE);
|
||||
$query->addTag('entity_query_block_content');
|
||||
$this->assertCount(2, $query->execute());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests with no conditions set.
|
||||
*
|
||||
* @throws \Drupal\Core\Entity\EntityStorageException
|
||||
*/
|
||||
public function testNoConditions(): void {
|
||||
$this->assertEquals(
|
||||
$this->expectations['block_reusable'],
|
||||
$this->selectionHandler->getReferenceableEntities()
|
||||
);
|
||||
|
||||
$this->blockNonReusable->setReusable();
|
||||
$this->blockNonReusable->save();
|
||||
|
||||
// Ensure that the block is now returned as a referenceable entity.
|
||||
$this->assertEquals(
|
||||
$this->expectations['both_blocks'],
|
||||
$this->selectionHandler->getReferenceableEntities()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests setting 'reusable' condition on different levels.
|
||||
*
|
||||
* @dataProvider fieldConditionProvider
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testFieldConditions($condition_type, $is_reusable): void {
|
||||
$this->selectionHandler->setTestMode($condition_type, $is_reusable);
|
||||
$this->assertEquals(
|
||||
$is_reusable ? $this->expectations['block_reusable'] : $this->expectations['block_non_reusable'],
|
||||
$this->selectionHandler->getReferenceableEntities()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides possible fields and condition types.
|
||||
*/
|
||||
public static function fieldConditionProvider() {
|
||||
$cases = [];
|
||||
foreach (['base', 'group', 'nested_group'] as $condition_type) {
|
||||
foreach ([TRUE, FALSE] as $reusable) {
|
||||
$cases["$condition_type:" . ($reusable ? 'reusable' : 'non-reusable')] = [
|
||||
$condition_type,
|
||||
$reusable,
|
||||
];
|
||||
}
|
||||
}
|
||||
return $cases;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel;
|
||||
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
|
||||
/**
|
||||
* Tests the permissions of content blocks.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\block_content\BlockContentPermissions
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentPermissionsTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'block',
|
||||
'block_content',
|
||||
'block_content_test',
|
||||
'system',
|
||||
'user',
|
||||
];
|
||||
|
||||
/**
|
||||
* The permission handler.
|
||||
*
|
||||
* @var \Drupal\user\PermissionHandlerInterface
|
||||
*/
|
||||
protected $permissionHandler;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('user');
|
||||
$this->installEntitySchema('block_content');
|
||||
|
||||
$this->permissionHandler = $this->container->get('user.permissions');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::blockTypePermissions
|
||||
*/
|
||||
public function testDynamicPermissions(): void {
|
||||
$permissions = $this->permissionHandler->getPermissions();
|
||||
$this->assertArrayNotHasKey('edit any basic block content', $permissions, 'The per-block-type permission does not exist.');
|
||||
$this->assertArrayNotHasKey('edit any square block content', $permissions, 'The per-block-type permission does not exist.');
|
||||
|
||||
// Create a basic block content type.
|
||||
BlockContentType::create([
|
||||
'id' => 'basic',
|
||||
'label' => 'A basic block type',
|
||||
'description' => 'Provides a basic block type',
|
||||
])->save();
|
||||
|
||||
// Create a square block content type.
|
||||
BlockContentType::create([
|
||||
'id' => 'square',
|
||||
'label' => 'A square block type',
|
||||
'description' => 'Provides a block type that is square',
|
||||
])->save();
|
||||
|
||||
$permissions = $this->permissionHandler->getPermissions();
|
||||
|
||||
// Assert the basic permission has been created.
|
||||
$this->assertArrayHasKey('edit any basic block content', $permissions, 'The per-block-type permission exists.');
|
||||
$this->assertEquals(
|
||||
'<em class="placeholder">A basic block type</em>: Edit content block',
|
||||
$permissions['edit any basic block content']['title']->render()
|
||||
);
|
||||
|
||||
// Assert the square permission has been created.
|
||||
$this->assertArrayHasKey('edit any square block content', $permissions, 'The per-block-type permission exists.');
|
||||
$this->assertEquals(
|
||||
'<em class="placeholder">A square block type</em>: Edit content block',
|
||||
$permissions['edit any square block content']['title']->render()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
|
||||
/**
|
||||
* Tests revision based functions for Block Content.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentRevisionsTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'block',
|
||||
'block_content',
|
||||
'system',
|
||||
'user',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('user');
|
||||
$this->installEntitySchema('block_content');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests block content revision user id doesn't throw error with null field.
|
||||
*/
|
||||
public function testNullRevisionUser(): void {
|
||||
BlockContentType::create([
|
||||
'id' => 'basic',
|
||||
'label' => 'A basic block type',
|
||||
])->save();
|
||||
|
||||
$block = BlockContent::create([
|
||||
'info' => 'Test',
|
||||
'type' => 'basic',
|
||||
'revision_user' => NULL,
|
||||
]);
|
||||
$block->save();
|
||||
$this->assertNull($block->getRevisionUserId());
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel;
|
||||
|
||||
use Drupal\block\Entity\Block;
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Component\Plugin\PluginBase;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\Tests\user\Traits\UserCreationTrait;
|
||||
use Drupal\block_content\Hook\BlockContentHooks;
|
||||
|
||||
/**
|
||||
* Tests the block content.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentTest extends KernelTestBase {
|
||||
|
||||
use UserCreationTrait;
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block', 'block_content', 'system', 'user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('user');
|
||||
$this->installEntitySchema('block_content');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the editing links for BlockContentBlock.
|
||||
*/
|
||||
public function testOperationLinks(): void {
|
||||
// Create a block content type.
|
||||
BlockContentType::create([
|
||||
'id' => 'spiffy',
|
||||
'label' => 'Very spiffy',
|
||||
'description' => "Provides a block type that increases your site's spiffy rating by up to 11%",
|
||||
])->save();
|
||||
// And a block content entity.
|
||||
$block_content = BlockContent::create([
|
||||
'info' => 'Spiffy prototype',
|
||||
'type' => 'spiffy',
|
||||
]);
|
||||
$block_content->save();
|
||||
$block = Block::create([
|
||||
'plugin' => 'block_content' . PluginBase::DERIVATIVE_SEPARATOR . $block_content->uuid(),
|
||||
'region' => 'content',
|
||||
'id' => 'machine_name',
|
||||
'theme' => 'stark',
|
||||
]);
|
||||
|
||||
// The anonymous user doesn't have the "administer block" permission.
|
||||
$blockContentEntityOperation = new BlockContentHooks();
|
||||
$this->assertEmpty($blockContentEntityOperation->entityOperation($block));
|
||||
|
||||
$this->setUpCurrentUser(['uid' => 1], ['edit any spiffy block content', 'administer blocks']);
|
||||
|
||||
// The admin user does have the "administer block" permission.
|
||||
$this->assertEquals([
|
||||
'block-edit' => [
|
||||
'title' => 'Edit block',
|
||||
'url' => $block_content->toUrl('edit-form')->setOptions([]),
|
||||
'weight' => 50,
|
||||
],
|
||||
], $blockContentEntityOperation->entityOperation($block));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
|
||||
/**
|
||||
* Tests validation of block_content_type entities.
|
||||
*
|
||||
* @group block_content
|
||||
* @group #slow
|
||||
*/
|
||||
class BlockContentTypeValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block_content'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static array $propertiesWithOptionalValues = ['description'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->entity = BlockContentType::create([
|
||||
'id' => 'test',
|
||||
'label' => 'Test',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel;
|
||||
|
||||
use Drupal\block\Entity\Block;
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\block_content\Hook\BlockContentHooks;
|
||||
|
||||
/**
|
||||
* Tests the block_content_theme_suggestions_block() function.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockTemplateSuggestionsTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'user',
|
||||
'block',
|
||||
'block_content',
|
||||
'system',
|
||||
];
|
||||
|
||||
/**
|
||||
* The BlockContent entity used for testing.
|
||||
*
|
||||
* @var \Drupal\block_content\Entity\BlockContent
|
||||
*/
|
||||
protected $blockContent;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->installEntitySchema('block_content');
|
||||
|
||||
// Create a block content type.
|
||||
$block_content_type = BlockContentType::create([
|
||||
'id' => 'test_block',
|
||||
'label' => 'A test block type',
|
||||
'description' => "Provides a test block type.",
|
||||
]);
|
||||
$block_content_type->save();
|
||||
|
||||
$this->blockContent = BlockContent::create([
|
||||
'info' => 'The Test Block',
|
||||
'type' => 'test_block',
|
||||
]);
|
||||
$this->blockContent->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests template suggestions from block_content_theme_suggestions_block().
|
||||
*/
|
||||
public function testBlockThemeHookSuggestions(): void {
|
||||
// Create a block using a block_content plugin.
|
||||
$block = Block::create([
|
||||
'plugin' => 'block_content:' . $this->blockContent->uuid(),
|
||||
'region' => 'footer',
|
||||
'id' => 'machine_name',
|
||||
]);
|
||||
|
||||
$variables['elements']['#id'] = $block->id();
|
||||
$variables['elements']['content']['#block_content'] = $this->blockContent;
|
||||
$variables['elements']['content']['#view_mode'] = 'full';
|
||||
$suggestions = [];
|
||||
$suggestions[] = 'block__block_content__' . $block->uuid();
|
||||
$blockTemplateSuggestionsAlter = new BlockContentHooks();
|
||||
$blockTemplateSuggestionsAlter->themeSuggestionsBlockAlter($suggestions, $variables);
|
||||
|
||||
$this->assertSame([
|
||||
'block__block_content__' . $block->uuid(),
|
||||
'block__block_content__view__full',
|
||||
'block__block_content__type__test_block',
|
||||
'block__block_content__view_type__test_block__full',
|
||||
'block__block_content__id__machine_name',
|
||||
'block__block_content__id_view__machine_name__full',
|
||||
], $suggestions);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Migrate;
|
||||
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\field\FieldConfigInterface;
|
||||
use Drupal\field\FieldStorageConfigInterface;
|
||||
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
|
||||
|
||||
/**
|
||||
* Attaches a body field to the block type.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class MigrateBlockContentBodyFieldTest extends MigrateDrupal7TestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block', 'block_content', 'filter', 'text'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('block_content');
|
||||
$this->installConfig(['block_content']);
|
||||
$this->executeMigrations([
|
||||
'block_content_type',
|
||||
'block_content_body_field',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the block content body field migration.
|
||||
*/
|
||||
public function testBlockContentBodyFieldMigration(): void {
|
||||
/** @var \Drupal\field\FieldStorageConfigInterface $storage */
|
||||
$storage = FieldStorageConfig::load('block_content.body');
|
||||
$this->assertInstanceOf(FieldStorageConfigInterface::class, $storage);
|
||||
$this->assertSame('block_content', $storage->getTargetEntityTypeId());
|
||||
$this->assertSame(['basic'], array_values($storage->getBundles()));
|
||||
$this->assertSame('body', $storage->getName());
|
||||
|
||||
/** @var \Drupal\field\FieldConfigInterface $field */
|
||||
$field = FieldConfig::load('block_content.basic.body');
|
||||
$this->assertInstanceOf(FieldConfigInterface::class, $field);
|
||||
$this->assertSame('block_content', $field->getTargetEntityTypeId());
|
||||
$this->assertSame('basic', $field->getTargetBundle());
|
||||
$this->assertSame('body', $field->getName());
|
||||
$this->assertSame('Body', $field->getLabel());
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Migrate;
|
||||
|
||||
use Drupal\Core\Entity\Entity\EntityViewDisplay;
|
||||
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
|
||||
|
||||
/**
|
||||
* Tests migration of block content body field display configuration.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class MigrateBlockContentEntityDisplayTest extends MigrateDrupal7TestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block', 'block_content', 'filter', 'text'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('block_content');
|
||||
$this->installConfig(static::$modules);
|
||||
$this->executeMigrations([
|
||||
'block_content_type',
|
||||
'block_content_body_field',
|
||||
'block_content_entity_display',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts a display entity.
|
||||
*
|
||||
* @param string $id
|
||||
* The entity ID.
|
||||
* @param string $component_id
|
||||
* The ID of the display component.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function assertDisplay(string $id, string $component_id): void {
|
||||
$component = EntityViewDisplay::load($id)->getComponent($component_id);
|
||||
$this->assertIsArray($component);
|
||||
$this->assertSame('hidden', $component['label']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the migrated display configuration.
|
||||
*/
|
||||
public function testMigration(): void {
|
||||
$this->assertDisplay('block_content.basic.default', 'body');
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Migrate;
|
||||
|
||||
use Drupal\Core\Entity\Entity\EntityFormDisplay;
|
||||
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
|
||||
|
||||
/**
|
||||
* Tests migration of block content body field form display configuration.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class MigrateBlockContentEntityFormDisplayTest extends MigrateDrupal7TestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block', 'block_content', 'filter', 'text'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('block_content');
|
||||
$this->installConfig(static::$modules);
|
||||
$this->executeMigrations([
|
||||
'block_content_type',
|
||||
'block_content_body_field',
|
||||
'block_content_entity_form_display',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts a display entity.
|
||||
*
|
||||
* @param string $id
|
||||
* The entity ID.
|
||||
* @param string $component_id
|
||||
* The ID of the form component.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function assertDisplay(string $id, string $component_id): void {
|
||||
$component = EntityFormDisplay::load($id)->getComponent($component_id);
|
||||
$this->assertIsArray($component);
|
||||
$this->assertSame('text_textarea_with_summary', $component['type']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the migrated display configuration.
|
||||
*/
|
||||
public function testMigration(): void {
|
||||
$this->assertDisplay('block_content.basic.default', 'body');
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Migrate;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\migrate\MigrateException;
|
||||
use Drupal\Tests\migrate_drupal\Kernel\MigrateDrupalTestBase;
|
||||
use Drupal\migrate_drupal\Tests\StubTestTrait;
|
||||
|
||||
/**
|
||||
* Test stub creation for block_content entities.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class MigrateBlockContentStubTest extends MigrateDrupalTestBase {
|
||||
|
||||
use StubTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block_content'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('block_content');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests creation of block content stubs with no block_content_type available.
|
||||
*/
|
||||
public function testStubFailure(): void {
|
||||
// Expected MigrateException thrown when no bundles exist.
|
||||
$this->expectException(MigrateException::class);
|
||||
$this->expectExceptionMessage('Stubbing failed, no bundles available for entity type: block_content');
|
||||
$this->createEntityStub('block_content');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests creation of block content stubs when there is a block_content_type.
|
||||
*/
|
||||
public function testStubSuccess(): void {
|
||||
BlockContentType::create([
|
||||
'id' => 'test_block_content_type',
|
||||
'label' => 'Test block content type',
|
||||
])->save();
|
||||
$this->performStubTest('block_content');
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Migrate;
|
||||
|
||||
use Drupal\block_content\BlockContentTypeInterface;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
|
||||
|
||||
/**
|
||||
* Tests migration of the basic block content type.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class MigrateBlockContentTypeTest extends MigrateDrupal7TestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block', 'block_content', 'filter', 'text'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('block_content');
|
||||
$this->installConfig(['block_content']);
|
||||
$this->executeMigration('block_content_type');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the block content type migration.
|
||||
*/
|
||||
public function testBlockContentTypeMigration(): void {
|
||||
/** @var \Drupal\block_content\BlockContentTypeInterface $entity */
|
||||
$entity = BlockContentType::load('basic');
|
||||
$this->assertInstanceOf(BlockContentTypeInterface::class, $entity);
|
||||
$this->assertSame('Basic', $entity->label());
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Migrate\d6;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
|
||||
|
||||
/**
|
||||
* Upgrade content blocks.
|
||||
*
|
||||
* @group migrate_drupal_6
|
||||
*/
|
||||
class MigrateBlockContentTest extends MigrateDrupal6TestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block', 'block_content'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('block_content');
|
||||
$this->installConfig(['block_content']);
|
||||
|
||||
$this->executeMigrations([
|
||||
'd6_filter_format',
|
||||
'block_content_type',
|
||||
'block_content_body_field',
|
||||
'd6_custom_block',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the Drupal 6 content block to Drupal 8 migration.
|
||||
*/
|
||||
public function testBlockMigration(): void {
|
||||
/** @var \Drupal\block_content\Entity\BlockContent $block */
|
||||
$block = BlockContent::load(1);
|
||||
$this->assertSame('My block 1', $block->label());
|
||||
$requestTime = \Drupal::time()->getRequestTime();
|
||||
$this->assertGreaterThanOrEqual($requestTime, (int) $block->getChangedTime());
|
||||
$this->assertLessThanOrEqual(time(), $block->getChangedTime());
|
||||
$this->assertSame('en', $block->language()->getId());
|
||||
$this->assertSame('<h3>My first content block body</h3>', $block->body->value);
|
||||
$this->assertSame('full_html', $block->body->format);
|
||||
|
||||
$block = BlockContent::load(2);
|
||||
$this->assertSame('My block 2', $block->label());
|
||||
$this->assertGreaterThanOrEqual($requestTime, (int) $block->getChangedTime());
|
||||
$this->assertGreaterThanOrEqual($requestTime, (int) $block->getChangedTime());
|
||||
$this->assertLessThanOrEqual(time(), $block->getChangedTime());
|
||||
$this->assertSame('en', $block->language()->getId());
|
||||
$this->assertSame('<h3>My second content block body</h3>', $block->body->value);
|
||||
$this->assertSame('full_html', $block->body->format);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Migrate\d6;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
|
||||
|
||||
/**
|
||||
* Tests migration of i18n content block strings.
|
||||
*
|
||||
* @group migrate_drupal_6
|
||||
*/
|
||||
class MigrateCustomBlockContentTranslationTest extends MigrateDrupal6TestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'block_content',
|
||||
'content_translation',
|
||||
'language',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('block_content');
|
||||
$this->installConfig(['block_content']);
|
||||
$this->executeMigrations([
|
||||
'language',
|
||||
'd6_filter_format',
|
||||
'block_content_type',
|
||||
'block_content_body_field',
|
||||
'd6_custom_block',
|
||||
'd6_custom_block_translation',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the Drupal 6 i18n content block strings to Drupal 8 migration.
|
||||
*/
|
||||
public function testCustomBlockContentTranslation(): void {
|
||||
/** @var \Drupal\block_content\Entity\BlockContent $block */
|
||||
$block = BlockContent::load(1)->getTranslation('fr');
|
||||
$this->assertSame('fr - Static Block', $block->label());
|
||||
$this->assertGreaterThanOrEqual(\Drupal::time()->getRequestTime(), $block->getChangedTime());
|
||||
$this->assertLessThanOrEqual(time(), $block->getChangedTime());
|
||||
$this->assertSame('fr', $block->language()->getId());
|
||||
$this->assertSame('<h3>fr - My first content block body</h3>', $block->body->value);
|
||||
$this->assertSame('full_html', $block->body->format);
|
||||
|
||||
$block = $block->getTranslation('zu');
|
||||
$this->assertSame('My block 1', $block->label());
|
||||
$this->assertGreaterThanOrEqual(\Drupal::time()->getRequestTime(), $block->getChangedTime());
|
||||
$this->assertLessThanOrEqual(time(), $block->getChangedTime());
|
||||
$this->assertSame('zu', $block->language()->getId());
|
||||
$this->assertSame('<h3>zu - My first content block body</h3>', $block->body->value);
|
||||
$this->assertSame('full_html', $block->body->format);
|
||||
|
||||
$block = BlockContent::load(2)->getTranslation('fr');
|
||||
$this->assertSame('Encore un bloc statique', $block->label());
|
||||
$this->assertGreaterThanOrEqual(\Drupal::time()->getRequestTime(), $block->getChangedTime());
|
||||
$this->assertLessThanOrEqual(time(), $block->getChangedTime());
|
||||
$this->assertSame('fr', $block->language()->getId());
|
||||
$this->assertSame('Nom de vocabulaire beaucoup plus long que trente-deux caractères', $block->body->value);
|
||||
$this->assertSame('full_html', $block->body->format);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Migrate\d7;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
|
||||
|
||||
/**
|
||||
* Tests migration of i18n content block strings.
|
||||
*
|
||||
* @group migrate_drupal_7
|
||||
*/
|
||||
class MigrateCustomBlockContentTranslationTest extends MigrateDrupal7TestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'block_content',
|
||||
'content_translation',
|
||||
'filter',
|
||||
'language',
|
||||
'text',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('block_content');
|
||||
$this->installConfig(['block_content']);
|
||||
$this->executeMigrations([
|
||||
'language',
|
||||
'd7_filter_format',
|
||||
'block_content_type',
|
||||
'block_content_body_field',
|
||||
'd7_custom_block',
|
||||
'd7_custom_block_translation',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the Drupal 7 i18n content block strings to Drupal 8 migration.
|
||||
*/
|
||||
public function testCustomBlockContentTranslation(): void {
|
||||
/** @var \Drupal\block_content\Entity\BlockContent $block */
|
||||
$block = BlockContent::load(1)->getTranslation('fr');
|
||||
$this->assertSame('fr - Mildly amusing limerick of the day', $block->label());
|
||||
$this->assertGreaterThanOrEqual($block->getChangedTime(), \Drupal::time()->getRequestTime());
|
||||
$this->assertLessThanOrEqual(time(), $block->getChangedTime());
|
||||
$this->assertSame('fr', $block->language()->getId());
|
||||
$translation = "fr - A fellow jumped off a high wall\r\nAnd had a most terrible fall\r\nHe went back to bed\r\nWith a bump on his head\r\nThat's why you don't jump off a wall";
|
||||
$this->assertSame($translation, $block->body->value);
|
||||
$this->assertSame('filtered_html', $block->body->format);
|
||||
|
||||
$block = $block->getTranslation('is');
|
||||
$this->assertSame('is - Mildly amusing limerick of the day', $block->label());
|
||||
$this->assertGreaterThanOrEqual($block->getChangedTime(), \Drupal::time()->getRequestTime());
|
||||
$this->assertLessThanOrEqual(time(), $block->getChangedTime());
|
||||
$this->assertSame('is', $block->language()->getId());
|
||||
$text = "A fellow jumped off a high wall\r\nAnd had a most terrible fall\r\nHe went back to bed\r\nWith a bump on his head\r\nThat's why you don't jump off a wall";
|
||||
$this->assertSame($text, $block->body->value);
|
||||
$this->assertSame('filtered_html', $block->body->format);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Migrate\d7;
|
||||
|
||||
use Drupal\block_content\BlockContentInterface;
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
|
||||
|
||||
/**
|
||||
* Tests migration of content blocks.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class MigrateCustomBlockTest extends MigrateDrupal7TestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'block_content',
|
||||
'filter',
|
||||
'text',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('block_content');
|
||||
$this->installConfig(static::$modules);
|
||||
|
||||
$this->executeMigrations([
|
||||
'd7_filter_format',
|
||||
'block_content_type',
|
||||
'block_content_body_field',
|
||||
'd7_custom_block',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests migration of content blocks from Drupal 7 to Drupal 8.
|
||||
*/
|
||||
public function testCustomBlockMigration(): void {
|
||||
$block = BlockContent::load(1);
|
||||
$this->assertInstanceOf(BlockContentInterface::class, $block);
|
||||
/** @var \Drupal\block_content\BlockContentInterface $block */
|
||||
$this->assertSame('Limerick', $block->label());
|
||||
|
||||
$expected_body = "A fellow jumped off a high wall\r\nAnd had a most terrible fall\r\nHe went back to bed\r\nWith a bump on his head\r\nThat's why you don't jump off a wall";
|
||||
$this->assertSame($expected_body, $block->body->value);
|
||||
$this->assertSame('filtered_html', $block->body->format);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests D6 block boxes source plugin.
|
||||
*
|
||||
* @covers \Drupal\block_content\Plugin\migrate\source\d6\Box
|
||||
* @group block_content
|
||||
*/
|
||||
class BoxTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block_content', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
$tests[0]['source_data']['boxes'] = [
|
||||
[
|
||||
'bid' => 1,
|
||||
'body' => '<p>I made some custom content.</p>',
|
||||
'info' => 'Static Block',
|
||||
'format' => 1,
|
||||
],
|
||||
[
|
||||
'bid' => 2,
|
||||
'body' => '<p>I made some more custom content.</p>',
|
||||
'info' => 'Test Content',
|
||||
'format' => 1,
|
||||
],
|
||||
];
|
||||
// The expected results are identical to the source data.
|
||||
$tests[0]['expected_data'] = $tests[0]['source_data']['boxes'];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
// cspell:ignore objectid objectindex plid
|
||||
|
||||
/**
|
||||
* Tests i18n content block translations source plugin.
|
||||
*
|
||||
* @covers \Drupal\block_content\Plugin\migrate\source\d6\BoxTranslation
|
||||
*
|
||||
* @group content_translation
|
||||
*/
|
||||
class BoxTranslationTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block_content', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
// The source data.
|
||||
$tests[0]['source_data']['boxes'] = [
|
||||
[
|
||||
'bid' => 1,
|
||||
'body' => 'box 1 body',
|
||||
'info' => 'box 1 title',
|
||||
'format' => '2',
|
||||
],
|
||||
[
|
||||
'bid' => 2,
|
||||
'body' => 'box 2 body',
|
||||
'info' => 'box 2 title',
|
||||
'format' => '2',
|
||||
],
|
||||
];
|
||||
|
||||
$tests[0]['source_data']['i18n_strings'] = [
|
||||
[
|
||||
'lid' => 1,
|
||||
'objectid' => 1,
|
||||
'type' => 'block',
|
||||
'property' => 'title',
|
||||
'objectindex' => 1,
|
||||
'format' => 0,
|
||||
],
|
||||
[
|
||||
'lid' => 2,
|
||||
'objectid' => 1,
|
||||
'type' => 'block',
|
||||
'property' => 'body',
|
||||
'objectindex' => 1,
|
||||
'format' => 0,
|
||||
],
|
||||
[
|
||||
'lid' => 3,
|
||||
'objectid' => 2,
|
||||
'type' => 'block',
|
||||
'property' => 'body',
|
||||
'objectindex' => 2,
|
||||
'format' => 2,
|
||||
],
|
||||
];
|
||||
|
||||
$tests[0]['source_data']['locales_target'] = [
|
||||
[
|
||||
'lid' => 1,
|
||||
'language' => 'fr',
|
||||
'translation' => 'fr - title translation',
|
||||
'plid' => 0,
|
||||
'plural' => 0,
|
||||
'i18n_status' => 0,
|
||||
],
|
||||
[
|
||||
'lid' => 2,
|
||||
'language' => 'fr',
|
||||
'translation' => 'fr - body translation',
|
||||
'plid' => 0,
|
||||
'plural' => 0,
|
||||
'i18n_status' => 0,
|
||||
],
|
||||
[
|
||||
'lid' => 3,
|
||||
'language' => 'zu',
|
||||
'translation' => 'zu - body translation',
|
||||
'plid' => 0,
|
||||
'plural' => 0,
|
||||
'i18n_status' => 0,
|
||||
],
|
||||
];
|
||||
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'lid' => '1',
|
||||
'property' => 'title',
|
||||
'language' => 'fr',
|
||||
'translation' => 'fr - title translation',
|
||||
'bid' => '1',
|
||||
'format' => '2',
|
||||
'title_translated' => 'fr - title translation',
|
||||
'body_translated' => 'fr - body translation',
|
||||
'title' => 'box 1 title',
|
||||
'body' => 'box 1 body',
|
||||
],
|
||||
[
|
||||
'lid' => '2',
|
||||
'property' => 'body',
|
||||
'language' => 'fr',
|
||||
'translation' => 'fr - body translation',
|
||||
'bid' => '1',
|
||||
'format' => '2',
|
||||
'title_translated' => 'fr - title translation',
|
||||
'body_translated' => 'fr - body translation',
|
||||
'title' => 'box 1 title',
|
||||
'body' => 'box 1 body',
|
||||
],
|
||||
[
|
||||
'lid' => '3',
|
||||
'property' => 'body',
|
||||
'language' => 'zu',
|
||||
'translation' => 'zu - body translation',
|
||||
'bid' => '2',
|
||||
'format' => '2',
|
||||
'title_translated' => NULL,
|
||||
'body_translated' => 'zu - body translation',
|
||||
'title' => 'box 2 title',
|
||||
'body' => 'box 2 body',
|
||||
],
|
||||
];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests d7_block_custom source plugin.
|
||||
*
|
||||
* @covers \Drupal\block_content\Plugin\migrate\source\d7\BlockCustom
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockCustomTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block_content', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
$tests[0]['source_data']['block_custom'] = [
|
||||
[
|
||||
'bid' => '1',
|
||||
'body' => "I don't feel creative enough to write anything clever here.",
|
||||
'info' => 'Meh',
|
||||
'format' => 'filtered_html',
|
||||
],
|
||||
];
|
||||
// The expected results are identical to the source data.
|
||||
$tests[0]['expected_data'] = $tests[0]['source_data']['block_custom'];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
// cspell:ignore objectid objectindex plid
|
||||
|
||||
/**
|
||||
* Tests i18n content block translations source plugin.
|
||||
*
|
||||
* @covers \Drupal\block_content\Plugin\migrate\source\d7\BlockCustomTranslation
|
||||
*
|
||||
* @group content_translation
|
||||
*/
|
||||
class BlockCustomTranslationTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block_content', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
// The source data.
|
||||
$tests[0]['source_data']['block_custom'] = [
|
||||
[
|
||||
'bid' => 1,
|
||||
'body' => 'box 1 body',
|
||||
'info' => 'box 1 title',
|
||||
'format' => '2',
|
||||
],
|
||||
[
|
||||
'bid' => 2,
|
||||
'body' => 'box 2 body',
|
||||
'info' => 'box 2 title',
|
||||
'format' => '2',
|
||||
],
|
||||
[
|
||||
'bid' => 4,
|
||||
'body' => 'box 2 body',
|
||||
'info' => 'box 2 title',
|
||||
'format' => '2',
|
||||
],
|
||||
];
|
||||
|
||||
$tests[0]['source_data']['i18n_string'] = [
|
||||
[
|
||||
'lid' => 1,
|
||||
'objectid' => 1,
|
||||
'type' => 'block',
|
||||
'property' => 'title',
|
||||
'objectindex' => 1,
|
||||
'format' => 0,
|
||||
],
|
||||
[
|
||||
'lid' => 2,
|
||||
'objectid' => 1,
|
||||
'type' => 'block',
|
||||
'property' => 'body',
|
||||
'objectindex' => 1,
|
||||
'format' => 0,
|
||||
],
|
||||
[
|
||||
'lid' => 3,
|
||||
'objectid' => 2,
|
||||
'type' => 'block',
|
||||
'property' => 'body',
|
||||
'objectindex' => 2,
|
||||
'format' => 2,
|
||||
],
|
||||
[
|
||||
'lid' => 4,
|
||||
'objectid' => 4,
|
||||
'type' => 'block',
|
||||
'property' => 'body',
|
||||
'objectindex' => 4,
|
||||
'format' => 2,
|
||||
],
|
||||
];
|
||||
|
||||
$tests[0]['source_data']['locales_target'] = [
|
||||
[
|
||||
'lid' => 1,
|
||||
'language' => 'fr',
|
||||
'translation' => 'fr - title translation',
|
||||
'plid' => 0,
|
||||
'plural' => 0,
|
||||
'i18n_status' => 0,
|
||||
],
|
||||
[
|
||||
'lid' => 2,
|
||||
'language' => 'fr',
|
||||
'translation' => 'fr - body translation',
|
||||
'plid' => 0,
|
||||
'plural' => 0,
|
||||
'i18n_status' => 0,
|
||||
],
|
||||
[
|
||||
'lid' => 3,
|
||||
'language' => 'zu',
|
||||
'translation' => 'zu - body translation',
|
||||
'plid' => 0,
|
||||
'plural' => 0,
|
||||
'i18n_status' => 0,
|
||||
],
|
||||
];
|
||||
|
||||
$tests[0]['source_data']['system'] = [
|
||||
[
|
||||
'type' => 'module',
|
||||
'name' => 'system',
|
||||
'schema_version' => '7001',
|
||||
'status' => '1',
|
||||
],
|
||||
];
|
||||
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'lid' => '1',
|
||||
'property' => 'title',
|
||||
'language' => 'fr',
|
||||
'translation' => 'fr - title translation',
|
||||
'bid' => '1',
|
||||
'format' => '2',
|
||||
'title_translated' => 'fr - title translation',
|
||||
'body_translated' => 'fr - body translation',
|
||||
'title' => 'box 1 title',
|
||||
'body' => 'box 1 body',
|
||||
],
|
||||
[
|
||||
'lid' => '2',
|
||||
'property' => 'body',
|
||||
'language' => 'fr',
|
||||
'translation' => 'fr - body translation',
|
||||
'bid' => '1',
|
||||
'format' => '2',
|
||||
'title_translated' => 'fr - title translation',
|
||||
'body_translated' => 'fr - body translation',
|
||||
'title' => 'box 1 title',
|
||||
'body' => 'box 1 body',
|
||||
],
|
||||
[
|
||||
'lid' => '3',
|
||||
'property' => 'body',
|
||||
'language' => 'zu',
|
||||
'translation' => 'zu - body translation',
|
||||
'bid' => '2',
|
||||
'format' => '2',
|
||||
'title_translated' => NULL,
|
||||
'body_translated' => 'zu - body translation',
|
||||
'title' => 'box 2 title',
|
||||
'body' => 'box 2 body',
|
||||
],
|
||||
];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Views;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the Drupal\block_content\Plugin\views\field\Type handler.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class FieldTypeTest extends ViewsKernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'block_content',
|
||||
'block_content_test_views',
|
||||
];
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_field_type'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp($import_test_views = TRUE): void {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
if ($import_test_views) {
|
||||
ViewTestData::createTestViews(get_class($this), ['block_content_test_views']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the field type.
|
||||
*/
|
||||
public function testFieldType(): void {
|
||||
$this->installEntitySchema('block_content');
|
||||
BlockContentType::create([
|
||||
'id' => 'basic',
|
||||
'label' => 'basic',
|
||||
'revision' => FALSE,
|
||||
]);
|
||||
$block_content = BlockContent::create([
|
||||
'info' => $this->randomMachineName(),
|
||||
'type' => 'basic',
|
||||
'langcode' => 'en',
|
||||
]);
|
||||
$block_content->save();
|
||||
|
||||
$expected_result[] = [
|
||||
'id' => $block_content->id(),
|
||||
'type' => $block_content->bundle(),
|
||||
];
|
||||
$column_map = [
|
||||
'id' => 'id',
|
||||
'type:target_id' => 'type',
|
||||
];
|
||||
|
||||
$view = Views::getView('test_field_type');
|
||||
$this->executeView($view);
|
||||
$this->assertIdenticalResultset($view, $expected_result, $column_map, 'The correct block_content type was displayed.');
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Views;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\views\Tests\ViewResultAssertionTrait;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the integration of block_content_revision table.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class RevisionRelationshipsTest extends KernelTestBase {
|
||||
|
||||
use ViewResultAssertionTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'block_content',
|
||||
'block_content_test_views',
|
||||
'system',
|
||||
'user',
|
||||
'views',
|
||||
];
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = [
|
||||
'test_block_content_revision_id',
|
||||
'test_block_content_revision_revision_id',
|
||||
];
|
||||
|
||||
/**
|
||||
* Create a block_content with revision and rest result count for both views.
|
||||
*/
|
||||
public function testBlockContentRevisionRelationship(): void {
|
||||
$this->installEntitySchema('block_content');
|
||||
ViewTestData::createTestViews(static::class, ['block_content_test_views']);
|
||||
|
||||
BlockContentType::create([
|
||||
'id' => 'basic',
|
||||
'label' => 'basic',
|
||||
'revision' => TRUE,
|
||||
]);
|
||||
$block_content = BlockContent::create([
|
||||
'info' => $this->randomMachineName(),
|
||||
'type' => 'basic',
|
||||
'langcode' => 'en',
|
||||
]);
|
||||
$block_content->save();
|
||||
// Create revision of the block_content.
|
||||
$block_content_revision = clone $block_content;
|
||||
$block_content_revision->setNewRevision();
|
||||
$block_content_revision->save();
|
||||
$column_map = [
|
||||
'revision_id' => 'revision_id',
|
||||
'id_1' => 'id_1',
|
||||
'block_content_field_data_block_content_field_revision_id' => 'block_content_field_data_block_content_field_revision_id',
|
||||
];
|
||||
|
||||
// Here should be two rows.
|
||||
$view = Views::getView('test_block_content_revision_id');
|
||||
$view->preview(NULL, [$block_content->id()]);
|
||||
$resultset_id = [
|
||||
[
|
||||
'revision_id' => '1',
|
||||
'id_1' => '1',
|
||||
'block_content_field_data_block_content_field_revision_id' => '1',
|
||||
],
|
||||
[
|
||||
'revision_id' => '2',
|
||||
'id_1' => '1',
|
||||
'block_content_field_data_block_content_field_revision_id' => '1',
|
||||
],
|
||||
];
|
||||
$this->assertIdenticalResultset($view, $resultset_id, $column_map);
|
||||
|
||||
// There should be only one row with active revision 2.
|
||||
$view_revision = Views::getView('test_block_content_revision_revision_id');
|
||||
$view_revision->preview(NULL, [$block_content->id()]);
|
||||
$resultset_revision_id = [
|
||||
[
|
||||
'revision_id' => '2',
|
||||
'id_1' => '1',
|
||||
'block_content_field_data_block_content_field_revision_id' => '1',
|
||||
],
|
||||
];
|
||||
$this->assertIdenticalResultset($view_revision, $resultset_revision_id, $column_map);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,153 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Views;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Tests\user\Traits\UserCreationTrait;
|
||||
use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
|
||||
use Drupal\views\Tests\ViewResultAssertionTrait;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the block_content_revision_user field.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class RevisionUserTest extends ViewsKernelTestBase {
|
||||
|
||||
use UserCreationTrait;
|
||||
use ViewResultAssertionTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'block_content',
|
||||
'block_content_test_views',
|
||||
'system',
|
||||
'user',
|
||||
'views',
|
||||
];
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_block_content_revision_user'];
|
||||
|
||||
/**
|
||||
* Map column names.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $columnMap = [
|
||||
'id' => 'id',
|
||||
'revision_id' => 'revision_id',
|
||||
'revision_user' => 'revision_user',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp($import_test_views = TRUE): void {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$this->installEntitySchema('block_content');
|
||||
$this->installEntitySchema('user');
|
||||
|
||||
if ($import_test_views) {
|
||||
ViewTestData::createTestViews(get_class($this), ['block_content_test_views']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the block_content_revision_user relationship.
|
||||
*/
|
||||
public function testRevisionUser(): void {
|
||||
$primary_author = $this->createUser();
|
||||
$secondary_author = $this->createUser();
|
||||
|
||||
$block_content_type = BlockContentType::create([
|
||||
'id' => 'basic',
|
||||
'label' => 'basic block',
|
||||
]);
|
||||
$block_content_type->save();
|
||||
|
||||
$block_content = BlockContent::create([
|
||||
'info' => 'Test block content',
|
||||
'type' => 'basic',
|
||||
]);
|
||||
$block_content->setRevisionUserId($primary_author->id());
|
||||
$block_content->save();
|
||||
|
||||
$view = Views::getView('test_block_content_revision_user');
|
||||
$this->executeView($view);
|
||||
$this->assertIdenticalResultset($view, [
|
||||
[
|
||||
'id' => 1,
|
||||
'revision_id' => 1,
|
||||
'revision_user' => $primary_author->id(),
|
||||
],
|
||||
], static::$columnMap);
|
||||
|
||||
// Test results shows the revision author.
|
||||
$block_content->setRevisionUser($secondary_author);
|
||||
$block_content->setNewRevision();
|
||||
$block_content->save();
|
||||
|
||||
$view = Views::getView('test_block_content_revision_user');
|
||||
$this->executeView($view);
|
||||
$this->assertIdenticalResultset($view, [
|
||||
[
|
||||
'id' => 1,
|
||||
'revision_id' => 2,
|
||||
'revision_user' => $secondary_author->id(),
|
||||
],
|
||||
], static::$columnMap);
|
||||
|
||||
// Build a larger dataset to allow filtering.
|
||||
$block_content2_title = $this->randomString();
|
||||
$block_content2 = BlockContent::create([
|
||||
'info' => $block_content2_title,
|
||||
'type' => 'basic',
|
||||
]);
|
||||
$block_content2->save();
|
||||
$block_content2->setRevisionUser($primary_author);
|
||||
$block_content2->setNewRevision();
|
||||
$block_content2->save();
|
||||
|
||||
$view = Views::getView('test_block_content_revision_user');
|
||||
$this->executeView($view);
|
||||
$this->assertIdenticalResultset($view, [
|
||||
[
|
||||
'id' => 1,
|
||||
'revision_id' => 2,
|
||||
'revision_user' => $secondary_author->id(),
|
||||
],
|
||||
[
|
||||
'id' => 2,
|
||||
'revision_id' => 4,
|
||||
'revision_user' => $primary_author->id(),
|
||||
],
|
||||
], static::$columnMap);
|
||||
|
||||
// Test filter by revision_author.
|
||||
$view = Views::getView('test_block_content_revision_user');
|
||||
$view->initHandlers();
|
||||
$view->filter['revision_user']->value = [$secondary_author->id()];
|
||||
$this->executeView($view);
|
||||
$this->assertIdenticalResultset($view, [
|
||||
[
|
||||
'id' => 1,
|
||||
'revision_id' => 2,
|
||||
'revision_user' => $secondary_author->id(),
|
||||
],
|
||||
], static::$columnMap);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\block_content\Unit\Menu;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Tests\Core\Menu\LocalTaskIntegrationTestBase;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* Tests existence of block_content local tasks.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentLocalTasksTest extends LocalTaskIntegrationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
$this->directoryList = [
|
||||
'system' => 'core/modules/system',
|
||||
'block_content' => 'core/modules/block_content',
|
||||
];
|
||||
parent::setUp();
|
||||
|
||||
$config_factory = $this->getConfigFactoryStub([
|
||||
'system.theme' => ['default' => 'test_c'],
|
||||
]);
|
||||
|
||||
$themes = [];
|
||||
$themes['test_a'] = (object) [
|
||||
'status' => 0,
|
||||
];
|
||||
$themes['test_b'] = (object) [
|
||||
'status' => 1,
|
||||
'info' => [
|
||||
'name' => 'test_b',
|
||||
],
|
||||
];
|
||||
$themes['test_c'] = (object) [
|
||||
'status' => 1,
|
||||
'info' => [
|
||||
'name' => 'test_c',
|
||||
],
|
||||
];
|
||||
$theme_handler = $this->createMock('Drupal\Core\Extension\ThemeHandlerInterface');
|
||||
$theme_handler->expects($this->any())
|
||||
->method('listInfo')
|
||||
->willReturn($themes);
|
||||
|
||||
// Add services required for block local tasks.
|
||||
$entity_type_manager = $this->createMock(EntityTypeManagerInterface::class);
|
||||
$entity_type_manager->expects($this->any())
|
||||
->method('getDefinitions')
|
||||
->willReturn([]);
|
||||
|
||||
$container = new ContainerBuilder();
|
||||
$container->set('config.factory', $config_factory);
|
||||
$container->set('theme_handler', $theme_handler);
|
||||
$container->set('entity_type.manager', $entity_type_manager);
|
||||
\Drupal::setContainer($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks block_content listing local tasks.
|
||||
*
|
||||
* @dataProvider getBlockContentListingRoutes
|
||||
*/
|
||||
public function testBlockContentListLocalTasks($route): void {
|
||||
$this->assertLocalTasks($route, [
|
||||
0 => [
|
||||
'system.admin_content',
|
||||
'entity.block_content.collection',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of routes to test.
|
||||
*/
|
||||
public static function getBlockContentListingRoutes() {
|
||||
return [
|
||||
['entity.block_content.collection', 'system.admin_content'],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user