updated core to 8.6.1 via composer
This commit is contained in:
@@ -5,7 +5,7 @@ package: Core
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- block
|
||||
- text
|
||||
- user
|
||||
- drupal:block
|
||||
- drupal:text
|
||||
- drupal:user
|
||||
configure: entity.block_content.collection
|
||||
|
||||
@@ -8,22 +8,6 @@
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
|
||||
/**
|
||||
* Implements hook_update_dependencies().
|
||||
*/
|
||||
function block_content_update_dependencies() {
|
||||
// The update function that adds the status field must run after
|
||||
// content_translation_update_8400() which fixes NULL values for the
|
||||
// 'content_translation_status' field.
|
||||
if (\Drupal::moduleHandler()->moduleExists('content_translation')) {
|
||||
$dependencies['block_content'][8400] = [
|
||||
'content_translation' => 8400,
|
||||
];
|
||||
|
||||
return $dependencies;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add 'revision_translation_affected' field to 'block_content' entities.
|
||||
*/
|
||||
@@ -110,9 +94,9 @@ function block_content_update_8400() {
|
||||
->setTranslatable(TRUE)
|
||||
->setDefaultValue(TRUE);
|
||||
|
||||
$has_content_translation_status_field = \Drupal::moduleHandler()->moduleExists('content_translation') && $definition_update_manager->getFieldStorageDefinition('content_translation_status', 'block_content');
|
||||
$has_content_translation_status_field = $definition_update_manager->getFieldStorageDefinition('content_translation_status', 'block_content');
|
||||
if ($has_content_translation_status_field) {
|
||||
$status->setInitialValueFromField('content_translation_status');
|
||||
$status->setInitialValueFromField('content_translation_status', TRUE);
|
||||
}
|
||||
else {
|
||||
$status->setInitialValue(TRUE);
|
||||
@@ -138,3 +122,19 @@ function block_content_update_8400() {
|
||||
$definition_update_manager->uninstallFieldStorageDefinition($content_translation_status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add 'reusable' field to 'block_content' entities.
|
||||
*/
|
||||
function block_content_update_8600() {
|
||||
$reusable = BaseFieldDefinition::create('boolean')
|
||||
->setLabel(t('Reusable'))
|
||||
->setDescription(t('A boolean indicating whether this block is reusable.'))
|
||||
->setTranslatable(FALSE)
|
||||
->setRevisionable(FALSE)
|
||||
->setDefaultValue(TRUE)
|
||||
->setInitialValue(TRUE);
|
||||
|
||||
\Drupal::entityDefinitionUpdateManager()
|
||||
->installFieldStorageDefinition('reusable', 'block_content', 'block_content', $reusable);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\Core\Database\Query\SelectInterface;
|
||||
use Drupal\Core\Database\Query\AlterableInterface;
|
||||
use Drupal\Core\Database\Query\ConditionInterface;
|
||||
|
||||
/**
|
||||
* Implements hook_help().
|
||||
@@ -105,3 +108,73 @@ function block_content_add_body_field($block_type_id, $label = 'Body') {
|
||||
|
||||
return $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_query_TAG_alter().
|
||||
*
|
||||
* Alters any 'entity_reference' query where the entity type is
|
||||
* 'block_content' and the query has the tag 'block_content_access'.
|
||||
*
|
||||
* These queries should only return reusable blocks unless a condition on
|
||||
* 'reusable' is explicitly set.
|
||||
*
|
||||
* Block_content entities that are reusable should by default not be selectable
|
||||
* as entity reference values. A module can still create an instance of
|
||||
* \Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface
|
||||
* that will allow selection of non-reusable blocks by explicitly setting
|
||||
* a condition on the 'reusable' field.
|
||||
*
|
||||
* @see \Drupal\block_content\BlockContentAccessControlHandler
|
||||
*/
|
||||
function block_content_query_entity_reference_alter(AlterableInterface $query) {
|
||||
if ($query instanceof SelectInterface && $query->getMetaData('entity_type') === 'block_content' && $query->hasTag('block_content_access')) {
|
||||
$data_table = \Drupal::entityTypeManager()->getDefinition('block_content')->getDataTable();
|
||||
if (array_key_exists($data_table, $query->getTables()) && !_block_content_has_reusable_condition($query->conditions(), $query->getTables())) {
|
||||
$query->condition("$data_table.reusable", TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to find nested conditions using the reusable field.
|
||||
*
|
||||
* @todo Replace this function with a call to the API in
|
||||
* https://www.drupal.org/project/drupal/issues/2984930
|
||||
*
|
||||
* @param array $condition
|
||||
* The condition or condition group to check.
|
||||
* @param array $tables
|
||||
* The tables from the related select query.
|
||||
*
|
||||
* @see \Drupal\Core\Database\Query\SelectInterface::getTables
|
||||
*
|
||||
* @return bool
|
||||
* Whether the conditions contain any condition using the reusable field.
|
||||
*/
|
||||
function _block_content_has_reusable_condition(array $condition, array $tables) {
|
||||
// If this is a condition group call this function recursively for each nested
|
||||
// condition until a condition is found that return TRUE.
|
||||
if (isset($condition['#conjunction'])) {
|
||||
foreach (array_filter($condition, 'is_array') as $nested_condition) {
|
||||
if (_block_content_has_reusable_condition($nested_condition, $tables)) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
if (isset($condition['field'])) {
|
||||
$field = $condition['field'];
|
||||
if (is_object($field) && $field instanceof ConditionInterface) {
|
||||
return _block_content_has_reusable_condition($field->conditions(), $tables);
|
||||
}
|
||||
$field_parts = explode('.', $field);
|
||||
$data_table = \Drupal::entityTypeManager()->getDefinition('block_content')->getDataTable();
|
||||
foreach ($tables as $table) {
|
||||
if ($table['table'] === $data_table && $field_parts[0] === $table['alias'] && $field_parts[1] === 'reusable') {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Post update functions for Custom Block.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityUpdater;
|
||||
use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
|
||||
|
||||
/**
|
||||
* Adds a 'reusable' filter to all Custom Block views.
|
||||
*/
|
||||
function block_content_post_update_add_views_reusable_filter(&$sandbox = NULL) {
|
||||
$entity_type = \Drupal::entityTypeManager()->getDefinition('block_content');
|
||||
$storage = \Drupal::entityTypeManager()->getStorage('block_content');
|
||||
|
||||
// If the storage class is an instance SqlContentEntityStorage we can use it
|
||||
// to determine the table to use, otherwise we have to get the table from the
|
||||
// entity type.
|
||||
if ($storage instanceof SqlContentEntityStorage) {
|
||||
$table = $entity_type->isTranslatable() ? $storage->getDataTable() : $storage->getBaseTable();
|
||||
}
|
||||
else {
|
||||
$table = $entity_type->isTranslatable() ? $entity_type->getDataTable() : $entity_type->getBaseTable();
|
||||
}
|
||||
// If we were not able to get a table name we can not update the views.
|
||||
if (empty($table)) {
|
||||
return;
|
||||
}
|
||||
|
||||
\Drupal::classResolver(ConfigEntityUpdater::class)->update($sandbox, 'view', function ($view) use ($table) {
|
||||
/** @var \Drupal\views\ViewEntityInterface $view */
|
||||
if ($view->get('base_table') !== $table) {
|
||||
return FALSE;
|
||||
}
|
||||
$save_view = FALSE;
|
||||
$displays = $view->get('display');
|
||||
foreach ($displays as $display_name => &$display) {
|
||||
// Update the default display and displays that have overridden filters.
|
||||
if (!isset($display['display_options']['filters']['reusable']) &&
|
||||
($display_name === 'default' || isset($display['display_options']['filters']))) {
|
||||
$display['display_options']['filters']['reusable'] = [
|
||||
'id' => 'reusable',
|
||||
'table' => $table,
|
||||
'field' => 'reusable',
|
||||
'relationship' => 'none',
|
||||
'group_type' => 'group',
|
||||
'admin_label' => '',
|
||||
'operator' => '=',
|
||||
'value' => '1',
|
||||
'group' => 1,
|
||||
'exposed' => FALSE,
|
||||
'expose' => [
|
||||
'operator_id' => '',
|
||||
'label' => '',
|
||||
'description' => '',
|
||||
'use_operator' => FALSE,
|
||||
'operator' => '',
|
||||
'identifier' => '',
|
||||
'required' => FALSE,
|
||||
'remember' => FALSE,
|
||||
'multiple' => 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' => 'reusable',
|
||||
'plugin_id' => 'boolean',
|
||||
];
|
||||
$save_view = TRUE;
|
||||
}
|
||||
}
|
||||
if ($save_view) {
|
||||
$view->set('display', $displays);
|
||||
}
|
||||
return $save_view;
|
||||
});
|
||||
}
|
||||
@@ -1,11 +1,3 @@
|
||||
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:
|
||||
@@ -26,16 +18,6 @@ block_content.add_form:
|
||||
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:
|
||||
@@ -75,14 +57,6 @@ block_content.type_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'
|
||||
_title_callback: '\Drupal\Core\Entity\Controller\EntityController::title'
|
||||
requirements:
|
||||
_entity_access: 'block_content_type.update'
|
||||
|
||||
entity.block_content.collection:
|
||||
path: '/admin/structure/block/block-content'
|
||||
defaults:
|
||||
|
||||
@@ -431,6 +431,44 @@ display:
|
||||
entity_type: block_content
|
||||
entity_field: type
|
||||
plugin_id: bundle
|
||||
reusable:
|
||||
id: reusable
|
||||
table: block_content_field_data
|
||||
field: reusable
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: '='
|
||||
value: '1'
|
||||
group: 1
|
||||
exposed: false
|
||||
expose:
|
||||
operator_id: ''
|
||||
label: ''
|
||||
description: ''
|
||||
use_operator: false
|
||||
operator: ''
|
||||
identifier: ''
|
||||
required: false
|
||||
remember: false
|
||||
multiple: false
|
||||
remember_roles:
|
||||
authenticated: authenticated
|
||||
is_grouped: false
|
||||
group_info:
|
||||
label: ''
|
||||
description: ''
|
||||
identifier: ''
|
||||
optional: true
|
||||
widget: select
|
||||
multiple: false
|
||||
remember: false
|
||||
default_group: All
|
||||
default_group_multiple: { }
|
||||
group_items: { }
|
||||
entity_type: block_content
|
||||
entity_field: reusable
|
||||
plugin_id: boolean
|
||||
sorts: { }
|
||||
title: 'Custom block library'
|
||||
header: { }
|
||||
|
||||
@@ -38,4 +38,3 @@ migration_dependencies:
|
||||
provider:
|
||||
- block_content
|
||||
- migrate_drupal
|
||||
|
||||
|
||||
@@ -35,4 +35,3 @@ migration_dependencies:
|
||||
provider:
|
||||
- block_content
|
||||
- migrate_drupal
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\block_content\Access;
|
||||
|
||||
use Drupal\Core\Access\AccessibleInterface;
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
||||
/**
|
||||
* An access group where all the dependencies must be allowed.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class AccessGroupAnd implements AccessibleInterface {
|
||||
|
||||
/**
|
||||
* The access dependencies.
|
||||
*
|
||||
* @var \Drupal\Core\Access\AccessibleInterface[]
|
||||
*/
|
||||
protected $dependencies = [];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addDependency(AccessibleInterface $dependency) {
|
||||
$this->dependencies[] = $dependency;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function access($operation, AccountInterface $account = NULL, $return_as_object = FALSE) {
|
||||
$access_result = AccessResult::neutral();
|
||||
foreach (array_slice($this->dependencies, 1) as $dependency) {
|
||||
$access_result = $access_result->andIf($dependency->access($operation, $account, TRUE));
|
||||
}
|
||||
return $return_as_object ? $access_result : $access_result->isAllowed();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDependencies() {
|
||||
return $this->dependencies;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\block_content\Access;
|
||||
|
||||
/**
|
||||
* Interface for AccessibleInterface objects that have an access dependency.
|
||||
*
|
||||
* Objects should implement this interface when their access depends on access
|
||||
* to another object that implements \Drupal\Core\Access\AccessibleInterface.
|
||||
* This interface simply provides the getter method for the access
|
||||
* dependency object. Objects that implement this interface are responsible for
|
||||
* checking access of the access dependency because the dependency may not take
|
||||
* effect in all cases. For instance an entity may only need the access
|
||||
* dependency set when it is embedded within another entity and its access
|
||||
* should be dependent on access to the entity in which it is embedded.
|
||||
*
|
||||
* To check the access to the dependency the object implementing this interface
|
||||
* can use code like this:
|
||||
* @code
|
||||
* $accessible->getAccessDependency()->access($op, $account, TRUE);
|
||||
* @endcode
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
interface DependentAccessInterface {
|
||||
|
||||
/**
|
||||
* Gets the access dependency.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessibleInterface|null
|
||||
* The access dependency or NULL if none has been set.
|
||||
*/
|
||||
public function getAccessDependency();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\block_content\Access;
|
||||
|
||||
use Drupal\Core\Access\AccessibleInterface;
|
||||
|
||||
/**
|
||||
* An interface to allow adding an access dependency.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
interface RefinableDependentAccessInterface extends DependentAccessInterface {
|
||||
|
||||
/**
|
||||
* Sets the access dependency.
|
||||
*
|
||||
* If an access dependency is already set this will replace the existing
|
||||
* dependency.
|
||||
*
|
||||
* @param \Drupal\Core\Access\AccessibleInterface $access_dependency
|
||||
* The object upon which access depends.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setAccessDependency(AccessibleInterface $access_dependency);
|
||||
|
||||
/**
|
||||
* Adds an access dependency into the existing access dependency.
|
||||
*
|
||||
* If no existing dependency is currently set this will set the dependency
|
||||
* will be set to the new value.
|
||||
*
|
||||
* If there is an existing dependency and it is not an instance of
|
||||
* AccessGroupAnd the dependency will be set as a new AccessGroupAnd
|
||||
* instance with the existing and new dependencies as the members of the
|
||||
* group.
|
||||
*
|
||||
* If there is an existing dependency and it is a instance of AccessGroupAnd
|
||||
* the dependency will be added to the existing access group.
|
||||
*
|
||||
* @param \Drupal\Core\Access\AccessibleInterface $access_dependency
|
||||
* The access dependency to merge.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addAccessDependency(AccessibleInterface $access_dependency);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\block_content\Access;
|
||||
|
||||
use Drupal\Core\Access\AccessibleInterface;
|
||||
|
||||
/**
|
||||
* Trait for \Drupal\block_content\Access\RefinableDependentAccessInterface.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
trait RefinableDependentAccessTrait {
|
||||
|
||||
/**
|
||||
* The access dependency.
|
||||
*
|
||||
* @var \Drupal\Core\Access\AccessibleInterface
|
||||
*/
|
||||
protected $accessDependency;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setAccessDependency(AccessibleInterface $access_dependency) {
|
||||
$this->accessDependency = $access_dependency;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAccessDependency() {
|
||||
return $this->accessDependency;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addAccessDependency(AccessibleInterface $access_dependency) {
|
||||
if (empty($this->accessDependency)) {
|
||||
$this->accessDependency = $access_dependency;
|
||||
return $this;
|
||||
}
|
||||
if (!$this->accessDependency instanceof AccessGroupAnd) {
|
||||
$accessGroup = new AccessGroupAnd();
|
||||
$this->accessDependency = $accessGroup->addDependency($this->accessDependency);
|
||||
}
|
||||
$this->accessDependency->addDependency($access_dependency);
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,27 +2,87 @@
|
||||
|
||||
namespace Drupal\block_content;
|
||||
|
||||
use Drupal\block_content\Access\DependentAccessInterface;
|
||||
use Drupal\block_content\Event\BlockContentGetDependencyEvent;
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Entity\EntityHandlerInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityAccessControlHandler;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
/**
|
||||
* Defines the access control handler for the custom block entity type.
|
||||
*
|
||||
* @see \Drupal\block_content\Entity\BlockContent
|
||||
*/
|
||||
class BlockContentAccessControlHandler extends EntityAccessControlHandler {
|
||||
class BlockContentAccessControlHandler extends EntityAccessControlHandler implements EntityHandlerInterface {
|
||||
|
||||
/**
|
||||
* The event dispatcher.
|
||||
*
|
||||
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
|
||||
*/
|
||||
protected $eventDispatcher;
|
||||
|
||||
/**
|
||||
* BlockContentAccessControlHandler constructor.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type.
|
||||
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher
|
||||
* The event dispatcher.
|
||||
*/
|
||||
public function __construct(EntityTypeInterface $entity_type, EventDispatcherInterface $dispatcher) {
|
||||
parent::__construct($entity_type);
|
||||
$this->eventDispatcher = $dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
|
||||
return new static(
|
||||
$entity_type,
|
||||
$container->get('event_dispatcher')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
|
||||
if ($operation === 'view') {
|
||||
return AccessResult::allowedIf($entity->isPublished())->addCacheableDependency($entity)
|
||||
$access = AccessResult::allowedIf($entity->isPublished())
|
||||
->orIf(AccessResult::allowedIfHasPermission($account, 'administer blocks'));
|
||||
}
|
||||
return parent::checkAccess($entity, $operation, $account);
|
||||
else {
|
||||
$access = parent::checkAccess($entity, $operation, $account);
|
||||
}
|
||||
// Add the entity as a cacheable dependency because access will at least be
|
||||
// determined by whether the block is reusable.
|
||||
$access->addCacheableDependency($entity);
|
||||
/** @var \Drupal\block_content\BlockContentInterface $entity */
|
||||
if ($entity->isReusable() === FALSE) {
|
||||
if (!$entity instanceof DependentAccessInterface) {
|
||||
throw new \LogicException("Non-reusable block entities must implement \Drupal\block_content\Access\DependentAccessInterface for access control.");
|
||||
}
|
||||
$dependency = $entity->getAccessDependency();
|
||||
if (empty($dependency)) {
|
||||
// If an access dependency has not been set let modules set one.
|
||||
$event = new BlockContentGetDependencyEvent($entity);
|
||||
$this->eventDispatcher->dispatch(BlockContentEvents::BLOCK_CONTENT_GET_DEPENDENCY, $event);
|
||||
$dependency = $event->getAccessDependency();
|
||||
if (empty($dependency)) {
|
||||
return AccessResult::forbidden("Non-reusable blocks must set an access dependency for access control.");
|
||||
}
|
||||
}
|
||||
/** @var \Drupal\Core\Entity\EntityInterface $dependency */
|
||||
$access = $access->andIf($dependency->access($operation, $account, TRUE));
|
||||
}
|
||||
return $access;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\block_content;
|
||||
|
||||
/**
|
||||
* Defines events for the block_content module.
|
||||
*
|
||||
* @see \Drupal\block_content\Event\BlockContentGetDependencyEvent
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class BlockContentEvents {
|
||||
|
||||
/**
|
||||
* Name of the event when getting the dependency of a non-reusable block.
|
||||
*
|
||||
* This event allows modules to provide a dependency for non-reusable block
|
||||
* access if
|
||||
* \Drupal\block_content\Access\DependentAccessInterface::getAccessDependency()
|
||||
* did not return a dependency during access checking.
|
||||
*
|
||||
* @Event
|
||||
*
|
||||
* @see \Drupal\block_content\Event\BlockContentGetDependencyEvent
|
||||
* @see \Drupal\block_content\BlockContentAccessControlHandler::checkAccess()
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const BLOCK_CONTENT_GET_DEPENDENCY = 'block_content.get_dependency';
|
||||
|
||||
}
|
||||
@@ -54,11 +54,11 @@ class BlockContentForm extends ContentEntityForm {
|
||||
|
||||
if ($insert) {
|
||||
$logger->notice('@type: added %info.', $context);
|
||||
drupal_set_message($this->t('@type %info has been created.', $t_args));
|
||||
$this->messenger()->addStatus($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));
|
||||
$this->messenger()->addStatus($this->t('@type %info has been updated.', $t_args));
|
||||
}
|
||||
|
||||
if ($block->id()) {
|
||||
@@ -83,7 +83,7 @@ class BlockContentForm extends ContentEntityForm {
|
||||
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');
|
||||
$this->messenger()->addError($this->t('The block could not be saved.'));
|
||||
$form_state->setRebuild();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Drupal\block_content;
|
||||
|
||||
use Drupal\block_content\Access\RefinableDependentAccessInterface;
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
use Drupal\Core\Entity\EntityChangedInterface;
|
||||
use Drupal\Core\Entity\EntityPublishedInterface;
|
||||
@@ -10,7 +11,7 @@ use Drupal\Core\Entity\RevisionLogInterface;
|
||||
/**
|
||||
* Provides an interface defining a custom block entity.
|
||||
*/
|
||||
interface BlockContentInterface extends ContentEntityInterface, EntityChangedInterface, RevisionLogInterface, EntityPublishedInterface {
|
||||
interface BlockContentInterface extends ContentEntityInterface, EntityChangedInterface, RevisionLogInterface, EntityPublishedInterface, RefinableDependentAccessInterface {
|
||||
|
||||
/**
|
||||
* Returns the block revision log message.
|
||||
@@ -48,6 +49,28 @@ interface BlockContentInterface extends ContentEntityInterface, EntityChangedInt
|
||||
*/
|
||||
public function setRevisionLog($revision_log);
|
||||
|
||||
/**
|
||||
* Determines if the block is reusable or not.
|
||||
*
|
||||
* @return bool
|
||||
* Returns TRUE if reusable and FALSE otherwise.
|
||||
*/
|
||||
public function isReusable();
|
||||
|
||||
/**
|
||||
* Sets the block to be reusable.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setReusable();
|
||||
|
||||
/**
|
||||
* Sets the block to be non-reusable.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setNonReusable();
|
||||
|
||||
/**
|
||||
* Sets the theme value.
|
||||
*
|
||||
|
||||
@@ -28,4 +28,19 @@ class BlockContentListBuilder extends EntityListBuilder {
|
||||
return $row + parent::buildRow($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getEntityIds() {
|
||||
$query = $this->getStorage()->getQuery()
|
||||
->sort($this->entityType->getKey('id'));
|
||||
$query->condition('reusable', TRUE);
|
||||
|
||||
// Only add the pager if a limit is specified.
|
||||
if ($this->limit) {
|
||||
$query->pager($this->limit);
|
||||
}
|
||||
return $query->execute();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -100,12 +100,12 @@ class BlockContentTypeForm extends BundleEntityFormBase {
|
||||
$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.', ['%label' => $block_type->label()]));
|
||||
$this->messenger()->addStatus(t('Custom block type %label has been updated.', ['%label' => $block_type->label()]));
|
||||
$logger->notice('Custom block type %label has been updated.', ['%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.', ['%label' => $block_type->label()]));
|
||||
$this->messenger()->addStatus(t('Custom block type %label has been added.', ['%label' => $block_type->label()]));
|
||||
$logger->notice('Custom block type %label has been added.', ['%label' => $block_type->label(), 'link' => $edit_link]);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ class BlockContentViewsData extends EntityViewsData {
|
||||
|
||||
$data['block_content_field_data']['type']['field']['id'] = 'field';
|
||||
|
||||
$data['block_content_field_data']['table']['wizard_id'] = 'block_content';
|
||||
|
||||
$data['block_content']['block_content_listing_empty'] = [
|
||||
'title' => $this->t('Empty block library behavior'),
|
||||
'help' => $this->t('Provides a link to add a new block.'),
|
||||
|
||||
@@ -98,11 +98,12 @@ class BlockContentController extends ControllerBase {
|
||||
* The current request object.
|
||||
*
|
||||
* @return array
|
||||
* A form array as expected by drupal_render().
|
||||
* A form array as expected by
|
||||
* \Drupal\Core\Render\RendererInterface::render().
|
||||
*/
|
||||
public function addForm(BlockContentTypeInterface $block_content_type, Request $request) {
|
||||
$block = $this->blockContentStorage->create([
|
||||
'type' => $block_content_type->id()
|
||||
'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
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Drupal\block_content\Entity;
|
||||
|
||||
use Drupal\block_content\Access\RefinableDependentAccessTrait;
|
||||
use Drupal\Core\Entity\EditorialContentEntityBase;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
@@ -15,6 +16,13 @@ use Drupal\user\UserInterface;
|
||||
* @ContentEntityType(
|
||||
* id = "block_content",
|
||||
* label = @Translation("Custom block"),
|
||||
* label_collection = @Translation("Custom blocks"),
|
||||
* label_singular = @Translation("custom block"),
|
||||
* label_plural = @Translation("custom blocks"),
|
||||
* label_count = @PluralTranslation(
|
||||
* singular = "@count custom block",
|
||||
* plural = "@count custom blocks",
|
||||
* ),
|
||||
* bundle_label = @Translation("Custom block type"),
|
||||
* handlers = {
|
||||
* "storage" = "Drupal\Core\Entity\Sql\SqlContentEntityStorage",
|
||||
@@ -70,6 +78,8 @@ use Drupal\user\UserInterface;
|
||||
*/
|
||||
class BlockContent extends EditorialContentEntityBase implements BlockContentInterface {
|
||||
|
||||
use RefinableDependentAccessTrait;
|
||||
|
||||
/**
|
||||
* The theme the block is being created in.
|
||||
*
|
||||
@@ -111,7 +121,9 @@ class BlockContent extends EditorialContentEntityBase implements BlockContentInt
|
||||
*/
|
||||
public function postSave(EntityStorageInterface $storage, $update = TRUE) {
|
||||
parent::postSave($storage, $update);
|
||||
static::invalidateBlockPluginCache();
|
||||
if ($this->isReusable() || (isset($this->original) && $this->original->isReusable())) {
|
||||
static::invalidateBlockPluginCache();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,7 +131,14 @@ class BlockContent extends EditorialContentEntityBase implements BlockContentInt
|
||||
*/
|
||||
public static function postDelete(EntityStorageInterface $storage, array $entities) {
|
||||
parent::postDelete($storage, $entities);
|
||||
static::invalidateBlockPluginCache();
|
||||
/** @var \Drupal\block_content\BlockContentInterface $block */
|
||||
foreach ($entities as $block) {
|
||||
if ($block->isReusable()) {
|
||||
// If any deleted blocks are reusable clear the block cache.
|
||||
static::invalidateBlockPluginCache();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,6 +212,13 @@ class BlockContent extends EditorialContentEntityBase implements BlockContentInt
|
||||
->setTranslatable(TRUE)
|
||||
->setRevisionable(TRUE);
|
||||
|
||||
$fields['reusable'] = BaseFieldDefinition::create('boolean')
|
||||
->setLabel(t('Reusable'))
|
||||
->setDescription(t('A boolean indicating whether this block is reusable.'))
|
||||
->setTranslatable(FALSE)
|
||||
->setRevisionable(FALSE)
|
||||
->setDefaultValue(TRUE);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
@@ -275,6 +301,27 @@ class BlockContent extends EditorialContentEntityBase implements BlockContentInt
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isReusable() {
|
||||
return (bool) $this->get('reusable')->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setReusable() {
|
||||
return $this->set('reusable', TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setNonReusable() {
|
||||
return $this->set('reusable', FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates the block plugin cache after changes and deletions.
|
||||
*/
|
||||
|
||||
@@ -11,6 +11,14 @@ use Drupal\block_content\BlockContentTypeInterface;
|
||||
* @ConfigEntityType(
|
||||
* id = "block_content_type",
|
||||
* label = @Translation("Custom block type"),
|
||||
* label_collection = @Translation("Custom block types"),
|
||||
* label_singular = @Translation("custom block type"),
|
||||
* label_plural = @Translation("custom block types"),
|
||||
* label_count = @PluralTranslation(
|
||||
* singular = "@count custom block type",
|
||||
* plural = "@count custom block types",
|
||||
* ),
|
||||
* label_collection = @Translation("Custom block library"),
|
||||
* handlers = {
|
||||
* "form" = {
|
||||
* "default" = "Drupal\block_content\BlockContentTypeForm",
|
||||
@@ -18,6 +26,9 @@ use Drupal\block_content\BlockContentTypeInterface;
|
||||
* "edit" = "Drupal\block_content\BlockContentTypeForm",
|
||||
* "delete" = "Drupal\block_content\Form\BlockContentTypeDeleteForm"
|
||||
* },
|
||||
* "route_provider" = {
|
||||
* "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider"
|
||||
* },
|
||||
* "list_builder" = "Drupal\block_content\BlockContentTypeListBuilder"
|
||||
* },
|
||||
* admin_permission = "administer blocks",
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\block_content\Event;
|
||||
|
||||
use Drupal\block_content\BlockContentInterface;
|
||||
use Drupal\Core\Access\AccessibleInterface;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* Block content event to allow setting an access dependency.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class BlockContentGetDependencyEvent extends Event {
|
||||
|
||||
/**
|
||||
* The block content entity.
|
||||
*
|
||||
* @var \Drupal\block_content\BlockContentInterface
|
||||
*/
|
||||
protected $blockContent;
|
||||
|
||||
/**
|
||||
* The dependency.
|
||||
*
|
||||
* @var \Drupal\Core\Access\AccessibleInterface
|
||||
*/
|
||||
protected $accessDependency;
|
||||
|
||||
/**
|
||||
* BlockContentGetDependencyEvent constructor.
|
||||
*
|
||||
* @param \Drupal\block_content\BlockContentInterface $blockContent
|
||||
* The block content entity.
|
||||
*/
|
||||
public function __construct(BlockContentInterface $blockContent) {
|
||||
$this->blockContent = $blockContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the block content entity.
|
||||
*
|
||||
* @return \Drupal\block_content\BlockContentInterface
|
||||
* The block content entity.
|
||||
*/
|
||||
public function getBlockContentEntity() {
|
||||
return $this->blockContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the access dependency.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessibleInterface
|
||||
* The access dependency.
|
||||
*/
|
||||
public function getAccessDependency() {
|
||||
return $this->accessDependency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the access dependency.
|
||||
*
|
||||
* @param \Drupal\Core\Access\AccessibleInterface $access_dependency
|
||||
* The access dependency.
|
||||
*/
|
||||
public function setAccessDependency(AccessibleInterface $access_dependency) {
|
||||
$this->accessDependency = $access_dependency;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,7 +29,7 @@ class BlockContentBlock extends BlockBase implements ContainerFactoryPluginInter
|
||||
/**
|
||||
* The Plugin Block Manager.
|
||||
*
|
||||
* @var \Drupal\Core\Block\BlockManagerInterface.
|
||||
* @var \Drupal\Core\Block\BlockManagerInterface
|
||||
*/
|
||||
protected $blockManager;
|
||||
|
||||
@@ -43,7 +43,7 @@ class BlockContentBlock extends BlockBase implements ContainerFactoryPluginInter
|
||||
/**
|
||||
* The Drupal account to use for checking for access to block.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface.
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $account;
|
||||
|
||||
@@ -190,9 +190,9 @@ class BlockContentBlock extends BlockBase implements ContainerFactoryPluginInter
|
||||
return [
|
||||
'#markup' => $this->t('Block with uuid %uuid does not exist. <a href=":url">Add custom block</a>.', [
|
||||
'%uuid' => $this->getDerivativeId(),
|
||||
':url' => $this->urlGenerator->generate('block_content.add_page')
|
||||
':url' => $this->urlGenerator->generate('block_content.add_page'),
|
||||
]),
|
||||
'#access' => $this->account->hasPermission('administer blocks')
|
||||
'#access' => $this->account->hasPermission('administer blocks'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ class BlockContent extends DeriverBase implements ContainerDeriverInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDerivativeDefinitions($base_plugin_definition) {
|
||||
$block_contents = $this->blockContentStorage->loadMultiple();
|
||||
$block_contents = $this->blockContentStorage->loadByProperties(['reusable' => TRUE]);
|
||||
// Reset the discovered definitions.
|
||||
$this->derivatives = [];
|
||||
/** @var $block_content \Drupal\block_content\Entity\BlockContent */
|
||||
@@ -51,7 +51,7 @@ class BlockContent extends DeriverBase implements ContainerDeriverInterface {
|
||||
$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'] = [
|
||||
$block_content->getConfigDependencyName()
|
||||
$block_content->getConfigDependencyName(),
|
||||
];
|
||||
}
|
||||
return parent::getDerivativeDefinitions($base_plugin_definition);
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\block_content\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
|
||||
/**
|
||||
* Gets Drupal 6 i18n custom block translations from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d6_box_translation",
|
||||
* source_module = "i18nblocks"
|
||||
* )
|
||||
*/
|
||||
class BoxTranslation extends DrupalSqlBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
// Build a query based on i18n_strings table where each row has the
|
||||
// translation for only one property, either title or description. The
|
||||
// method prepareRow() is then used to obtain the translation for the
|
||||
// other property.
|
||||
$query = $this->select('boxes', 'b')
|
||||
->fields('b', ['bid', 'format', 'body'])
|
||||
->fields('i18n', ['property'])
|
||||
->fields('lt', ['lid', 'translation', 'language'])
|
||||
->orderBy('b.bid')
|
||||
->isNotNull('lt.lid');
|
||||
|
||||
// Use 'title' for the info field to match the property name in the
|
||||
// i18n_strings table.
|
||||
$query->addField('b', 'info', 'title');
|
||||
|
||||
// Add in the property, which is either title or body. Cast the bid to text
|
||||
// so PostgreSQL can make the join.
|
||||
$query->leftJoin('i18n_strings', 'i18n', 'i18n.objectid = CAST(b.bid as CHAR(255))');
|
||||
$query->condition('i18n.type', 'block');
|
||||
|
||||
// Add in the translation for the property.
|
||||
$query->leftJoin('locales_target', 'lt', 'lt.lid = i18n.lid');
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prepareRow(Row $row) {
|
||||
$language = $row->getSourceProperty('language');
|
||||
$bid = $row->getSourceProperty('bid');
|
||||
|
||||
// If this row has been migrated it is a duplicate then skip it.
|
||||
if ($this->idMap->lookupDestinationIds(['bid' => $bid, 'language' => $language])) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Save the translation for this property.
|
||||
$property = $row->getSourceProperty('property');
|
||||
$row->setSourceProperty($property . '_translated', $row->getSourceProperty('translation'));
|
||||
|
||||
// Get the translation for the property not already in the row.
|
||||
$translation = ($property === 'title') ? 'body' : 'title';
|
||||
$query = $this->select('i18n_strings', 'i18n')
|
||||
->fields('i18n', ['lid'])
|
||||
->condition('i18n.property', $translation)
|
||||
->condition('i18n.objectid', $bid);
|
||||
$query->leftJoin('locales_target', 'lt', 'i18n.lid = lt.lid');
|
||||
$query->condition('lt.language', $language)
|
||||
->addField('lt', 'translation');
|
||||
$results = $query->execute()->fetchAssoc();
|
||||
if (!$results) {
|
||||
$row->setSourceProperty($translation . '_translated', NULL);
|
||||
}
|
||||
else {
|
||||
$row->setSourceProperty($translation . '_translated', $results['translation']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return [
|
||||
'bid' => $this->t('The block numeric identifier.'),
|
||||
'format' => $this->t('Input format of the custom block/box content.'),
|
||||
'lid' => $this->t('i18n_string table id'),
|
||||
'language' => $this->t('Language for this field.'),
|
||||
'property' => $this->t('Block property'),
|
||||
'translation' => $this->t('The translation of the value of "property".'),
|
||||
'title' => $this->t('Block title.'),
|
||||
'title_translated' => $this->t('Block title translation.'),
|
||||
'body' => $this->t('Block body.'),
|
||||
'body_translated' => $this->t('Block body translation.'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids['bid']['type'] = 'integer';
|
||||
$ids['bid']['alias'] = 'b';
|
||||
$ids['language']['type'] = 'string';
|
||||
return $ids;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\block_content\Plugin\views\wizard;
|
||||
|
||||
use Drupal\views\Plugin\views\wizard\WizardPluginBase;
|
||||
|
||||
/**
|
||||
* Used for creating 'block_content' views with the wizard.
|
||||
*
|
||||
* @ViewsWizard(
|
||||
* id = "block_content",
|
||||
* base_table = "block_content_field_data",
|
||||
* title = @Translation("Custom Block"),
|
||||
* )
|
||||
*/
|
||||
class BlockContent extends WizardPluginBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFilters() {
|
||||
$filters = parent::getFilters();
|
||||
$filters['reusable'] = [
|
||||
'id' => 'reusable',
|
||||
'plugin_id' => 'boolean',
|
||||
'table' => $this->base_table,
|
||||
'field' => 'reusable',
|
||||
'value' => '1',
|
||||
'entity_type' => $this->entityTypeId,
|
||||
'entity_field' => 'reusable',
|
||||
];
|
||||
return $filters;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,7 +34,7 @@ abstract class BlockContentTestBase extends WebTestBase {
|
||||
* @var array
|
||||
*/
|
||||
protected $permissions = [
|
||||
'administer blocks'
|
||||
'administer blocks',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -83,7 +83,7 @@ abstract class BlockContentTestBase extends WebTestBase {
|
||||
$block_content = BlockContent::create([
|
||||
'info' => $title,
|
||||
'type' => $bundle,
|
||||
'langcode' => 'en'
|
||||
'langcode' => 'en',
|
||||
]);
|
||||
if ($block_content && $save === TRUE) {
|
||||
$block_content->save();
|
||||
|
||||
@@ -6,7 +6,7 @@ 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\Component\Render\FormattableMarkup;
|
||||
use Drupal\views\Tests\ViewTestBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
|
||||
@@ -73,7 +73,7 @@ abstract class BlockContentTestBase extends ViewTestBase {
|
||||
if ($block_content = BlockContent::create($settings)) {
|
||||
$status = $block_content->save();
|
||||
}
|
||||
$this->assertEqual($status, SAVED_NEW, SafeMarkup::format('Created block content %info.', ['%info' => $block_content->label()]));
|
||||
$this->assertEqual($status, SAVED_NEW, new FormattableMarkup('Created block content %info.', ['%info' => $block_content->label()]));
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
@@ -99,13 +99,13 @@ abstract class BlockContentTestBase extends ViewTestBase {
|
||||
$values += [
|
||||
'id' => $id,
|
||||
'label' => $id,
|
||||
'revision' => FALSE
|
||||
'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.', ['%bundle' => $bundle->id()]));
|
||||
$this->assertEqual($status, SAVED_NEW, new FormattableMarkup('Created block content type %bundle.', ['%bundle' => $bundle->id()]));
|
||||
return $bundle;
|
||||
}
|
||||
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains database additions to drupal-8.bare.standard.php.gz for testing the
|
||||
* upgrade path of https://www.drupal.org/project/drupal/issues/2976334.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\Core\Serialization\Yaml;
|
||||
|
||||
$connection = Database::getConnection();
|
||||
|
||||
// Override configuration for 'block_content' View with extra display with with
|
||||
// overridden filters.
|
||||
$config = Yaml::decode(file_get_contents(__DIR__ . '/views.view.block_content_2976334.yml'));
|
||||
$connection->update('config')
|
||||
->fields([
|
||||
'data' => serialize($config),
|
||||
])
|
||||
->condition('name', 'views.view.' . $config['id'])
|
||||
->execute();
|
||||
+602
@@ -0,0 +1,602 @@
|
||||
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: { }
|
||||
page_2:
|
||||
display_plugin: page
|
||||
id: page_2
|
||||
display_title: 'Page 2'
|
||||
position: 2
|
||||
display_options:
|
||||
display_extenders: { }
|
||||
path: extra-view-display
|
||||
filters:
|
||||
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
|
||||
info:
|
||||
id: info
|
||||
table: block_content_field_data
|
||||
field: info
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: 'contains'
|
||||
value: block2
|
||||
group: 1
|
||||
exposed: false
|
||||
expose:
|
||||
operator_id: ''
|
||||
label: ''
|
||||
description: ''
|
||||
use_operator: false
|
||||
operator: ''
|
||||
identifier: ''
|
||||
required: false
|
||||
remember: false
|
||||
multiple: false
|
||||
remember_roles:
|
||||
authenticated: authenticated
|
||||
placeholder: ''
|
||||
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
|
||||
defaults:
|
||||
filters: false
|
||||
filter_groups: false
|
||||
filter_groups:
|
||||
operator: AND
|
||||
groups:
|
||||
1: AND
|
||||
cache_metadata:
|
||||
max-age: 0
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url
|
||||
- url.query_args
|
||||
- user.permissions
|
||||
tags: { }
|
||||
+1
-1
@@ -5,4 +5,4 @@ package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- block_content
|
||||
- drupal:block_content
|
||||
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\block_content_test\Plugin\EntityReferenceSelection;
|
||||
|
||||
use Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection;
|
||||
|
||||
/**
|
||||
* Test EntityReferenceSelection with conditions on the 'reusable' field.
|
||||
*/
|
||||
class TestSelection extends DefaultSelection {
|
||||
|
||||
/**
|
||||
* The condition type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $conditionType;
|
||||
|
||||
/**
|
||||
* Whether to set the condition for reusable or non-reusable blocks.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $isReusable;
|
||||
|
||||
/**
|
||||
* Sets the test mode.
|
||||
*
|
||||
* @param string $condition_type
|
||||
* The condition type.
|
||||
* @param bool $is_reusable
|
||||
* Whether to set the condition for reusable or non-reusable blocks.
|
||||
*/
|
||||
public function setTestMode($condition_type = NULL, $is_reusable = NULL) {
|
||||
$this->conditionType = $condition_type;
|
||||
$this->isReusable = $is_reusable;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') {
|
||||
$query = parent::buildEntityQuery($match, $match_operator);
|
||||
if ($this->conditionType) {
|
||||
/** @var \Drupal\Core\Database\Query\ConditionInterface $add_condition */
|
||||
$add_condition = NULL;
|
||||
switch ($this->conditionType) {
|
||||
case 'base':
|
||||
$add_condition = $query;
|
||||
break;
|
||||
|
||||
case 'group':
|
||||
$group = $query->andConditionGroup()
|
||||
->exists('type');
|
||||
$add_condition = $group;
|
||||
$query->condition($group);
|
||||
break;
|
||||
|
||||
case "nested_group":
|
||||
$query->exists('type');
|
||||
$sub_group = $query->andConditionGroup()
|
||||
->exists('type');
|
||||
$add_condition = $sub_group;
|
||||
$group = $query->andConditionGroup()
|
||||
->exists('type')
|
||||
->condition($sub_group);
|
||||
$query->condition($group);
|
||||
break;
|
||||
}
|
||||
if ($this->isReusable) {
|
||||
$add_condition->condition('reusable', 1);
|
||||
}
|
||||
else {
|
||||
$add_condition->condition('reusable', 0);
|
||||
}
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -5,5 +5,5 @@ package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- block_content
|
||||
- views
|
||||
- drupal:block_content
|
||||
- drupal:views
|
||||
|
||||
@@ -7,7 +7,7 @@ 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 Drupal\Tests\system\Functional\Entity\EntityCacheTagsTestBase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
@@ -29,7 +29,7 @@ class BlockContentCacheTagsTest extends EntityCacheTagsTestBase {
|
||||
$block_content_type = BlockContentType::create([
|
||||
'id' => 'basic',
|
||||
'label' => 'basic',
|
||||
'revision' => FALSE
|
||||
'revision' => FALSE,
|
||||
]);
|
||||
$block_content_type->save();
|
||||
block_content_add_body_field($block_content_type->id());
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Database\Database;
|
||||
|
||||
/**
|
||||
@@ -30,7 +29,7 @@ class BlockContentCreationTest extends BlockContentTestBase {
|
||||
*/
|
||||
protected $permissions = [
|
||||
'administer blocks',
|
||||
'administer block_content display'
|
||||
'administer block_content display',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -56,7 +55,7 @@ class BlockContentCreationTest extends BlockContentTestBase {
|
||||
// Check that the Basic block has been created.
|
||||
$this->assertRaw(format_string('@block %name has been created.', [
|
||||
'@block' => 'basic',
|
||||
'%name' => $edit['info[0][value]']
|
||||
'%name' => $edit['info[0][value]'],
|
||||
]), 'Basic block created.');
|
||||
|
||||
// Check that the view mode setting is hidden because only one exists.
|
||||
@@ -75,7 +74,7 @@ class BlockContentCreationTest extends BlockContentTestBase {
|
||||
|
||||
// Check that the Basic block has been created.
|
||||
$this->assertRaw(format_string('A custom block with block description %value already exists.', [
|
||||
'%value' => $edit['info[0][value]']
|
||||
'%value' => $edit['info[0][value]'],
|
||||
]));
|
||||
$this->assertResponse(200);
|
||||
}
|
||||
@@ -105,7 +104,7 @@ class BlockContentCreationTest extends BlockContentTestBase {
|
||||
// Check that the Basic block has been created.
|
||||
$this->assertRaw(format_string('@block %name has been created.', [
|
||||
'@block' => 'basic',
|
||||
'%name' => $edit['info[0][value]']
|
||||
'%name' => $edit['info[0][value]'],
|
||||
]), 'Basic block created.');
|
||||
|
||||
// Save our block permanently
|
||||
@@ -157,7 +156,7 @@ class BlockContentCreationTest extends BlockContentTestBase {
|
||||
|
||||
// Check that the Basic block has been created.
|
||||
$this->assertRaw(format_string('A custom block with block description %value already exists.', [
|
||||
'%value' => $edit['info[0][value]']
|
||||
'%value' => $edit['info[0][value]'],
|
||||
]));
|
||||
$this->assertResponse(200);
|
||||
}
|
||||
@@ -239,7 +238,7 @@ class BlockContentCreationTest extends BlockContentTestBase {
|
||||
|
||||
// Place the block.
|
||||
$instance = [
|
||||
'id' => Unicode::strtolower($edit['info[0][value]']),
|
||||
'id' => mb_strtolower($edit['info[0][value]']),
|
||||
'settings[label]' => $edit['info[0][value]'],
|
||||
'region' => 'sidebar_first',
|
||||
];
|
||||
@@ -291,7 +290,7 @@ class BlockContentCreationTest extends BlockContentTestBase {
|
||||
public function testConfigDependencies() {
|
||||
$block = $this->createBlockContent();
|
||||
// Place the block.
|
||||
$block_placement_id = Unicode::strtolower($block->label());
|
||||
$block_placement_id = mb_strtolower($block->label());
|
||||
$instance = [
|
||||
'id' => $block_placement_id,
|
||||
'settings[label]' => $block->label(),
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
|
||||
/**
|
||||
* Tests the listing of custom blocks.
|
||||
*
|
||||
@@ -103,7 +105,20 @@ class BlockContentListTest extends BlockContentTestBase {
|
||||
$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.'));
|
||||
$this->assertText(t('There are no custom blocks yet.'));
|
||||
|
||||
$block_content = BlockContent::create([
|
||||
'info' => 'Non-reusable block',
|
||||
'type' => 'basic',
|
||||
'reusable' => FALSE,
|
||||
]);
|
||||
$block_content->save();
|
||||
|
||||
$this->drupalGet('admin/structure/block/block-content');
|
||||
// Confirm that the empty text is displayed.
|
||||
$this->assertSession()->pageTextContains('There are no custom blocks yet.');
|
||||
// Confirm the non-reusable block is not on the page.
|
||||
$this->assertSession()->pageTextNotContains('Non-reusable block');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
|
||||
/**
|
||||
* Tests the Views-powered listing of custom blocks.
|
||||
*
|
||||
@@ -112,6 +114,19 @@ class BlockContentListViewsTest extends BlockContentTestBase {
|
||||
// Confirm that the empty text is displayed.
|
||||
$this->assertText('There are no custom blocks available.');
|
||||
$this->assertLink('custom block');
|
||||
|
||||
$block_content = BlockContent::create([
|
||||
'info' => 'Non-reusable block',
|
||||
'type' => 'basic',
|
||||
'reusable' => FALSE,
|
||||
]);
|
||||
$block_content->save();
|
||||
|
||||
$this->drupalGet('admin/structure/block/block-content');
|
||||
// Confirm that the empty text is displayed.
|
||||
$this->assertSession()->pageTextContains('There are no custom blocks available.');
|
||||
// Confirm the non-reusable block is not on the page.
|
||||
$this->assertSession()->pageTextNotContains('Non-reusable block');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ class BlockContentSaveTest extends BlockContentTestBase {
|
||||
'info' => $info,
|
||||
'body' => ['value' => $this->randomMachineName(32)],
|
||||
'type' => 'basic',
|
||||
'id' => $test_id
|
||||
'id' => $test_id,
|
||||
];
|
||||
$block = BlockContent::create($block_array);
|
||||
$block->enforceIsNew(TRUE);
|
||||
|
||||
@@ -31,7 +31,7 @@ abstract class BlockContentTestBase extends BrowserTestBase {
|
||||
* @var array
|
||||
*/
|
||||
protected $permissions = [
|
||||
'administer blocks'
|
||||
'administer blocks',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -80,7 +80,7 @@ abstract class BlockContentTestBase extends BrowserTestBase {
|
||||
$block_content = BlockContent::create([
|
||||
'info' => $title,
|
||||
'type' => $bundle,
|
||||
'langcode' => 'en'
|
||||
'langcode' => 'en',
|
||||
]);
|
||||
if ($block_content && $save === TRUE) {
|
||||
$block_content->save();
|
||||
|
||||
@@ -4,8 +4,7 @@ namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\content_translation\Tests\ContentTranslationUITestBase;
|
||||
use Drupal\Tests\content_translation\Functional\ContentTranslationUITestBase;
|
||||
|
||||
/**
|
||||
* Tests the block content translation UI.
|
||||
@@ -24,7 +23,7 @@ class BlockContentTranslationUITest extends ContentTranslationUITestBase {
|
||||
'content_translation',
|
||||
'block',
|
||||
'field_ui',
|
||||
'block_content'
|
||||
'block_content',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -60,7 +59,7 @@ class BlockContentTranslationUITest extends ContentTranslationUITestBase {
|
||||
$bundle = BlockContentType::create([
|
||||
'id' => $this->bundle,
|
||||
'label' => $this->bundle,
|
||||
'revision' => FALSE
|
||||
'revision' => FALSE,
|
||||
]);
|
||||
$bundle->save();
|
||||
}
|
||||
@@ -73,7 +72,7 @@ class BlockContentTranslationUITest extends ContentTranslationUITestBase {
|
||||
'translate any entity',
|
||||
'access administration pages',
|
||||
'administer blocks',
|
||||
'administer block_content fields'
|
||||
'administer block_content fields',
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -96,7 +95,7 @@ class BlockContentTranslationUITest extends ContentTranslationUITestBase {
|
||||
$block_content = BlockContent::create([
|
||||
'info' => $title,
|
||||
'type' => $bundle,
|
||||
'langcode' => 'en'
|
||||
'langcode' => 'en',
|
||||
]);
|
||||
$block_content->save();
|
||||
return $block_content;
|
||||
@@ -106,7 +105,7 @@ class BlockContentTranslationUITest extends ContentTranslationUITestBase {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNewEntityValues($langcode) {
|
||||
return ['info' => Unicode::strtolower($this->randomMachineName())] + parent::getNewEntityValues($langcode);
|
||||
return ['info' => mb_strtolower($this->randomMachineName())] + parent::getNewEntityValues($langcode);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,7 +161,7 @@ class BlockContentTranslationUITest extends ContentTranslationUITestBase {
|
||||
$bundle = BlockContentType::create([
|
||||
'id' => $disabled_bundle,
|
||||
'label' => $disabled_bundle,
|
||||
'revision' => FALSE
|
||||
'revision' => FALSE,
|
||||
]);
|
||||
$bundle->save();
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ class BlockContentTypeTest extends BlockContentTestBase {
|
||||
*/
|
||||
protected $permissions = [
|
||||
'administer blocks',
|
||||
'administer block_content fields'
|
||||
'administer block_content fields',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -122,7 +122,7 @@ class BlockContentTypeTest extends BlockContentTestBase {
|
||||
$front_page_path => 'Home',
|
||||
'admin/structure/block' => 'Block layout',
|
||||
'admin/structure/block/block-content' => 'Custom block library',
|
||||
'admin/structure/block/block-content/manage/basic' => 'Bar',
|
||||
'admin/structure/block/block-content/manage/basic' => 'Edit Bar',
|
||||
]);
|
||||
\Drupal::entityManager()->clearCachedFieldDefinitions();
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Hal;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Tests\block_content\Functional\Rest\BlockContentResourceTestBase;
|
||||
use Drupal\Tests\hal\Functional\EntityResource\HalEntityNormalizationTrait;
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class BlockContentHalJsonAnonTest extends BlockContentResourceTestBase {
|
||||
|
||||
use HalEntityNormalizationTrait;
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
$default_normalization = parent::getExpectedNormalizedEntity();
|
||||
|
||||
$normalization = $this->applyHalFieldNormalization($default_normalization);
|
||||
|
||||
return $normalization + [
|
||||
'_links' => [
|
||||
'self' => [
|
||||
'href' => $this->baseUrl . '/block/1?_format=hal_json',
|
||||
],
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/block_content/basic',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
return parent::getNormalizedPostEntity() + [
|
||||
'_links' => [
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/block_content/basic',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedCacheContexts() {
|
||||
// The 'url.site' cache context is added for '_links' in the response.
|
||||
return Cache::mergeTags(parent::getExpectedCacheContexts(), ['url.site']);
|
||||
}
|
||||
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class BlockContentHalJsonBasicAuthTest extends BlockContentHalJsonAnonTest {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class BlockContentHalJsonCookieTest extends BlockContentHalJsonAnonTest {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\block_content\Functional\Rest\BlockContentTypeResourceTestBase;
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class BlockContentTypeHalJsonAnonTest extends BlockContentTypeResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\block_content\Functional\Rest\BlockContentTypeResourceTestBase;
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class BlockContentTypeHalJsonBasicAuthTest extends BlockContentTypeResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal', 'basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\block_content\Functional\Rest\BlockContentTypeResourceTestBase;
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class BlockContentTypeHalJsonCookieTest extends BlockContentTypeResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace Drupal\Tests\block_content\Functional;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
|
||||
/**
|
||||
* Create a block and test block edit functionality.
|
||||
@@ -28,7 +27,7 @@ class PageEditTest extends BlockContentTestBase {
|
||||
$body_key = 'body[0][value]';
|
||||
// Create block to edit.
|
||||
$edit = [];
|
||||
$edit['info[0][value]'] = Unicode::strtolower($this->randomMachineName(8));
|
||||
$edit['info[0][value]'] = mb_strtolower($this->randomMachineName(8));
|
||||
$edit[$body_key] = $this->randomMachineName(16);
|
||||
$this->drupalPostForm('block/add/basic', $edit, t('Save'));
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentJsonAnonTest extends BlockContentResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentJsonBasicAuthTest extends BlockContentResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentJsonCookieTest extends BlockContentResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
+203
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Tests\rest\Functional\BcTimestampNormalizerUnixTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
|
||||
/**
|
||||
* ResourceTestBase for BlockContent entity.
|
||||
*/
|
||||
abstract class BlockContentResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
use BcTimestampNormalizerUnixTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['block_content'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $entityTypeId = 'block_content';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $patchProtectedFieldNames = [
|
||||
'changed' => NULL,
|
||||
];
|
||||
|
||||
/**
|
||||
* @var \Drupal\block_content\BlockContentInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpAuthorization($method) {
|
||||
$this->grantPermissionsToTestedRole(['administer blocks']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
if (!BlockContentType::load('basic')) {
|
||||
$block_content_type = BlockContentType::create([
|
||||
'id' => 'basic',
|
||||
'label' => 'basic',
|
||||
'revision' => TRUE,
|
||||
]);
|
||||
$block_content_type->save();
|
||||
block_content_add_body_field($block_content_type->id());
|
||||
}
|
||||
|
||||
// Create a "Llama" custom block.
|
||||
$block_content = BlockContent::create([
|
||||
'info' => 'Llama',
|
||||
'type' => 'basic',
|
||||
'body' => [
|
||||
'value' => 'The name "llama" was adopted by European settlers from native Peruvians.',
|
||||
'format' => 'plain_text',
|
||||
],
|
||||
])
|
||||
->setUnpublished();
|
||||
$block_content->save();
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
return [
|
||||
'id' => [
|
||||
[
|
||||
'value' => 1,
|
||||
],
|
||||
],
|
||||
'uuid' => [
|
||||
[
|
||||
'value' => $this->entity->uuid(),
|
||||
],
|
||||
],
|
||||
'langcode' => [
|
||||
[
|
||||
'value' => 'en',
|
||||
],
|
||||
],
|
||||
'reusable' => [
|
||||
[
|
||||
'value' => TRUE,
|
||||
],
|
||||
],
|
||||
'type' => [
|
||||
[
|
||||
'target_id' => 'basic',
|
||||
'target_type' => 'block_content_type',
|
||||
'target_uuid' => BlockContentType::load('basic')->uuid(),
|
||||
],
|
||||
],
|
||||
'info' => [
|
||||
[
|
||||
'value' => 'Llama',
|
||||
],
|
||||
],
|
||||
'revision_log' => [],
|
||||
'changed' => [
|
||||
$this->formatExpectedTimestampItemValues($this->entity->getChangedTime()),
|
||||
],
|
||||
'revision_id' => [
|
||||
[
|
||||
'value' => 1,
|
||||
],
|
||||
],
|
||||
'revision_created' => [
|
||||
$this->formatExpectedTimestampItemValues((int) $this->entity->getRevisionCreationTime()),
|
||||
],
|
||||
'revision_user' => [],
|
||||
'revision_translation_affected' => [
|
||||
[
|
||||
'value' => TRUE,
|
||||
],
|
||||
],
|
||||
'default_langcode' => [
|
||||
[
|
||||
'value' => TRUE,
|
||||
],
|
||||
],
|
||||
'body' => [
|
||||
[
|
||||
'value' => 'The name "llama" was adopted by European settlers from native Peruvians.',
|
||||
'format' => 'plain_text',
|
||||
'summary' => NULL,
|
||||
'processed' => "<p>The name "llama" was adopted by European settlers from native Peruvians.</p>\n",
|
||||
],
|
||||
],
|
||||
'status' => [
|
||||
[
|
||||
'value' => FALSE,
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
return [
|
||||
'type' => [
|
||||
[
|
||||
'target_id' => 'basic',
|
||||
],
|
||||
],
|
||||
'info' => [
|
||||
[
|
||||
'value' => 'Dramallama',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedUnauthorizedAccessMessage($method) {
|
||||
if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) {
|
||||
return parent::getExpectedUnauthorizedAccessMessage($method);
|
||||
}
|
||||
|
||||
return parent::getExpectedUnauthorizedAccessMessage($method);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedUnauthorizedAccessCacheability() {
|
||||
// @see \Drupal\block_content\BlockContentAccessControlHandler()
|
||||
return parent::getExpectedUnauthorizedAccessCacheability()
|
||||
->addCacheTags(['block_content:1']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedCacheTags() {
|
||||
return Cache::mergeTags(parent::getExpectedCacheTags(), ['config:filter.format.plain_text']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedCacheContexts() {
|
||||
return Cache::mergeContexts(['url.site'], $this->container->getParameter('renderer.config')['required_cache_contexts']);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentTypeJsonAnonTest extends BlockContentTypeResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentTypeJsonBasicAuthTest extends BlockContentTypeResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentTypeJsonCookieTest extends BlockContentTypeResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
|
||||
abstract class BlockContentTypeResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['block_content'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $entityTypeId = 'block_content_type';
|
||||
|
||||
/**
|
||||
* @var \Drupal\block_content\Entity\BlockContentTypeInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpAuthorization($method) {
|
||||
$this->grantPermissionsToTestedRole(['administer blocks']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
$block_content_type = BlockContentType::create([
|
||||
'id' => 'pascal',
|
||||
'label' => 'Pascal',
|
||||
'revision' => FALSE,
|
||||
'description' => 'Provides a competitive alternative to the "basic" type',
|
||||
]);
|
||||
|
||||
$block_content_type->save();
|
||||
|
||||
return $block_content_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
return [
|
||||
'dependencies' => [],
|
||||
'description' => 'Provides a competitive alternative to the "basic" type',
|
||||
'id' => 'pascal',
|
||||
'label' => 'Pascal',
|
||||
'langcode' => 'en',
|
||||
'revision' => 0,
|
||||
'status' => TRUE,
|
||||
'uuid' => $this->entity->uuid(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
// @todo Update in https://www.drupal.org/node/2300677.
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentTypeXmlAnonTest extends BlockContentTypeResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentTypeXmlBasicAuthTest extends BlockContentTypeResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentTypeXmlCookieTest extends BlockContentTypeResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentXmlAnonTest extends BlockContentResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentXmlBasicAuthTest extends BlockContentResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class BlockContentXmlCookieTest extends BlockContentResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
@@ -36,7 +36,7 @@ class UnpublishedBlockTest extends BrowserTestBase {
|
||||
$page = $this->getSession()->getPage();
|
||||
$this->assertTrue($page->has('css', '.block-block-content' . $block_content->uuid()));
|
||||
|
||||
$block_content->setPublished(FALSE);
|
||||
$block_content->setUnpublished();
|
||||
$block_content->save();
|
||||
|
||||
$this->drupalGet('<front>');
|
||||
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Update;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
|
||||
|
||||
/**
|
||||
* Tests 'reusable' field related update functions for the Block Content module.
|
||||
*
|
||||
* @group Update
|
||||
* @group block_content
|
||||
* @group legacy
|
||||
*/
|
||||
class BlockContentReusableUpdateTest extends UpdatePathTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setDatabaseDumpFiles() {
|
||||
$this->databaseDumpFiles = [
|
||||
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
|
||||
// Override the 'block_content' view with an extra display with overridden
|
||||
// filters. This extra display should also have a filter added for
|
||||
// 'reusable' field so that it does not expose non-reusable fields. This
|
||||
// display also has a filter that only shows blocks that contain 'block2'
|
||||
// in the 'info' field.
|
||||
__DIR__ . '/../../../fixtures/update/drupal-8.views_block_content-2976334.php',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests adding 'reusable' entity base field to the block content entity type.
|
||||
*
|
||||
* @see block_content_update_8600()
|
||||
* @see block_content_post_update_add_views_reusable_filter()
|
||||
*/
|
||||
public function testReusableFieldAddition() {
|
||||
$assert_session = $this->assertSession();
|
||||
$entity_definition_update_manager = \Drupal::entityDefinitionUpdateManager();
|
||||
|
||||
// Ensure that 'reusable' field is not present before updates.
|
||||
$this->assertEmpty($entity_definition_update_manager->getFieldStorageDefinition('reusable', 'block_content'));
|
||||
|
||||
// Ensure that 'reusable' filter is not present before updates.
|
||||
$view_config = \Drupal::configFactory()->get('views.view.block_content');
|
||||
$this->assertFalse($view_config->isNew());
|
||||
$this->assertEmpty($view_config->get('display.default.display_options.filters.reusable'));
|
||||
$this->assertEmpty($view_config->get('display.page_2.display_options.filters.reusable'));
|
||||
// Run updates.
|
||||
$this->runUpdates();
|
||||
|
||||
// Ensure that 'reusable' filter is present after updates.
|
||||
\Drupal::configFactory()->clearStaticCache();
|
||||
$view_config = \Drupal::configFactory()->get('views.view.block_content');
|
||||
$this->assertNotEmpty($view_config->get('display.default.display_options.filters.reusable'));
|
||||
$this->assertNotEmpty($view_config->get('display.page_2.display_options.filters.reusable'));
|
||||
|
||||
// Check that the field exists and is configured correctly.
|
||||
$reusable_field = $entity_definition_update_manager->getFieldStorageDefinition('reusable', 'block_content');
|
||||
$this->assertEquals('Reusable', $reusable_field->getLabel());
|
||||
$this->assertEquals('A boolean indicating whether this block is reusable.', $reusable_field->getDescription());
|
||||
$this->assertEquals(FALSE, $reusable_field->isRevisionable());
|
||||
$this->assertEquals(FALSE, $reusable_field->isTranslatable());
|
||||
|
||||
$after_block1 = BlockContent::create([
|
||||
'info' => 'After update block1',
|
||||
'type' => 'basic_block',
|
||||
]);
|
||||
$after_block1->save();
|
||||
// Add second block that will be shown with the 'info' filter on the
|
||||
// additional view display.
|
||||
$after_block2 = BlockContent::create([
|
||||
'info' => 'After update block2',
|
||||
'type' => 'basic_block',
|
||||
]);
|
||||
$after_block2->save();
|
||||
|
||||
$this->assertTrue($after_block1->isReusable());
|
||||
$this->assertTrue($after_block2->isReusable());
|
||||
|
||||
$admin_user = $this->drupalCreateUser(['administer blocks']);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
$block_non_reusable = BlockContent::create([
|
||||
'info' => 'block1 non reusable',
|
||||
'type' => 'basic_block',
|
||||
'reusable' => FALSE,
|
||||
]);
|
||||
$block_non_reusable->save();
|
||||
// Add second block that would be shown with the 'info' filter on the
|
||||
// additional view display if the 'reusable' filter was not added.
|
||||
$block2_non_reusable = BlockContent::create([
|
||||
'info' => 'block2 non reusable',
|
||||
'type' => 'basic_block',
|
||||
'reusable' => FALSE,
|
||||
]);
|
||||
$block2_non_reusable->save();
|
||||
$this->assertFalse($block_non_reusable->isReusable());
|
||||
$this->assertFalse($block2_non_reusable->isReusable());
|
||||
|
||||
// Ensure the Custom Block view shows the reusable blocks only.
|
||||
$this->drupalGet('admin/structure/block/block-content');
|
||||
$assert_session->statusCodeEquals('200');
|
||||
$assert_session->responseContains('view-id-block_content');
|
||||
$assert_session->pageTextContains($after_block1->label());
|
||||
$assert_session->pageTextContains($after_block2->label());
|
||||
$assert_session->pageTextNotContains($block_non_reusable->label());
|
||||
$assert_session->pageTextNotContains($block2_non_reusable->label());
|
||||
|
||||
// Ensure the view's other display also only shows reusable blocks and still
|
||||
// filters on the 'info' field.
|
||||
$this->drupalGet('extra-view-display');
|
||||
$assert_session->statusCodeEquals('200');
|
||||
$assert_session->responseContains('view-id-block_content');
|
||||
$assert_session->pageTextNotContains($after_block1->label());
|
||||
$assert_session->pageTextContains($after_block2->label());
|
||||
$assert_session->pageTextNotContains($block_non_reusable->label());
|
||||
$assert_session->pageTextNotContains($block2_non_reusable->label());
|
||||
|
||||
// Ensure the Custom Block listing without Views installed shows the only
|
||||
// reusable blocks.
|
||||
$this->drupalGet('admin/structure/block/block-content');
|
||||
$this->container->get('module_installer')->uninstall(['views_ui', 'views']);
|
||||
$this->drupalGet('admin/structure/block/block-content');
|
||||
$assert_session->statusCodeEquals('200');
|
||||
$assert_session->responseNotContains('view-id-block_content');
|
||||
$assert_session->pageTextContains($after_block1->label());
|
||||
$assert_session->pageTextContains($after_block2->label());
|
||||
$assert_session->pageTextNotContains($block_non_reusable->label());
|
||||
$assert_session->pageTextNotContains($block2_non_reusable->label());
|
||||
|
||||
$this->drupalGet('block/' . $after_block1->id());
|
||||
$assert_session->statusCodeEquals('200');
|
||||
|
||||
// Ensure the non-reusable block is not accessible in the form.
|
||||
$this->drupalGet('block/' . $block_non_reusable->id());
|
||||
$assert_session->statusCodeEquals('403');
|
||||
|
||||
$this->drupalLogout();
|
||||
|
||||
$this->drupalLogin($this->createUser([
|
||||
'access user profiles',
|
||||
'administer blocks',
|
||||
]));
|
||||
$this->drupalGet('block/' . $after_block1->id());
|
||||
$assert_session->statusCodeEquals('200');
|
||||
|
||||
$this->drupalGet('block/' . $block_non_reusable->id());
|
||||
$assert_session->statusCodeEquals('403');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,6 +9,7 @@ use Drupal\FunctionalTests\Update\UpdatePathTestBase;
|
||||
* Tests update functions for the Block Content module.
|
||||
*
|
||||
* @group Update
|
||||
* @group legacy
|
||||
*/
|
||||
class BlockContentUpdateTest extends UpdatePathTestBase {
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ class BlockContentFieldFilterTest extends BlockContentTestBase {
|
||||
*/
|
||||
public $blockContentInfos = [];
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Drupal\Tests\block_content\Functional\Views;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
|
||||
@@ -68,7 +68,7 @@ abstract class BlockContentTestBase extends ViewTestBase {
|
||||
if ($block_content = BlockContent::create($settings)) {
|
||||
$status = $block_content->save();
|
||||
}
|
||||
$this->assertEqual($status, SAVED_NEW, SafeMarkup::format('Created block content %info.', ['%info' => $block_content->label()]));
|
||||
$this->assertEqual($status, SAVED_NEW, new FormattableMarkup('Created block content %info.', ['%info' => $block_content->label()]));
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
@@ -94,13 +94,13 @@ abstract class BlockContentTestBase extends ViewTestBase {
|
||||
$values += [
|
||||
'id' => $id,
|
||||
'label' => $id,
|
||||
'revision' => FALSE
|
||||
'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.', ['%bundle' => $bundle->id()]));
|
||||
$this->assertEqual($status, SAVED_NEW, new FormattableMarkup('Created block content type %bundle.', ['%bundle' => $bundle->id()]));
|
||||
return $bundle;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Functional\Views;
|
||||
|
||||
use Drupal\Tests\block_content\Functional\BlockContentTestBase;
|
||||
|
||||
/**
|
||||
* Tests block_content wizard and generic entity integration.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentWizardTest extends BlockContentTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['block_content', 'views_ui'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer views']));
|
||||
$this->createBlockContentType('Basic block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests creating a 'block_content' entity view.
|
||||
*/
|
||||
public function testViewAddBlockContent() {
|
||||
$view = [];
|
||||
$view['label'] = $this->randomMachineName(16);
|
||||
$view['id'] = strtolower($this->randomMachineName(16));
|
||||
$view['description'] = $this->randomMachineName(16);
|
||||
$view['page[create]'] = FALSE;
|
||||
$view['show[wizard_key]'] = 'block_content';
|
||||
$this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit'));
|
||||
|
||||
$view_storage_controller = $this->container->get('entity_type.manager')->getStorage('view');
|
||||
/** @var \Drupal\views\Entity\View $view */
|
||||
$view = $view_storage_controller->load($view['id']);
|
||||
|
||||
$display_options = $view->getDisplay('default')['display_options'];
|
||||
|
||||
$this->assertEquals('block_content', $display_options['filters']['reusable']['entity_type']);
|
||||
$this->assertEquals('reusable', $display_options['filters']['reusable']['entity_field']);
|
||||
$this->assertEquals('boolean', $display_options['filters']['reusable']['plugin_id']);
|
||||
$this->assertEquals('1', $display_options['filters']['reusable']['value']);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel;
|
||||
|
||||
use Drupal\block_content\BlockContentAccessControlHandler;
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Core\Access\AccessibleInterface;
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\user\Entity\Role;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* Tests the block content entity access handler.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\block_content\BlockContentAccessControlHandler
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentAccessHandlerTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'block',
|
||||
'block_content',
|
||||
'system',
|
||||
'user',
|
||||
];
|
||||
|
||||
/**
|
||||
* The BlockContent access controller to test.
|
||||
*
|
||||
* @var \Drupal\block_content\BlockContentAccessControlHandler
|
||||
*/
|
||||
protected $accessControlHandler;
|
||||
|
||||
/**
|
||||
* The BlockContent entity used for testing.
|
||||
*
|
||||
* @var \Drupal\block_content\Entity\BlockContent
|
||||
*/
|
||||
protected $blockEntity;
|
||||
|
||||
/**
|
||||
* The test role.
|
||||
*
|
||||
* @var \Drupal\user\RoleInterface
|
||||
*/
|
||||
protected $role;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installSchema('system', ['sequence']);
|
||||
$this->installSchema('system', ['sequences']);
|
||||
$this->installSchema('user', ['users_data']);
|
||||
$this->installEntitySchema('user');
|
||||
$this->installEntitySchema('block_content');
|
||||
|
||||
// Create a block content type.
|
||||
$block_content_type = BlockContentType::create([
|
||||
'id' => 'square',
|
||||
'label' => 'A square block type',
|
||||
'description' => "Provides a block type that is square.",
|
||||
]);
|
||||
$block_content_type->save();
|
||||
|
||||
$this->blockEntity = BlockContent::create([
|
||||
'info' => 'The Block',
|
||||
'type' => 'square',
|
||||
]);
|
||||
$this->blockEntity->save();
|
||||
|
||||
// Create user 1 test does not have all permissions.
|
||||
User::create([
|
||||
'name' => 'admin',
|
||||
])->save();
|
||||
|
||||
$this->role = Role::create([
|
||||
'id' => 'roly',
|
||||
'label' => 'roly poly',
|
||||
]);
|
||||
$this->role->save();
|
||||
$this->accessControlHandler = new BlockContentAccessControlHandler(\Drupal::entityTypeManager()->getDefinition('block_content'), \Drupal::service('event_dispatcher'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::checkAccess
|
||||
*
|
||||
* @dataProvider providerTestAccess
|
||||
*/
|
||||
public function testAccess($operation, $published, $reusable, $permissions, $parent_access, $expected_access) {
|
||||
$published ? $this->blockEntity->setPublished() : $this->blockEntity->setUnpublished();
|
||||
$reusable ? $this->blockEntity->setReusable() : $this->blockEntity->setNonReusable();
|
||||
|
||||
$user = User::create([
|
||||
'name' => 'Someone',
|
||||
'mail' => 'hi@example.com',
|
||||
]);
|
||||
|
||||
if ($permissions) {
|
||||
foreach ($permissions as $permission) {
|
||||
$this->role->grantPermission($permission);
|
||||
}
|
||||
$this->role->save();
|
||||
}
|
||||
$user->addRole($this->role->id());
|
||||
$user->save();
|
||||
|
||||
if ($parent_access) {
|
||||
$parent_entity = $this->prophesize(AccessibleInterface::class);
|
||||
$expected_parent_result = NULL;
|
||||
switch ($parent_access) {
|
||||
case 'allowed':
|
||||
$expected_parent_result = AccessResult::allowed();
|
||||
break;
|
||||
|
||||
case 'neutral':
|
||||
$expected_parent_result = AccessResult::neutral();
|
||||
break;
|
||||
|
||||
case 'forbidden':
|
||||
$expected_parent_result = AccessResult::forbidden();
|
||||
break;
|
||||
}
|
||||
$parent_entity->access($operation, $user, TRUE)
|
||||
->willReturn($expected_parent_result)
|
||||
->shouldBeCalled();
|
||||
|
||||
$this->blockEntity->setAccessDependency($parent_entity->reveal());
|
||||
|
||||
}
|
||||
$this->blockEntity->save();
|
||||
|
||||
$result = $this->accessControlHandler->access($this->blockEntity, $operation, $user, TRUE);
|
||||
switch ($expected_access) {
|
||||
case 'allowed':
|
||||
$this->assertTrue($result->isAllowed());
|
||||
break;
|
||||
|
||||
case 'forbidden':
|
||||
$this->assertTrue($result->isForbidden());
|
||||
break;
|
||||
|
||||
case 'neutral':
|
||||
$this->assertTrue($result->isNeutral());
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->fail('Unexpected access type');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dataprovider for testAccess().
|
||||
*/
|
||||
public function providerTestAccess() {
|
||||
$cases = [
|
||||
'view:published:reusable' => [
|
||||
'view',
|
||||
TRUE,
|
||||
TRUE,
|
||||
[],
|
||||
NULL,
|
||||
'allowed',
|
||||
],
|
||||
'view:unpublished:reusable' => [
|
||||
'view',
|
||||
FALSE,
|
||||
TRUE,
|
||||
[],
|
||||
NULL,
|
||||
'neutral',
|
||||
],
|
||||
'view:unpublished:reusable:admin' => [
|
||||
'view',
|
||||
FALSE,
|
||||
TRUE,
|
||||
['administer blocks'],
|
||||
NULL,
|
||||
'allowed',
|
||||
],
|
||||
'view:published:reusable:admin' => [
|
||||
'view',
|
||||
TRUE,
|
||||
TRUE,
|
||||
['administer blocks'],
|
||||
NULL,
|
||||
'allowed',
|
||||
],
|
||||
'view:published:non_reusable' => [
|
||||
'view',
|
||||
TRUE,
|
||||
FALSE,
|
||||
[],
|
||||
NULL,
|
||||
'forbidden',
|
||||
],
|
||||
'view:published:non_reusable:parent_allowed' => [
|
||||
'view',
|
||||
TRUE,
|
||||
FALSE,
|
||||
[],
|
||||
'allowed',
|
||||
'allowed',
|
||||
],
|
||||
'view:published:non_reusable:parent_neutral' => [
|
||||
'view',
|
||||
TRUE,
|
||||
FALSE,
|
||||
[],
|
||||
'neutral',
|
||||
'neutral',
|
||||
],
|
||||
'view:published:non_reusable:parent_forbidden' => [
|
||||
'view',
|
||||
TRUE,
|
||||
FALSE,
|
||||
[],
|
||||
'forbidden',
|
||||
'forbidden',
|
||||
],
|
||||
];
|
||||
foreach (['update', 'delete'] as $operation) {
|
||||
$cases += [
|
||||
$operation . ':published:reusable' => [
|
||||
$operation,
|
||||
TRUE,
|
||||
TRUE,
|
||||
[],
|
||||
NULL,
|
||||
'neutral',
|
||||
],
|
||||
$operation . ':unpublished:reusable' => [
|
||||
$operation,
|
||||
FALSE,
|
||||
TRUE,
|
||||
[],
|
||||
NULL,
|
||||
'neutral',
|
||||
],
|
||||
$operation . ':unpublished:reusable:admin' => [
|
||||
$operation,
|
||||
FALSE,
|
||||
TRUE,
|
||||
['administer blocks'],
|
||||
NULL,
|
||||
'allowed',
|
||||
],
|
||||
$operation . ':published:reusable:admin' => [
|
||||
$operation,
|
||||
TRUE,
|
||||
TRUE,
|
||||
['administer blocks'],
|
||||
NULL,
|
||||
'allowed',
|
||||
],
|
||||
$operation . ':published:non_reusable' => [
|
||||
$operation,
|
||||
TRUE,
|
||||
FALSE,
|
||||
[],
|
||||
NULL,
|
||||
'forbidden',
|
||||
],
|
||||
$operation . ':published:non_reusable:parent_allowed' => [
|
||||
$operation,
|
||||
TRUE,
|
||||
FALSE,
|
||||
[],
|
||||
'allowed',
|
||||
'neutral',
|
||||
],
|
||||
$operation . ':published:non_reusable:parent_neutral' => [
|
||||
$operation,
|
||||
TRUE,
|
||||
FALSE,
|
||||
[],
|
||||
'neutral',
|
||||
'neutral',
|
||||
],
|
||||
$operation . ':published:non_reusable:parent_forbidden' => [
|
||||
$operation,
|
||||
TRUE,
|
||||
FALSE,
|
||||
[],
|
||||
'forbidden',
|
||||
'forbidden',
|
||||
],
|
||||
];
|
||||
return $cases;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?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 block content plugin deriver.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentDeriverTest 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 that only reusable blocks are derived.
|
||||
*/
|
||||
public function testReusableBlocksOnlyAreDerived() {
|
||||
// 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 up to 11%",
|
||||
]);
|
||||
$block_content_type->save();
|
||||
// And a block content entity.
|
||||
$block_content = BlockContent::create([
|
||||
'info' => 'Spiffy prototype',
|
||||
'type' => 'spiffy',
|
||||
]);
|
||||
$block_content->save();
|
||||
|
||||
// Ensure the reusable block content is provided as a derivative block
|
||||
// plugin.
|
||||
/** @var \Drupal\Core\Block\BlockManagerInterface $block_manager */
|
||||
$block_manager = $this->container->get('plugin.manager.block');
|
||||
$plugin_id = 'block_content' . PluginBase::DERIVATIVE_SEPARATOR . $block_content->uuid();
|
||||
$this->assertTrue($block_manager->hasDefinition($plugin_id));
|
||||
|
||||
// Set the block not to be reusable.
|
||||
$block_content->setNonReusable();
|
||||
$block_content->save();
|
||||
|
||||
// Ensure the non-reusable block content is not provided a derivative block
|
||||
// plugin.
|
||||
$this->assertFalse($block_manager->hasDefinition($plugin_id));
|
||||
}
|
||||
|
||||
}
|
||||
+189
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\block_content_test\Plugin\EntityReferenceSelection\TestSelection;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests EntityReference selection handlers don't return non-reusable blocks.
|
||||
*
|
||||
* @see block_content_query_entity_reference_alter()
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentEntityReferenceSelectionTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'block',
|
||||
'block_content',
|
||||
'block_content_test',
|
||||
'system',
|
||||
'user',
|
||||
];
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* Test reusable block.
|
||||
*
|
||||
* @var \Drupal\block_content\BlockContentInterface
|
||||
*/
|
||||
protected $blockReusable;
|
||||
|
||||
/**
|
||||
* Test non-reusable block.
|
||||
*
|
||||
* @var \Drupal\block_content\BlockContentInterface
|
||||
*/
|
||||
protected $blockNonReusable;
|
||||
|
||||
/**
|
||||
* Test selection handler.
|
||||
*
|
||||
* @var \Drupal\block_content_test\Plugin\EntityReferenceSelection\TestSelection
|
||||
*/
|
||||
protected $selectionHandler;
|
||||
|
||||
/**
|
||||
* Test block expectations.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $expectations;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->installSchema('system', ['sequence']);
|
||||
$this->installSchema('system', ['sequences']);
|
||||
$this->installEntitySchema('user');
|
||||
$this->installEntitySchema('block_content');
|
||||
|
||||
// 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 up to 11%",
|
||||
]);
|
||||
$block_content_type->save();
|
||||
$this->entityTypeManager = $this->container->get('entity_type.manager');
|
||||
|
||||
// And reusable block content entities.
|
||||
$this->blockReusable = BlockContent::create([
|
||||
'info' => 'Reusable Block',
|
||||
'type' => 'spiffy',
|
||||
]);
|
||||
$this->blockReusable->save();
|
||||
$this->blockNonReusable = BlockContent::create([
|
||||
'info' => 'Non-reusable Block',
|
||||
'type' => 'spiffy',
|
||||
'reusable' => FALSE,
|
||||
]);
|
||||
$this->blockNonReusable->save();
|
||||
|
||||
$configuration = [
|
||||
'target_type' => 'block_content',
|
||||
'target_bundles' => ['spiffy' => 'spiffy'],
|
||||
'sort' => ['field' => '_none'],
|
||||
];
|
||||
$this->selectionHandler = new TestSelection($configuration, '', '', $this->container->get('entity.manager'), $this->container->get('module_handler'), \Drupal::currentUser());
|
||||
|
||||
// Setup the 3 expectation cases.
|
||||
$this->expectations = [
|
||||
'both_blocks' => [
|
||||
'spiffy' => [
|
||||
$this->blockReusable->id() => $this->blockReusable->label(),
|
||||
$this->blockNonReusable->id() => $this->blockNonReusable->label(),
|
||||
],
|
||||
],
|
||||
'block_reusable' => ['spiffy' => [$this->blockReusable->id() => $this->blockReusable->label()]],
|
||||
'block_non_reusable' => ['spiffy' => [$this->blockNonReusable->id() => $this->blockNonReusable->label()]],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests to make sure queries without the expected tags are not altered.
|
||||
*
|
||||
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
|
||||
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
|
||||
*/
|
||||
public function testQueriesNotAltered() {
|
||||
// Ensure that queries without all the tags are not altered.
|
||||
$query = $this->entityTypeManager->getStorage('block_content')->getQuery();
|
||||
$this->assertCount(2, $query->execute());
|
||||
|
||||
$query = $this->entityTypeManager->getStorage('block_content')->getQuery();
|
||||
$query->addTag('block_content_access');
|
||||
$this->assertCount(2, $query->execute());
|
||||
|
||||
$query = $this->entityTypeManager->getStorage('block_content')->getQuery();
|
||||
$query->addTag('entity_query_block_content');
|
||||
$this->assertCount(2, $query->execute());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with no conditions set.
|
||||
*
|
||||
* @throws \Drupal\Core\Entity\EntityStorageException
|
||||
*/
|
||||
public function testNoConditions() {
|
||||
$this->assertEquals(
|
||||
$this->expectations['block_reusable'],
|
||||
$this->selectionHandler->getReferenceableEntities()
|
||||
);
|
||||
|
||||
$this->blockNonReusable->setReusable();
|
||||
$this->blockNonReusable->save();
|
||||
|
||||
// Ensure that the block is now returned as a referenceable entity.
|
||||
$this->assertEquals(
|
||||
$this->expectations['both_blocks'],
|
||||
$this->selectionHandler->getReferenceableEntities()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests setting 'reusable' condition on different levels.
|
||||
*
|
||||
* @dataProvider fieldConditionProvider
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testFieldConditions($condition_type, $is_reusable) {
|
||||
$this->selectionHandler->setTestMode($condition_type, $is_reusable);
|
||||
$this->assertEquals(
|
||||
$is_reusable ? $this->expectations['block_reusable'] : $this->expectations['block_non_reusable'],
|
||||
$this->selectionHandler->getReferenceableEntities()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides possible fields and condition types.
|
||||
*/
|
||||
public function fieldConditionProvider() {
|
||||
$cases = [];
|
||||
foreach (['base', 'group', 'nested_group'] as $condition_type) {
|
||||
foreach ([TRUE, FALSE] as $reusable) {
|
||||
$cases["$condition_type:" . ($reusable ? 'reusable' : 'non-reusable')] = [
|
||||
$condition_type,
|
||||
$reusable,
|
||||
];
|
||||
}
|
||||
}
|
||||
return $cases;
|
||||
}
|
||||
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Migrate\d6;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
|
||||
|
||||
/**
|
||||
* Tests migration of i18n custom block strings.
|
||||
*
|
||||
* @group migrate_drupal_6
|
||||
*/
|
||||
class MigrateCustomBlockContentTranslationTest extends MigrateDrupal6TestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'block_content',
|
||||
'content_translation',
|
||||
'language',
|
||||
// Required for translation migrations.
|
||||
'migrate_drupal_multilingual',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installConfig(['block_content']);
|
||||
$this->installEntitySchema('block_content');
|
||||
$this->executeMigrations([
|
||||
'language',
|
||||
'd6_filter_format',
|
||||
'block_content_type',
|
||||
'block_content_body_field',
|
||||
'd6_custom_block',
|
||||
'd6_custom_block_translation',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the Drupal 6 i18n custom block strings to Drupal 8 migration.
|
||||
*/
|
||||
public function testCustomBlockContentTranslation() {
|
||||
/** @var \Drupal\block_content\Entity\BlockContent $block */
|
||||
$block = BlockContent::load(1)->getTranslation('fr');
|
||||
$this->assertSame('fr - Static Block', $block->label());
|
||||
$this->assertGreaterThanOrEqual(REQUEST_TIME, $block->getChangedTime());
|
||||
$this->assertLessThanOrEqual(time(), $block->getChangedTime());
|
||||
$this->assertSame('fr', $block->language()->getId());
|
||||
$this->assertSame('<h3>fr - My first custom block body</h3>', $block->body->value);
|
||||
$this->assertSame('full_html', $block->body->format);
|
||||
|
||||
$block = $block->getTranslation('zu');
|
||||
$this->assertSame('My block 1', $block->label());
|
||||
$this->assertGreaterThanOrEqual(REQUEST_TIME, $block->getChangedTime());
|
||||
$this->assertLessThanOrEqual(time(), $block->getChangedTime());
|
||||
$this->assertSame('zu', $block->language()->getId());
|
||||
$this->assertSame('<h3>zu - My first custom block body</h3>', $block->body->value);
|
||||
$this->assertSame('full_html', $block->body->format);
|
||||
|
||||
$block = BlockContent::load(2)->getTranslation('fr');
|
||||
$this->assertSame('Encore un bloc statique', $block->label());
|
||||
$this->assertGreaterThanOrEqual(REQUEST_TIME, $block->getChangedTime());
|
||||
$this->assertLessThanOrEqual(time(), $block->getChangedTime());
|
||||
$this->assertSame('fr', $block->language()->getId());
|
||||
$this->assertSame('Nom de vocabulaire beaucoup plus long que trente-deux caractères', $block->body->value);
|
||||
$this->assertSame('full_html', $block->body->format);
|
||||
}
|
||||
|
||||
}
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests i18n custom block translations source plugin.
|
||||
*
|
||||
* @covers \Drupal\block_content\Plugin\migrate\source\d6\BoxTranslation
|
||||
*
|
||||
* @group content_translation
|
||||
*/
|
||||
class BoxTranslationTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['block_content', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
// The source data.
|
||||
$tests[0]['database']['boxes'] = [
|
||||
[
|
||||
'bid' => 1,
|
||||
'body' => 'box 1 body',
|
||||
'info' => 'box 1 title',
|
||||
'format' => '2',
|
||||
],
|
||||
[
|
||||
'bid' => 2,
|
||||
'body' => 'box 2 body',
|
||||
'info' => 'box 2 title',
|
||||
'format' => '2',
|
||||
],
|
||||
];
|
||||
|
||||
$tests[0]['database']['i18n_strings'] = [
|
||||
[
|
||||
'lid' => 1,
|
||||
'objectid' => 1,
|
||||
'type' => 'block',
|
||||
'property' => 'title',
|
||||
'objectindex' => 1,
|
||||
'format' => 0,
|
||||
],
|
||||
[
|
||||
'lid' => 2,
|
||||
'objectid' => 1,
|
||||
'type' => 'block',
|
||||
'property' => 'body',
|
||||
'objectindex' => 1,
|
||||
'format' => 0,
|
||||
],
|
||||
[
|
||||
'lid' => 3,
|
||||
'objectid' => 2,
|
||||
'type' => 'block',
|
||||
'property' => 'body',
|
||||
'objectindex' => 2,
|
||||
'format' => 2,
|
||||
],
|
||||
];
|
||||
|
||||
$tests[0]['database']['locales_target'] = [
|
||||
[
|
||||
'lid' => 1,
|
||||
'language' => 'fr',
|
||||
'translation' => 'fr - title translation',
|
||||
'plid' => 0,
|
||||
'plural' => 0,
|
||||
'i18n_status' => 0,
|
||||
],
|
||||
[
|
||||
'lid' => 2,
|
||||
'language' => 'fr',
|
||||
'translation' => 'fr - body translation',
|
||||
'plid' => 0,
|
||||
'plural' => 0,
|
||||
'i18n_status' => 0,
|
||||
],
|
||||
[
|
||||
'lid' => 3,
|
||||
'language' => 'zu',
|
||||
'translation' => 'zu - body translation',
|
||||
'plid' => 0,
|
||||
'plural' => 0,
|
||||
'i18n_status' => 0,
|
||||
],
|
||||
];
|
||||
|
||||
$tests[0]['expected_results'] = [
|
||||
[
|
||||
'lid' => '1',
|
||||
'property' => 'title',
|
||||
'language' => 'fr',
|
||||
'translation' => 'fr - title translation',
|
||||
'bid' => '1',
|
||||
'format' => '2',
|
||||
'title_translated' => 'fr - title translation',
|
||||
'body_translated' => 'fr - body translation',
|
||||
'title' => 'box 1 title',
|
||||
'body' => 'box 1 body',
|
||||
],
|
||||
[
|
||||
'lid' => '2',
|
||||
'property' => 'body',
|
||||
'language' => 'fr',
|
||||
'translation' => 'fr - body translation',
|
||||
'bid' => '1',
|
||||
'format' => '2',
|
||||
'title_translated' => 'fr - title translation',
|
||||
'body_translated' => 'fr - body translation',
|
||||
'title' => 'box 1 title',
|
||||
'body' => 'box 1 body',
|
||||
],
|
||||
[
|
||||
'lid' => '3',
|
||||
'property' => 'body',
|
||||
'language' => 'zu',
|
||||
'translation' => 'zu - body translation',
|
||||
'bid' => '2',
|
||||
'format' => '2',
|
||||
'title_translated' => NULL,
|
||||
'body_translated' => 'zu - body translation',
|
||||
'title' => 'box 2 title',
|
||||
'body' => 'box 2 body',
|
||||
],
|
||||
];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Unit\Access;
|
||||
|
||||
use Drupal\block_content\Access\AccessGroupAnd;
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests accessible groups.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class AccessGroupAndTest extends UnitTestCase {
|
||||
|
||||
use AccessibleTestingTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->account = $this->prophesize(AccountInterface::class)->reveal();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\block_content\Access\AccessGroupAnd
|
||||
*/
|
||||
public function testGroups() {
|
||||
$allowedAccessible = $this->createAccessibleDouble(AccessResult::allowed());
|
||||
$forbiddenAccessible = $this->createAccessibleDouble(AccessResult::forbidden());
|
||||
$neutralAccessible = $this->createAccessibleDouble(AccessResult::neutral());
|
||||
|
||||
// Ensure that groups with no dependencies return a neutral access result.
|
||||
$this->assertTrue((new AccessGroupAnd())->access('view', $this->account, TRUE)->isNeutral());
|
||||
|
||||
$andNeutral = new AccessGroupAnd();
|
||||
$andNeutral->addDependency($allowedAccessible)->addDependency($neutralAccessible);
|
||||
$this->assertTrue($andNeutral->access('view', $this->account, TRUE)->isNeutral());
|
||||
|
||||
$andForbidden = $andNeutral;
|
||||
$andForbidden->addDependency($forbiddenAccessible);
|
||||
$this->assertTrue($andForbidden->access('view', $this->account, TRUE)->isForbidden());
|
||||
|
||||
// Ensure that groups added to other groups works.
|
||||
$andGroupsForbidden = new AccessGroupAnd();
|
||||
$andGroupsForbidden->addDependency($andNeutral)->addDependency($andForbidden);
|
||||
$this->assertTrue($andGroupsForbidden->access('view', $this->account, TRUE)->isForbidden());
|
||||
// Ensure you can add a non-group accessible object.
|
||||
$andGroupsForbidden->addDependency($allowedAccessible);
|
||||
$this->assertTrue($andGroupsForbidden->access('view', $this->account, TRUE)->isForbidden());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Unit\Access;
|
||||
|
||||
use Drupal\Core\Access\AccessibleInterface;
|
||||
use Drupal\Core\Access\AccessResultInterface;
|
||||
|
||||
/**
|
||||
* Helper methods testing accessible interfaces.
|
||||
*/
|
||||
trait AccessibleTestingTrait {
|
||||
|
||||
/**
|
||||
* The test account.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $account;
|
||||
|
||||
/**
|
||||
* Creates AccessibleInterface object from access result object for testing.
|
||||
*
|
||||
* @param \Drupal\Core\Access\AccessResultInterface $accessResult
|
||||
* The accessible result to return.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessibleInterface
|
||||
* The AccessibleInterface object.
|
||||
*/
|
||||
private function createAccessibleDouble(AccessResultInterface $accessResult) {
|
||||
$accessible = $this->prophesize(AccessibleInterface::class);
|
||||
$accessible->access('view', $this->account, TRUE)
|
||||
->willReturn($accessResult);
|
||||
return $accessible->reveal();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Unit\Access;
|
||||
|
||||
use Drupal\block_content\Access\AccessGroupAnd;
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\block_content\Access\RefinableDependentAccessInterface;
|
||||
use Drupal\block_content\Access\RefinableDependentAccessTrait;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\block_content\Access\RefinableDependentAccessTrait
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class DependentAccessTest extends UnitTestCase {
|
||||
use AccessibleTestingTrait;
|
||||
|
||||
/**
|
||||
* An accessible object that results in forbidden access result.
|
||||
*
|
||||
* @var \Drupal\Core\Access\AccessibleInterface
|
||||
*/
|
||||
protected $forbidden;
|
||||
|
||||
/**
|
||||
* An accessible object that results in neutral access result.
|
||||
*
|
||||
* @var \Drupal\Core\Access\AccessibleInterface
|
||||
*/
|
||||
protected $neutral;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->account = $this->prophesize(AccountInterface::class)->reveal();
|
||||
$this->forbidden = $this->createAccessibleDouble(AccessResult::forbidden('Because I said so'));
|
||||
$this->neutral = $this->createAccessibleDouble(AccessResult::neutral('I have no opinion'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the previous dependency is replaced when using set.
|
||||
*
|
||||
* @covers ::setAccessDependency
|
||||
*
|
||||
* @dataProvider providerTestSetFirst
|
||||
*/
|
||||
public function testSetAccessDependency($use_set_first) {
|
||||
$testRefinable = new RefinableDependentAccessTraitTestClass();
|
||||
|
||||
if ($use_set_first) {
|
||||
$testRefinable->setAccessDependency($this->forbidden);
|
||||
}
|
||||
else {
|
||||
$testRefinable->addAccessDependency($this->forbidden);
|
||||
}
|
||||
$accessResult = $testRefinable->getAccessDependency()->access('view', $this->account, TRUE);
|
||||
$this->assertTrue($accessResult->isForbidden());
|
||||
$this->assertEquals('Because I said so', $accessResult->getReason());
|
||||
|
||||
// Calling setAccessDependency() replaces the existing dependency.
|
||||
$testRefinable->setAccessDependency($this->neutral);
|
||||
$dependency = $testRefinable->getAccessDependency();
|
||||
$this->assertFalse($dependency instanceof AccessGroupAnd);
|
||||
$accessResult = $dependency->access('view', $this->account, TRUE);
|
||||
$this->assertTrue($accessResult->isNeutral());
|
||||
$this->assertEquals('I have no opinion', $accessResult->getReason());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests merging a new dependency with existing non-group access dependency.
|
||||
*
|
||||
* @dataProvider providerTestSetFirst
|
||||
*/
|
||||
public function testMergeNonGroup($use_set_first) {
|
||||
$testRefinable = new RefinableDependentAccessTraitTestClass();
|
||||
if ($use_set_first) {
|
||||
$testRefinable->setAccessDependency($this->forbidden);
|
||||
}
|
||||
else {
|
||||
$testRefinable->addAccessDependency($this->forbidden);
|
||||
}
|
||||
|
||||
$accessResult = $testRefinable->getAccessDependency()->access('view', $this->account, TRUE);
|
||||
$this->assertTrue($accessResult->isForbidden());
|
||||
$this->assertEquals('Because I said so', $accessResult->getReason());
|
||||
|
||||
$testRefinable->addAccessDependency($this->neutral);
|
||||
/** @var \Drupal\block_content\Access\AccessGroupAnd $dependency */
|
||||
$dependency = $testRefinable->getAccessDependency();
|
||||
// Ensure the new dependency create a new AND group when merged.
|
||||
$this->assertTrue($dependency instanceof AccessGroupAnd);
|
||||
$dependencies = $dependency->getDependencies();
|
||||
$accessResultForbidden = $dependencies[0]->access('view', $this->account, TRUE);
|
||||
$this->assertTrue($accessResultForbidden->isForbidden());
|
||||
$this->assertEquals('Because I said so', $accessResultForbidden->getReason());
|
||||
$accessResultNeutral = $dependencies[1]->access('view', $this->account, TRUE);
|
||||
$this->assertTrue($accessResultNeutral->isNeutral());
|
||||
$this->assertEquals('I have no opinion', $accessResultNeutral->getReason());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests merging a new dependency with an existing access group dependency.
|
||||
*
|
||||
* @dataProvider providerTestSetFirst
|
||||
*/
|
||||
public function testMergeGroup($use_set_first) {
|
||||
$andGroup = new AccessGroupAnd();
|
||||
$andGroup->addDependency($this->forbidden);
|
||||
$testRefinable = new RefinableDependentAccessTraitTestClass();
|
||||
if ($use_set_first) {
|
||||
$testRefinable->setAccessDependency($andGroup);
|
||||
}
|
||||
else {
|
||||
$testRefinable->addAccessDependency($andGroup);
|
||||
}
|
||||
|
||||
$testRefinable->addAccessDependency($this->neutral);
|
||||
/** @var \Drupal\block_content\Access\AccessGroupAnd $dependency */
|
||||
$dependency = $testRefinable->getAccessDependency();
|
||||
|
||||
// Ensure the new dependency is merged with the existing group.
|
||||
$this->assertTrue($dependency instanceof AccessGroupAnd);
|
||||
$dependencies = $dependency->getDependencies();
|
||||
$accessResultForbidden = $dependencies[0]->access('view', $this->account, TRUE);
|
||||
$this->assertTrue($accessResultForbidden->isForbidden());
|
||||
$this->assertEquals('Because I said so', $accessResultForbidden->getReason());
|
||||
$accessResultNeutral = $dependencies[1]->access('view', $this->account, TRUE);
|
||||
$this->assertTrue($accessResultNeutral->isNeutral());
|
||||
$this->assertEquals('I have no opinion', $accessResultNeutral->getReason());
|
||||
}
|
||||
|
||||
/**
|
||||
* Dataprovider for all test methods.
|
||||
*
|
||||
* Provides test cases for calling setAccessDependency() or
|
||||
* mergeAccessDependency() first. A call to either should behave the same on a
|
||||
* new RefinableDependentAccessInterface object.
|
||||
*/
|
||||
public function providerTestSetFirst() {
|
||||
return [
|
||||
[TRUE],
|
||||
[FALSE],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test class that implements RefinableDependentAccessInterface.
|
||||
*/
|
||||
class RefinableDependentAccessTraitTestClass implements RefinableDependentAccessInterface {
|
||||
|
||||
use RefinableDependentAccessTrait;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user