Move into nested docroot
This commit is contained in:
parent
83a0d3a149
commit
c8b70abde9
13405 changed files with 0 additions and 0 deletions
11
web/core/modules/block_content/block_content.info.yml
Normal file
11
web/core/modules/block_content/block_content.info.yml
Normal file
|
@ -0,0 +1,11 @@
|
|||
name: 'Custom Block'
|
||||
type: module
|
||||
description: 'Allows the creation of custom blocks through the user interface.'
|
||||
package: Core
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- block
|
||||
- text
|
||||
- user
|
||||
configure: entity.block_content.collection
|
63
web/core/modules/block_content/block_content.install
Normal file
63
web/core/modules/block_content/block_content.install
Normal file
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Install, update and uninstall functions for the block_content module.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
|
||||
/**
|
||||
* Add 'revision_translation_affected' field to 'block_content' entities.
|
||||
*/
|
||||
function block_content_update_8001() {
|
||||
// Install the definition that this field had in
|
||||
// \Drupal\block_content\Entity\BlockContent::baseFieldDefinitions()
|
||||
// at the time that this update function was written. If/when code is
|
||||
// deployed that changes that definition, the corresponding module must
|
||||
// implement an update function that invokes
|
||||
// \Drupal::entityDefinitionUpdateManager()->updateFieldStorageDefinition()
|
||||
// with the new definition.
|
||||
$storage_definition = BaseFieldDefinition::create('boolean')
|
||||
->setLabel(t('Revision translation affected'))
|
||||
->setDescription(t('Indicates if the last edit of a translation belongs to current revision.'))
|
||||
->setReadOnly(TRUE)
|
||||
->setRevisionable(TRUE)
|
||||
->setTranslatable(TRUE);
|
||||
|
||||
\Drupal::entityDefinitionUpdateManager()
|
||||
->installFieldStorageDefinition('revision_translation_affected', 'block_content', 'block_content', $storage_definition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generalizes the d6_block_content_type and d6_block_content_body_field
|
||||
* migrations.
|
||||
*/
|
||||
function block_content_update_8002() {
|
||||
// Removed in issue #2569605. The Migrate and Migrate Drupal modules are
|
||||
// marked experimental and do not need to support the update path until they
|
||||
// are stable.
|
||||
// @see https://www.drupal.org/node/2569469
|
||||
}
|
||||
|
||||
/**
|
||||
* Add 'revision_created' and 'revision_user' fields to 'block_content' entities.
|
||||
*/
|
||||
function block_content_update_8003() {
|
||||
$revision_created = BaseFieldDefinition::create('created')
|
||||
->setLabel(t('Revision create time'))
|
||||
->setDescription(t('The time that the current revision was created.'))
|
||||
->setRevisionable(TRUE);
|
||||
|
||||
\Drupal::entityDefinitionUpdateManager()
|
||||
->installFieldStorageDefinition('revision_created', 'block_content', 'block_content', $revision_created);
|
||||
|
||||
$revision_user = BaseFieldDefinition::create('entity_reference')
|
||||
->setLabel(t('Revision user'))
|
||||
->setDescription(t('The user ID of the author of the current revision.'))
|
||||
->setSetting('target_type', 'user')
|
||||
->setRevisionable(TRUE);
|
||||
|
||||
\Drupal::entityDefinitionUpdateManager()
|
||||
->installFieldStorageDefinition('revision_user', 'block_content', 'block_content', $revision_user);
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
drupal.block_content:
|
||||
version: VERSION
|
||||
js:
|
||||
js/block_content.js: {}
|
||||
dependencies:
|
||||
- core/jquery
|
||||
- core/drupal
|
||||
- core/drupal.form
|
|
@ -0,0 +1,13 @@
|
|||
block_content_type_add:
|
||||
route_name: block_content.type_add
|
||||
title: 'Add custom block type'
|
||||
appears_on:
|
||||
- entity.block_content_type.collection
|
||||
|
||||
block_content_add_action:
|
||||
route_name: block_content.add_page
|
||||
title: 'Add custom block'
|
||||
appears_on:
|
||||
- block.admin_library
|
||||
- entity.block_content.collection
|
||||
class: \Drupal\block_content\Plugin\Menu\LocalAction\BlockContentAddLocalAction
|
|
@ -0,0 +1,10 @@
|
|||
block_content.block_edit:
|
||||
title: 'Edit'
|
||||
group: block_content
|
||||
route_name: 'entity.block_content.canonical'
|
||||
|
||||
block_content.block_delete:
|
||||
title: 'Delete'
|
||||
group: block_content
|
||||
route_name: 'entity.block_content.delete_form'
|
||||
weight: 1
|
28
web/core/modules/block_content/block_content.links.task.yml
Normal file
28
web/core/modules/block_content/block_content.links.task.yml
Normal file
|
@ -0,0 +1,28 @@
|
|||
entity.block_content.collection:
|
||||
title: 'Custom block library'
|
||||
route_name: entity.block_content.collection
|
||||
base_route: block.admin_display
|
||||
block_content.list_sub:
|
||||
title: Blocks
|
||||
route_name: entity.block_content.collection
|
||||
parent_id: entity.block_content.collection
|
||||
entity.block_content_type.collection:
|
||||
title: Block types
|
||||
route_name: entity.block_content_type.collection
|
||||
parent_id: entity.block_content.collection
|
||||
weight: 1
|
||||
|
||||
entity.block_content.canonical:
|
||||
title: Edit
|
||||
route_name: entity.block_content.canonical
|
||||
base_route: entity.block_content.canonical
|
||||
entity.block_content.delete_form:
|
||||
title: Delete
|
||||
route_name: entity.block_content.delete_form
|
||||
base_route: entity.block_content.canonical
|
||||
|
||||
# Default tab for custom block type editing.
|
||||
entity.block_content_type.edit_form:
|
||||
title: 'Edit'
|
||||
route_name: entity.block_content_type.edit_form
|
||||
base_route: entity.block_content_type.edit_form
|
107
web/core/modules/block_content/block_content.module
Normal file
107
web/core/modules/block_content/block_content.module
Normal file
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Allows the creation of custom blocks through the user interface.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
|
||||
/**
|
||||
* Implements hook_help().
|
||||
*/
|
||||
function block_content_help($route_name, RouteMatchInterface $route_match) {
|
||||
switch ($route_name) {
|
||||
case 'help.page.block_content':
|
||||
$field_ui = \Drupal::moduleHandler()->moduleExists('field_ui') ? \Drupal::url('help.page', array('name' => 'field_ui')) : '#';
|
||||
$output = '';
|
||||
$output .= '<h3>' . t('About') . '</h3>';
|
||||
$output .= '<p>' . t('The Custom Block module allows you to create and manage custom <em>block types</em> and <em>content-containing blocks</em> from the <a href = ":block-library" >Custom block library<a/> page. Custom block types have fields; see the <a href=":field-help">Field module help</a> for more information. Once created, custom blocks can be placed in regions just like blocks provided by other modules; see the <a href=":blocks">Block module help</a> page for details. For more information, see the <a href=":online-help">online documentation for the Custom Block module</a>.', array(':block-library' => \Drupal::url('entity.block_content.collection'), ':block-content' => \Drupal::url('entity.block_content.collection'), ':field-help' => \Drupal::url('help.page', array('name' => 'field')), ':blocks' => \Drupal::url('help.page', array('name' => 'block')), ':online-help' => 'https://www.drupal.org/documentation/modules/block_content')) . '</p>';
|
||||
$output .= '<h3>' . t('Uses') . '</h3>';
|
||||
$output .= '<dl>';
|
||||
$output .= '<dt>' . t('Creating and managing custom block types') . '</dt>';
|
||||
$output .= '<dd>' . t('Users with the <em>Administer blocks</em> permission can create and edit custom block types with fields and display settings, from the <a href=":types">Block types</a> page in the Custom block library. For more information about managing fields and display settings, see the <a href=":field-ui">Field UI module help</a>.', array(':types' => \Drupal::url('entity.block_content_type.collection'), ':field-ui' => $field_ui)) . '</dd>';
|
||||
$output .= '<dt>' . t('Creating custom blocks') . '</dt>';
|
||||
$output .= '<dd>' . t('Users with the <em>Administer blocks</em> permission can create, edit, and delete custom blocks of each defined custom block type, from the <a href=":block-library">Blocks</a> page in the Custom block library. After creating a block, place it in a region from the <a href=":blocks">Block layout</a> page; see the <a href=":block_help">Block module help</a> for more information about placing blocks.', array(':blocks' => \Drupal::url('block.admin_display'), ':block-library' => \Drupal::url('entity.block_content.collection'), ':block_help' => \Drupal::url('help.page', array('name' => 'block')))) . '</dd>';
|
||||
$output .= '</dl>';
|
||||
return $output;
|
||||
|
||||
case 'entity.block_content.collection':
|
||||
$output = '<p>' . t('Blocks in the block library belong to <a href=":types">Custom block types</a>, each with its own fields and display settings. After creating a block, place it in a region from the <a href=":blocks">Block layout</a> page.', array(':types' => \Drupal::url('entity.block_content_type.collection'), ':blocks' => \Drupal::url('block.admin_display'))) . '</p>';
|
||||
return $output;
|
||||
|
||||
case 'entity.block_content_type.collection':
|
||||
$output = '<p>' . t('Each block type has its own fields and display settings. Create blocks of each type on the <a href=":block-library">Blocks</a> page in the custom block library.', array(':block-library' => \Drupal::url('entity.block_content.collection'))) . '</p>';
|
||||
return $output;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_theme().
|
||||
*/
|
||||
function block_content_theme($existing, $type, $theme, $path) {
|
||||
return array(
|
||||
'block_content_add_list' => array(
|
||||
'variables' => array('content' => NULL),
|
||||
'file' => 'block_content.pages.inc',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_type_alter().
|
||||
*/
|
||||
function block_content_entity_type_alter(array &$entity_types) {
|
||||
/** @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
|
||||
// Add a translation handler for fields if the language module is enabled.
|
||||
if (\Drupal::moduleHandler()->moduleExists('language')) {
|
||||
$translation = $entity_types['block_content']->get('translation');
|
||||
$translation['block_content'] = TRUE;
|
||||
$entity_types['block_content']->set('translation', $translation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the default body field to a custom block type.
|
||||
*
|
||||
* @param string $block_type_id
|
||||
* Id of the block type.
|
||||
* @param string $label
|
||||
* (optional) The label for the body instance. Defaults to 'Body'
|
||||
*
|
||||
* @return \Drupal\field\Entity\FieldConfig
|
||||
* A Body field object.
|
||||
*/
|
||||
function block_content_add_body_field($block_type_id, $label = 'Body') {
|
||||
// Add or remove the body field, as needed.
|
||||
$field = FieldConfig::loadByName('block_content', $block_type_id, 'body');
|
||||
if (empty($field)) {
|
||||
$field = FieldConfig::create([
|
||||
'field_storage' => FieldStorageConfig::loadByName('block_content', 'body'),
|
||||
'bundle' => $block_type_id,
|
||||
'label' => $label,
|
||||
'settings' => array('display_summary' => FALSE),
|
||||
]);
|
||||
$field->save();
|
||||
|
||||
// Assign widget settings for the 'default' form mode.
|
||||
entity_get_form_display('block_content', $block_type_id, 'default')
|
||||
->setComponent('body', array(
|
||||
'type' => 'text_textarea_with_summary',
|
||||
))
|
||||
->save();
|
||||
|
||||
// Assign display settings for 'default' view mode.
|
||||
entity_get_display('block_content', $block_type_id, 'default')
|
||||
->setComponent('body', array(
|
||||
'label' => 'hidden',
|
||||
'type' => 'text_default',
|
||||
))
|
||||
->save();
|
||||
}
|
||||
|
||||
return $field;
|
||||
}
|
36
web/core/modules/block_content/block_content.pages.inc
Normal file
36
web/core/modules/block_content/block_content.pages.inc
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides page callbacks for custom blocks.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Url;
|
||||
|
||||
/**
|
||||
* Prepares variables for a custom block type creation list templates.
|
||||
*
|
||||
* Default template: block-content-add-list.html.twig.
|
||||
*
|
||||
* @param array $variables
|
||||
* An associative array containing:
|
||||
* - content: An array of block types.
|
||||
*
|
||||
* @see block_content_add_page()
|
||||
*/
|
||||
function template_preprocess_block_content_add_list(&$variables) {
|
||||
$variables['types'] = array();
|
||||
$query = \Drupal::request()->query->all();
|
||||
foreach ($variables['content'] as $type) {
|
||||
$variables['types'][$type->id()] = array(
|
||||
'link' => \Drupal::l($type->label(), new Url('block_content.add_form', array('block_content_type' => $type->id()), array('query' => $query))),
|
||||
'description' => array(
|
||||
'#markup' => $type->getDescription(),
|
||||
),
|
||||
'title' => $type->label(),
|
||||
'localized_options' => array(
|
||||
'query' => $query,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
91
web/core/modules/block_content/block_content.routing.yml
Normal file
91
web/core/modules/block_content/block_content.routing.yml
Normal file
|
@ -0,0 +1,91 @@
|
|||
entity.block_content_type.collection:
|
||||
path: '/admin/structure/block/block-content/types'
|
||||
defaults:
|
||||
_entity_list: 'block_content_type'
|
||||
_title: 'Custom block library'
|
||||
requirements:
|
||||
_permission: 'administer blocks'
|
||||
|
||||
block_content.add_page:
|
||||
path: '/block/add'
|
||||
defaults:
|
||||
_controller: '\Drupal\block_content\Controller\BlockContentController::add'
|
||||
_title: 'Add custom block'
|
||||
options:
|
||||
_admin_route: TRUE
|
||||
requirements:
|
||||
_permission: 'administer blocks'
|
||||
|
||||
block_content.add_form:
|
||||
path: '/block/add/{block_content_type}'
|
||||
defaults:
|
||||
_controller: '\Drupal\block_content\Controller\BlockContentController::addForm'
|
||||
_title_callback: 'Drupal\block_content\Controller\BlockContentController::getAddFormTitle'
|
||||
options:
|
||||
_admin_route: TRUE
|
||||
requirements:
|
||||
_permission: 'administer blocks'
|
||||
|
||||
entity.block_content_type.delete_form:
|
||||
path: '/admin/structure/block/block-content/manage/{block_content_type}/delete'
|
||||
defaults:
|
||||
_entity_form: 'block_content_type.delete'
|
||||
_title: 'Delete'
|
||||
requirements:
|
||||
_entity_access: 'block_content_type.delete'
|
||||
options:
|
||||
_admin_route: TRUE
|
||||
|
||||
entity.block_content.canonical:
|
||||
path: '/block/{block_content}'
|
||||
defaults:
|
||||
_entity_form: 'block_content.edit'
|
||||
options:
|
||||
_admin_route: TRUE
|
||||
requirements:
|
||||
_entity_access: 'block_content.update'
|
||||
block_content: \d+
|
||||
|
||||
entity.block_content.edit_form:
|
||||
path: '/block/{block_content}'
|
||||
defaults:
|
||||
_entity_form: 'block_content.edit'
|
||||
options:
|
||||
_admin_route: TRUE
|
||||
requirements:
|
||||
_entity_access: 'block_content.update'
|
||||
block_content: \d+
|
||||
|
||||
entity.block_content.delete_form:
|
||||
path: '/block/{block_content}/delete'
|
||||
defaults:
|
||||
_entity_form: 'block_content.delete'
|
||||
_title: 'Delete'
|
||||
options:
|
||||
_admin_route: TRUE
|
||||
requirements:
|
||||
_entity_access: 'block_content.delete'
|
||||
block_content: \d+
|
||||
|
||||
block_content.type_add:
|
||||
path: '/admin/structure/block/block-content/types/add'
|
||||
defaults:
|
||||
_entity_form: 'block_content_type.add'
|
||||
_title: 'Add'
|
||||
requirements:
|
||||
_permission: 'administer blocks'
|
||||
|
||||
entity.block_content_type.edit_form:
|
||||
path: '/admin/structure/block/block-content/manage/{block_content_type}'
|
||||
defaults:
|
||||
_entity_form: 'block_content_type.edit'
|
||||
requirements:
|
||||
_entity_access: 'block_content_type.update'
|
||||
|
||||
entity.block_content.collection:
|
||||
path: '/admin/structure/block/block-content'
|
||||
defaults:
|
||||
_title: 'Custom block library'
|
||||
_entity_list: 'block_content'
|
||||
requirements:
|
||||
_permission: 'administer blocks'
|
|
@ -0,0 +1,9 @@
|
|||
langcode: en
|
||||
status: false
|
||||
dependencies:
|
||||
module:
|
||||
- block_content
|
||||
id: block_content.full
|
||||
label: Full
|
||||
targetEntityType: block_content
|
||||
cache: true
|
|
@ -0,0 +1,18 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- block_content
|
||||
- text
|
||||
id: block_content.body
|
||||
field_name: body
|
||||
entity_type: block_content
|
||||
type: text_with_summary
|
||||
settings: { }
|
||||
module: text
|
||||
locked: false
|
||||
cardinality: 1
|
||||
translatable: true
|
||||
indexes: { }
|
||||
persist_with_no_fields: true
|
||||
custom_storage: false
|
|
@ -0,0 +1,497 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- block_content
|
||||
- user
|
||||
id: block_content
|
||||
label: 'Custom block library'
|
||||
module: views
|
||||
description: 'Find and manage custom blocks.'
|
||||
tag: default
|
||||
base_table: block_content_field_data
|
||||
base_field: id
|
||||
core: 8.x
|
||||
display:
|
||||
default:
|
||||
display_plugin: default
|
||||
id: default
|
||||
display_title: Master
|
||||
position: 0
|
||||
display_options:
|
||||
access:
|
||||
type: perm
|
||||
options:
|
||||
perm: 'administer blocks'
|
||||
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: 50
|
||||
offset: 0
|
||||
id: 0
|
||||
total_pages: null
|
||||
tags:
|
||||
previous: '‹ Previous'
|
||||
next: 'Next ›'
|
||||
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
|
||||
style:
|
||||
type: table
|
||||
options:
|
||||
grouping: { }
|
||||
row_class: ''
|
||||
default_row_class: true
|
||||
override: true
|
||||
sticky: false
|
||||
caption: ''
|
||||
summary: ''
|
||||
description: ''
|
||||
columns:
|
||||
info: info
|
||||
type: type
|
||||
changed: changed
|
||||
operations: operations
|
||||
info:
|
||||
info:
|
||||
sortable: true
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
type:
|
||||
sortable: true
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
changed:
|
||||
sortable: true
|
||||
default_sort_order: desc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
operations:
|
||||
sortable: false
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
default: changed
|
||||
empty_table: true
|
||||
row:
|
||||
type: fields
|
||||
fields:
|
||||
info:
|
||||
id: info
|
||||
table: block_content_field_data
|
||||
field: info
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: 'Block description'
|
||||
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:
|
||||
link_to_entity: true
|
||||
group_column: value
|
||||
group_columns: { }
|
||||
group_rows: true
|
||||
delta_limit: 0
|
||||
delta_offset: 0
|
||||
delta_reversed: false
|
||||
delta_first_last: false
|
||||
multi_type: separator
|
||||
separator: ', '
|
||||
field_api_classes: false
|
||||
entity_type: null
|
||||
entity_field: info
|
||||
plugin_id: field
|
||||
type:
|
||||
id: type
|
||||
table: block_content_field_data
|
||||
field: type
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: 'Block type'
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
text: ''
|
||||
make_link: false
|
||||
path: ''
|
||||
absolute: false
|
||||
external: false
|
||||
replace_spaces: false
|
||||
path_case: none
|
||||
trim_whitespace: false
|
||||
alt: ''
|
||||
rel: ''
|
||||
link_class: ''
|
||||
prefix: ''
|
||||
suffix: ''
|
||||
target: ''
|
||||
nl2br: false
|
||||
max_length: 0
|
||||
word_boundary: true
|
||||
ellipsis: true
|
||||
more_link: false
|
||||
more_link_text: ''
|
||||
more_link_path: ''
|
||||
strip_tags: false
|
||||
trim: false
|
||||
preserve_tags: ''
|
||||
html: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: true
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
click_sort_column: target_id
|
||||
type: entity_reference_label
|
||||
settings:
|
||||
link: false
|
||||
group_column: target_id
|
||||
group_columns: { }
|
||||
group_rows: true
|
||||
delta_limit: 0
|
||||
delta_offset: 0
|
||||
delta_reversed: false
|
||||
delta_first_last: false
|
||||
multi_type: separator
|
||||
separator: ', '
|
||||
field_api_classes: false
|
||||
entity_type: block_content
|
||||
entity_field: type
|
||||
plugin_id: field
|
||||
changed:
|
||||
id: changed
|
||||
table: block_content_field_data
|
||||
field: changed
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: Updated
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
text: ''
|
||||
make_link: false
|
||||
path: ''
|
||||
absolute: false
|
||||
external: false
|
||||
replace_spaces: false
|
||||
path_case: none
|
||||
trim_whitespace: false
|
||||
alt: ''
|
||||
rel: ''
|
||||
link_class: ''
|
||||
prefix: ''
|
||||
suffix: ''
|
||||
target: ''
|
||||
nl2br: false
|
||||
max_length: 0
|
||||
word_boundary: true
|
||||
ellipsis: true
|
||||
more_link: false
|
||||
more_link_text: ''
|
||||
more_link_path: ''
|
||||
strip_tags: false
|
||||
trim: false
|
||||
preserve_tags: ''
|
||||
html: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: true
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
entity_type: block_content
|
||||
entity_field: changed
|
||||
type: timestamp
|
||||
settings:
|
||||
date_format: short
|
||||
custom_date_format: ''
|
||||
timezone: ''
|
||||
plugin_id: field
|
||||
operations:
|
||||
id: operations
|
||||
table: block_content
|
||||
field: operations
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: Operations
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
text: ''
|
||||
make_link: false
|
||||
path: ''
|
||||
absolute: false
|
||||
external: false
|
||||
replace_spaces: false
|
||||
path_case: none
|
||||
trim_whitespace: false
|
||||
alt: ''
|
||||
rel: ''
|
||||
link_class: ''
|
||||
prefix: ''
|
||||
suffix: ''
|
||||
target: ''
|
||||
nl2br: false
|
||||
max_length: 0
|
||||
word_boundary: true
|
||||
ellipsis: true
|
||||
more_link: false
|
||||
more_link_text: ''
|
||||
more_link_path: ''
|
||||
strip_tags: false
|
||||
trim: false
|
||||
preserve_tags: ''
|
||||
html: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: true
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
destination: true
|
||||
entity_type: block_content
|
||||
plugin_id: entity_operations
|
||||
filters:
|
||||
info:
|
||||
id: info
|
||||
table: block_content_field_data
|
||||
field: info
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: contains
|
||||
value: ''
|
||||
group: 1
|
||||
exposed: true
|
||||
expose:
|
||||
operator_id: info_op
|
||||
label: 'Block description'
|
||||
description: ''
|
||||
use_operator: false
|
||||
operator: info_op
|
||||
identifier: info
|
||||
required: false
|
||||
remember: false
|
||||
multiple: false
|
||||
remember_roles:
|
||||
authenticated: authenticated
|
||||
anonymous: '0'
|
||||
administrator: '0'
|
||||
is_grouped: false
|
||||
group_info:
|
||||
label: ''
|
||||
description: ''
|
||||
identifier: ''
|
||||
optional: true
|
||||
widget: select
|
||||
multiple: false
|
||||
remember: false
|
||||
default_group: All
|
||||
default_group_multiple: { }
|
||||
group_items: { }
|
||||
entity_type: block_content
|
||||
entity_field: info
|
||||
plugin_id: string
|
||||
type:
|
||||
id: type
|
||||
table: block_content_field_data
|
||||
field: type
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: in
|
||||
value: { }
|
||||
group: 1
|
||||
exposed: true
|
||||
expose:
|
||||
operator_id: type_op
|
||||
label: 'Block type'
|
||||
description: ''
|
||||
use_operator: false
|
||||
operator: type_op
|
||||
identifier: type
|
||||
required: false
|
||||
remember: false
|
||||
multiple: false
|
||||
remember_roles:
|
||||
authenticated: authenticated
|
||||
anonymous: '0'
|
||||
administrator: '0'
|
||||
reduce: false
|
||||
is_grouped: false
|
||||
group_info:
|
||||
label: ''
|
||||
description: ''
|
||||
identifier: ''
|
||||
optional: true
|
||||
widget: select
|
||||
multiple: false
|
||||
remember: false
|
||||
default_group: All
|
||||
default_group_multiple: { }
|
||||
group_items: { }
|
||||
entity_type: block_content
|
||||
entity_field: type
|
||||
plugin_id: bundle
|
||||
sorts: { }
|
||||
title: 'Custom block library'
|
||||
header: { }
|
||||
footer: { }
|
||||
empty:
|
||||
area_text_custom:
|
||||
id: area_text_custom
|
||||
table: views
|
||||
field: area_text_custom
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
empty: true
|
||||
tokenize: false
|
||||
content: 'There are no custom blocks available. '
|
||||
plugin_id: text_custom
|
||||
block_content_listing_empty:
|
||||
admin_label: ''
|
||||
empty: true
|
||||
field: block_content_listing_empty
|
||||
group_type: group
|
||||
id: block_content_listing_empty
|
||||
label: ''
|
||||
relationship: none
|
||||
table: block_content
|
||||
plugin_id: block_content_listing_empty
|
||||
entity_type: block_content
|
||||
relationships: { }
|
||||
arguments: { }
|
||||
display_extenders: { }
|
||||
cache_metadata:
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url
|
||||
- url.query_args
|
||||
- user.permissions
|
||||
max-age: 0
|
||||
tags: { }
|
||||
page_1:
|
||||
display_plugin: page
|
||||
id: page_1
|
||||
display_title: Page
|
||||
position: 1
|
||||
display_options:
|
||||
display_extenders: { }
|
||||
path: admin/structure/block/block-content
|
||||
menu:
|
||||
type: tab
|
||||
title: 'Custom block library'
|
||||
description: ''
|
||||
parent: block.admin_display
|
||||
weight: 0
|
||||
context: '0'
|
||||
menu_name: admin
|
||||
cache_metadata:
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url
|
||||
- url.query_args
|
||||
- user.permissions
|
||||
max-age: 0
|
||||
tags: { }
|
|
@ -0,0 +1,18 @@
|
|||
# Schema for the configuration files of the Custom Block module.
|
||||
|
||||
block_content.type.*:
|
||||
type: config_entity
|
||||
label: 'Custom block type settings'
|
||||
mapping:
|
||||
id:
|
||||
type: string
|
||||
label: 'ID'
|
||||
label:
|
||||
type: label
|
||||
label: 'Label'
|
||||
revision:
|
||||
type: integer
|
||||
label: 'Create new revision'
|
||||
description:
|
||||
type: text
|
||||
label: 'Description'
|
57
web/core/modules/block_content/js/block_content.js
Normal file
57
web/core/modules/block_content/js/block_content.js
Normal file
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* @file
|
||||
* Defines Javascript behaviors for the block_content module.
|
||||
*/
|
||||
|
||||
(function ($, Drupal) {
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Sets summaries about revision and translation of block content.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches summary behaviour block content form tabs.
|
||||
*
|
||||
* Specifically, it updates summaries to the revision information and the
|
||||
* translation options.
|
||||
*/
|
||||
Drupal.behaviors.blockContentDetailsSummaries = {
|
||||
attach: function (context) {
|
||||
var $context = $(context);
|
||||
$context.find('.block-content-form-revision-information').drupalSetSummary(function (context) {
|
||||
var $revisionContext = $(context);
|
||||
var revisionCheckbox = $revisionContext.find('.js-form-item-revision input');
|
||||
|
||||
// Return 'New revision' if the 'Create new revision' checkbox is checked,
|
||||
// or if the checkbox doesn't exist, but the revision log does. For users
|
||||
// without the "Administer content" permission the checkbox won't appear,
|
||||
// but the revision log will if the content type is set to auto-revision.
|
||||
if (revisionCheckbox.is(':checked') || (!revisionCheckbox.length && $revisionContext.find('.js-form-item-revision-log textarea').length)) {
|
||||
return Drupal.t('New revision');
|
||||
}
|
||||
|
||||
return Drupal.t('No revision');
|
||||
});
|
||||
|
||||
$context.find('fieldset.block-content-translation-options').drupalSetSummary(function (context) {
|
||||
var $translationContext = $(context);
|
||||
var translate;
|
||||
var $checkbox = $translationContext.find('.js-form-item-translation-translate input');
|
||||
|
||||
if ($checkbox.size()) {
|
||||
translate = $checkbox.is(':checked') ? Drupal.t('Needs to be updated') : Drupal.t('Does not need to be updated');
|
||||
}
|
||||
else {
|
||||
$checkbox = $translationContext.find('.js-form-item-translation-retranslate input');
|
||||
translate = $checkbox.is(':checked') ? Drupal.t('Flag other translations as outdated') : Drupal.t('Do not flag other translations as outdated');
|
||||
}
|
||||
|
||||
return translate;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery, Drupal);
|
|
@ -0,0 +1,35 @@
|
|||
id: block_content_body_field
|
||||
label: Block content body field configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
source:
|
||||
plugin: embedded_data
|
||||
data_rows:
|
||||
-
|
||||
entity_type: block_content
|
||||
bundle: basic
|
||||
field_name: body
|
||||
label: Body
|
||||
display_summary: false
|
||||
ids:
|
||||
entity_type:
|
||||
type: string
|
||||
bundle:
|
||||
type: string
|
||||
field_name:
|
||||
type: string
|
||||
process:
|
||||
entity_type: entity_type
|
||||
bundle: bundle
|
||||
field_name: field_name
|
||||
label: label
|
||||
'settings/display_summary': display_summary
|
||||
destination:
|
||||
plugin: entity:field_config
|
||||
migration_dependencies:
|
||||
required:
|
||||
- block_content_type
|
||||
provider:
|
||||
- block_content
|
||||
- migrate_drupal
|
|
@ -0,0 +1,22 @@
|
|||
id: block_content_type
|
||||
label: Block content type
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
source:
|
||||
plugin: embedded_data
|
||||
data_rows:
|
||||
-
|
||||
id: basic
|
||||
label: Basic
|
||||
ids:
|
||||
id:
|
||||
type: string
|
||||
process:
|
||||
id: id
|
||||
label: label
|
||||
destination:
|
||||
plugin: entity:block_content_type
|
||||
provider:
|
||||
- block_content
|
||||
- migrate_drupal
|
|
@ -0,0 +1,22 @@
|
|||
id: d6_custom_block
|
||||
label: Custom blocks
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
source:
|
||||
plugin: d6_box
|
||||
process:
|
||||
id: bid
|
||||
info: info
|
||||
'body/format':
|
||||
plugin: migration
|
||||
migration: d6_filter_format
|
||||
source: format
|
||||
'body/value': body
|
||||
destination:
|
||||
plugin: entity:block_content
|
||||
default_bundle: basic
|
||||
no_stub: true
|
||||
migration_dependencies:
|
||||
required:
|
||||
- d6_filter_format
|
||||
- block_content_body_field
|
|
@ -0,0 +1,22 @@
|
|||
id: d7_custom_block
|
||||
label: Custom blocks
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
source:
|
||||
plugin: d7_block_custom
|
||||
process:
|
||||
id: bid
|
||||
info: info
|
||||
'body/format':
|
||||
plugin: migration
|
||||
migration: d7_filter_format
|
||||
source: format
|
||||
'body/value': body
|
||||
destination:
|
||||
plugin: entity:block_content
|
||||
default_bundle: basic
|
||||
no_stub: true
|
||||
migration_dependencies:
|
||||
required:
|
||||
- d7_filter_format
|
||||
- block_content_body_field
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityAccessControlHandler;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
||||
/**
|
||||
* Defines the access control handler for the custom block entity type.
|
||||
*
|
||||
* @see \Drupal\block_content\Entity\BlockContent
|
||||
*/
|
||||
class BlockContentAccessControlHandler extends EntityAccessControlHandler {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
|
||||
if ($operation === 'view') {
|
||||
return AccessResult::allowed();
|
||||
}
|
||||
return parent::checkAccess($entity, $operation, $account);
|
||||
}
|
||||
|
||||
}
|
221
web/core/modules/block_content/src/BlockContentForm.php
Normal file
221
web/core/modules/block_content/src/BlockContentForm.php
Normal file
|
@ -0,0 +1,221 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Core\Entity\ContentEntityForm;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Form handler for the custom block edit forms.
|
||||
*/
|
||||
class BlockContentForm extends ContentEntityForm {
|
||||
|
||||
/**
|
||||
* The custom block storage.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
*/
|
||||
protected $blockContentStorage;
|
||||
|
||||
/**
|
||||
* The custom block type storage.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
*/
|
||||
protected $blockContentTypeStorage;
|
||||
|
||||
/**
|
||||
* The language manager.
|
||||
*
|
||||
* @var \Drupal\Core\Language\LanguageManagerInterface
|
||||
*/
|
||||
protected $languageManager;
|
||||
|
||||
/**
|
||||
* The block content entity.
|
||||
*
|
||||
* @var \Drupal\block_content\BlockContentInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* Constructs a BlockContentForm object.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* @param \Drupal\Core\Entity\EntityStorageInterface $block_content_storage
|
||||
* The custom block storage.
|
||||
* @param \Drupal\Core\Entity\EntityStorageInterface $block_content_type_storage
|
||||
* The custom block type storage.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager.
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $entity_manager, EntityStorageInterface $block_content_storage, EntityStorageInterface $block_content_type_storage, LanguageManagerInterface $language_manager) {
|
||||
parent::__construct($entity_manager);
|
||||
$this->blockContentStorage = $block_content_storage;
|
||||
$this->blockContentTypeStorage = $block_content_type_storage;
|
||||
$this->languageManager = $language_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
$entity_manager = $container->get('entity.manager');
|
||||
return new static(
|
||||
$entity_manager,
|
||||
$entity_manager->getStorage('block_content'),
|
||||
$entity_manager->getStorage('block_content_type'),
|
||||
$container->get('language_manager')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides \Drupal\Core\Entity\EntityForm::prepareEntity().
|
||||
*
|
||||
* Prepares the custom block object.
|
||||
*
|
||||
* Fills in a few default values, and then invokes
|
||||
* hook_block_content_prepare() on all modules.
|
||||
*/
|
||||
protected function prepareEntity() {
|
||||
$block = $this->entity;
|
||||
// Set up default values, if required.
|
||||
$block_type = $this->blockContentTypeStorage->load($block->bundle());
|
||||
if (!$block->isNew()) {
|
||||
$block->setRevisionLogMessage(NULL);
|
||||
}
|
||||
// Always use the default revision setting.
|
||||
$block->setNewRevision($block_type->shouldCreateNewRevision());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function form(array $form, FormStateInterface $form_state) {
|
||||
$block = $this->entity;
|
||||
$account = $this->currentUser();
|
||||
|
||||
if ($this->operation == 'edit') {
|
||||
$form['#title'] = $this->t('Edit custom block %label', array('%label' => $block->label()));
|
||||
}
|
||||
// Override the default CSS class name, since the user-defined custom block
|
||||
// type name in 'TYPE-block-form' potentially clashes with third-party class
|
||||
// names.
|
||||
$form['#attributes']['class'][0] = 'block-' . Html::getClass($block->bundle()) . '-form';
|
||||
|
||||
$form['advanced'] = array(
|
||||
'#type' => 'vertical_tabs',
|
||||
'#weight' => 99,
|
||||
);
|
||||
|
||||
// Add a log field if the "Create new revision" option is checked, or if the
|
||||
// current user has the ability to check that option.
|
||||
$form['revision_information'] = array(
|
||||
'#type' => 'details',
|
||||
'#title' => $this->t('Revision information'),
|
||||
// Open by default when "Create new revision" is checked.
|
||||
'#open' => $block->isNewRevision(),
|
||||
'#group' => 'advanced',
|
||||
'#attributes' => array(
|
||||
'class' => array('block-content-form-revision-information'),
|
||||
),
|
||||
'#attached' => array(
|
||||
'library' => array('block_content/drupal.block_content'),
|
||||
),
|
||||
'#weight' => 20,
|
||||
'#access' => $block->isNewRevision() || $account->hasPermission('administer blocks'),
|
||||
);
|
||||
|
||||
$form['revision_information']['revision'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Create new revision'),
|
||||
'#default_value' => $block->isNewRevision(),
|
||||
'#access' => $account->hasPermission('administer blocks'),
|
||||
);
|
||||
|
||||
// Check the revision log checkbox when the log textarea is filled in.
|
||||
// This must not happen if "Create new revision" is enabled by default,
|
||||
// since the state would auto-disable the checkbox otherwise.
|
||||
if (!$block->isNewRevision()) {
|
||||
$form['revision_information']['revision']['#states'] = array(
|
||||
'checked' => array(
|
||||
'textarea[name="revision_log"]' => array('empty' => FALSE),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
$form['revision_information']['revision_log'] = array(
|
||||
'#type' => 'textarea',
|
||||
'#title' => $this->t('Revision log message'),
|
||||
'#rows' => 4,
|
||||
'#default_value' => $block->getRevisionLog(),
|
||||
'#description' => $this->t('Briefly describe the changes you have made.'),
|
||||
);
|
||||
|
||||
return parent::form($form, $form_state, $block);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function save(array $form, FormStateInterface $form_state) {
|
||||
$block = $this->entity;
|
||||
|
||||
// Save as a new revision if requested to do so.
|
||||
if (!$form_state->isValueEmpty('revision')) {
|
||||
$block->setNewRevision();
|
||||
// If a new revision is created, save the current user as revision author.
|
||||
$block->setRevisionCreationTime(REQUEST_TIME);
|
||||
$block->setRevisionUserId(\Drupal::currentUser()->id());
|
||||
}
|
||||
|
||||
$insert = $block->isNew();
|
||||
$block->save();
|
||||
$context = array('@type' => $block->bundle(), '%info' => $block->label());
|
||||
$logger = $this->logger('block_content');
|
||||
$block_type = $this->blockContentTypeStorage->load($block->bundle());
|
||||
$t_args = array('@type' => $block_type->label(), '%info' => $block->label());
|
||||
|
||||
if ($insert) {
|
||||
$logger->notice('@type: added %info.', $context);
|
||||
drupal_set_message($this->t('@type %info has been created.', $t_args));
|
||||
}
|
||||
else {
|
||||
$logger->notice('@type: updated %info.', $context);
|
||||
drupal_set_message($this->t('@type %info has been updated.', $t_args));
|
||||
}
|
||||
|
||||
if ($block->id()) {
|
||||
$form_state->setValue('id', $block->id());
|
||||
$form_state->set('id', $block->id());
|
||||
if ($insert) {
|
||||
if (!$theme = $block->getTheme()) {
|
||||
$theme = $this->config('system.theme')->get('default');
|
||||
}
|
||||
$form_state->setRedirect(
|
||||
'block.admin_add',
|
||||
array(
|
||||
'plugin_id' => 'block_content:' . $block->uuid(),
|
||||
'theme' => $theme,
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
$form_state->setRedirectUrl($block->urlInfo('collection'));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// In the unlikely case something went wrong on save, the block will be
|
||||
// rebuilt and block form redisplayed.
|
||||
drupal_set_message($this->t('The block could not be saved.'), 'error');
|
||||
$form_state->setRebuild();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
85
web/core/modules/block_content/src/BlockContentInterface.php
Normal file
85
web/core/modules/block_content/src/BlockContentInterface.php
Normal file
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
use Drupal\Core\Entity\EntityChangedInterface;
|
||||
use Drupal\Core\Entity\RevisionLogInterface;
|
||||
|
||||
/**
|
||||
* Provides an interface defining a custom block entity.
|
||||
*/
|
||||
interface BlockContentInterface extends ContentEntityInterface, EntityChangedInterface, RevisionLogInterface {
|
||||
|
||||
/**
|
||||
* Returns the block revision log message.
|
||||
*
|
||||
* @return string
|
||||
* The revision log message.
|
||||
*
|
||||
* @deprecated in Drupal 8.2.0, will be removed before Drupal 9.0.0. Use
|
||||
* \Drupal\Core\Entity\RevisionLogInterface::getRevisionLogMessage() instead.
|
||||
*/
|
||||
public function getRevisionLog();
|
||||
|
||||
/**
|
||||
* Sets the block description.
|
||||
*
|
||||
* @param string $info
|
||||
* The block description.
|
||||
*
|
||||
* @return \Drupal\block_content\BlockContentInterface
|
||||
* The class instance that this method is called on.
|
||||
*/
|
||||
public function setInfo($info);
|
||||
|
||||
/**
|
||||
* Sets the block revision log message.
|
||||
*
|
||||
* @param string $revision_log
|
||||
* The revision log message.
|
||||
*
|
||||
* @return \Drupal\block_content\BlockContentInterface
|
||||
* The class instance that this method is called on.
|
||||
*
|
||||
* @deprecated in Drupal 8.2.0, will be removed before Drupal 9.0.0. Use
|
||||
* \Drupal\Core\Entity\RevisionLogInterface::setRevisionLogMessage() instead.
|
||||
*/
|
||||
public function setRevisionLog($revision_log);
|
||||
|
||||
/**
|
||||
* Sets the theme value.
|
||||
*
|
||||
* When creating a new block content block from the block library, the user is
|
||||
* redirected to the configure form for that block in the given theme. The
|
||||
* theme is stored against the block when the block content add form is shown.
|
||||
*
|
||||
* @param string $theme
|
||||
* The theme name.
|
||||
*
|
||||
* @return \Drupal\block_content\BlockContentInterface
|
||||
* The class instance that this method is called on.
|
||||
*/
|
||||
public function setTheme($theme);
|
||||
|
||||
/**
|
||||
* Gets the theme value.
|
||||
*
|
||||
* When creating a new block content block from the block library, the user is
|
||||
* redirected to the configure form for that block in the given theme. The
|
||||
* theme is stored against the block when the block content add form is shown.
|
||||
*
|
||||
* @return string
|
||||
* The theme name.
|
||||
*/
|
||||
public function getTheme();
|
||||
|
||||
/**
|
||||
* Gets the configured instances of this custom block.
|
||||
*
|
||||
* @return array
|
||||
* Array of Drupal\block\Core\Plugin\Entity\Block entities.
|
||||
*/
|
||||
public function getInstances();
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content;
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityListBuilder;
|
||||
use Drupal\Core\Routing\RedirectDestinationTrait;
|
||||
|
||||
/**
|
||||
* Defines a class to build a listing of custom block entities.
|
||||
*
|
||||
* @see \Drupal\block_content\Entity\BlockContent
|
||||
*/
|
||||
class BlockContentListBuilder extends EntityListBuilder {
|
||||
|
||||
use RedirectDestinationTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildHeader() {
|
||||
$header['label'] = t('Block description');
|
||||
return $header + parent::buildHeader();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildRow(EntityInterface $entity) {
|
||||
$row['label'] = $entity->label();
|
||||
return $row + parent::buildRow($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefaultOperations(EntityInterface $entity) {
|
||||
$operations = parent::getDefaultOperations($entity);
|
||||
if (isset($operations['edit'])) {
|
||||
$operations['edit']['query']['destination'] = $this->getRedirectDestination()->get();
|
||||
}
|
||||
return $operations;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\content_translation\ContentTranslationHandler;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Defines the translation handler for custom blocks.
|
||||
*/
|
||||
class BlockContentTranslationHandler extends ContentTranslationHandler {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function entityFormAlter(array &$form, FormStateInterface $form_state, EntityInterface $entity) {
|
||||
parent::entityFormAlter($form, $form_state, $entity);
|
||||
// Move the translation fieldset to a vertical tab.
|
||||
if (isset($form['translation'])) {
|
||||
$form['translation'] += array(
|
||||
'#group' => 'additional_settings',
|
||||
'#weight' => 100,
|
||||
'#attributes' => array(
|
||||
'class' => array('block-content-translation-options'),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function entityFormTitle(EntityInterface $entity) {
|
||||
$block_type = BlockContentType::load($entity->bundle());
|
||||
return t('<em>Edit @type</em> @title', array('@type' => $block_type->label(), '@title' => $entity->label()));
|
||||
}
|
||||
|
||||
}
|
113
web/core/modules/block_content/src/BlockContentTypeForm.php
Normal file
113
web/core/modules/block_content/src/BlockContentTypeForm.php
Normal file
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content;
|
||||
|
||||
use Drupal\Core\Entity\BundleEntityFormBase;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\language\Entity\ContentLanguageSettings;
|
||||
|
||||
/**
|
||||
* Base form for category edit forms.
|
||||
*/
|
||||
class BlockContentTypeForm extends BundleEntityFormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function form(array $form, FormStateInterface $form_state) {
|
||||
$form = parent::form($form, $form_state);
|
||||
|
||||
/* @var \Drupal\block_content\BlockContentTypeInterface $block_type */
|
||||
$block_type = $this->entity;
|
||||
|
||||
if ($this->operation == 'add') {
|
||||
$form['#title'] = $this->t('Add custom block type');
|
||||
}
|
||||
else {
|
||||
$form['#title'] = $this->t('Edit %label custom block type', array('%label' => $block_type->label()));
|
||||
}
|
||||
|
||||
$form['label'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Label'),
|
||||
'#maxlength' => 255,
|
||||
'#default_value' => $block_type->label(),
|
||||
'#description' => t("Provide a label for this block type to help identify it in the administration pages."),
|
||||
'#required' => TRUE,
|
||||
);
|
||||
$form['id'] = array(
|
||||
'#type' => 'machine_name',
|
||||
'#default_value' => $block_type->id(),
|
||||
'#machine_name' => array(
|
||||
'exists' => '\Drupal\block_content\Entity\BlockContentType::load',
|
||||
),
|
||||
'#maxlength' => EntityTypeInterface::BUNDLE_MAX_LENGTH,
|
||||
);
|
||||
|
||||
$form['description'] = array(
|
||||
'#type' => 'textarea',
|
||||
'#default_value' => $block_type->getDescription(),
|
||||
'#description' => t('Enter a description for this block type.'),
|
||||
'#title' => t('Description'),
|
||||
);
|
||||
|
||||
$form['revision'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Create new revision'),
|
||||
'#default_value' => $block_type->shouldCreateNewRevision(),
|
||||
'#description' => t('Create a new revision by default for this block type.'),
|
||||
);
|
||||
|
||||
if ($this->moduleHandler->moduleExists('language')) {
|
||||
$form['language'] = array(
|
||||
'#type' => 'details',
|
||||
'#title' => t('Language settings'),
|
||||
'#group' => 'additional_settings',
|
||||
);
|
||||
|
||||
$language_configuration = ContentLanguageSettings::loadByEntityTypeBundle('block_content', $block_type->id());
|
||||
$form['language']['language_configuration'] = array(
|
||||
'#type' => 'language_configuration',
|
||||
'#entity_information' => array(
|
||||
'entity_type' => 'block_content',
|
||||
'bundle' => $block_type->id(),
|
||||
),
|
||||
'#default_value' => $language_configuration,
|
||||
);
|
||||
|
||||
$form['#submit'][] = 'language_configuration_element_submit';
|
||||
}
|
||||
|
||||
$form['actions'] = array('#type' => 'actions');
|
||||
$form['actions']['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Save'),
|
||||
);
|
||||
|
||||
return $this->protectBundleIdElement($form);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function save(array $form, FormStateInterface $form_state) {
|
||||
$block_type = $this->entity;
|
||||
$status = $block_type->save();
|
||||
|
||||
$edit_link = $this->entity->link($this->t('Edit'));
|
||||
$logger = $this->logger('block_content');
|
||||
if ($status == SAVED_UPDATED) {
|
||||
drupal_set_message(t('Custom block type %label has been updated.', array('%label' => $block_type->label())));
|
||||
$logger->notice('Custom block type %label has been updated.', array('%label' => $block_type->label(), 'link' => $edit_link));
|
||||
}
|
||||
else {
|
||||
block_content_add_body_field($block_type->id());
|
||||
drupal_set_message(t('Custom block type %label has been added.', array('%label' => $block_type->label())));
|
||||
$logger->notice('Custom block type %label has been added.', array('%label' => $block_type->label(), 'link' => $edit_link));
|
||||
}
|
||||
|
||||
$form_state->setRedirectUrl($this->entity->urlInfo('collection'));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityInterface;
|
||||
|
||||
/**
|
||||
* Provides an interface defining a custom block type entity.
|
||||
*/
|
||||
interface BlockContentTypeInterface extends ConfigEntityInterface {
|
||||
|
||||
/**
|
||||
* Returns the description of the block type.
|
||||
*
|
||||
* @return string
|
||||
* The description of the type of this block.
|
||||
*/
|
||||
public function getDescription();
|
||||
|
||||
/**
|
||||
* Returns whether a new revision should be created by default.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if a new revision should be created by default.
|
||||
*/
|
||||
public function shouldCreateNewRevision();
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
|
||||
/**
|
||||
* Defines a class to build a listing of custom block type entities.
|
||||
*
|
||||
* @see \Drupal\block_content\Entity\BlockContentType
|
||||
*/
|
||||
class BlockContentTypeListBuilder extends ConfigEntityListBuilder {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefaultOperations(EntityInterface $entity) {
|
||||
$operations = parent::getDefaultOperations($entity);
|
||||
// Place the edit operation after the operations added by field_ui.module
|
||||
// which have the weights 15, 20, 25.
|
||||
if (isset($operations['edit'])) {
|
||||
$operations['edit']['weight'] = 30;
|
||||
}
|
||||
return $operations;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildHeader() {
|
||||
$header['type'] = t('Block type');
|
||||
$header['description'] = t('Description');
|
||||
return $header + parent::buildHeader();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildRow(EntityInterface $entity) {
|
||||
$row['type'] = $entity->link();
|
||||
$row['description']['data']['#markup'] = $entity->getDescription();
|
||||
return $row + parent::buildRow($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getTitle() {
|
||||
return $this->t('Custom block types');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content;
|
||||
|
||||
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityViewBuilder;
|
||||
|
||||
/**
|
||||
* View builder handler for custom blocks.
|
||||
*/
|
||||
class BlockContentViewBuilder extends EntityViewBuilder {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function view(EntityInterface $entity, $view_mode = 'full', $langcode = NULL) {
|
||||
return $this->viewMultiple(array($entity), $view_mode, $langcode)[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function viewMultiple(array $entities = array(), $view_mode = 'full', $langcode = NULL) {
|
||||
$build_list = parent::viewMultiple($entities, $view_mode, $langcode);
|
||||
// Apply the buildMultiple() #pre_render callback immediately, to make
|
||||
// bubbling of attributes and contextual links to the actual block work.
|
||||
// @see \Drupal\block\BlockViewBuilder::buildBlock()
|
||||
unset($build_list['#pre_render'][0]);
|
||||
return $this->buildMultiple($build_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getBuildDefaults(EntityInterface $entity, $view_mode) {
|
||||
$build = parent::getBuildDefaults($entity, $view_mode);
|
||||
// The custom block will be rendered in the wrapped block template already
|
||||
// and thus has no entity template itself.
|
||||
unset($build['#theme']);
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function alterBuild(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
|
||||
parent::alterBuild($build, $entity, $display, $view_mode);
|
||||
// Add contextual links for this custom block.
|
||||
if (!$entity->isNew()) {
|
||||
$build['#contextual_links']['block_content'] = array(
|
||||
'route_parameters' => array('block_content' => $entity->id()),
|
||||
'metadata' => array('changed' => $entity->getChangedTime()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
54
web/core/modules/block_content/src/BlockContentViewsData.php
Normal file
54
web/core/modules/block_content/src/BlockContentViewsData.php
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content;
|
||||
|
||||
use Drupal\views\EntityViewsData;
|
||||
|
||||
/**
|
||||
* Provides the views data for the block_content entity type.
|
||||
*/
|
||||
class BlockContentViewsData extends EntityViewsData {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getViewsData() {
|
||||
|
||||
$data = parent::getViewsData();
|
||||
|
||||
$data['block_content_field_data']['id']['field']['id'] = 'field';
|
||||
|
||||
$data['block_content_field_data']['info']['field']['id'] = 'field';
|
||||
$data['block_content_field_data']['info']['field']['link_to_entity default'] = TRUE;
|
||||
|
||||
$data['block_content_field_data']['type']['field']['id'] = 'field';
|
||||
|
||||
$data['block_content']['block_content_listing_empty'] = array(
|
||||
'title' => $this->t('Empty block library behavior'),
|
||||
'help' => $this->t('Provides a link to add a new block.'),
|
||||
'area' => array(
|
||||
'id' => 'block_content_listing_empty',
|
||||
),
|
||||
);
|
||||
// Advertise this table as a possible base table.
|
||||
$data['block_content_field_revision']['table']['base']['help'] = $this->t('Block Content revision is a history of changes to block content.');
|
||||
$data['block_content_field_revision']['table']['base']['defaults']['title'] = 'info';
|
||||
|
||||
// @todo EntityViewsData should add these relationships by default.
|
||||
// https://www.drupal.org/node/2410275
|
||||
$data['block_content_field_revision']['id']['relationship']['id'] = 'standard';
|
||||
$data['block_content_field_revision']['id']['relationship']['base'] = 'block_content_field_data';
|
||||
$data['block_content_field_revision']['id']['relationship']['base field'] = 'id';
|
||||
$data['block_content_field_revision']['id']['relationship']['title'] = $this->t('Block Content');
|
||||
$data['block_content_field_revision']['id']['relationship']['label'] = $this->t('Get the actual block content from a block content revision.');
|
||||
|
||||
$data['block_content_field_revision']['revision_id']['relationship']['id'] = 'standard';
|
||||
$data['block_content_field_revision']['revision_id']['relationship']['base'] = 'block_content_field_data';
|
||||
$data['block_content_field_revision']['revision_id']['relationship']['base field'] = 'revision_id';
|
||||
$data['block_content_field_revision']['revision_id']['relationship']['title'] = $this->t('Block Content');
|
||||
$data['block_content_field_revision']['revision_id']['relationship']['label'] = $this->t('Get the actual block content from a block content revision.');
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Controller;
|
||||
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\block_content\BlockContentTypeInterface;
|
||||
use Drupal\Core\Extension\ThemeHandlerInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class BlockContentController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* The custom block storage.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
*/
|
||||
protected $blockContentStorage;
|
||||
|
||||
/**
|
||||
* The custom block type storage.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
*/
|
||||
protected $blockContentTypeStorage;
|
||||
|
||||
/**
|
||||
* The theme handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ThemeHandlerInterface
|
||||
*/
|
||||
protected $themeHandler;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
$entity_manager = $container->get('entity.manager');
|
||||
return new static(
|
||||
$entity_manager->getStorage('block_content'),
|
||||
$entity_manager->getStorage('block_content_type'),
|
||||
$container->get('theme_handler')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a BlockContent object.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityStorageInterface $block_content_storage
|
||||
* The custom block storage.
|
||||
* @param \Drupal\Core\Entity\EntityStorageInterface $block_content_type_storage
|
||||
* The custom block type storage.
|
||||
* @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
|
||||
* The theme handler.
|
||||
*/
|
||||
public function __construct(EntityStorageInterface $block_content_storage, EntityStorageInterface $block_content_type_storage, ThemeHandlerInterface $theme_handler) {
|
||||
$this->blockContentStorage = $block_content_storage;
|
||||
$this->blockContentTypeStorage = $block_content_type_storage;
|
||||
$this->themeHandler = $theme_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays add custom block links for available types.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The current request object.
|
||||
*
|
||||
* @return array
|
||||
* A render array for a list of the custom block types that can be added or
|
||||
* if there is only one custom block type defined for the site, the function
|
||||
* returns the custom block add page for that custom block type.
|
||||
*/
|
||||
public function add(Request $request) {
|
||||
$types = $this->blockContentTypeStorage->loadMultiple();
|
||||
if ($types && count($types) == 1) {
|
||||
$type = reset($types);
|
||||
return $this->addForm($type, $request);
|
||||
}
|
||||
if (count($types) === 0) {
|
||||
return array(
|
||||
'#markup' => $this->t('You have not created any block types yet. Go to the <a href=":url">block type creation page</a> to add a new block type.', [
|
||||
':url' => Url::fromRoute('block_content.type_add')->toString(),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
return array('#theme' => 'block_content_add_list', '#content' => $types);
|
||||
}
|
||||
|
||||
/**
|
||||
* Presents the custom block creation form.
|
||||
*
|
||||
* @param \Drupal\block_content\BlockContentTypeInterface $block_content_type
|
||||
* The custom block type to add.
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The current request object.
|
||||
*
|
||||
* @return array
|
||||
* A form array as expected by drupal_render().
|
||||
*/
|
||||
public function addForm(BlockContentTypeInterface $block_content_type, Request $request) {
|
||||
$block = $this->blockContentStorage->create(array(
|
||||
'type' => $block_content_type->id()
|
||||
));
|
||||
if (($theme = $request->query->get('theme')) && in_array($theme, array_keys($this->themeHandler->listInfo()))) {
|
||||
// We have navigated to this page from the block library and will keep track
|
||||
// of the theme for redirecting the user to the configuration page for the
|
||||
// newly created block in the given theme.
|
||||
$block->setTheme($theme);
|
||||
}
|
||||
return $this->entityFormBuilder()->getForm($block);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the page title for this controller.
|
||||
*
|
||||
* @param \Drupal\block_content\BlockContentTypeInterface $block_content_type
|
||||
* The custom block type being added.
|
||||
*
|
||||
* @return string
|
||||
* The page title.
|
||||
*/
|
||||
public function getAddFormTitle(BlockContentTypeInterface $block_content_type) {
|
||||
return $this->t('Add %type custom block', array('%type' => $block_content_type->label()));
|
||||
}
|
||||
|
||||
}
|
301
web/core/modules/block_content/src/Entity/BlockContent.php
Normal file
301
web/core/modules/block_content/src/Entity/BlockContent.php
Normal file
|
@ -0,0 +1,301 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Entity;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityBase;
|
||||
use Drupal\Core\Entity\EntityChangedTrait;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\block_content\BlockContentInterface;
|
||||
use Drupal\user\UserInterface;
|
||||
|
||||
/**
|
||||
* Defines the custom block entity class.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "block_content",
|
||||
* label = @Translation("Custom block"),
|
||||
* bundle_label = @Translation("Custom block type"),
|
||||
* handlers = {
|
||||
* "storage" = "Drupal\Core\Entity\Sql\SqlContentEntityStorage",
|
||||
* "access" = "Drupal\block_content\BlockContentAccessControlHandler",
|
||||
* "list_builder" = "Drupal\block_content\BlockContentListBuilder",
|
||||
* "view_builder" = "Drupal\block_content\BlockContentViewBuilder",
|
||||
* "views_data" = "Drupal\block_content\BlockContentViewsData",
|
||||
* "form" = {
|
||||
* "add" = "Drupal\block_content\BlockContentForm",
|
||||
* "edit" = "Drupal\block_content\BlockContentForm",
|
||||
* "delete" = "Drupal\block_content\Form\BlockContentDeleteForm",
|
||||
* "default" = "Drupal\block_content\BlockContentForm"
|
||||
* },
|
||||
* "translation" = "Drupal\block_content\BlockContentTranslationHandler"
|
||||
* },
|
||||
* admin_permission = "administer blocks",
|
||||
* base_table = "block_content",
|
||||
* revision_table = "block_content_revision",
|
||||
* data_table = "block_content_field_data",
|
||||
* links = {
|
||||
* "canonical" = "/block/{block_content}",
|
||||
* "delete-form" = "/block/{block_content}/delete",
|
||||
* "edit-form" = "/block/{block_content}",
|
||||
* "collection" = "/admin/structure/block/block-content",
|
||||
* },
|
||||
* translatable = TRUE,
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "revision" = "revision_id",
|
||||
* "bundle" = "type",
|
||||
* "label" = "info",
|
||||
* "langcode" = "langcode",
|
||||
* "uuid" = "uuid"
|
||||
* },
|
||||
* bundle_entity_type = "block_content_type",
|
||||
* field_ui_base_route = "entity.block_content_type.edit_form",
|
||||
* render_cache = FALSE,
|
||||
* )
|
||||
*
|
||||
* Note that render caching of block_content entities is disabled because they
|
||||
* are always rendered as blocks, and blocks already have their own render
|
||||
* caching.
|
||||
* See https://www.drupal.org/node/2284917#comment-9132521 for more information.
|
||||
*/
|
||||
class BlockContent extends ContentEntityBase implements BlockContentInterface {
|
||||
|
||||
use EntityChangedTrait;
|
||||
|
||||
/**
|
||||
* The theme the block is being created in.
|
||||
*
|
||||
* When creating a new custom block from the block library, the user is
|
||||
* redirected to the configure form for that block in the given theme. The
|
||||
* theme is stored against the block when the custom block add form is shown.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $theme;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createDuplicate() {
|
||||
$duplicate = parent::createDuplicate();
|
||||
$duplicate->revision_id->value = NULL;
|
||||
$duplicate->id->value = NULL;
|
||||
return $duplicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setTheme($theme) {
|
||||
$this->theme = $theme;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTheme() {
|
||||
return $this->theme;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function postSave(EntityStorageInterface $storage, $update = TRUE) {
|
||||
parent::postSave($storage, $update);
|
||||
static::invalidateBlockPluginCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function postDelete(EntityStorageInterface $storage, array $entities) {
|
||||
parent::postDelete($storage, $entities);
|
||||
static::invalidateBlockPluginCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getInstances() {
|
||||
return \Drupal::entityTypeManager()->getStorage('block')->loadByProperties(array('plugin' => 'block_content:' . $this->uuid()));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function preSaveRevision(EntityStorageInterface $storage, \stdClass $record) {
|
||||
parent::preSaveRevision($storage, $record);
|
||||
|
||||
if (!$this->isNewRevision() && isset($this->original) && (!isset($record->revision_log) || $record->revision_log === '')) {
|
||||
// If we are updating an existing block_content without adding a new
|
||||
// revision and the user did not supply a revision log, keep the existing
|
||||
// one.
|
||||
$record->revision_log = $this->original->getRevisionLogMessage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function delete() {
|
||||
foreach ($this->getInstances() as $instance) {
|
||||
$instance->delete();
|
||||
}
|
||||
parent::delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
|
||||
/** @var \Drupal\Core\Field\BaseFieldDefinition[] $fields */
|
||||
$fields = parent::baseFieldDefinitions($entity_type);
|
||||
|
||||
$fields['id']->setLabel(t('Custom block ID'))
|
||||
->setDescription(t('The custom block ID.'));
|
||||
|
||||
$fields['uuid']->setDescription(t('The custom block UUID.'));
|
||||
|
||||
$fields['revision_id']->setDescription(t('The revision ID.'));
|
||||
|
||||
$fields['langcode']->setDescription(t('The custom block language code.'));
|
||||
|
||||
$fields['type']->setLabel(t('Block type'))
|
||||
->setDescription(t('The block type.'));
|
||||
|
||||
$fields['info'] = BaseFieldDefinition::create('string')
|
||||
->setLabel(t('Block description'))
|
||||
->setDescription(t('A brief description of your block.'))
|
||||
->setRevisionable(TRUE)
|
||||
->setTranslatable(TRUE)
|
||||
->setRequired(TRUE)
|
||||
->setDisplayOptions('form', array(
|
||||
'type' => 'string_textfield',
|
||||
'weight' => -5,
|
||||
))
|
||||
->setDisplayConfigurable('form', TRUE)
|
||||
->addConstraint('UniqueField', []);
|
||||
|
||||
$fields['revision_log'] = BaseFieldDefinition::create('string_long')
|
||||
->setLabel(t('Revision log message'))
|
||||
->setDescription(t('The log entry explaining the changes in this revision.'))
|
||||
->setRevisionable(TRUE);
|
||||
|
||||
$fields['changed'] = BaseFieldDefinition::create('changed')
|
||||
->setLabel(t('Changed'))
|
||||
->setDescription(t('The time that the custom block was last edited.'))
|
||||
->setTranslatable(TRUE)
|
||||
->setRevisionable(TRUE);
|
||||
|
||||
$fields['revision_created'] = BaseFieldDefinition::create('created')
|
||||
->setLabel(t('Revision create time'))
|
||||
->setDescription(t('The time that the current revision was created.'))
|
||||
->setRevisionable(TRUE);
|
||||
|
||||
$fields['revision_user'] = BaseFieldDefinition::create('entity_reference')
|
||||
->setLabel(t('Revision user'))
|
||||
->setDescription(t('The user ID of the author of the current revision.'))
|
||||
->setSetting('target_type', 'user')
|
||||
->setRevisionable(TRUE);
|
||||
|
||||
$fields['revision_translation_affected'] = BaseFieldDefinition::create('boolean')
|
||||
->setLabel(t('Revision translation affected'))
|
||||
->setDescription(t('Indicates if the last edit of a translation belongs to current revision.'))
|
||||
->setReadOnly(TRUE)
|
||||
->setRevisionable(TRUE)
|
||||
->setTranslatable(TRUE);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRevisionLog() {
|
||||
return $this->getRevisionLogMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setInfo($info) {
|
||||
$this->set('info', $info);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setRevisionLog($revision_log) {
|
||||
return $this->setRevisionLogMessage($revision_log);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRevisionCreationTime() {
|
||||
return $this->get('revision_created')->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setRevisionCreationTime($timestamp) {
|
||||
$this->set('revision_created', $timestamp);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRevisionUser() {
|
||||
return $this->get('revision_user')->entity;
|
||||
}
|
||||
|
||||
public function setRevisionUser(UserInterface $account) {
|
||||
$this->set('revision_user', $account);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRevisionUserId() {
|
||||
return $this->get('revision_user')->entity->id();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setRevisionUserId($user_id) {
|
||||
$this->set('revision_user', $user_id);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRevisionLogMessage() {
|
||||
return $this->get('revision_log')->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setRevisionLogMessage($revision_log_message) {
|
||||
$this->set('revision_log', $revision_log_message);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates the block plugin cache after changes and deletions.
|
||||
*/
|
||||
protected static function invalidateBlockPluginCache() {
|
||||
// Invalidate the block cache to update custom block-based derivatives.
|
||||
\Drupal::service('plugin.manager.block')->clearCachedDefinitions();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Entity;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityBundleBase;
|
||||
use Drupal\block_content\BlockContentTypeInterface;
|
||||
|
||||
/**
|
||||
* Defines the custom block type entity.
|
||||
*
|
||||
* @ConfigEntityType(
|
||||
* id = "block_content_type",
|
||||
* label = @Translation("Custom block type"),
|
||||
* handlers = {
|
||||
* "form" = {
|
||||
* "default" = "Drupal\block_content\BlockContentTypeForm",
|
||||
* "add" = "Drupal\block_content\BlockContentTypeForm",
|
||||
* "edit" = "Drupal\block_content\BlockContentTypeForm",
|
||||
* "delete" = "Drupal\block_content\Form\BlockContentTypeDeleteForm"
|
||||
* },
|
||||
* "list_builder" = "Drupal\block_content\BlockContentTypeListBuilder"
|
||||
* },
|
||||
* admin_permission = "administer blocks",
|
||||
* config_prefix = "type",
|
||||
* bundle_of = "block_content",
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "label" = "label"
|
||||
* },
|
||||
* links = {
|
||||
* "delete-form" = "/admin/structure/block/block-content/manage/{block_content_type}/delete",
|
||||
* "edit-form" = "/admin/structure/block/block-content/manage/{block_content_type}",
|
||||
* "collection" = "/admin/structure/block/block-content/types",
|
||||
* },
|
||||
* config_export = {
|
||||
* "id",
|
||||
* "label",
|
||||
* "revision",
|
||||
* "description",
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class BlockContentType extends ConfigEntityBundleBase implements BlockContentTypeInterface {
|
||||
|
||||
/**
|
||||
* The custom block type ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* The custom block type label.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $label;
|
||||
|
||||
/**
|
||||
* The default revision setting for custom blocks of this type.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $revision;
|
||||
|
||||
/**
|
||||
* The description of the block type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDescription() {
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function shouldCreateNewRevision() {
|
||||
return $this->revision;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Form;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityDeleteForm;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Provides a confirmation form for deleting a custom block entity.
|
||||
*/
|
||||
class BlockContentDeleteForm extends ContentEntityDeleteForm {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$instances = $this->entity->getInstances();
|
||||
|
||||
$form['message'] = array(
|
||||
'#markup' => $this->formatPlural(count($instances), 'This will also remove 1 placed block instance.', 'This will also remove @count placed block instances.'),
|
||||
'#access' => !empty($instances),
|
||||
);
|
||||
|
||||
return parent::buildForm($form, $form_state);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Form;
|
||||
|
||||
use Drupal\Core\Entity\EntityDeleteForm;
|
||||
use Drupal\Core\Entity\Query\QueryFactory;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides a confirmation form for deleting a custom block type entity.
|
||||
*/
|
||||
class BlockContentTypeDeleteForm extends EntityDeleteForm {
|
||||
|
||||
/**
|
||||
* The query factory to create entity queries.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\Query\QueryFactory
|
||||
*/
|
||||
public $queryFactory;
|
||||
|
||||
/**
|
||||
* Constructs a query factory object.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\Query\QueryFactory $query_factory
|
||||
* The entity query object.
|
||||
*/
|
||||
public function __construct(QueryFactory $query_factory) {
|
||||
$this->queryFactory = $query_factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('entity.query')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$blocks = $this->queryFactory->get('block_content')->condition('type', $this->entity->id())->execute();
|
||||
if (!empty($blocks)) {
|
||||
$caption = '<p>' . $this->formatPlural(count($blocks), '%label is used by 1 custom block on your site. You can not remove this block type until you have removed all of the %label blocks.', '%label is used by @count custom blocks on your site. You may not remove %label until you have removed all of the %label custom blocks.', array('%label' => $this->entity->label())) . '</p>';
|
||||
$form['description'] = array('#markup' => $caption);
|
||||
return $form;
|
||||
}
|
||||
else {
|
||||
return parent::buildForm($form, $form_state);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Plugin\Block;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Block\BlockBase;
|
||||
use Drupal\Core\Block\BlockManagerInterface;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Routing\UrlGeneratorInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Defines a generic custom block type.
|
||||
*
|
||||
* @Block(
|
||||
* id = "block_content",
|
||||
* admin_label = @Translation("Custom block"),
|
||||
* category = @Translation("Custom"),
|
||||
* deriver = "Drupal\block_content\Plugin\Derivative\BlockContent"
|
||||
* )
|
||||
*/
|
||||
class BlockContentBlock extends BlockBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* The Plugin Block Manager.
|
||||
*
|
||||
* @var \Drupal\Core\Block\BlockManagerInterface.
|
||||
*/
|
||||
protected $blockManager;
|
||||
|
||||
/**
|
||||
* The entity manager service.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityManagerInterface
|
||||
*/
|
||||
protected $entityManager;
|
||||
|
||||
/**
|
||||
* The Drupal account to use for checking for access to block.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface.
|
||||
*/
|
||||
protected $account;
|
||||
|
||||
/**
|
||||
* The block content entity.
|
||||
*
|
||||
* @var \Drupal\block_content\BlockContentInterface
|
||||
*/
|
||||
protected $blockContent;
|
||||
|
||||
/**
|
||||
* The URL generator.
|
||||
*
|
||||
* @var \Drupal\Core\Routing\UrlGeneratorInterface
|
||||
*/
|
||||
protected $urlGenerator;
|
||||
|
||||
/**
|
||||
* Constructs a new BlockContentBlock.
|
||||
*
|
||||
* @param array $configuration
|
||||
* A configuration array containing information about the plugin instance.
|
||||
* @param string $plugin_id
|
||||
* The plugin ID for the plugin instance.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
* @param \Drupal\Core\Block\BlockManagerInterface $block_manager
|
||||
* The Plugin Block Manager.
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager service.
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The account for which view access should be checked.
|
||||
* @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
|
||||
* The URL generator.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, BlockManagerInterface $block_manager, EntityManagerInterface $entity_manager, AccountInterface $account, UrlGeneratorInterface $url_generator) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
|
||||
$this->blockManager = $block_manager;
|
||||
$this->entityManager = $entity_manager;
|
||||
$this->account = $account;
|
||||
$this->urlGenerator = $url_generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('plugin.manager.block'),
|
||||
$container->get('entity.manager'),
|
||||
$container->get('current_user'),
|
||||
$container->get('url_generator')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defaultConfiguration() {
|
||||
return array(
|
||||
'status' => TRUE,
|
||||
'info' => '',
|
||||
'view_mode' => 'full',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides \Drupal\Core\Block\BlockBase::blockForm().
|
||||
*
|
||||
* Adds body and description fields to the block configuration form.
|
||||
*/
|
||||
public function blockForm($form, FormStateInterface $form_state) {
|
||||
$uuid = $this->getDerivativeId();
|
||||
$block = $this->entityManager->loadEntityByUuid('block_content', $uuid);
|
||||
$options = $this->entityManager->getViewModeOptionsByBundle('block_content', $block->bundle());
|
||||
|
||||
$form['view_mode'] = array(
|
||||
'#type' => 'select',
|
||||
'#options' => $options,
|
||||
'#title' => $this->t('View mode'),
|
||||
'#description' => $this->t('Output the block in this view mode.'),
|
||||
'#default_value' => $this->configuration['view_mode'],
|
||||
'#access' => (count($options) > 1),
|
||||
);
|
||||
$form['title']['#description'] = $this->t('The title of the block as shown to the user.');
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function blockSubmit($form, FormStateInterface $form_state) {
|
||||
// Invalidate the block cache to update custom block-based derivatives.
|
||||
$this->configuration['view_mode'] = $form_state->getValue('view_mode');
|
||||
$this->blockManager->clearCachedDefinitions();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function blockAccess(AccountInterface $account) {
|
||||
if ($this->getEntity()) {
|
||||
return $this->getEntity()->access('view', $account, TRUE);
|
||||
}
|
||||
return AccessResult::forbidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function build() {
|
||||
if ($block = $this->getEntity()) {
|
||||
return $this->entityManager->getViewBuilder($block->getEntityTypeId())->view($block, $this->configuration['view_mode']);
|
||||
}
|
||||
else {
|
||||
return array(
|
||||
'#markup' => $this->t('Block with uuid %uuid does not exist. <a href=":url">Add custom block</a>.', array(
|
||||
'%uuid' => $this->getDerivativeId(),
|
||||
':url' => $this->urlGenerator->generate('block_content.add_page')
|
||||
)),
|
||||
'#access' => $this->account->hasPermission('administer blocks')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the block content entity of the block.
|
||||
*
|
||||
* @return \Drupal\block_content\BlockContentInterface|null
|
||||
* The block content entity.
|
||||
*/
|
||||
protected function getEntity() {
|
||||
$uuid = $this->getDerivativeId();
|
||||
if (!isset($this->blockContent)) {
|
||||
$this->blockContent = $this->entityManager->loadEntityByUuid('block_content', $uuid);
|
||||
}
|
||||
return $this->blockContent;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Plugin\Derivative;
|
||||
|
||||
use Drupal\Component\Plugin\Derivative\DeriverBase;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Retrieves block plugin definitions for all custom blocks.
|
||||
*/
|
||||
class BlockContent extends DeriverBase implements ContainerDeriverInterface {
|
||||
|
||||
/**
|
||||
* The custom block storage.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
*/
|
||||
protected $blockContentStorage;
|
||||
|
||||
/**
|
||||
* Constructs a BlockContent object.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityStorageInterface $block_content_storage
|
||||
* The custom block storage.
|
||||
*/
|
||||
public function __construct(EntityStorageInterface $block_content_storage) {
|
||||
$this->blockContentStorage = $block_content_storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, $base_plugin_id) {
|
||||
$entity_manager = $container->get('entity.manager');
|
||||
return new static(
|
||||
$entity_manager->getStorage('block_content')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDerivativeDefinitions($base_plugin_definition) {
|
||||
$block_contents = $this->blockContentStorage->loadMultiple();
|
||||
// Reset the discovered definitions.
|
||||
$this->derivatives = [];
|
||||
/** @var $block_content \Drupal\block_content\Entity\BlockContent */
|
||||
foreach ($block_contents as $block_content) {
|
||||
$this->derivatives[$block_content->uuid()] = $base_plugin_definition;
|
||||
$this->derivatives[$block_content->uuid()]['admin_label'] = $block_content->label();
|
||||
$this->derivatives[$block_content->uuid()]['config_dependencies']['content'] = array(
|
||||
$block_content->getConfigDependencyName()
|
||||
);
|
||||
}
|
||||
return parent::getDerivativeDefinitions($base_plugin_definition);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Plugin\Menu\LocalAction;
|
||||
|
||||
use Drupal\Core\Menu\LocalActionDefault;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Core\Routing\UrlGeneratorTrait;
|
||||
|
||||
/**
|
||||
* Modifies the 'Add custom block' local action.
|
||||
*/
|
||||
class BlockContentAddLocalAction extends LocalActionDefault {
|
||||
use UrlGeneratorTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getOptions(RouteMatchInterface $route_match) {
|
||||
$options = parent::getOptions($route_match);
|
||||
// If the route specifies a theme, append it to the query string.
|
||||
if ($theme = $route_match->getParameter('theme')) {
|
||||
$options['query']['theme'] = $theme;
|
||||
}
|
||||
// Adds a destination on custom block listing.
|
||||
if ($route_match->getRouteName() == 'entity.block_content.collection') {
|
||||
$options['query']['destination'] = $this->url('<current>');
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
|
||||
/**
|
||||
* Drupal 6 block source from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d6_box"
|
||||
* )
|
||||
*/
|
||||
class Box extends DrupalSqlBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
$query = $this->select('boxes', 'b')
|
||||
->fields('b', array('bid', 'body', 'info', 'format'));
|
||||
$query->orderBy('b.bid');
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return array(
|
||||
'bid' => $this->t('The numeric identifier of the block/box'),
|
||||
'body' => $this->t('The block/box content'),
|
||||
'info' => $this->t('Admin title of the block/box.'),
|
||||
'format' => $this->t('Input format of the custom block/box content.'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids['bid']['type'] = 'integer';
|
||||
return $ids;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
|
||||
/**
|
||||
* Drupal 7 custom block source from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d7_block_custom"
|
||||
* )
|
||||
*/
|
||||
class BlockCustom extends DrupalSqlBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
return $this->select('block_custom', 'b')->fields('b');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return array(
|
||||
'bid' => $this->t('The numeric identifier of the block/box'),
|
||||
'body' => $this->t('The block/box content'),
|
||||
'info' => $this->t('Admin title of the block/box.'),
|
||||
'format' => $this->t('Input format of the custom block/box content.'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids['bid']['type'] = 'integer';
|
||||
return $ids;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Plugin\views\area;
|
||||
|
||||
use Drupal\Core\Access\AccessManagerInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\views\Plugin\views\area\AreaPluginBase;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Defines an area plugin to display a block add link.
|
||||
*
|
||||
* @ingroup views_area_handlers
|
||||
*
|
||||
* @ViewsArea("block_content_listing_empty")
|
||||
*/
|
||||
class ListingEmpty extends AreaPluginBase {
|
||||
|
||||
/**
|
||||
* The access manager.
|
||||
*
|
||||
* @var \Drupal\Core\Access\AccessManagerInterface
|
||||
*/
|
||||
protected $accessManager;
|
||||
|
||||
/**
|
||||
* The current user.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $currentUser;
|
||||
|
||||
/**
|
||||
* Constructs a new ListingEmpty.
|
||||
*
|
||||
* @param array $configuration
|
||||
* A configuration array containing information about the plugin instance.
|
||||
* @param string $plugin_id
|
||||
* The plugin ID for the plugin instance.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
* @param \Drupal\Core\Access\AccessManagerInterface $access_manager
|
||||
* The access manager.
|
||||
* @param \Drupal\Core\Session\AccountInterface $current_user
|
||||
* The current user.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, AccessManagerInterface $access_manager, AccountInterface $current_user) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
|
||||
$this->accessManager = $access_manager;
|
||||
$this->currentUser = $current_user;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('access_manager'),
|
||||
$container->get('current_user')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function render($empty = FALSE) {
|
||||
if (!$empty || !empty($this->options['empty'])) {
|
||||
/** @var \Drupal\Core\Access\AccessResultInterface|\Drupal\Core\Cache\CacheableDependencyInterface $access_result */
|
||||
$access_result = $this->accessManager->checkNamedRoute('block_content.add_page', array(), $this->currentUser, TRUE);
|
||||
$element = array(
|
||||
'#markup' => $this->t('Add a <a href=":url">custom block</a>.', array(':url' => Url::fromRoute('block_content.add_page')->toString())),
|
||||
'#access' => $access_result->isAllowed(),
|
||||
'#cache' => [
|
||||
'contexts' => $access_result->getCacheContexts(),
|
||||
'tags' => $access_result->getCacheTags(),
|
||||
'max-age' => $access_result->getCacheMaxAge(),
|
||||
],
|
||||
);
|
||||
return $element;
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Tests;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\system\Tests\Entity\EntityCacheTagsTestBase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Tests the Custom Block entity's cache tags.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentCacheTagsTest extends EntityCacheTagsTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = array('block_content');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
$block_content_type = BlockContentType::create(array(
|
||||
'id' => 'basic',
|
||||
'label' => 'basic',
|
||||
'revision' => FALSE
|
||||
));
|
||||
$block_content_type->save();
|
||||
block_content_add_body_field($block_content_type->id());
|
||||
|
||||
// Create a "Llama" custom block.
|
||||
$block_content = BlockContent::create(array(
|
||||
'info' => 'Llama',
|
||||
'type' => 'basic',
|
||||
'body' => array(
|
||||
'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) {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Each comment must have a comment body, which always has a text format.
|
||||
*/
|
||||
protected function getAdditionalCacheTagsForEntity(EntityInterface $entity) {
|
||||
return ['config:filter.format.plain_text'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the block is cached with the correct contexts and tags.
|
||||
*/
|
||||
public function testBlock() {
|
||||
$block = $this->drupalPlaceBlock('block_content:' . $this->entity->uuid());
|
||||
$build = $this->container->get('entity.manager')->getViewBuilder('block')->view($block, 'block');
|
||||
|
||||
// Render the block.
|
||||
// @todo The request stack manipulation won't be necessary once
|
||||
// https://www.drupal.org/node/2367555 is fixed and the
|
||||
// corresponding $request->isMethodSafe() checks are removed from
|
||||
// Drupal\Core\Render\Renderer.
|
||||
$request_stack = $this->container->get('request_stack');
|
||||
$request_stack->push(new Request());
|
||||
$this->container->get('renderer')->renderRoot($build);
|
||||
$request_stack->pop();
|
||||
|
||||
// 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_contexts = ['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions'];
|
||||
$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_contexts = ['theme'];
|
||||
$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.
|
||||
$cid = $this->createCacheId($expected_block_cache_keys, $expected_block_cache_contexts);
|
||||
$redirected_cid = $this->createCacheId($expected_block_cache_keys, Cache::mergeContexts($expected_block_cache_contexts, $expected_entity_cache_contexts));
|
||||
$this->verifyRenderCache($cid, Cache::mergeTags($expected_block_cache_tags, $expected_entity_cache_tags), ($cid !== $redirected_cid) ? $redirected_cid : NULL);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,302 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Tests;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Database\Database;
|
||||
|
||||
/**
|
||||
* Create a block and test saving it.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentCreationTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* Enable dummy module that implements hook_block_insert() for exceptions and
|
||||
* field_ui to edit display settings.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('block_content_test', 'dblog', 'field_ui');
|
||||
|
||||
/**
|
||||
* Permissions to grant admin user.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $permissions = array(
|
||||
'administer blocks',
|
||||
'administer block_content display'
|
||||
);
|
||||
|
||||
/**
|
||||
* Sets the test up.
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->drupalLogin($this->adminUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a "Basic page" block and verifies its consistency in the database.
|
||||
*/
|
||||
public function testBlockContentCreation() {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Create a block.
|
||||
$edit = array();
|
||||
$edit['info[0][value]'] = 'Test Block';
|
||||
$edit['body[0][value]'] = $this->randomMachineName(16);
|
||||
$this->drupalPostForm('block/add/basic', $edit, t('Save'));
|
||||
|
||||
// Check that the Basic block has been created.
|
||||
$this->assertRaw(format_string('@block %name has been created.', array(
|
||||
'@block' => 'basic',
|
||||
'%name' => $edit['info[0][value]']
|
||||
)), 'Basic block created.');
|
||||
|
||||
// Check that the view mode setting is hidden because only one exists.
|
||||
$this->assertNoFieldByXPath('//select[@name="settings[view_mode]"]', NULL, 'View mode setting hidden because only one exists');
|
||||
|
||||
// Check that the block exists in the database.
|
||||
$blocks = entity_load_multiple_by_properties('block_content', array('info' => $edit['info[0][value]']));
|
||||
$block = reset($blocks);
|
||||
$this->assertTrue($block, 'Custom Block found in database.');
|
||||
|
||||
// Check that attempting to create another block with the same value for
|
||||
// 'info' returns an error.
|
||||
$this->drupalPostForm('block/add/basic', $edit, t('Save'));
|
||||
|
||||
// Check that the Basic block has been created.
|
||||
$this->assertRaw(format_string('A custom block with block description %value already exists.', array(
|
||||
'%value' => $edit['info[0][value]']
|
||||
)));
|
||||
$this->assertResponse(200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a "Basic page" block with multiple view modes.
|
||||
*/
|
||||
public function testBlockContentCreationMultipleViewModes() {
|
||||
// Add a new view mode and verify if it is selected as expected.
|
||||
$this->drupalLogin($this->drupalCreateUser(array('administer display modes')));
|
||||
$this->drupalGet('admin/structure/display-modes/view/add/block_content');
|
||||
$edit = array(
|
||||
'id' => 'test_view_mode',
|
||||
'label' => 'Test View Mode',
|
||||
);
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
$this->assertRaw(t('Saved the %label view mode.', array('%label' => $edit['label'])));
|
||||
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Create a block.
|
||||
$edit = array();
|
||||
$edit['info[0][value]'] = 'Test Block';
|
||||
$edit['body[0][value]'] = $this->randomMachineName(16);
|
||||
$this->drupalPostForm('block/add/basic', $edit, t('Save'));
|
||||
|
||||
// Check that the Basic block has been created.
|
||||
$this->assertRaw(format_string('@block %name has been created.', array(
|
||||
'@block' => 'basic',
|
||||
'%name' => $edit['info[0][value]']
|
||||
)), 'Basic block created.');
|
||||
|
||||
// Save our block permanently
|
||||
$this->drupalPostForm(NULL, NULL, t('Save block'));
|
||||
|
||||
// Set test_view_mode as a custom display to be available on the list.
|
||||
$this->drupalGet('admin/structure/block/block-content');
|
||||
$this->drupalGet('admin/structure/block/block-content/types');
|
||||
$this->clickLink(t('Manage display'));
|
||||
$this->drupalGet('admin/structure/block/block-content/manage/basic/display');
|
||||
$custom_view_mode = array(
|
||||
'display_modes_custom[test_view_mode]' => 1,
|
||||
);
|
||||
$this->drupalPostForm(NULL, $custom_view_mode, t('Save'));
|
||||
|
||||
// Go to the configure page and change the view mode.
|
||||
$this->drupalGet('admin/structure/block/manage/testblock');
|
||||
|
||||
// Test the available view mode options.
|
||||
$this->assertOption('edit-settings-view-mode', 'default', 'The default view mode is available.');
|
||||
$this->assertOption('edit-settings-view-mode', 'test_view_mode', 'The test view mode is available.');
|
||||
|
||||
$view_mode['settings[view_mode]'] = 'test_view_mode';
|
||||
$this->drupalPostForm(NULL, $view_mode, t('Save block'));
|
||||
|
||||
// Check that the view mode setting is shown because more than one exists.
|
||||
$this->drupalGet('admin/structure/block/manage/testblock');
|
||||
$this->assertFieldByXPath('//select[@name="settings[view_mode]"]', NULL, 'View mode setting shown because multiple exist');
|
||||
|
||||
// Change the view mode.
|
||||
$view_mode['settings[view_mode]'] = 'test_view_mode';
|
||||
$this->drupalPostForm(NULL, $view_mode, t('Save block'));
|
||||
|
||||
// Go to the configure page and verify the view mode has changed.
|
||||
$this->drupalGet('admin/structure/block/manage/testblock');
|
||||
$this->assertFieldByXPath('//select[@name="settings[view_mode]"]/option[@selected="selected"]/@value', 'test_view_mode', 'View mode changed to Test View Mode');
|
||||
|
||||
// Check that the block exists in the database.
|
||||
$blocks = entity_load_multiple_by_properties('block_content', array('info' => $edit['info[0][value]']));
|
||||
$block = reset($blocks);
|
||||
$this->assertTrue($block, 'Custom Block found in database.');
|
||||
|
||||
// Check that attempting to create another block with the same value for
|
||||
// 'info' returns an error.
|
||||
$this->drupalPostForm('block/add/basic', $edit, t('Save'));
|
||||
|
||||
// Check that the Basic block has been created.
|
||||
$this->assertRaw(format_string('A custom block with block description %value already exists.', array(
|
||||
'%value' => $edit['info[0][value]']
|
||||
)));
|
||||
$this->assertResponse(200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a default custom block.
|
||||
*
|
||||
* Creates a custom block from defaults and ensures that the 'basic block'
|
||||
* type is being used.
|
||||
*/
|
||||
public function testDefaultBlockContentCreation() {
|
||||
$edit = array();
|
||||
$edit['info[0][value]'] = $this->randomMachineName(8);
|
||||
$edit['body[0][value]'] = $this->randomMachineName(16);
|
||||
// Don't pass the custom block type in the url so the default is forced.
|
||||
$this->drupalPostForm('block/add', $edit, t('Save'));
|
||||
|
||||
// Check that the block has been created and that it is a basic block.
|
||||
$this->assertRaw(format_string('@block %name has been created.', array(
|
||||
'@block' => 'basic',
|
||||
'%name' => $edit['info[0][value]'],
|
||||
)), 'Basic block created.');
|
||||
|
||||
// Check that the block exists in the database.
|
||||
$blocks = entity_load_multiple_by_properties('block_content', array('info' => $edit['info[0][value]']));
|
||||
$block = reset($blocks);
|
||||
$this->assertTrue($block, 'Default Custom Block found in database.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that a transaction rolls back the failed creation.
|
||||
*/
|
||||
public function testFailedBlockCreation() {
|
||||
// Create a block.
|
||||
try {
|
||||
$this->createBlockContent('fail_creation');
|
||||
$this->fail('Expected exception has not been thrown.');
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
$this->pass('Expected exception has been thrown.');
|
||||
}
|
||||
|
||||
if (Database::getConnection()->supportsTransactions()) {
|
||||
// Check that the block does not exist in the database.
|
||||
$id = db_select('block_content_field_data', 'b')
|
||||
->fields('b', array('id'))
|
||||
->condition('info', 'fail_creation')
|
||||
->execute()
|
||||
->fetchField();
|
||||
$this->assertFalse($id, 'Transactions supported, and block not found in database.');
|
||||
}
|
||||
else {
|
||||
// Check that the block exists in the database.
|
||||
$id = db_select('block_content_field_data', 'b')
|
||||
->fields('b', array('id'))
|
||||
->condition('info', 'fail_creation')
|
||||
->execute()
|
||||
->fetchField();
|
||||
$this->assertTrue($id, 'Transactions not supported, and block found in database.');
|
||||
|
||||
// Check that the failed rollback was logged.
|
||||
$records = db_query("SELECT wid FROM {watchdog} WHERE message LIKE 'Explicit rollback failed%'")->fetchAll();
|
||||
$this->assertTrue(count($records) > 0, 'Transactions not supported, and rollback error logged to watchdog.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test deleting a block.
|
||||
*/
|
||||
public function testBlockDelete() {
|
||||
// Create a block.
|
||||
$edit = array();
|
||||
$edit['info[0][value]'] = $this->randomMachineName(8);
|
||||
$body = $this->randomMachineName(16);
|
||||
$edit['body[0][value]'] = $body;
|
||||
$this->drupalPostForm('block/add/basic', $edit, t('Save'));
|
||||
|
||||
// Place the block.
|
||||
$instance = array(
|
||||
'id' => Unicode::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->drupalPostForm($url, $instance, t('Save block'));
|
||||
|
||||
$block = BlockContent::load(1);
|
||||
|
||||
// Test getInstances method.
|
||||
$this->assertEqual(1, count($block->getInstances()));
|
||||
|
||||
// Navigate to home page.
|
||||
$this->drupalGet('');
|
||||
$this->assertText($body);
|
||||
|
||||
// Delete the block.
|
||||
$this->drupalGet('block/1/delete');
|
||||
$this->assertText(\Drupal::translation()->formatPlural(1, 'This will also remove 1 placed block instance.', 'This will also remove @count placed block instance.'));
|
||||
|
||||
$this->drupalPostForm(NULL, array(), 'Delete');
|
||||
$this->assertRaw(t('The custom block %name has been deleted.', array('%name' => $edit['info[0][value]'])));
|
||||
|
||||
// Create another block and force the plugin cache to flush.
|
||||
$edit2 = array();
|
||||
$edit2['info[0][value]'] = $this->randomMachineName(8);
|
||||
$body2 = $this->randomMachineName(16);
|
||||
$edit2['body[0][value]'] = $body2;
|
||||
$this->drupalPostForm('block/add/basic', $edit2, t('Save'));
|
||||
|
||||
$this->assertNoRaw('Error message');
|
||||
|
||||
// Create another block with no instances, and test we don't get a
|
||||
// confirmation message about deleting instances.
|
||||
$edit3 = array();
|
||||
$edit3['info[0][value]'] = $this->randomMachineName(8);
|
||||
$body = $this->randomMachineName(16);
|
||||
$edit3['body[0][value]'] = $body;
|
||||
$this->drupalPostForm('block/add/basic', $edit3, t('Save'));
|
||||
|
||||
// Show the delete confirm form.
|
||||
$this->drupalGet('block/3/delete');
|
||||
$this->assertNoText('This will also remove');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that placed content blocks create a dependency in the block placement.
|
||||
*/
|
||||
public function testConfigDependencies() {
|
||||
$block = $this->createBlockContent();
|
||||
// Place the block.
|
||||
$block_placement_id = Unicode::strtolower($block->label());
|
||||
$instance = array(
|
||||
'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->drupalPostForm($url, $instance, t('Save block'));
|
||||
|
||||
$dependencies = \Drupal::service('config.manager')->findConfigEntityDependentsAsEntities('content', array($block->getConfigDependencyName()));
|
||||
$block_placement = reset($dependencies);
|
||||
$this->assertEqual($block_placement_id, $block_placement->id(), "The block placement config entity has a dependency on the block content entity.");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Tests;
|
||||
|
||||
/**
|
||||
* Tests the listing of custom 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 {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('block', 'block_content', 'config_translation');
|
||||
|
||||
/**
|
||||
* Tests the custom block listing page.
|
||||
*/
|
||||
public function testListing() {
|
||||
$this->drupalLogin($this->drupalCreateUser(array('administer blocks', 'translate configuration')));
|
||||
$this->drupalGet('admin/structure/block/block-content');
|
||||
|
||||
// Test for the page title.
|
||||
$this->assertTitle(t('Custom block library') . ' | Drupal');
|
||||
|
||||
// Test for the table.
|
||||
$element = $this->xpath('//div[@class="layout-content"]//table');
|
||||
$this->assertTrue($element, 'Configuration entity list table found.');
|
||||
|
||||
// Test the table header.
|
||||
$elements = $this->xpath('//div[@class="layout-content"]//table/thead/tr/th');
|
||||
$this->assertEqual(count($elements), 2, 'Correct number of table header cells found.');
|
||||
|
||||
// Test the contents of each th cell.
|
||||
$expected_items = array(t('Block description'), t('Operations'));
|
||||
foreach ($elements as $key => $element) {
|
||||
$this->assertEqual($element[0], $expected_items[$key]);
|
||||
}
|
||||
|
||||
$label = 'Antelope';
|
||||
$new_label = 'Albatross';
|
||||
// Add a new entity using the operations link.
|
||||
$link_text = t('Add custom block');
|
||||
$this->assertLink($link_text);
|
||||
$this->clickLink($link_text);
|
||||
$this->assertResponse(200);
|
||||
$edit = array();
|
||||
$edit['info[0][value]'] = $label;
|
||||
$edit['body[0][value]'] = $this->randomMachineName(16);
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
|
||||
// Confirm that once the user returns to the listing, the text of the label
|
||||
// (versus elsewhere on the page).
|
||||
$this->assertFieldByXpath('//td', $label, 'Label found for added block.');
|
||||
|
||||
// Check the number of table row cells.
|
||||
$elements = $this->xpath('//div[@class="layout-content"]//table/tbody/tr[@class="odd"]/td');
|
||||
$this->assertEqual(count($elements), 2, 'Correct number of table row cells found.');
|
||||
// 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->assertIdentical((string) $elements[0], $label);
|
||||
|
||||
// Edit the entity using the operations link.
|
||||
$blocks = $this->container
|
||||
->get('entity.manager')
|
||||
->getStorage('block_content')
|
||||
->loadByProperties(array('info' => $label));
|
||||
$block = reset($blocks);
|
||||
if (!empty($block)) {
|
||||
$this->assertLinkByHref('block/' . $block->id());
|
||||
$this->clickLink(t('Edit'));
|
||||
$this->assertResponse(200);
|
||||
$this->assertTitle(strip_tags(t('Edit custom block %label', array('%label' => $label)) . ' | Drupal'));
|
||||
$edit = array('info[0][value]' => $new_label);
|
||||
$this->drupalPostForm(NULL, $edit, t('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->assertFieldByXpath('//td', $new_label, 'Label found for updated custom block.');
|
||||
|
||||
// Delete the added entity using the operations link.
|
||||
$this->assertLinkByHref('block/' . $block->id() . '/delete');
|
||||
$delete_text = t('Delete');
|
||||
$this->clickLink($delete_text);
|
||||
$this->assertResponse(200);
|
||||
$this->assertTitle(strip_tags(t('Are you sure you want to delete the custom block %label?', array('%label' => $new_label)) . ' | Drupal'));
|
||||
$this->drupalPostForm(NULL, array(), $delete_text);
|
||||
|
||||
// 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->assertNoFieldByXpath('//td', $new_label, 'No label found for deleted custom block.');
|
||||
|
||||
// Confirm that the empty text is displayed.
|
||||
$this->assertText(t('There is no Custom block yet.'));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Tests;
|
||||
|
||||
/**
|
||||
* Tests the Views-powered listing of custom blocks.
|
||||
*
|
||||
* @group block_content
|
||||
* @see \Drupal\block\BlockContentListBuilder
|
||||
* @see \Drupal\block_content\Tests\BlockContentListTest
|
||||
*/
|
||||
class BlockContentListViewsTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['block', 'block_content', 'config_translation', 'views'];
|
||||
|
||||
/**
|
||||
* Tests the custom block listing page.
|
||||
*/
|
||||
public function testListing() {
|
||||
$this->drupalLogin($this->drupalCreateUser(array('administer blocks', 'translate configuration')));
|
||||
$this->drupalGet('admin/structure/block/block-content');
|
||||
|
||||
// Test for the page title.
|
||||
$this->assertTitle(t('Custom block library') . ' | Drupal');
|
||||
|
||||
// Test for the exposed filters.
|
||||
$this->assertFieldByName('info');
|
||||
$this->assertFieldByName('type');
|
||||
|
||||
// Test for the table.
|
||||
$element = $this->xpath('//div[@class="layout-content"]//table');
|
||||
$this->assertTrue($element, 'Views table found.');
|
||||
|
||||
// Test the table header.
|
||||
$elements = $this->xpath('//div[@class="layout-content"]//table/thead/tr/th');
|
||||
$this->assertEqual(count($elements), 4, 'Correct number of table header cells found.');
|
||||
|
||||
// Test the contents of each th cell.
|
||||
$expected_items = ['Block description', 'Block type', 'Updated', 'Operations'];
|
||||
foreach ($elements as $key => $element) {
|
||||
if ($element->xpath('a')) {
|
||||
$this->assertIdentical(trim((string) $element->xpath('a')[0]), $expected_items[$key]);
|
||||
}
|
||||
else {
|
||||
$this->assertIdentical(trim((string) $element[0]), $expected_items[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$label = 'Antelope';
|
||||
$new_label = 'Albatross';
|
||||
// Add a new entity using the operations link.
|
||||
$link_text = t('Add custom block');
|
||||
$this->assertLink($link_text);
|
||||
$this->clickLink($link_text);
|
||||
$this->assertResponse(200);
|
||||
$edit = array();
|
||||
$edit['info[0][value]'] = $label;
|
||||
$edit['body[0][value]'] = $this->randomMachineName(16);
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
|
||||
// Confirm that once the user returns to the listing, the text of the label
|
||||
// (versus elsewhere on the page).
|
||||
$this->assertFieldByXpath('//td/a', $label, 'Label found for added block.');
|
||||
|
||||
// Check the number of table row cells.
|
||||
$elements = $this->xpath('//div[@class="layout-content"]//table/tbody/tr/td');
|
||||
$this->assertEqual(count($elements), 4, 'Correct number of table row cells found.');
|
||||
// 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->assertIdentical((string) $elements[0]->xpath('a')[0], $label);
|
||||
|
||||
// Edit the entity using the operations link.
|
||||
$blocks = $this->container
|
||||
->get('entity.manager')
|
||||
->getStorage('block_content')
|
||||
->loadByProperties(array('info' => $label));
|
||||
$block = reset($blocks);
|
||||
if (!empty($block)) {
|
||||
$this->assertLinkByHref('block/' . $block->id());
|
||||
$this->clickLink(t('Edit'));
|
||||
$this->assertResponse(200);
|
||||
$this->assertTitle(strip_tags(t('Edit custom block %label', array('%label' => $label)) . ' | Drupal'));
|
||||
$edit = array('info[0][value]' => $new_label);
|
||||
$this->drupalPostForm(NULL, $edit, t('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->assertFieldByXpath('//td/a', $new_label, 'Label found for updated custom block.');
|
||||
|
||||
// Delete the added entity using the operations link.
|
||||
$this->assertLinkByHref('block/' . $block->id() . '/delete');
|
||||
$delete_text = t('Delete');
|
||||
$this->clickLink($delete_text);
|
||||
$this->assertResponse(200);
|
||||
$this->assertTitle(strip_tags(t('Are you sure you want to delete the custom block %label?', array('%label' => $new_label)) . ' | Drupal'));
|
||||
$this->drupalPostForm(NULL, array(), $delete_text);
|
||||
|
||||
// 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->assertNoFieldByXpath('//td', $new_label, 'No label found for deleted custom block.');
|
||||
|
||||
// Confirm that the empty text is displayed.
|
||||
$this->assertText('There are no custom blocks available.');
|
||||
$this->assertLink('custom block');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Tests;
|
||||
|
||||
/**
|
||||
* Create a block and test block access by attempting to view the block.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentPageViewTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('block_content_test');
|
||||
|
||||
/**
|
||||
* Checks block edit and fallback functionality.
|
||||
*/
|
||||
public function testPageEdit() {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$block = $this->createBlockContent();
|
||||
|
||||
// Attempt to view the block.
|
||||
$this->drupalGet('block-content/' . $block->id());
|
||||
|
||||
// Assert response was '200' and not '403 Access denied'.
|
||||
$this->assertResponse('200', 'User was able the view the block');
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertRaw(t('This block is broken or missing. You may be missing content or you might need to enable the original module.'));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Tests;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\user\Entity\User;
|
||||
use Drupal\user\UserInterface;
|
||||
|
||||
/**
|
||||
* Create a block with revisions.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentRevisionsTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* Stores blocks created during the test.
|
||||
* @var array
|
||||
*/
|
||||
protected $blocks;
|
||||
|
||||
/**
|
||||
* Stores log messages used during the test.
|
||||
* @var array
|
||||
*/
|
||||
protected $revisionLogs;
|
||||
|
||||
/**
|
||||
* Sets the test up.
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
/** @var UserInterface $user */
|
||||
$user = User::load(1);
|
||||
|
||||
// Create initial block.
|
||||
$block = $this->createBlockContent('initial');
|
||||
|
||||
$blocks = array();
|
||||
$logs = array();
|
||||
|
||||
// Get original block.
|
||||
$blocks[] = $block->getRevisionId();
|
||||
$logs[] = '';
|
||||
|
||||
// Create three revisions.
|
||||
$revision_count = 3;
|
||||
for ($i = 0; $i < $revision_count; $i++) {
|
||||
$block->setNewRevision(TRUE);
|
||||
$block->setRevisionLogMessage($this->randomMachineName(32));
|
||||
$block->setRevisionUser($this->adminUser);
|
||||
$block->setRevisionCreationTime(REQUEST_TIME);
|
||||
$logs[] = $block->getRevisionLogMessage();
|
||||
$block->save();
|
||||
$blocks[] = $block->getRevisionId();
|
||||
}
|
||||
|
||||
$this->blocks = $blocks;
|
||||
$this->revisionLogs = $logs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks block revision related operations.
|
||||
*/
|
||||
public function testRevisions() {
|
||||
$blocks = $this->blocks;
|
||||
$logs = $this->revisionLogs;
|
||||
|
||||
foreach ($blocks as $delta => $revision_id) {
|
||||
// Confirm the correct revision text appears.
|
||||
/** @var \Drupal\block_content\BlockContentInterface $loaded */
|
||||
$loaded = entity_revision_load('block_content', $revision_id);
|
||||
// Verify revision log is the same.
|
||||
$this->assertEqual($loaded->getRevisionLogMessage(), $logs[$delta], format_string('Correct log message found for revision @revision', array(
|
||||
'@revision' => $loaded->getRevisionId(),
|
||||
)));
|
||||
if ($delta > 0) {
|
||||
$this->assertTrue($loaded->getRevisionUser() instanceof UserInterface, 'Revision User found.');
|
||||
$this->assertTrue(is_numeric($loaded->getRevisionUserId()), 'Revision User ID found.');
|
||||
$this->assertTrue(is_numeric($loaded->getRevisionCreationTime()), 'Revision time found.');
|
||||
}
|
||||
}
|
||||
|
||||
// Confirm that this is the default revision.
|
||||
$this->assertTrue($loaded->isDefaultRevision(), 'Third block revision is the default one.');
|
||||
|
||||
// Make a new revision and set it to not be default.
|
||||
// This will create a new revision that is not "front facing".
|
||||
// Save this as a non-default revision.
|
||||
$loaded->setNewRevision();
|
||||
$loaded->isDefaultRevision(FALSE);
|
||||
$loaded->body = $this->randomMachineName(8);
|
||||
$loaded->save();
|
||||
|
||||
$this->drupalGet('block/' . $loaded->id());
|
||||
$this->assertNoText($loaded->body->value, 'Revision body text is not present on default version of block.');
|
||||
|
||||
// Verify that the non-default revision id is greater than the default
|
||||
// revision id.
|
||||
$default_revision = BlockContent::load($loaded->id());
|
||||
$this->assertTrue($loaded->getRevisionId() > $default_revision->getRevisionId(), 'Revision id is greater than default revision id.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Tests;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
|
||||
/**
|
||||
* Tests $block_content->save() for saving content.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentSaveTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('block_content_test');
|
||||
|
||||
/**
|
||||
* Sets the test up.
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalLogin($this->adminUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether custom block IDs are saved properly during an import.
|
||||
*/
|
||||
public function testImport() {
|
||||
// Custom block ID must be a number that is not in the database.
|
||||
$max_id = db_query('SELECT MAX(id) FROM {block_content}')->fetchField();
|
||||
$test_id = $max_id + mt_rand(1000, 1000000);
|
||||
$info = $this->randomMachineName(8);
|
||||
$block_array = array(
|
||||
'info' => $info,
|
||||
'body' => array('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->assertEqual($block->id(), $test_id, 'Block imported using provide id');
|
||||
|
||||
// Test the import saved.
|
||||
$block_by_id = BlockContent::load($test_id);
|
||||
$this->assertTrue($block_by_id, 'Custom block load by block ID.');
|
||||
$this->assertIdentical($block_by_id->body->value, $block_array['body']['value']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests determining changes in hook_block_presave().
|
||||
*
|
||||
* Verifies the static block load cache is cleared upon save.
|
||||
*/
|
||||
public function testDeterminingChanges() {
|
||||
// Initial creation.
|
||||
$block = $this->createBlockContent('test_changes');
|
||||
$this->assertEqual($block->getChangedTime(), REQUEST_TIME, 'Creating a block sets default "changed" timestamp.');
|
||||
|
||||
// Update the block without applying changes.
|
||||
$block->save();
|
||||
$this->assertEqual($block->label(), 'test_changes', '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->assertEqual($block->label(), 'updated_presave_update', 'Changes have been determined.');
|
||||
$this->assertEqual($block->getChangedTime(), 979534800, 'Saving a custom block uses "changed" timestamp set in presave hook.');
|
||||
|
||||
// Test the static block load cache to be cleared.
|
||||
$block = BlockContent::load($block->id());
|
||||
$this->assertEqual($block->label(), 'updated_presave', '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() {
|
||||
// block_content_test_block_content_insert() triggers a save on insert if the
|
||||
// title equals 'new'.
|
||||
$block = $this->createBlockContent('new');
|
||||
$this->assertEqual($block->label(), 'BlockContent ' . $block->id(), 'Custom block saved on block insert.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Tests;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Sets up block content types.
|
||||
*/
|
||||
abstract class BlockContentTestBase extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Profile to use.
|
||||
*/
|
||||
protected $profile = 'testing';
|
||||
|
||||
/**
|
||||
* Admin user
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
/**
|
||||
* Permissions to grant admin user.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $permissions = array(
|
||||
'administer blocks'
|
||||
);
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('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() {
|
||||
parent::setUp();
|
||||
if ($this->autoCreateBasicBlockType) {
|
||||
$this->createBlockContentType('basic', TRUE);
|
||||
}
|
||||
|
||||
$this->adminUser = $this->drupalCreateUser($this->permissions);
|
||||
$this->drupalPlaceBlock('local_actions_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a custom 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 custom block.
|
||||
*/
|
||||
protected function createBlockContent($title = FALSE, $bundle = 'basic', $save = TRUE) {
|
||||
$title = $title ?: $this->randomMachineName();
|
||||
$block_content = BlockContent::create(array(
|
||||
'info' => $title,
|
||||
'type' => $bundle,
|
||||
'langcode' => 'en'
|
||||
));
|
||||
if ($block_content && $save === TRUE) {
|
||||
$block_content->save();
|
||||
}
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a custom block type (bundle).
|
||||
*
|
||||
* @param string $label
|
||||
* The block type label.
|
||||
* @param bool $create_body
|
||||
* Whether or not to create the body field
|
||||
*
|
||||
* @return \Drupal\block_content\Entity\BlockContentType
|
||||
* Created custom block type.
|
||||
*/
|
||||
protected function createBlockContentType($label, $create_body = FALSE) {
|
||||
$bundle = BlockContentType::create(array(
|
||||
'id' => $label,
|
||||
'label' => $label,
|
||||
'revision' => FALSE,
|
||||
));
|
||||
$bundle->save();
|
||||
if ($create_body) {
|
||||
block_content_add_body_field($bundle->id());
|
||||
}
|
||||
return $bundle;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Tests;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\content_translation\Tests\ContentTranslationUITestBase;
|
||||
|
||||
/**
|
||||
* Tests the block content translation UI.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentTranslationUITest extends ContentTranslationUITestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array(
|
||||
'language',
|
||||
'content_translation',
|
||||
'block',
|
||||
'field_ui',
|
||||
'block_content'
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultCacheContexts = [
|
||||
'languages:language_interface',
|
||||
'session',
|
||||
'theme',
|
||||
'url.path',
|
||||
'url.query_args',
|
||||
'user.permissions',
|
||||
'user.roles:authenticated',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->entityTypeId = 'block_content';
|
||||
$this->bundle = 'basic';
|
||||
$this->testLanguageSelector = FALSE;
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setupBundle() {
|
||||
// Create the basic bundle since it is provided by standard.
|
||||
$bundle = BlockContentType::create(array(
|
||||
'id' => $this->bundle,
|
||||
'label' => $this->bundle,
|
||||
'revision' => FALSE
|
||||
));
|
||||
$bundle->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTranslatorPermissions() {
|
||||
return array_merge(parent::getTranslatorPermissions(), array(
|
||||
'translate any entity',
|
||||
'access administration pages',
|
||||
'administer blocks',
|
||||
'administer block_content fields'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a custom block.
|
||||
*
|
||||
* @param bool|string $title
|
||||
* (optional) Title of block. When no value is given uses a random name.
|
||||
* Defaults to FALSE.
|
||||
* @param bool|string $bundle
|
||||
* (optional) Bundle name. When no value is given, defaults to
|
||||
* $this->bundle. Defaults to FALSE.
|
||||
*
|
||||
* @return \Drupal\block_content\Entity\BlockContent
|
||||
* Created custom block.
|
||||
*/
|
||||
protected function createBlockContent($title = FALSE, $bundle = FALSE) {
|
||||
$title = $title ?: $this->randomMachineName();
|
||||
$bundle = $bundle ?: $this->bundle;
|
||||
$block_content = BlockContent::create(array(
|
||||
'info' => $title,
|
||||
'type' => $bundle,
|
||||
'langcode' => 'en'
|
||||
));
|
||||
$block_content->save();
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNewEntityValues($langcode) {
|
||||
return array('info' => Unicode::strtolower($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() {
|
||||
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::entityManager()->getStorage($this->entityTypeId);
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
|
||||
$entity = $storage->create(array('type' => 'basic') + $values);
|
||||
$entity->save();
|
||||
$entity->addTranslation('it', $values);
|
||||
|
||||
try {
|
||||
$message = 'Blocks can have translations with the same "info" value.';
|
||||
$entity->save();
|
||||
$this->pass($message);
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
$this->fail($message);
|
||||
}
|
||||
|
||||
// Check that the translate operation link is shown.
|
||||
$this->drupalGet('admin/structure/block/block-content');
|
||||
$this->assertLinkByHref('block/' . $entity->id() . '/translations');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that no metadata is stored for a disabled bundle.
|
||||
*/
|
||||
public function testDisabledBundle() {
|
||||
// Create a bundle that does not have translation enabled.
|
||||
$disabled_bundle = $this->randomMachineName();
|
||||
$bundle = BlockContentType::create(array(
|
||||
'id' => $disabled_bundle,
|
||||
'label' => $disabled_bundle,
|
||||
'revision' => FALSE
|
||||
));
|
||||
$bundle->save();
|
||||
|
||||
// Create a block content for each bundle.
|
||||
$enabled_block_content = $this->createBlockContent();
|
||||
$disabled_block_content = $this->createBlockContent(FALSE, $bundle->id());
|
||||
|
||||
// Make sure that only a single row was inserted into the block table.
|
||||
$rows = db_query('SELECT * FROM {block_content_field_data} WHERE id = :id', array(':id' => $enabled_block_content->id()))->fetchAll();
|
||||
$this->assertEqual(1, count($rows));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function doTestTranslationEdit() {
|
||||
$storage = $this->container->get('entity_type.manager')
|
||||
->getStorage($this->entityTypeId);
|
||||
$storage->resetCache([$this->entityId]);
|
||||
$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 = array('language' => $languages[$langcode]);
|
||||
$url = $entity->urlInfo('edit-form', $options);
|
||||
$this->drupalGet($url);
|
||||
|
||||
$title = t('<em>Edit @type</em> @title [%language translation]', array(
|
||||
'@type' => $entity->bundle(),
|
||||
'@title' => $entity->getTranslation($langcode)->label(),
|
||||
'%language' => $languages[$langcode]->getName(),
|
||||
));
|
||||
$this->assertRaw($title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,239 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Tests;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Component\Utility\Html;
|
||||
|
||||
/**
|
||||
* Ensures that custom block type functions work correctly.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentTypeTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('field_ui');
|
||||
|
||||
/**
|
||||
* Permissions to grant admin user.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $permissions = array(
|
||||
'administer blocks',
|
||||
'administer block_content fields'
|
||||
);
|
||||
|
||||
/**
|
||||
* Whether or not to create an initial block type.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $autoCreateBasicBlockType = FALSE;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests creating a block type programmatically and via a form.
|
||||
*/
|
||||
public function testBlockContentTypeCreation() {
|
||||
// Log in a test user.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Test the page with no block-types.
|
||||
$this->drupalGet('block/add');
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('You have not created any block types yet');
|
||||
$this->clickLink('block type creation page');
|
||||
|
||||
// Create a block type via the user interface.
|
||||
$edit = array(
|
||||
'id' => 'foo',
|
||||
'label' => 'title for foo',
|
||||
);
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
$block_type = BlockContentType::load('foo');
|
||||
$this->assertTrue($block_type, 'The new block type has been created.');
|
||||
|
||||
$field_definitions = \Drupal::entityManager()->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->assertEqual($block_type->language()->getId(), $default_langcode);
|
||||
|
||||
// Create block types programmatically.
|
||||
$this->createBlockContentType('basic', TRUE);
|
||||
$field_definitions = \Drupal::entityManager()->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('other');
|
||||
$field_definitions = \Drupal::entityManager()->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->assertTrue($block_type, 'The new block type has been created.');
|
||||
|
||||
$this->drupalGet('block/add/' . $block_type->id());
|
||||
$this->assertResponse(200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests editing a block type using the UI.
|
||||
*/
|
||||
public function testBlockContentTypeEditing() {
|
||||
// Now create an initial block-type.
|
||||
$this->createBlockContentType('basic', TRUE);
|
||||
|
||||
$this->drupalLogin($this->adminUser);
|
||||
// We need two block types to prevent /block/add redirecting.
|
||||
$this->createBlockContentType('other');
|
||||
|
||||
$field_definitions = \Drupal::entityManager()->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->assertRaw('Block description', 'Block info field was found.');
|
||||
$this->assertRaw('Body', 'Body field was found.');
|
||||
|
||||
// Change the block type name.
|
||||
$edit = array(
|
||||
'label' => 'Bar',
|
||||
);
|
||||
$this->drupalGet('admin/structure/block/block-content/manage/basic');
|
||||
$this->assertTitle(format_string('Edit @type custom block type | Drupal', ['@type' => 'basic']));
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
\Drupal::entityManager()->clearCachedFieldDefinitions();
|
||||
|
||||
$this->drupalGet('block/add');
|
||||
$this->assertRaw('Bar', 'New name was displayed.');
|
||||
$this->clickLink('Bar');
|
||||
$this->assertUrl(\Drupal::url('block_content.add_form', ['block_content_type' => 'basic'], ['absolute' => TRUE]), [], 'Original machine name was used in URL.');
|
||||
|
||||
// Remove the body field.
|
||||
$this->drupalPostForm('admin/structure/block/block-content/manage/basic/fields/block_content.basic.body/delete', array(), t('Delete'));
|
||||
// Resave the settings for this type.
|
||||
$this->drupalPostForm('admin/structure/block/block-content/manage/basic', array(), t('Save'));
|
||||
// Check that the body field doesn't exist.
|
||||
$this->drupalGet('block/add/basic');
|
||||
$this->assertNoRaw('Body', 'Body field was not found.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests deleting a block type that still has content.
|
||||
*/
|
||||
public function testBlockContentTypeDeletion() {
|
||||
// Now create an initial block-type.
|
||||
$this->createBlockContentType('basic', TRUE);
|
||||
|
||||
// Create a block type programmatically.
|
||||
$type = $this->createBlockContentType('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/block-content/manage/' . $type->id() . '/delete');
|
||||
$this->assertRaw(
|
||||
t('%label is used by 1 custom block on your site. You can not remove this block type until you have removed all of the %label blocks.', array('%label' => $type->label())),
|
||||
'The block type will not be deleted until all blocks of that type are removed.'
|
||||
);
|
||||
$this->assertNoText(t('This action cannot be undone.'), 'The block type deletion confirmation form is not available.');
|
||||
|
||||
// Delete the block.
|
||||
$block->delete();
|
||||
// Attempt to delete the block type, which should now be allowed.
|
||||
$this->drupalGet('admin/structure/block/block-content/manage/' . $type->id() . '/delete');
|
||||
$this->assertRaw(
|
||||
t('Are you sure you want to delete the custom block type %type?', array('%type' => $type->id())),
|
||||
'The block type is available for deletion.'
|
||||
);
|
||||
$this->assertText(t('This action cannot be undone.'), 'The custom block type deletion confirmation form is available.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that redirects work as expected when multiple block types exist.
|
||||
*/
|
||||
public function testsBlockContentAddTypes() {
|
||||
// Now create an initial block-type.
|
||||
$this->createBlockContentType('basic', TRUE);
|
||||
|
||||
$this->drupalLogin($this->adminUser);
|
||||
// Create two block types programmatically.
|
||||
$type = $this->createBlockContentType('foo');
|
||||
$type = $this->createBlockContentType('bar');
|
||||
|
||||
// Get the custom block storage.
|
||||
$storage = $this->container
|
||||
->get('entity.manager')
|
||||
->getStorage('block_content');
|
||||
|
||||
// Install all themes.
|
||||
\Drupal::service('theme_handler')->install(['bartik', 'seven', 'stark']);
|
||||
$theme_settings = $this->config('system.theme');
|
||||
foreach (['bartik', 'seven', 'stark'] as $default_theme) {
|
||||
// Change the default theme.
|
||||
$theme_settings->set('default', $default_theme)->save();
|
||||
\Drupal::service('router.builder')->rebuild();
|
||||
|
||||
// For each installed theme, go to its block page and test the redirects.
|
||||
foreach (['bartik', 'seven', 'stark'] 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->clickLinkPartialName('Place block');
|
||||
$this->clickLink(t('Add custom block'));
|
||||
// The seven theme has markup inside the link, we cannot use clickLink().
|
||||
if ($default_theme == 'seven') {
|
||||
$options = $theme != $default_theme ? array('query' => array('theme' => $theme)) : array();
|
||||
$this->assertLinkByHref(\Drupal::url('block_content.add_form', array('block_content_type' => 'foo'), $options));
|
||||
$this->drupalGet('block/add/foo', $options);
|
||||
}
|
||||
else {
|
||||
$this->clickLink('foo');
|
||||
}
|
||||
// Create a new block.
|
||||
$edit = array('info[0][value]' => $this->randomMachineName(8));
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
$blocks = $storage->loadByProperties(array('info' => $edit['info[0][value]']));
|
||||
if (!empty($blocks)) {
|
||||
$block = reset($blocks);
|
||||
$this->assertUrl(\Drupal::url('block.admin_add', array('plugin_id' => 'block_content:' . $block->uuid(), 'theme' => $theme), array('absolute' => TRUE)));
|
||||
$this->drupalPostForm(NULL, array(), t('Save block'));
|
||||
$this->assertUrl(\Drupal::url('block.admin_display_theme', array('theme' => $theme), array('absolute' => TRUE, 'query' => array('block-placement' => Html::getClass($edit['info[0][value]'])))));
|
||||
}
|
||||
else {
|
||||
$this->fail('Could not load created block.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test that adding a block from the 'custom blocks list' doesn't send you
|
||||
// to the block configure form.
|
||||
$this->drupalGet('admin/structure/block/block-content');
|
||||
$this->clickLink(t('Add custom block'));
|
||||
$this->clickLink('foo');
|
||||
$edit = array('info[0][value]' => $this->randomMachineName(8));
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
$blocks = $storage->loadByProperties(array('info' => $edit['info[0][value]']));
|
||||
if (!empty($blocks)) {
|
||||
$this->assertUrl(\Drupal::url('entity.block_content.collection', array(), array('absolute' => TRUE)));
|
||||
}
|
||||
else {
|
||||
$this->fail('Could not load created block.');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Tests;
|
||||
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\system\Tests\Update\UpdatePathTestBase;
|
||||
|
||||
/**
|
||||
* Tests adding revision_user and revision_created fields.
|
||||
*
|
||||
* @group Update
|
||||
*/
|
||||
class BlockContentUpdateEntityFields extends UpdatePathTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setDatabaseDumpFiles() {
|
||||
$this->databaseDumpFiles = [
|
||||
__DIR__ . '/../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that email token in status_blocked of user.mail is updated.
|
||||
*/
|
||||
public function testAddingFields() {
|
||||
$this->runUpdates();
|
||||
|
||||
$post_revision_created = \Drupal::entityDefinitionUpdateManager()->getFieldStorageDefinition('revision_created', 'block_content');
|
||||
$post_revision_user = \Drupal::entityDefinitionUpdateManager()->getFieldStorageDefinition('revision_user', 'block_content');
|
||||
$this->assertTrue($post_revision_created instanceof BaseFieldDefinition, "Revision created field found");
|
||||
$this->assertTrue($post_revision_user instanceof BaseFieldDefinition, "Revision user field found");
|
||||
|
||||
$this->assertEqual('created', $post_revision_created->getType(), "Field is type created");
|
||||
$this->assertEqual('entity_reference', $post_revision_user->getType(), "Field is type entity_reference");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Tests;
|
||||
|
||||
/**
|
||||
* Tests block content validation constraints.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentValidationTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* Tests the block content validation constraints.
|
||||
*/
|
||||
public function testValidation() {
|
||||
// Add a block.
|
||||
$description = $this->randomMachineName();
|
||||
$block = $this->createBlockContent($description, 'basic');
|
||||
// Validate the block.
|
||||
$violations = $block->validate();
|
||||
// Make sure we have no violations.
|
||||
$this->assertEqual(count($violations), 0);
|
||||
// Save the block.
|
||||
$block->save();
|
||||
|
||||
// Add another block with the same description.
|
||||
$block = $this->createBlockContent($description, 'basic');
|
||||
// Validate this block.
|
||||
$violations = $block->validate();
|
||||
// Make sure we have 1 violation.
|
||||
$this->assertEqual(count($violations), 1);
|
||||
// Make sure the violation is on the info property
|
||||
$this->assertEqual($violations[0]->getPropertyPath(), 'info');
|
||||
// Make sure the message is correct.
|
||||
$this->assertEqual($violations[0]->getMessage(), format_string('A custom block with block description %value already exists.', [
|
||||
'%value' => $block->label(),
|
||||
]));
|
||||
}
|
||||
|
||||
}
|
71
web/core/modules/block_content/src/Tests/PageEditTest.php
Normal file
71
web/core/modules/block_content/src/Tests/PageEditTest.php
Normal file
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Tests;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
|
||||
/**
|
||||
* Create a block and test block edit functionality.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class PageEditTest extends BlockContentTestBase {
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks block edit functionality.
|
||||
*/
|
||||
public function testPageEdit() {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
$title_key = 'info[0][value]';
|
||||
$body_key = 'body[0][value]';
|
||||
// Create block to edit.
|
||||
$edit = array();
|
||||
$edit['info[0][value]'] = Unicode::strtolower($this->randomMachineName(8));
|
||||
$edit[$body_key] = $this->randomMachineName(16);
|
||||
$this->drupalPostForm('block/add/basic', $edit, t('Save'));
|
||||
|
||||
// Check that the block exists in the database.
|
||||
$blocks = \Drupal::entityQuery('block_content')->condition('info', $edit['info[0][value]'])->execute();
|
||||
$block = BlockContent::load(reset($blocks));
|
||||
$this->assertTrue($block, 'Custom block found in database.');
|
||||
|
||||
// Load the edit page.
|
||||
$this->drupalGet('block/' . $block->id());
|
||||
$this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
|
||||
$this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
|
||||
|
||||
// Edit the content of the block.
|
||||
$edit = array();
|
||||
$edit[$title_key] = $this->randomMachineName(8);
|
||||
$edit[$body_key] = $this->randomMachineName(16);
|
||||
// Stay on the current page, without reloading.
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
|
||||
// Edit the same block, creating a new revision.
|
||||
$this->drupalGet("block/" . $block->id());
|
||||
$edit = array();
|
||||
$edit['info[0][value]'] = $this->randomMachineName(8);
|
||||
$edit[$body_key] = $this->randomMachineName(16);
|
||||
$edit['revision'] = TRUE;
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
|
||||
// Ensure that the block revision has been created.
|
||||
\Drupal::entityManager()->getStorage('block_content')->resetCache(array($block->id()));
|
||||
$revised_block = BlockContent::load($block->id());
|
||||
$this->assertNotIdentical($block->getRevisionId(), $revised_block->getRevisionId(), 'A new revision has been created.');
|
||||
|
||||
// Test deleting the block.
|
||||
$this->drupalGet("block/" . $revised_block->id());
|
||||
$this->clickLink(t('Delete'));
|
||||
$this->assertText(format_string('Are you sure you want to delete the custom block @label?', array('@label' => $revised_block->label())));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Tests\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}
|
||||
*/
|
||||
public static $modules = array('language');
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = array('test_field_filters');
|
||||
|
||||
/**
|
||||
* List of block_content infos by language.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $blockContentInfos = [];
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// 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 = array(
|
||||
'en' => 'Food in Paris',
|
||||
'es' => 'Comida en Paris',
|
||||
'fr' => 'Nouriture 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 (array('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() {
|
||||
// Test the info filter page, which filters for info contains 'Comida'.
|
||||
// Should show just the Spanish translation, once.
|
||||
$this->assertPageCounts('test-info-filter', array('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', array('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', array('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', array('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.
|
||||
*/
|
||||
protected function assertPageCounts($path, $counts, $message) {
|
||||
// Get the text of the page.
|
||||
$this->drupalGet($path);
|
||||
$text = $this->getTextContent();
|
||||
|
||||
foreach ($counts as $langcode => $count) {
|
||||
$this->assertEqual(substr_count($text, $this->blockContentInfos[$langcode]), $count, 'Translation ' . $langcode . ' has count ' . $count . ' with ' . $message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Tests\Views;
|
||||
|
||||
/**
|
||||
* Tests the block_content integration into views.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentIntegrationTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = array('test_block_content_view');
|
||||
|
||||
/**
|
||||
* Tests basic block_content view with a block_content_type argument.
|
||||
*/
|
||||
public function testBlockContentViewTypeArgument() {
|
||||
// Create two content types with three block_contents each.
|
||||
$types = array();
|
||||
$all_ids = array();
|
||||
$block_contents = array();
|
||||
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(array('type' => $type->id()));
|
||||
$block_contents[$type->id()][$block_content->id()] = $block_content;
|
||||
$all_ids[] = $block_content->id();
|
||||
}
|
||||
}
|
||||
|
||||
$this->drupalGet('test-block_content-view');
|
||||
$this->assertResponse(404);
|
||||
|
||||
$this->drupalGet('test-block_content-view/all');
|
||||
$this->assertResponse(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.
|
||||
*/
|
||||
protected function assertIds(array $expected_ids = array()) {
|
||||
$result = $this->xpath('//span[@class="field-content"]');
|
||||
$ids = array();
|
||||
foreach ($result as $element) {
|
||||
$ids[] = (int) $element;
|
||||
}
|
||||
$this->assertEqual($ids, $expected_ids);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Tests\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'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('block', 'block_content', 'views');
|
||||
|
||||
/**
|
||||
* Tests the redirect destination when editing block content.
|
||||
*/
|
||||
public function testRedirectDestination() {
|
||||
$this->drupalLogin($this->drupalCreateUser(array('administer blocks')));
|
||||
$this->drupalGet('admin/structure/block/block-content');
|
||||
|
||||
// Create a custom block.
|
||||
$this->clickLink('custom block');
|
||||
$edit = array();
|
||||
$edit['info[0][value]'] = 'Test redirect destination';
|
||||
$edit['body[0][value]'] = $this->randomMachineName(16);
|
||||
$this->drupalPostForm(NULL, $edit, 'Save');
|
||||
|
||||
// Check the block content is present in the view redirect destination.
|
||||
$this->drupalGet('admin/content/redirect_destination');
|
||||
$this->assertText('Test redirect destination');
|
||||
|
||||
// Edit the created block and save.
|
||||
$this->clickLink('Edit');
|
||||
$this->drupalPostForm(NULL, [], 'Save');
|
||||
$this->assertUrl('admin/content/redirect_destination');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Tests\Views;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\views\Tests\ViewTestBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
|
||||
/**
|
||||
* 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 = array(
|
||||
'administer blocks',
|
||||
);
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('block', 'block_content', 'block_content_test_views');
|
||||
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
// Ensure the basic bundle exists. This is provided by the standard profile.
|
||||
$this->createBlockContentType(array('id' => 'basic'));
|
||||
|
||||
$this->adminUser = $this->drupalCreateUser($this->permissions);
|
||||
|
||||
if ($import_test_views) {
|
||||
ViewTestData::createTestViews(get_class($this), array('block_content_test_views'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a custom block.
|
||||
*
|
||||
* @param array $settings
|
||||
* (optional) An associative array of settings for the block_content, as
|
||||
* used in entity_create().
|
||||
*
|
||||
* @return \Drupal\block_content\Entity\BlockContent
|
||||
* Created custom block.
|
||||
*/
|
||||
protected function createBlockContent(array $settings = array()) {
|
||||
$status = 0;
|
||||
$settings += array(
|
||||
'info' => $this->randomMachineName(),
|
||||
'type' => 'basic',
|
||||
'langcode' => 'en',
|
||||
);
|
||||
if ($block_content = BlockContent::create($settings)) {
|
||||
$status = $block_content->save();
|
||||
}
|
||||
$this->assertEqual($status, SAVED_NEW, SafeMarkup::format('Created block content %info.', array('%info' => $block_content->label())));
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a custom block type (bundle).
|
||||
*
|
||||
* @param array $values
|
||||
* An array of settings to change from the defaults.
|
||||
*
|
||||
* @return \Drupal\block_content\Entity\BlockContentType
|
||||
* Created custom block type.
|
||||
*/
|
||||
protected function createBlockContentType(array $values = array()) {
|
||||
// Find a non-existent random type name.
|
||||
if (!isset($values['id'])) {
|
||||
do {
|
||||
$id = strtolower($this->randomMachineName(8));
|
||||
} while (BlockContentType::load($id));
|
||||
}
|
||||
else {
|
||||
$id = $values['id'];
|
||||
}
|
||||
$values += array(
|
||||
'id' => $id,
|
||||
'label' => $id,
|
||||
'revision' => FALSE
|
||||
);
|
||||
$bundle = BlockContentType::create($values);
|
||||
$status = $bundle->save();
|
||||
block_content_add_body_field($bundle->id());
|
||||
|
||||
$this->assertEqual($status, SAVED_NEW, SafeMarkup::format('Created block content type %bundle.', array('%bundle' => $bundle->id())));
|
||||
return $bundle;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Tests\Views;
|
||||
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the Drupal\block_content\Plugin\views\field\Type handler.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class FieldTypeTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = array('test_field_type');
|
||||
|
||||
public function testFieldType() {
|
||||
$block_content = $this->createBlockContent();
|
||||
$expected_result[] = array(
|
||||
'id' => $block_content->id(),
|
||||
'type' => $block_content->bundle(),
|
||||
);
|
||||
$column_map = array(
|
||||
'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,92 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block_content\Tests\Views;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\views\Tests\ViewTestBase;
|
||||
use Drupal\views\Views;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
|
||||
/**
|
||||
* Tests the integration of block_content_revision table of block_content module.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class RevisionRelationshipsTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('block_content' , 'block_content_test_views');
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = array('test_block_content_revision_id', 'test_block_content_revision_revision_id');
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
BlockContentType::create(array(
|
||||
'id' => 'basic',
|
||||
'label' => 'basic',
|
||||
'revision' => TRUE,
|
||||
));
|
||||
ViewTestData::createTestViews(get_class($this), array('block_content_test_views'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a block_content with revision and rest result count for both views.
|
||||
*/
|
||||
public function testBlockContentRevisionRelationship() {
|
||||
$block_content = BlockContent::create(array(
|
||||
'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 = array(
|
||||
'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_id = Views::getView('test_block_content_revision_id');
|
||||
$this->executeView($view_id, array($block_content->id()));
|
||||
$resultset_id = array(
|
||||
array(
|
||||
'revision_id' => '1',
|
||||
'id_1' => '1',
|
||||
'block_content_field_data_block_content_field_revision_id' => '1',
|
||||
),
|
||||
array(
|
||||
'revision_id' => '2',
|
||||
'id_1' => '1',
|
||||
'block_content_field_data_block_content_field_revision_id' => '1',
|
||||
),
|
||||
);
|
||||
$this->assertIdenticalResultset($view_id, $resultset_id, $column_map);
|
||||
|
||||
// There should be only one row with active revision 2.
|
||||
$view_revision_id = Views::getView('test_block_content_revision_revision_id');
|
||||
$this->executeView($view_revision_id, array($block_content->id()));
|
||||
$resultset_revision_id = array(
|
||||
array(
|
||||
'revision_id' => '2',
|
||||
'id_1' => '1',
|
||||
'block_content_field_data_block_content_field_revision_id' => '1',
|
||||
),
|
||||
);
|
||||
$this->assertIdenticalResultset($view_revision_id, $resultset_revision_id, $column_map);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
{#
|
||||
/**
|
||||
* @file
|
||||
* Default theme implementation to present a list of custom block types.
|
||||
*
|
||||
* Available variables:
|
||||
* - types: A collection of all the available custom block types.
|
||||
* Each block type contains the following:
|
||||
* - link: A link to add a block of this type.
|
||||
* - description: A description of this custom block type.
|
||||
*
|
||||
* @see template_preprocess_block_content_add_list()
|
||||
*
|
||||
* @ingroup themeable
|
||||
*/
|
||||
#}
|
||||
{% spaceless %}
|
||||
<dl>
|
||||
{% for type in types %}
|
||||
<dt>{{ type.link }}</dt>
|
||||
<dd>{{ type.description }}</dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
{% endspaceless %}
|
|
@ -0,0 +1,8 @@
|
|||
name: "Custom Block module tests"
|
||||
type: module
|
||||
description: "Support module for custom block related testing."
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- block_content
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* A dummy module for testing custom block related hooks.
|
||||
*
|
||||
* This is a dummy module that implements custom block related hooks to test API
|
||||
* interaction with the block_content module.
|
||||
*/
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
|
||||
/**
|
||||
* Implements hook_block_content_view().
|
||||
*/
|
||||
function block_content_test_block_content_view(array &$build, BlockContent $block_content, $view_mode) {
|
||||
// Add extra content.
|
||||
$build['extra_content'] = array(
|
||||
'#markup' => '<blink>Yowser</blink>',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_block_content_presave().
|
||||
*/
|
||||
function block_content_test_block_content_presave(BlockContent $block_content) {
|
||||
if ($block_content->label() == 'testing_block_content_presave') {
|
||||
$block_content->setInfo($block_content->label() . '_presave');
|
||||
}
|
||||
// Determine changes.
|
||||
if (!empty($block_content->original) && $block_content->original->label() == 'test_changes') {
|
||||
if ($block_content->original->label() != $block_content->label()) {
|
||||
$block_content->setInfo($block_content->label() . '_presave');
|
||||
// Drupal 1.0 release.
|
||||
$block_content->changed = 979534800;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_block_content_update().
|
||||
*/
|
||||
function block_content_test_block_content_update(BlockContent $block_content) {
|
||||
// Determine changes on update.
|
||||
if (!empty($block_content->original) && $block_content->original->label() == 'test_changes') {
|
||||
if ($block_content->original->label() != $block_content->label()) {
|
||||
$block_content->setInfo($block_content->label() . '_update');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_block_content_insert().
|
||||
*
|
||||
* This tests saving a block_content on block_content insert.
|
||||
*
|
||||
* @see \Drupal\block_content\Tests\BlockContentSaveTest::testBlockContentSaveOnInsert()
|
||||
*/
|
||||
function block_content_test_block_content_insert(BlockContent $block_content) {
|
||||
// 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,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:
|
||||
- classy
|
||||
id: foobargorilla
|
||||
theme: classy
|
||||
region: content
|
||||
weight: null
|
||||
provider: null
|
||||
plugin: 'block_content:fb5e8434-3617-4a1d-a252-8273e95ec30e'
|
||||
settings:
|
||||
id: 'block_content:fb5e8434-3617-4a1d-a252-8273e95ec30e'
|
||||
label: 'Foobar Gorilla'
|
||||
provider: block_content
|
||||
label_display: visible
|
||||
status: true
|
||||
info: ''
|
||||
view_mode: default
|
||||
visibility:
|
||||
request_path:
|
||||
id: request_path
|
||||
pages: ''
|
||||
negate: false
|
|
@ -0,0 +1,9 @@
|
|||
name: 'Block Content test views'
|
||||
type: module
|
||||
description: 'Provides default views for views block_content tests.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- block_content
|
||||
- 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
|
||||
core: 8.x
|
||||
display:
|
||||
default:
|
||||
display_plugin: default
|
||||
id: default
|
||||
display_title: Master
|
||||
position: 0
|
||||
display_options:
|
||||
access:
|
||||
type: none
|
||||
options: { }
|
||||
cache:
|
||||
type: tag
|
||||
options: { }
|
||||
query:
|
||||
type: views_query
|
||||
options:
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
replica: false
|
||||
query_comment: ''
|
||||
query_tags: { }
|
||||
exposed_form:
|
||||
type: basic
|
||||
options:
|
||||
submit_button: Apply
|
||||
reset_button: false
|
||||
reset_button_label: Reset
|
||||
exposed_sorts_label: 'Sort by'
|
||||
expose_sort_order: true
|
||||
sort_asc_label: Asc
|
||||
sort_desc_label: Desc
|
||||
pager:
|
||||
type: mini
|
||||
options:
|
||||
items_per_page: 10
|
||||
offset: 0
|
||||
id: 0
|
||||
total_pages: null
|
||||
expose:
|
||||
items_per_page: false
|
||||
items_per_page_label: 'Items per page'
|
||||
items_per_page_options: '5, 10, 25, 50'
|
||||
items_per_page_options_all: false
|
||||
items_per_page_options_all_label: '- All -'
|
||||
offset: false
|
||||
offset_label: Offset
|
||||
tags:
|
||||
previous: ‹‹
|
||||
next: ››
|
||||
style:
|
||||
type: table
|
||||
options:
|
||||
grouping: { }
|
||||
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,67 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- block_content
|
||||
id: test_block_content_revision_id
|
||||
label: null
|
||||
module: views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: block_content_field_revision
|
||||
base_field: revision_id
|
||||
core: '8'
|
||||
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: Master
|
||||
id: default
|
||||
position: 0
|
|
@ -0,0 +1,70 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- block_content
|
||||
id: test_block_content_revision_revision_id
|
||||
label: null
|
||||
module: views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: block_content_field_revision
|
||||
base_field: revision_id
|
||||
core: '8'
|
||||
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: Master
|
||||
id: default
|
||||
position: 0
|
|
@ -0,0 +1,192 @@
|
|||
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
|
||||
core: 8.x
|
||||
display:
|
||||
default:
|
||||
display_plugin: default
|
||||
id: default
|
||||
display_title: Master
|
||||
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: ''
|
||||
default_argument_skip_url: false
|
||||
summary_options:
|
||||
base_path: ''
|
||||
count: true
|
||||
items_per_page: 25
|
||||
override: false
|
||||
summary:
|
||||
sort_order: asc
|
||||
number_of_records: 0
|
||||
format: default_summary
|
||||
specify_validation: false
|
||||
validate:
|
||||
type: none
|
||||
fail: 'not found'
|
||||
validate_options: { }
|
||||
glossary: 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,339 @@
|
|||
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
|
||||
core: 8.x
|
||||
display:
|
||||
default:
|
||||
display_plugin: default
|
||||
id: default
|
||||
display_title: Master
|
||||
position: 0
|
||||
display_options:
|
||||
access:
|
||||
type: none
|
||||
options: { }
|
||||
cache:
|
||||
type: tag
|
||||
options: { }
|
||||
query:
|
||||
type: views_query
|
||||
options:
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
replica: false
|
||||
query_comment: ''
|
||||
query_tags: { }
|
||||
exposed_form:
|
||||
type: basic
|
||||
options:
|
||||
submit_button: Apply
|
||||
reset_button: false
|
||||
reset_button_label: Reset
|
||||
exposed_sorts_label: 'Sort by'
|
||||
expose_sort_order: true
|
||||
sort_asc_label: Asc
|
||||
sort_desc_label: Desc
|
||||
pager:
|
||||
type: 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,28 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- block_content
|
||||
id: test_field_type
|
||||
label: ''
|
||||
module: views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: block_content_field_data
|
||||
base_field: id
|
||||
core: '8'
|
||||
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: Master
|
||||
id: default
|
||||
position: 0
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Tests that deleting a block clears the cached definitions.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentDeletionTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['block', 'block_content', 'system', 'user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->installSchema('system', ['sequence']);
|
||||
$this->installEntitySchema('user');
|
||||
$this->installEntitySchema('block_content');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests deleting a block_content updates the discovered block plugin.
|
||||
*/
|
||||
public function testDeletingBlockContentShouldClearPluginCache() {
|
||||
// Create a block content type.
|
||||
$block_content_type = BlockContentType::create([
|
||||
'id' => 'spiffy',
|
||||
'label' => 'Mucho spiffy',
|
||||
'description' => "Provides a block type that increases your site's spiffiness 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));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
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 custom block type.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class MigrateBlockContentBodyFieldTest extends MigrateDrupal7TestBase {
|
||||
|
||||
public static $modules = array('block', 'block_content', 'filter', 'text');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installConfig(['block_content']);
|
||||
$this->installEntitySchema('block_content');
|
||||
$this->executeMigrations([
|
||||
'block_content_type',
|
||||
'block_content_body_field',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the block content body field migration.
|
||||
*/
|
||||
public function testBlockContentBodyFieldMigration() {
|
||||
/** @var \Drupal\field\FieldStorageConfigInterface $storage */
|
||||
$storage = FieldStorageConfig::load('block_content.body');
|
||||
$this->assertTrue($storage instanceof FieldStorageConfigInterface);
|
||||
$this->assertIdentical('block_content', $storage->getTargetEntityTypeId());
|
||||
$this->assertIdentical(['basic'], array_values($storage->getBundles()));
|
||||
$this->assertIdentical('body', $storage->getName());
|
||||
|
||||
/** @var \Drupal\field\FieldConfigInterface $field */
|
||||
$field = FieldConfig::load('block_content.basic.body');
|
||||
$this->assertTrue($field instanceof FieldConfigInterface);
|
||||
$this->assertIdentical('block_content', $field->getTargetEntityTypeId());
|
||||
$this->assertIdentical('basic', $field->getTargetBundle());
|
||||
$this->assertIdentical('body', $field->getName());
|
||||
$this->assertIdentical('Body', $field->getLabel());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
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}
|
||||
*/
|
||||
public static $modules = ['block_content'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('block_content');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests creation of block content stubs with no block_content_type available.
|
||||
*/
|
||||
public function testStubFailure() {
|
||||
$message = 'Expected MigrateException thrown when no bundles exist.';
|
||||
try {
|
||||
$this->createStub('block_content');
|
||||
$this->fail($message);
|
||||
}
|
||||
catch (MigrateException $e) {
|
||||
$this->pass($message);
|
||||
$this->assertEqual('Stubbing failed, no bundles available for entity type: block_content', $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests creation of block content stubs when there is a block_content_type.
|
||||
*/
|
||||
public function testStubSuccess() {
|
||||
BlockContentType::create([
|
||||
'id' => 'test_block_content_type',
|
||||
'label' => 'Test block content type',
|
||||
])->save();
|
||||
$this->performStubTest('block_content');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
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 {
|
||||
|
||||
public static $modules = array('block', 'block_content', 'filter', 'text');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installConfig(['block_content']);
|
||||
$this->installEntitySchema('block_content');
|
||||
$this->executeMigration('block_content_type');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the block content type migration.
|
||||
*/
|
||||
public function testBlockContentTypeMigration() {
|
||||
/** @var \Drupal\block_content\BlockContentTypeInterface $entity */
|
||||
$entity = BlockContentType::load('basic');
|
||||
$this->assertTrue($entity instanceof BlockContentTypeInterface);
|
||||
$this->assertIdentical('Basic', $entity->label());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Migrate\d6;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
|
||||
|
||||
/**
|
||||
* Upgrade custom blocks.
|
||||
*
|
||||
* @group migrate_drupal_6
|
||||
*/
|
||||
class MigrateBlockContentTest extends MigrateDrupal6TestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['block', 'block_content'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installConfig(['block_content']);
|
||||
$this->installEntitySchema('block_content');
|
||||
|
||||
$this->executeMigrations([
|
||||
'd6_filter_format',
|
||||
'block_content_type',
|
||||
'block_content_body_field',
|
||||
'd6_custom_block',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the Drupal 6 custom block to Drupal 8 migration.
|
||||
*/
|
||||
public function testBlockMigration() {
|
||||
/** @var BlockContent $block */
|
||||
$block = BlockContent::load(1);
|
||||
$this->assertIdentical('My block 1', $block->label());
|
||||
$this->assertTrue(REQUEST_TIME <= $block->getChangedTime() && $block->getChangedTime() <= time());
|
||||
$this->assertIdentical('en', $block->language()->getId());
|
||||
$this->assertIdentical('<h3>My first custom block body</h3>', $block->body->value);
|
||||
$this->assertIdentical('full_html', $block->body->format);
|
||||
|
||||
$block = BlockContent::load(2);
|
||||
$this->assertIdentical('My block 2', $block->label());
|
||||
$this->assertTrue(REQUEST_TIME <= $block->getChangedTime() && $block->getChangedTime() <= time());
|
||||
$this->assertIdentical('en', $block->language()->getId());
|
||||
$this->assertIdentical('<h3>My second custom block body</h3>', $block->body->value);
|
||||
$this->assertIdentical('full_html', $block->body->format);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
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 custom blocks.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class MigrateCustomBlockTest extends MigrateDrupal7TestBase {
|
||||
|
||||
public static $modules = array(
|
||||
'block_content',
|
||||
'filter',
|
||||
'text',
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installConfig(static::$modules);
|
||||
$this->installEntitySchema('block_content');
|
||||
|
||||
$this->executeMigrations([
|
||||
'd7_filter_format',
|
||||
'block_content_type',
|
||||
'block_content_body_field',
|
||||
'd7_custom_block',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests migration of custom blocks from Drupal 7 to Drupal 8.
|
||||
*/
|
||||
public function testCustomBlockMigration() {
|
||||
$block = BlockContent::load(1);
|
||||
$this->assertTrue($block instanceof BlockContentInterface);
|
||||
/** @var \Drupal\block_content\BlockContentInterface $block */
|
||||
$this->assertIdentical('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->assertIdentical($expected_body, $block->body->value);
|
||||
$this->assertIdentical('filtered_html', $block->body->format);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
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}
|
||||
*/
|
||||
public static $modules = ['block_content', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public 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,40 @@
|
|||
<?php
|
||||
|
||||
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}
|
||||
*/
|
||||
public static $modules = ['block_content', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public 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,80 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Unit\Menu;
|
||||
|
||||
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 {
|
||||
|
||||
protected function setUp() {
|
||||
$this->directoryList = array(
|
||||
'block' => 'core/modules/block',
|
||||
'block_content' => 'core/modules/block_content',
|
||||
);
|
||||
parent::setUp();
|
||||
|
||||
$config_factory = $this->getConfigFactoryStub(array('system.theme' => array(
|
||||
'default' => 'test_c',
|
||||
)));
|
||||
|
||||
$themes = array();
|
||||
$themes['test_a'] = (object) array(
|
||||
'status' => 0,
|
||||
);
|
||||
$themes['test_b'] = (object) array(
|
||||
'status' => 1,
|
||||
'info' => array(
|
||||
'name' => 'test_b',
|
||||
),
|
||||
);
|
||||
$themes['test_c'] = (object) array(
|
||||
'status' => 1,
|
||||
'info' => array(
|
||||
'name' => 'test_c',
|
||||
),
|
||||
);
|
||||
$theme_handler = $this->getMock('Drupal\Core\Extension\ThemeHandlerInterface');
|
||||
$theme_handler->expects($this->any())
|
||||
->method('listInfo')
|
||||
->will($this->returnValue($themes));
|
||||
|
||||
$container = new ContainerBuilder();
|
||||
$container->set('config.factory', $config_factory);
|
||||
$container->set('theme_handler', $theme_handler);
|
||||
\Drupal::setContainer($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks block_content listing local tasks.
|
||||
*
|
||||
* @dataProvider getBlockContentListingRoutes
|
||||
*/
|
||||
public function testBlockContentListLocalTasks($route) {
|
||||
$this->assertLocalTasks($route, array(
|
||||
0 => array(
|
||||
'block.admin_display',
|
||||
'entity.block_content.collection',
|
||||
),
|
||||
1 => array(
|
||||
'block_content.list_sub',
|
||||
'entity.block_content_type.collection',
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of routes to test.
|
||||
*/
|
||||
public function getBlockContentListingRoutes() {
|
||||
return array(
|
||||
array('entity.block_content.collection', 'entity.block_content_type.collection'),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
Reference in a new issue