contrib modules updates

This commit is contained in:
2019-02-27 10:39:59 +01:00
parent 04a4b8895d
commit e3cf889820
579 changed files with 18343 additions and 4076 deletions
@@ -1,11 +1,13 @@
name: Chaos tools
name: Chaos Tools
type: module
description: 'Provides a number of utility and helper APIs for Drupal developers and site builders.'
package: Chaos tool suite
# core: 8.x
dependencies:
- drupal:system (>=8.5)
# Information added by Drupal.org packaging script on 2017-04-28
version: '8.x-3.0'
# Information added by Drupal.org packaging script on 2019-02-21
version: '8.x-3.2'
core: '8.x'
project: 'ctools'
datestamp: 1493401747
datestamp: 1550728390
@@ -4,17 +4,17 @@ services:
arguments: ['@controller_resolver', '@form_builder', '@ctools.wizard.factory']
ctools.wizard.entity.form:
class: Drupal\ctools\Controller\WizardEntityFormController
arguments: ['@controller_resolver', '@form_builder', '@ctools.wizard.factory', '@entity.manager']
arguments: ['@controller_resolver', '@form_builder', '@ctools.wizard.factory', '@entity_type.manager']
ctools.wizard_enhancer:
class: Drupal\ctools\Routing\Enhancer\WizardEnhancer
tags:
- { name: route_enhancer }
ctools.wizard.factory:
class: Drupal\ctools\Wizard\WizardFactory
arguments: ['@form_builder', '@event_dispatcher']
arguments: ['@form_builder', '@event_dispatcher', '@renderer']
ctools.paramconverter.tempstore:
class: Drupal\ctools\ParamConverter\TempstoreConverter
arguments: ['@user.shared_tempstore', '@entity_type.manager']
arguments: ['@tempstore.shared', '@entity_type.manager']
tags:
- { name: paramconverter }
ctools.typed_data.resolver:
@@ -22,7 +22,7 @@ services:
arguments: ['@typed_data_manager', '@string_translation']
ctools.access:
class: Drupal\ctools\Access\TempstoreAccess
arguments: ['@user.shared_tempstore']
arguments: ['@tempstore.shared']
tags:
- { name: access_check, applies_to: _ctools_access }
plugin.manager.ctools.relationship:
@@ -33,6 +33,6 @@ services:
arguments: ['@entity.repository']
ctools.serializable.tempstore.factory:
class: Drupal\ctools\SerializableTempstoreFactory
arguments: ['@keyvalue.expirable', '@lock', '@request_stack', '%user.tempstore.expire%']
arguments: ['@keyvalue.expirable', '@lock', '@request_stack', '%tempstore.expire%', '@current_user']
tags:
- { name: backend_overridable }
@@ -1,14 +1,14 @@
name: Chaos tools blocks
name: Chaos Tools Blocks
type: module
description: 'Provides improvements to blocks that will one day be added to Drupal core.'
package: Chaos tool suite (Experimental)
# version: 3.x
# core: 8.x
dependencies:
- ctools
- ctools:ctools
# Information added by Drupal.org packaging script on 2017-04-28
version: '8.x-3.0'
# Information added by Drupal.org packaging script on 2019-02-21
version: '8.x-3.2'
core: '8.x'
project: 'ctools'
datestamp: 1493401747
datestamp: 1550728390
@@ -0,0 +1,16 @@
<?php
/**
* Remove ctools block from appearing on viewable block types.
* In general, users should be using the core block types instead.
*/
function ctools_block_plugin_filter_block_alter(array &$definitions, array $extra, $consumer) {
$moduleHandler = \Drupal::service('module_handler');
if ($moduleHandler->moduleExists('layout_builder')){
foreach ($definitions AS $label => $definition) {
if($definition['provider'] == 'ctools_block') {
unset($definitions[$label]);
}
}
}
}
@@ -5,7 +5,6 @@ namespace Drupal\ctools_block\Plugin\Block;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
@@ -189,7 +188,7 @@ class EntityField extends BlockBase implements ContextAwarePluginInterface, Cont
return [
'formatter' => [
'label' => 'above',
'type' => $field_type_definition['default_formatter'] ?: '',
'type' => isset($field_type_definition['default_formatter']) ? $field_type_definition['default_formatter'] : '',
'settings' => [],
'third_party_settings' => [],
'weight' => 0,
@@ -14,9 +14,9 @@ class EntityFieldDeriver extends EntityDeriverBase {
* {@inheritdoc}
*/
public function getDerivativeDefinitions($base_plugin_definition) {
$entity_type_labels = $this->entityManager->getEntityTypeLabels();
foreach ($this->entityManager->getFieldMap() as $entity_type_id => $entity_field_map) {
foreach ($this->entityManager->getFieldStorageDefinitions($entity_type_id) as $field_storage_definition) {
$entity_type_labels = $this->entityTypeRepository->getEntityTypeLabels();
foreach ($this->entityFieldManager->getFieldMap() as $entity_type_id => $entity_field_map) {
foreach ($this->entityFieldManager->getFieldStorageDefinitions($entity_type_id) as $field_storage_definition) {
$field_name = $field_storage_definition->getName();
// The blocks are based on fields. However, we are looping through field
@@ -36,7 +36,7 @@ class EntityFieldDeriver extends EntityDeriverBase {
else {
// We take the field label used on the first bundle.
$first_bundle = reset($field_info['bundles']);
$bundle_field_definitions = $this->entityManager->getFieldDefinitions($entity_type_id, $first_bundle);
$bundle_field_definitions = $this->entityFieldManager->getFieldDefinitions($entity_type_id, $first_bundle);
// The field storage config may exist, but it's possible that no
// fields are actually using it. If that's the case, skip to the next
@@ -1,4 +1,4 @@
name: 'Chaos tools blocks test'
name: 'Chaos Tools blocks test'
type: module
description: 'Support module for Chaos tools blocks tests.'
# core: 8.x
@@ -13,8 +13,8 @@ dependencies:
- user
features: true
# Information added by Drupal.org packaging script on 2017-04-28
version: '8.x-3.0'
# Information added by Drupal.org packaging script on 2019-02-21
version: '8.x-3.2'
core: '8.x'
project: 'ctools'
datestamp: 1493401747
datestamp: 1550728390
@@ -0,0 +1,11 @@
name: 'Entity Mask'
# core: 8.x
type: module
description: 'Allows an entity type to borrow the fields and display configuration of another entity type.'
# version: VERSION
# Information added by Drupal.org packaging script on 2019-02-21
version: '8.x-3.2'
core: '8.x'
project: 'ctools'
datestamp: 1550728390
@@ -0,0 +1,189 @@
<?php
use Drupal\Core\Entity\Display\EntityDisplayInterface;
use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
use Drupal\ctools_entity_mask\MaskContentEntityStorage;
/**
* Ensures that mask entity types have the same display modes as masked ones.
*
* @param array $display_modes
* The display modes.
*
* @see hook_entity_view_mode_info_alter()
* @see \Drupal\Core\Entity\EntityDisplayRepository::getAllDisplayModesByEntityType()
*/
function ctools_entity_mask_copy_display_modes(array &$display_modes) {
foreach (\Drupal::entityTypeManager()->getDefinitions() as $id => $entity_type) {
$mask = $entity_type->get('mask');
if ($mask && isset($display_modes[$mask])) {
$display_modes[$id] = $display_modes[$mask];
}
}
}
/**
* Implements hook_entity_view_mode_info_alter().
*/
function ctools_entity_mask_entity_view_mode_info_alter(&$view_modes) {
ctools_entity_mask_copy_display_modes($view_modes);
}
/**
* Implements hook_entity_form_mode_info_alter().
*/
function ctools_entity_mask_entity_form_mode_info_alter(&$form_modes) {
ctools_entity_mask_copy_display_modes($form_modes);
}
/**
* Implements hook_entity_type_alter().
*/
function ctools_entity_mask_entity_type_alter(array &$entity_types) {
/** @var \Drupal\Core\Entity\EntityTypeInterface $entity_type */
foreach ($entity_types as $entity_type) {
// Mask entities should use our specialized storage handler, which simulates
// a save but does not write anything to the database.
if ($entity_type->get('mask') && $entity_type->getStorageClass() == SqlContentEntityStorage::class) {
$entity_type->setStorageClass(MaskContentEntityStorage::class);
// Mask entities should not maintain any tables.
$entity_type->set('base_table', NULL);
$entity_type->set('revision_table', NULL);
$entity_type->set('data_table', NULL);
$entity_type->set('revision_data_table', NULL);
// Nor should they be exposed to Field UI.
$entity_type->set('field_ui_base_route', NULL);
}
}
}
/**
* Copies all components from a display for a masked entity type.
*
* If the given display is for a mask entity type, the corresponding display for
* the masked entity type is loaded and all of its components are copied into
* the given display. If no corresponding display exists for the masked entity
* type, the default display will be loaded and used.
*
* @param \Drupal\Core\Entity\Display\EntityDisplayInterface $display
* The display for the mask entity type.
*/
function ctools_entity_mask_copy_display(EntityDisplayInterface $display) {
$mask = \Drupal::entityTypeManager()
->getDefinition($display->getTargetEntityTypeId())
->get('mask');
// If the target entity type is not masking another entity type, there is
// nothing to do here.
if (empty($mask)) {
return;
}
// Try to load the corresponding entity display for the masked entity type,
// in descending order of preference.
$bundle = $display->getTargetBundle();
$displays = $display::loadMultiple([
$mask . '.' . $bundle . '.' . $display->getMode(),
$mask . '.' . $bundle . '.default',
]);
// Nothing to do if there is no display we can borrow components from.
if (empty($displays)) {
return;
}
foreach (reset($displays)->getComponents() as $key => $component) {
$display->setComponent($key, $component);
}
}
/**
* Implements hook_ENTITY_TYPE_create().
*/
function ctools_entity_mask_entity_view_display_create(EntityViewDisplayInterface $display) {
ctools_entity_mask_copy_display($display);
}
/**
* Implements hook_ENTITY_TYPE_create().
*/
function ctools_entity_mask_entity_form_display_create(EntityFormDisplayInterface $display) {
ctools_entity_mask_copy_display($display);
}
/**
* Implements hook_entity_view_display_alter().
*/
function ctools_entity_mask_entity_view_display_alter(EntityViewDisplayInterface $display, array $context) {
ctools_entity_mask_copy_display($display);
}
/**
* Implements hook_entity_form_display_alter().
*/
function ctools_entity_mask_entity_form_display_alter(EntityFormDisplayInterface $form_display, array $context) {
ctools_entity_mask_copy_display($form_display);
}
/**
* Implements hook_entity_bundle_field_info().
*/
function ctools_entity_mask_entity_bundle_field_info(EntityTypeInterface $entity_type, $bundle) {
$info = [];
$mask = $entity_type->get('mask');
// Nothing to do if the entity type is not masking another entity type.
if (empty($mask)) {
return $info;
}
$storage_info = ctools_entity_mask_entity_field_storage_info($entity_type);
/** @var \Drupal\field\FieldConfigInterface[] $fields */
$fields = \Drupal::entityTypeManager()
->getStorage('field_config')
->loadByProperties([
'entity_type' => $mask,
'bundle' => $bundle,
]);
foreach ($fields as $field) {
$field_name = $field->getName();
$info[$field_name] = $field
->createDuplicate()
->set('entity_type', $mask)
->set('fieldStorage', $storage_info[$field_name]);
}
return $info;
}
/**
* Implements hook_entity_field_storage_info().
*/
function ctools_entity_mask_entity_field_storage_info(EntityTypeInterface $entity_type) {
$info = [];
$mask = $entity_type->get('mask');
// Nothing to do if the entity type is not masking another entity type.
if (empty($mask)) {
return $info;
}
/** @var \Drupal\field\FieldStorageConfigInterface[] $fields */
$fields = \Drupal::entityTypeManager()
->getStorage('field_storage_config')
->loadByProperties([
'entity_type' => $mask,
]);
foreach ($fields as $field) {
$field_name = $field->getName();
$info[$field_name] = $field->createDuplicate()->set('entity_type', $mask);
}
return $info;
}
@@ -0,0 +1,81 @@
<?php
namespace Drupal\ctools_entity_mask;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\ContentEntityStorageBase;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
/**
* Storage handler that simulates a full save, without writing to the database.
*/
class MaskContentEntityStorage extends ContentEntityStorageBase {
/**
* {@inheritdoc}
*/
protected function readFieldItemsToPurge(FieldDefinitionInterface $field_definition, $batch_size) {
return [];
}
/**
* {@inheritdoc}
*/
protected function purgeFieldItems(ContentEntityInterface $entity, FieldDefinitionInterface $field_definition) {
}
/**
* {@inheritdoc}
*/
protected function doLoadRevisionFieldItems($revision_id) {
return NULL;
}
/**
* {@inheritdoc}
*/
protected function doSaveFieldItems(ContentEntityInterface $entity, array $names = []) {
}
/**
* {@inheritdoc}
*/
protected function doDeleteFieldItems($entities) {
}
/**
* {@inheritdoc}
*/
protected function doDeleteRevisionFieldItems(ContentEntityInterface $revision) {
}
/**
* {@inheritdoc}
*/
protected function doLoadMultiple(array $ids = NULL) {
return [];
}
/**
* {@inheritdoc}
*/
protected function has($id, EntityInterface $entity) {
return FALSE;
}
/**
* {@inheritdoc}
*/
protected function getQueryServiceName() {
return 'entity.query.null';
}
/**
* {@inheritdoc}
*/
public function countFieldData($storage_definition, $as_bool = FALSE) {
return $as_bool ? FALSE : 0;
}
}
@@ -0,0 +1,26 @@
<?php
namespace Drupal\ctools_entity_mask;
/**
* Provides common functionality for mask entities.
*/
trait MaskEntityTrait {
/**
* Implements \Drupal\Core\Entity\EntityInterface::id().
*
* Mask entities are generally not saved to the database like standard content
* entities, so it cannot be assumed that they will have a serial ID at any
* point in their lives. However, Drupal still expects all entities to have an
* identifier of some kind, so this dual-purposes the UUID as the canonical
* entity ID. (It would be nice if core did this as a rule for all entities
* and stopped using serial IDs, but, y'know, baby steps.)
*
* @return string
*/
public function id() {
return $this->uuid();
}
}
@@ -0,0 +1,7 @@
langcode: en
status: true
dependencies: { }
id: basic
label: 'Basic block'
revision: 0
description: 'A basic block contains a title and a body.'
@@ -0,0 +1,52 @@
langcode: en
status: true
dependencies:
config:
- block_content.type.basic
- field.field.block_content.basic.body
- field.field.block_content.basic.field_image
- field.field.block_content.basic.field_link
- image.style.thumbnail
module:
- image
- link
- text
id: block_content.basic.default
targetEntityType: block_content
bundle: basic
mode: default
content:
body:
type: text_textarea_with_summary
weight: 1
settings:
rows: 9
summary_rows: 3
placeholder: ''
third_party_settings: { }
region: content
field_image:
type: image_image
weight: 3
settings:
preview_image_style: thumbnail
progress_indicator: throbber
third_party_settings: { }
region: content
field_link:
weight: 2
settings:
placeholder_url: ''
placeholder_title: ''
third_party_settings: { }
type: link_default
region: content
info:
type: string_textfield
weight: 0
settings:
size: 60
placeholder: ''
third_party_settings: { }
region: content
hidden: { }
@@ -0,0 +1,46 @@
langcode: en
status: true
dependencies:
config:
- block_content.type.basic
- field.field.block_content.basic.body
- field.field.block_content.basic.field_image
- field.field.block_content.basic.field_link
module:
- image
- link
- text
id: block_content.basic.default
targetEntityType: block_content
bundle: basic
mode: default
content:
body:
type: text_default
weight: 0
label: hidden
settings: { }
third_party_settings: { }
region: content
field_image:
weight: 2
label: above
settings:
image_style: ''
image_link: ''
third_party_settings: { }
type: image
region: content
field_link:
weight: 1
label: above
settings:
trim_length: 80
url_only: false
url_plain: false
rel: ''
target: ''
third_party_settings: { }
type: link
region: content
hidden: { }
@@ -0,0 +1,21 @@
langcode: en
status: true
dependencies:
config:
- block_content.type.basic
- field.storage.block_content.body
module:
- text
id: block_content.basic.body
field_name: body
entity_type: block_content
bundle: basic
label: Body
description: ''
required: false
translatable: true
default_value: { }
default_value_callback: ''
settings:
display_summary: false
field_type: text_with_summary
@@ -0,0 +1,37 @@
langcode: en
status: true
dependencies:
config:
- block_content.type.basic
- field.storage.block_content.field_image
module:
- image
id: block_content.basic.field_image
field_name: field_image
entity_type: block_content
bundle: basic
label: Image
description: ''
required: false
translatable: false
default_value: { }
default_value_callback: ''
settings:
file_directory: '[date:custom:Y]-[date:custom:m]'
file_extensions: 'png gif jpg jpeg'
max_filesize: ''
max_resolution: ''
min_resolution: ''
alt_field: true
alt_field_required: true
title_field: false
title_field_required: false
default_image:
uuid: ''
alt: ''
title: ''
width: null
height: null
handler: 'default:file'
handler_settings: { }
field_type: image
@@ -0,0 +1,22 @@
langcode: en
status: true
dependencies:
config:
- block_content.type.basic
- field.storage.block_content.field_link
module:
- link
id: block_content.basic.field_link
field_name: field_link
entity_type: block_content
bundle: basic
label: Link
description: ''
required: false
translatable: false
default_value: { }
default_value_callback: ''
settings:
link_type: 17
title: 1
field_type: link
@@ -0,0 +1,29 @@
langcode: en
status: true
dependencies:
module:
- block_content
- file
- image
id: block_content.field_image
field_name: field_image
entity_type: block_content
type: image
settings:
uri_scheme: public
default_image:
uuid: ''
alt: ''
title: ''
width: null
height: null
target_type: file
display_field: false
display_default: false
module: image
locked: false
cardinality: 1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false
@@ -0,0 +1,18 @@
langcode: en
status: true
dependencies:
module:
- block_content
- link
id: block_content.field_link
field_name: field_link
entity_type: block_content
type: link
settings: { }
module: link
locked: false
cardinality: 1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false
@@ -0,0 +1,14 @@
name: 'Entity Mask test'
# core: 8.x
type: module
dependencies:
- block_content
- ctools_entity_mask
- image
- text
# Information added by Drupal.org packaging script on 2019-02-21
version: '8.x-3.2'
core: '8.x'
project: 'ctools'
datestamp: 1550728390
@@ -0,0 +1,9 @@
fake_block_content.add_form:
path: '/fake-block/add/{block_content_type}'
defaults:
_controller: '\Drupal\block_content\Controller\BlockContentController::addForm'
_title_callback: 'Drupal\block_content\Controller\BlockContentController::getAddFormTitle'
options:
_admin_route: TRUE
requirements:
_permission: 'administer blocks'
@@ -0,0 +1,70 @@
<?php
namespace Drupal\entity_mask_test\Entity;
use Drupal\block_content\Entity\BlockContent as BaseBlockContent;
use Drupal\ctools_entity_mask\MaskEntityTrait;
/**
* Provides a masked version of BlockContent.
*
* @todo Investigate a better way to copy the upstream properties instead of
* manually duplicating them.
*
* @ContentEntityType(
* id = "fake_block_content",
* label = @Translation("Custom block"),
* bundle_label = @Translation("Custom block type"),
* handlers = {
* "storage" = "Drupal\Core\Entity\Sql\SqlContentEntityStorage",
* "access" = "Drupal\block_content\BlockContentAccessControlHandler",
* "list_builder" = "Drupal\block_content\BlockContentListBuilder",
* "view_builder" = "Drupal\block_content\BlockContentViewBuilder",
* "views_data" = "Drupal\block_content\BlockContentViewsData",
* "form" = {
* "add" = "Drupal\block_content\BlockContentForm",
* "edit" = "Drupal\block_content\BlockContentForm",
* "delete" = "Drupal\block_content\Form\BlockContentDeleteForm",
* "default" = "Drupal\block_content\BlockContentForm"
* },
* "translation" = "Drupal\block_content\BlockContentTranslationHandler"
* },
* admin_permission = "administer blocks",
* base_table = "block_content",
* revision_table = "block_content_revision",
* data_table = "block_content_field_data",
* revision_data_table = "block_content_field_revision",
* show_revision_ui = TRUE,
* links = {
* "canonical" = "/block/{block_content}",
* "delete-form" = "/block/{block_content}/delete",
* "edit-form" = "/block/{block_content}",
* "collection" = "/admin/structure/block/block-content",
* "create" = "/block",
* },
* translatable = TRUE,
* entity_keys = {
* "id" = "id",
* "revision" = "revision_id",
* "bundle" = "type",
* "label" = "info",
* "langcode" = "langcode",
* "uuid" = "uuid",
* "published" = "status",
* },
* revision_metadata_keys = {
* "revision_user" = "revision_user",
* "revision_created" = "revision_created",
* "revision_log_message" = "revision_log"
* },
* bundle_entity_type = "block_content_type",
* field_ui_base_route = "entity.block_content_type.edit_form",
* render_cache = FALSE,
* mask = "block_content",
* )
*/
class BlockContent extends BaseBlockContent {
use MaskEntityTrait;
}
@@ -0,0 +1,110 @@
<?php
namespace Drupal\Tests\ctools_entity_mask\Functional;
use Drupal\entity_mask_test\Entity\BlockContent;
use Drupal\file\Entity\File;
use Drupal\Tests\BrowserTestBase;
/**
* @group ctools_entity_mask
*/
class DisplayTest extends BrowserTestBase {
/**
* {@inheritdoc}
*/
public static $modules = [
'block',
'block_content',
'ctools_entity_mask',
'entity_mask_test',
'field',
'field_ui',
'file',
'image',
'link',
'system',
'text',
'user',
];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$account = $this->drupalCreateUser(['administer blocks']);
$this->drupalLogin($account);
}
/**
* Tests that the form display for a masked entity replicates its source.
*/
public function testFormDisplay() {
$assert = $this->assertSession();
$this->drupalGet('/fake-block/add/basic');
$assert->statusCodeEquals(200);
$assert->fieldExists('Body');
$assert->fieldExists('Link');
$assert->fieldExists('Image');
}
/**
* Tests that the view display for a masked entity replicates its source.
*/
public function testViewDisplay() {
// Generate a random image for the image field, since that can potentially
// be tricky.
$image_uri = uniqid('public://') . '.png';
$image_uri = $this->getRandomGenerator()->image($image_uri, '100x100', '200x200');
$image = File::create(['uri' => $image_uri]);
$image->save();
$body = 'Qui animated corpse, cricket bat max brucks terribilem incessu zomby.';
$link = 'https://www.drupal.org/project/ctools';
$block = BlockContent::create([
'type' => 'basic',
'body' => $body,
'field_link' => $link,
'field_image' => $image,
]);
$block->save();
// Ensure that the entity is intact after serialization and deserialization,
// since that may prove to be a common storage mechanism for mask entities.
$block = serialize($block);
$block = unserialize($block);
$this->assertSame($body, $block->body->value);
$this->assertSame($link, $block->field_link->uri);
$this->assertSame($image_uri, $block->field_image->entity->getFileUri());
$build = \Drupal::entityTypeManager()
->getViewBuilder('fake_block_content')
->view($block);
// If the fields are not in the renderable array, something has gone awry.
$this->assertArrayHasKey('body', $build);
$this->assertArrayHasKey('field_link', $build);
$this->assertArrayHasKey('field_image', $build);
// Render the block and check the output too, just to be sure.
$rendered = \Drupal::service('renderer')->renderRoot($build);
$rendered = (string) $rendered;
$this->assertContains($block->body->value, $rendered);
$this->assertContains($block->field_link->uri, $rendered);
$image_url = $block->field_image->entity->getFileUri();
$image_url = file_create_url($image_url);
// file_create_url() will include the host and port, but the rendered output
// won't include those.
$image_url = file_url_transform_relative($image_url);
$this->assertContains($image_url, $rendered);
}
}
@@ -0,0 +1,216 @@
<?php
namespace Drupal\Tests\ctools_entity_mask\Kernel;
use Drupal\Core\Entity\Entity\EntityFormMode;
use Drupal\entity_mask_test\Entity\BlockContent;
use Drupal\KernelTests\KernelTestBase;
/**
* Basic test of entity type masking.
*
* @group ctools_entity_mask
*/
class EntityMaskTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = [
'block',
'block_content',
'ctools_entity_mask',
'entity_mask_test',
'field',
'field_ui',
'file',
'image',
'link',
'system',
'text',
'user',
];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig(['block_content', 'entity_mask_test']);
$this->installEntitySchema('fake_block_content');
}
/**
* Tests that fields are correctly masked.
*/
public function testFields() {
$block = BlockContent::create([
'type' => 'basic',
]);
$this->assertTrue($block->hasField('body'));
$this->assertTrue($block->hasField('field_link'));
$this->assertTrue($block->hasField('field_image'));
}
/**
* Tests that entity view displays are correctly masked.
*/
public function testViewDisplays() {
$view_modes = $this->container
->get('entity_display.repository')
->getAllViewModes();
$this->assertSame($view_modes['block_content'], $view_modes['fake_block_content']);
$display = entity_get_display('fake_block_content', 'basic', 'default');
$this->assertTrue($display->isNew());
$components = $display->getComponents();
$this->assertArrayHasKey('body', $components);
$this->assertArrayHasKey('field_link', $components);
$this->assertArrayHasKey('field_image', $components);
}
/**
* Tests that entity form displays are correctly masked.
*/
public function testFormDisplays() {
EntityFormMode::create([
'id' => 'block_content.foobar',
'label' => $this->randomString(),
'targetEntityType' => 'block_content',
])->save();
$form_modes = $this->container
->get('entity_display.repository')
->getAllFormModes();
$this->assertSame($form_modes['block_content'], $form_modes['fake_block_content']);
$display = entity_get_form_display('fake_block_content', 'basic', 'default');
$this->assertTrue($display->isNew());
$components = $display->getComponents();
$this->assertArrayHasKey('body', $components);
$this->assertArrayHasKey('field_link', $components);
$this->assertArrayHasKey('field_image', $components);
}
/**
* Tests that mask entity types define no tables.
*/
public function testNoTables() {
/** @var \Drupal\Core\Entity\EntityTypeInterface $entity_type */
$entity_type = $this->container
->get('entity_type.manager')
->getDefinition('fake_block_content');
$this->assertNull($entity_type->getBaseTable());
$this->assertNull($entity_type->getDataTable());
$this->assertNull($entity_type->getRevisionTable());
$this->assertNull($entity_type->getRevisionDataTable());
}
/**
* Tests that mask entity types are not exposed to Field UI.
*/
public function testNotExposedToFieldUI() {
/** @var \Drupal\Core\Entity\EntityTypeInterface $entity_type */
$entity_type = $this->container
->get('entity_type.manager')
->getDefinition('fake_block_content');
$this->assertNull($entity_type->get('field_ui_base_route'));
}
/**
* Asserts that a mask entity can be serialized and de-serialized coherently.
*
* @depends testFields
*/
public function testSerialization() {
$body = $this->getRandomGenerator()->paragraphs(2);
$link = 'https://www.drupal.org/project/ctools';
/** @var \Drupal\Core\Entity\EntityInterface $block */
$block = BlockContent::create([
'type' => 'basic',
'body' => $body,
'field_link' => $link,
]);
$block = serialize($block);
$block = unserialize($block);
$this->assertSame($body, $block->body->value);
$this->assertSame($link, $block->field_link->uri);
}
/**
* Tests that mask entities' isNew() method behaves consistently.
*/
public function testIsNew() {
$block = BlockContent::create(['type' => 'basic']);
$this->assertTrue($block->isNew());
$block->save();
$this->assertFalse($block->isNew());
}
/**
* Tests that mask entities' id() method returns the UUID.
*/
public function testId() {
$block = BlockContent::create(['type' => 'basic']);
$this->assertSame($block->id(), $block->uuid());
$block->save();
$this->assertSame($block->id(), $block->uuid());
}
/**
* Tests that mask entities cannot be loaded.
*
* @depends testId
*/
public function testLoad() {
$block = BlockContent::create(['type' => 'basic']);
$block->save();
/** @var \Drupal\Core\Entity\EntityStorageInterface $storage */
$storage = $this->container->get('entity_type.manager')->getStorage('fake_block_content');
$id = $block->id();
$this->assertNull($storage->load($id));
$this->assertEmpty($storage->loadMultiple([$id]));
}
/**
* Tests that deleting a mask entity doesn't throw an exception or anything.
*/
public function testDelete() {
$block = BlockContent::create(['type' => 'basic']);
$block->save();
$block->delete();
}
/**
* Tests that mask entities have field data after save.
*
* @depends testFields
* @depends testNoTables
*/
public function testSave() {
$body = $this->getRandomGenerator()->paragraphs(2);
$link = 'https://www.drupal.org/project/ctools';
/** @var \Drupal\Core\Entity\EntityInterface $block */
$block = BlockContent::create([
'type' => 'basic',
'body' => $body,
'field_link' => $link,
]);
// Ensure that the field values are preserved after save...
$this->assertSame($body, $block->body->value);
$this->assertSame($link, $block->field_link->uri);
}
}
@@ -1,15 +1,15 @@
name: Chaos tools Views
name: Chaos Tools Views
type: module
description: 'A set of improvements to the core Views code that allows for greater control over Blocks.'
package: Chaos tool suite (Experimental)
# version: 3.x
# core: 8.x
dependencies:
- block
- views
- drupal:block
- drupal:views
# Information added by Drupal.org packaging script on 2017-04-28
version: '8.x-3.0'
# Information added by Drupal.org packaging script on 2019-02-21
version: '8.x-3.2'
core: '8.x'
project: 'ctools'
datestamp: 1493401747
datestamp: 1550728390
@@ -2,11 +2,9 @@
namespace Drupal\ctools_views\Plugin\Display;
use Drupal\Core\Form\FormState;
use Drupal\Core\Form\FormStateInterface;
use Drupal\views\Plugin\Block\ViewsBlock;
use Drupal\views\Plugin\views\display\Block as CoreBlock;
use Drupal\views\Plugin\views\filter\InOperator;
/**
* Provides a Block display plugin that allows for greater control over Views
@@ -52,10 +50,14 @@ class Block extends CoreBlock {
$options['configure_sorts'] = $this->t('Configure sorts');
$form['allow']['#options'] = $options;
// Update the items_per_page if set.
$defaults = array_filter($form['allow']['#default_value']);
if (isset($defaults['items_per_page'])) {
$defaults['items_per_page'] = 'items_per_page';
$defaults = [];
if (!empty($form['allow']['#default_value'])) {
$defaults = array_filter($form['allow']['#default_value']);
if (!empty($defaults['items_per_page'])) {
$defaults['items_per_page'] = 'items_per_page';
}
}
$form['allow']['#default_value'] = $defaults;
}
@@ -157,7 +159,7 @@ class Block extends CoreBlock {
if (!empty($allow_settings['sort_fields'])) {
$form['override']['order_fields'][$field_name]['#attributes']['class'][] = 'draggable';
}
$form['override']['order_fields'][$field_name]['#weight'] = !empty($block_configuration['fields'][$field_name]['weight']) ? $block_configuration['fields'][$field_name]['weight'] : '';
$form['override']['order_fields'][$field_name]['#weight'] = !empty($block_configuration['fields'][$field_name]['weight']) ? $block_configuration['fields'][$field_name]['weight'] : 0;
if (!empty($allow_settings['hide_fields'])) {
$form['override']['order_fields'][$field_name]['hide'] = [
'#type' => 'checkbox',
@@ -41,11 +41,11 @@ class CToolsViewsBasicViewBlockTest extends UITestBase {
/**
* @inheritdoc
*/
protected function setUp() {
parent::setUp();
protected function setUp($import_test_views = TRUE) {
parent::setUp($import_test_views);
ViewTestData::createTestViews(get_class($this), array('ctools_views_test_views'));
$this->storage = $this->container->get('entity.manager')->getStorage('block');
$this->storage = $this->container->get('entity_type.manager')->getStorage('block');
}
/**
@@ -13,8 +13,8 @@ dependencies:
- node
- taxonomy
# Information added by Drupal.org packaging script on 2017-04-28
version: '8.x-3.0'
# Information added by Drupal.org packaging script on 2019-02-21
version: '8.x-3.2'
core: '8.x'
project: 'ctools'
datestamp: 1493401747
datestamp: 1550728390
@@ -108,7 +108,7 @@ display:
field_api_classes: false
filters:
status:
value: true
value: '1'
table: node_field_data
field: status
plugin_id: boolean
@@ -173,7 +173,7 @@ display:
filter_groups: false
filters:
status:
value: true
value: '1'
table: node_field_data
field: status
plugin_id: boolean
@@ -266,7 +266,7 @@ display:
filter_groups: false
filters:
status:
value: true
value: '1'
table: node_field_data
field: status
plugin_id: boolean
@@ -361,7 +361,7 @@ display:
filter_groups: false
filters:
status:
value: true
value: '1'
table: node_field_data
field: status
plugin_id: boolean
@@ -463,7 +463,7 @@ display:
filter_groups: false
filters:
status:
value: true
value: '1'
table: node_field_data
field: status
plugin_id: boolean
@@ -0,0 +1,6 @@
<?php
/**
* @file
* Plugin to provide access control based on node.
*/
@@ -2,13 +2,12 @@
namespace Drupal\ctools\Access;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Routing\Access\AccessInterface as CoreAccessInterface;
use Drupal\Core\Routing\RouteMatch;
use Drupal\Core\Session\AccountInterface;
use Drupal\ctools\Access\AccessInterface as CToolsAccessInterface;
use Drupal\user\SharedTempStoreFactory;
use Drupal\Core\TempStore\SharedTempStoreFactory;
use Symfony\Component\Routing\Route;
class TempstoreAccess implements CoreAccessInterface {
@@ -16,7 +15,7 @@ class TempstoreAccess implements CoreAccessInterface {
/**
* The shared tempstore factory.
*
* @var \Drupal\user\SharedTempStoreFactory
* @var \Drupal\Core\TempStore\SharedTempStoreFactory
*/
protected $tempstore;
@@ -2,5 +2,4 @@
namespace Drupal\ctools;
class ContextNotFoundException extends \Exception {}
@@ -3,7 +3,7 @@
namespace Drupal\ctools\Controller;
use Drupal\Core\Controller\ControllerResolverInterface;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\ctools\Wizard\WizardFactoryInterface;
@@ -14,11 +14,11 @@ use Drupal\ctools\Wizard\WizardFactoryInterface;
class WizardEntityFormController extends WizardFormController {
/**
* The entity manager service.
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityManager;
protected $entityTypeManager;
/**
* @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver
@@ -27,12 +27,12 @@ class WizardEntityFormController extends WizardFormController {
* The form builder.
* @param \Drupal\ctools\Wizard\WizardFactoryInterface $wizard_factory
* The wizard factory.
* @param \Drupal\Core\Entity\EntityManagerInterface $manager
* The entity manager.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
*/
public function __construct(ControllerResolverInterface $controller_resolver, FormBuilderInterface $form_builder, WizardFactoryInterface $wizard_factory, EntityManagerInterface $manager) {
public function __construct(ControllerResolverInterface $controller_resolver, FormBuilderInterface $form_builder, WizardFactoryInterface $wizard_factory, EntityTypeManagerInterface $entity_type_manager) {
parent::__construct($controller_resolver, $form_builder, $wizard_factory);
$this->entityManager = $manager;
$this->entityTypeManager = $entity_type_manager;
}
/**
@@ -41,7 +41,7 @@ class WizardEntityFormController extends WizardFormController {
protected function getFormArgument(RouteMatchInterface $route_match) {
$form_arg = $route_match->getRouteObject()->getDefault('_entity_wizard');
list($entity_type_id, $operation) = explode('.', $form_arg);
$definition = $this->entityManager->getDefinition($entity_type_id);
$definition = $this->entityTypeManager->getDefinition($entity_type_id);
$handlers = $definition->getHandlerClasses();
if (empty($handlers['wizard'][$operation])) {
throw new \Exception(sprintf('Unsupported wizard operation %s', $operation));
@@ -6,7 +6,6 @@ use Drupal\Core\Controller\ControllerResolverInterface;
use Drupal\Core\Controller\FormController;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\ctools\Wizard\FormWizardInterface;
use Drupal\ctools\Wizard\WizardFactoryInterface;
use Symfony\Component\HttpFoundation\Request;
@@ -25,7 +24,7 @@ class WizardFormController extends FormController {
/**
* Tempstore Factory for keeping track of values in each step of the wizard.
*
* @var \Drupal\user\SharedTempStoreFactory
* @var \Drupal\Core\TempStore\SharedTempStoreFactory
*/
protected $tempstore;
@@ -0,0 +1,56 @@
<?php
namespace Drupal\ctools\Event;
use Drupal\Core\Block\BlockPluginInterface;
use Drupal\ctools\Plugin\BlockVariantInterface;
use Symfony\Component\EventDispatcher\Event;
class BlockVariantEvent extends Event {
/**
* The block being acted upon.
*
* @var \Drupal\Core\Block\BlockPluginInterface
*/
protected $block;
/**
* The variant acting on the block.
*
* @var \Drupal\ctools\Plugin\BlockVariantInterface
*/
protected $variant;
/**
* BlockVariantEvent constructor.
*
* @param \Drupal\Core\Block\BlockPluginInterface $block
* The block plugin.
* @param \Drupal\ctools\Plugin\BlockVariantInterface $variant
* The variant plugin.
*/
public function __construct(BlockPluginInterface $block, BlockVariantInterface $variant) {
$this->block = $block;
$this->variant = $variant;
}
/**
* Gets the block plugin.
*
* @return \Drupal\Core\Block\BlockPluginInterface
*/
public function getBlock() {
return $this->block;
}
/**
* Gets the variant plugin.
*
* @return \Drupal\ctools\Plugin\BlockVariantInterface
*/
public function getVariant() {
return $this->variant;
}
}
@@ -0,0 +1,49 @@
<?php
namespace Drupal\ctools\Event;
/**
* Contains all events dispatched while manipulating blocks in a variant.
*/
final class BlockVariantEvents {
/**
* The name of the event triggered when a block is added to a variant.
*
* This event allows modules to react to a block being added to a variant. The
* event listener method receives a \Drupal\ctools\Event\BlockVariantEvent
* instance.
*
* @Event
*
* @var string
*/
const ADD_BLOCK = 'block.add';
/**
* The name of the event triggered when a block is modified in a variant.
*
* This event allows modules to react to a block being modified in a variant.
* The event listener method receives a \Drupal\ctools\Event\BlockVariantEvent
* instance.
*
* @Event
*
* @var string
*/
const UPDATE_BLOCK = 'block.update';
/**
* The name of the event triggered when a block is removed from a variant.
*
* This event allows modules to react to a block being removed from a variant.
* The event listener method receives a \Drupal\ctools\Event\BlockVariantEvent
* instance.
*
* @Event
*
* @var string
*/
const DELETE_BLOCK = 'block.delete';
}
@@ -2,7 +2,6 @@
namespace Drupal\ctools\Form;
use Drupal\Component\Plugin\PluginManagerInterface;
use Drupal\Component\Uuid\Uuid;
use Drupal\Core\Ajax\AjaxResponse;
@@ -12,7 +11,8 @@ use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContextAwarePluginInterface;
use Drupal\ctools\ConstraintConditionInterface;
use Drupal\user\SharedTempStoreFactory;
use Drupal\Core\TempStore\SharedTempStoreFactory;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
@@ -21,7 +21,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
abstract class ConditionConfigure extends FormBase {
/**
* @var \Drupal\user\SharedTempStoreFactory
* @var \Drupal\Core\TempStore\SharedTempStoreFactory
*/
protected $tempstore;
@@ -44,7 +44,7 @@ abstract class ConditionConfigure extends FormBase {
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container->get('user.shared_tempstore'), $container->get('plugin.manager.condition'));
return new static($container->get('tempstore.shared'), $container->get('plugin.manager.condition'));
}
function __construct(SharedTempStoreFactory $tempstore, PluginManagerInterface $manager) {
@@ -132,7 +132,8 @@ abstract class ConditionConfigure extends FormBase {
$response = new AjaxResponse();
$cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
list($route_name, $route_parameters) = $this->getParentRouteInfo($cached_values);
$response->addCommand(new RedirectCommand($this->url($route_name, $route_parameters)));
$url = Url::fromRoute($route_name, $route_parameters);
$response->addCommand(new RedirectCommand($url->toString()));
$response->addCommand(new CloseModalDialogCommand());
return $response;
}
@@ -8,13 +8,13 @@ use Drupal\Core\Form\ConfirmFormHelper;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\ctools\ConstraintConditionInterface;
use Drupal\user\SharedTempStoreFactory;
use Drupal\Core\TempStore\SharedTempStoreFactory;
use Symfony\Component\DependencyInjection\ContainerInterface;
abstract class ConditionDelete extends ConfirmFormBase {
/**
* @var \Drupal\user\SharedTempStoreFactory
* @var \Drupal\Core\TempStore\SharedTempStoreFactory
*/
protected $tempstore;
@@ -42,7 +42,7 @@ abstract class ConditionDelete extends ConfirmFormBase {
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container->get('user.shared_tempstore'), $container->get('plugin.manager.condition'));
return new static($container->get('tempstore.shared'), $container->get('plugin.manager.condition'));
}
function __construct(SharedTempStoreFactory $tempstore, PluginManagerInterface $manager) {
@@ -2,11 +2,9 @@
namespace Drupal\ctools\Form;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\CloseModalDialogCommand;
use Drupal\Core\Ajax\RedirectCommand;
use Drupal\Core\Entity\Entity;
use Drupal\Core\Entity\Plugin\DataType\EntityAdapter;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
@@ -14,23 +12,31 @@ use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Core\Plugin\Context\ContextInterface;
use Drupal\Core\Url;
use Drupal\user\SharedTempStoreFactory;
use Drupal\Core\TempStore\SharedTempStoreFactory;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
abstract class ContextConfigure extends FormBase {
/**
* @var \Drupal\user\SharedTempStoreFactory
* @var \Drupal\Core\TempStore\SharedTempStoreFactory
*/
protected $tempstore;
/**
* Object EntityTypeManager.
*
* @var Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* @var string
*/
protected $tempstore_id;
/**
* @var string;
* @var string
*/
protected $machine_name;
@@ -38,11 +44,15 @@ abstract class ContextConfigure extends FormBase {
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container->get('user.shared_tempstore'));
return new static(
$container->get('tempstore.shared'),
$container->get('entity_type.manager')
);
}
function __construct(SharedTempStoreFactory $tempstore) {
function __construct(SharedTempStoreFactory $tempstore, EntityTypeManagerInterface $entity_type_manager) {
$this->tempstore = $tempstore;
$this->entityTypeManager = $entity_type_manager;
}
/**
@@ -167,7 +177,7 @@ abstract class ContextConfigure extends FormBase {
if (strpos($context_definition->getDataType(), 'entity:') === 0) {
list(, $entity_type) = explode(':', $context_definition->getDataType());
if (is_numeric($form_state->getValue('context_value'))) {
$value = \Drupal::entityTypeManager()->getStorage($entity_type)->load($form_state->getValue('context_value'));
$value = $this->entityTypeManager->getStorage($entity_type)->load($form_state->getValue('context_value'));
}
}
// No loading required for non-entity values.
@@ -2,10 +2,9 @@
namespace Drupal\ctools\Form;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\ConfirmFormBase;
use Drupal\user\SharedTempStoreFactory;
use Drupal\Core\TempStore\SharedTempStoreFactory;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
@@ -14,7 +13,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
abstract class ContextDelete extends ConfirmFormBase {
/**
* @var \Drupal\user\SharedTempStoreFactory
* @var \Drupal\Core\TempStore\SharedTempStoreFactory
*/
protected $tempstore;
@@ -36,7 +35,7 @@ abstract class ContextDelete extends ConfirmFormBase {
protected $context_id;
public static function create(ContainerInterface $container) {
return new static($container->get('user.shared_tempstore'));
return new static($container->get('tempstore.shared'));
}
public function __construct(SharedTempStoreFactory $tempstore) {
@@ -2,7 +2,6 @@
namespace Drupal\ctools\Form;
use Drupal\Component\Plugin\PluginManagerInterface;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Ajax\AjaxResponse;
@@ -12,6 +11,7 @@ use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Form\FormBuilder;
abstract class ManageConditions extends FormBase {
@@ -20,17 +20,28 @@ abstract class ManageConditions extends FormBase {
*/
protected $manager;
/**
* The builder of form.
*
* @var \Drupal\Core\Form\FormBuilder
*/
protected $formBuilder;
/**
* @var string
*/
protected $machine_name;
public static function create(ContainerInterface $container) {
return new static($container->get('plugin.manager.condition'));
return new static(
$container->get('plugin.manager.condition'),
$container->get('form_builder')
);
}
function __construct(PluginManagerInterface $manager) {
function __construct(PluginManagerInterface $manager, FormBuilder $form_builder) {
$this->manager = $manager;
$this->formBuilder = $form_builder;
}
/**
@@ -91,11 +102,18 @@ abstract class ManageConditions extends FormBase {
public function add(array &$form, FormStateInterface $form_state) {
$condition = $form_state->getValue('conditions');
$content = \Drupal::formBuilder()->getForm($this->getConditionClass(), $condition, $this->getTempstoreId(), $this->machine_name);
$content = $this->formBuilder->getForm($this->getConditionClass(), $condition, $this->getTempstoreId(), $this->machine_name);
$content['#attached']['library'][] = 'core/drupal.dialog.ajax';
$cached_values = $form_state->getTemporaryValue('wizard');
list(, $route_parameters) = $this->getOperationsRouteInfo($cached_values, $this->machine_name, $form_state->getValue('conditions'));
$content['submit']['#attached']['drupalSettings']['ajax'][$content['submit']['#id']]['url'] = $this->url($this->getAddRoute($cached_values), $route_parameters, ['query' => [FormBuilderInterface::AJAX_FORM_REQUEST => TRUE]]);
$route_name = $this->getAddRoute($cached_values);
$route_options = [
'query' => [
FormBuilderInterface::AJAX_FORM_REQUEST => TRUE,
],
];
$url = Url::fromRoute($route_name, $route_parameters, $route_options);
$content['submit']['#attached']['drupalSettings']['ajax'][$content['submit']['#id']]['url'] = $url->toString();
$response = new AjaxResponse();
$response->addCommand(new OpenModalDialogCommand($this->t('Configure Required Context'), $content, array('width' => '700')));
return $response;
@@ -186,7 +204,7 @@ abstract class ManageConditions extends FormBase {
* Document the route name and parameters for edit/delete context operations.
*
* The route name returned from this method is used as a "base" to which
* ".edit" and ".delete" are appeneded in the getOperations() method.
* ".edit" and ".delete" are appended in the getOperations() method.
* Subclassing '\Drupal\ctools\Form\ConditionConfigure' and
* '\Drupal\ctools\Form\ConditionDelete' should set you up for using this
* approach quite seamlessly.
@@ -10,6 +10,7 @@ use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\TypedData\TypedDataManagerInterface;
use Drupal\Core\Url;
use Drupal\ctools\TypedDataResolver;
use Symfony\Component\DependencyInjection\ContainerInterface;
abstract class ManageContext extends FormBase {
@@ -35,6 +36,13 @@ abstract class ManageContext extends FormBase {
*/
protected $formBuilder;
/**
* The typed data resolver.
*
* @var \Drupal\ctools\TypedDataResolver
*/
protected $typedDataResolver;
/**
* An array of property types that are eligible as relationships.
*
@@ -49,13 +57,6 @@ abstract class ManageContext extends FormBase {
*/
protected $relationships = TRUE;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container->get('typed_data_manager'), $container->get('form_builder'));
}
/**
* ManageContext constructor.
*
@@ -63,12 +64,25 @@ abstract class ManageContext extends FormBase {
* The typed data manager.
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
* The form builder.
* @param \Drupal\ctools\TypedDataResolver $ctools_typed_data_resolver
* The typed data resolver.
*/
public function __construct(TypedDataManagerInterface $typed_data_manager, FormBuilderInterface $form_builder) {
public function __construct(TypedDataManagerInterface $typed_data_manager, FormBuilderInterface $form_builder, TypedDataResolver $ctools_typed_data_resolver) {
$this->typedDataManager = $typed_data_manager;
$this->formBuilder = $form_builder;
$this->typedDataResolver = $ctools_typed_data_resolver;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('typed_data_manager'),
$container->get('form_builder'),
$container->get('ctools.typed_data.resolver')
);
}
/**
* {@inheritdoc}
@@ -160,7 +174,14 @@ abstract class ManageContext extends FormBase {
$content['#attached']['library'][] = 'core/drupal.dialog.ajax';
$cached_values = $form_state->getTemporaryValue('wizard');
list(, $route_parameters) = $this->getContextOperationsRouteInfo($cached_values, $this->machine_name, $context);
$content['submit']['#attached']['drupalSettings']['ajax'][$content['submit']['#id']]['url'] = $this->url($this->getContextAddRoute($cached_values), $route_parameters, ['query' => [FormBuilderInterface::AJAX_FORM_REQUEST => TRUE]]);
$route_name = $this->getContextAddRoute($cached_values);
$route_options = [
'query' => [
FormBuilderInterface::AJAX_FORM_REQUEST => TRUE,
],
];
$url = Url::fromRoute($route_name, $route_parameters, $route_options);
$content['submit']['#attached']['drupalSettings']['ajax'][$content['submit']['#id']]['url'] = $url->toString();
$response = new AjaxResponse();
$response->addCommand(new OpenModalDialogCommand($this->t('Add new context'), $content, array('width' => '700')));
return $response;
@@ -172,7 +193,14 @@ abstract class ManageContext extends FormBase {
$content['#attached']['library'][] = 'core/drupal.dialog.ajax';
$cached_values = $form_state->getTemporaryValue('wizard');
list(, $route_parameters) = $this->getRelationshipOperationsRouteInfo($cached_values, $this->machine_name, $relationship);
$content['submit']['#attached']['drupalSettings']['ajax'][$content['submit']['#id']]['url'] = $this->url($this->getRelationshipAddRoute($cached_values), $route_parameters, ['query' => [FormBuilderInterface::AJAX_FORM_REQUEST => TRUE]]);
$route_name = $this->getRelationshipAddRoute($cached_values);
$route_options = [
'query' => [
FormBuilderInterface::AJAX_FORM_REQUEST => TRUE,
],
];
$url = Url::fromRoute($route_name, $route_parameters, $route_options);
$content['submit']['#attached']['drupalSettings']['ajax'][$content['submit']['#id']]['url'] = $url->toString();
$response = new AjaxResponse();
$response->addCommand(new OpenModalDialogCommand($this->t('Configure Relationship'), $content, array('width' => '700')));
return $response;
@@ -180,7 +208,7 @@ abstract class ManageContext extends FormBase {
protected function getAvailableRelationships($cached_values) {
/** @var \Drupal\ctools\TypedDataResolver $resolver */
$resolver = \Drupal::service('ctools.typed_data.resolver');
$resolver = $this->typedDataResolver;
return $resolver->getTokensForContexts($this->getContexts($cached_values));
}
@@ -9,6 +9,8 @@ use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\ctools\TypedDataResolver;
use Symfony\Component\DependencyInjection\ContainerInterface;
abstract class ManageResolverRelationships extends FormBase {
@@ -24,6 +26,43 @@ abstract class ManageResolverRelationships extends FormBase {
*/
protected $property_types = [];
/**
* The typed data resolver.
*
* @var \Drupal\ctools\TypedDataResolver
*/
protected $typedDataResolver;
/**
* The form builder.
*
* @var \Drupal\Core\Form\FormBuilder
*/
protected $formBuilder;
/**
* Constructs a new ManageResolverRelationships object.
*
* @param \Drupal\ctools\TypedDataResolver $ctools_typed_data_resolver
* The typed data resolver.
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
* The form builder.
*/
public function __construct(TypedDataResolver $ctools_typed_data_resolver, FormBuilderInterface $form_builder) {
$this->typedDataResolver = $ctools_typed_data_resolver;
$this->formBuilder = $form_builder;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('ctools.typed_data.resolver'),
$container->get('form_builder')
);
}
/**
* {@inheritdoc}
*/
@@ -80,11 +119,18 @@ abstract class ManageResolverRelationships extends FormBase {
public function addRelationship(array &$form, FormStateInterface $form_state) {
$relationship = $form_state->getValue('relationships');
$content = \Drupal::formBuilder()->getForm($this->getContextClass(), $relationship, $this->getTempstoreId(), $this->machine_name);
$content = $this->formBuilder->getForm($this->getContextClass(), $relationship, $this->getTempstoreId(), $this->machine_name);
$content['#attached']['library'][] = 'core/drupal.dialog.ajax';
$cached_values = $form_state->getTemporaryValue('wizard');
list(, $route_parameters) = $this->getRelationshipOperationsRouteInfo($cached_values, $this->machine_name, $relationship);
$content['submit']['#attached']['drupalSettings']['ajax'][$content['submit']['#id']]['url'] = $this->url($this->getAddRoute($cached_values), $route_parameters, ['query' => [FormBuilderInterface::AJAX_FORM_REQUEST => TRUE]]);
$route_name = $this->getAddRoute($cached_values);
$route_options = [
'query' => [
FormBuilderInterface::AJAX_FORM_REQUEST => TRUE,
],
];
$url = Url::fromRoute($route_name, $route_parameters, $route_options);
$content['submit']['#attached']['drupalSettings']['ajax'][$content['submit']['#id']]['url'] = $url->toString();
$response = new AjaxResponse();
$response->addCommand(new OpenModalDialogCommand($this->t('Configure Relationship'), $content, array('width' => '700')));
return $response;
@@ -92,7 +138,7 @@ abstract class ManageResolverRelationships extends FormBase {
protected function getAvailableRelationships($cached_values) {
/** @var \Drupal\ctools\TypedDataResolver $resolver */
$resolver = \Drupal::service('ctools.typed_data.resolver');
$resolver = $this->typedDataResolver;
return $resolver->getTokensForContexts($this->getContexts($cached_values));
}
@@ -8,13 +8,14 @@ use Drupal\Core\Ajax\RedirectCommand;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\ctools\TypedDataResolver;
use Drupal\user\SharedTempStoreFactory;
use Drupal\Core\TempStore\SharedTempStoreFactory;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
abstract class RelationshipConfigure extends FormBase {
/**
* @var \Drupal\user\SharedTempStoreFactory
* @var \Drupal\Core\TempStore\SharedTempStoreFactory
*/
protected $tempstore;
@@ -37,7 +38,7 @@ abstract class RelationshipConfigure extends FormBase {
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container->get('user.shared_tempstore'), $container->get('ctools.typed_data.resolver'));
return new static($container->get('tempstore.shared'), $container->get('ctools.typed_data.resolver'));
}
public function __construct(SharedTempStoreFactory $tempstore, TypedDataResolver $resolver) {
@@ -111,7 +112,8 @@ abstract class RelationshipConfigure extends FormBase {
$cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
list($route_name, $route_parameters) = $this->getParentRouteInfo($cached_values);
$response = new AjaxResponse();
$response->addCommand(new RedirectCommand($this->url($route_name, $route_parameters)));
$url = Url::fromRoute($route_name, $route_parameters);
$response->addCommand(new RedirectCommand($url->toString()));
$response->addCommand(new CloseModalDialogCommand());
return $response;
}
@@ -9,6 +9,7 @@ use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Form\FormBuilder;
abstract class RequiredContext extends FormBase {
@@ -17,6 +18,13 @@ abstract class RequiredContext extends FormBase {
*/
protected $typedDataManager;
/**
* The builder of form.
*
* @var \Drupal\Core\Form\FormBuilder
*/
protected $formBuilder;
/**
* @var string
*/
@@ -26,11 +34,15 @@ abstract class RequiredContext extends FormBase {
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container->get('typed_data_manager'));
return new static(
$container->get('typed_data_manager'),
$container->get('form_builder')
);
}
public function __construct(PluginManagerInterface $typed_data_manager) {
public function __construct(PluginManagerInterface $typed_data_manager, FormBuilder $form_builder) {
$this->typedDataManager = $typed_data_manager;
$this->formBuilder = $form_builder;
}
/**
@@ -98,7 +110,7 @@ abstract class RequiredContext extends FormBase {
*/
public function add(array &$form, FormStateInterface $form_state) {
$context = $form_state->getValue('contexts');
$content = \Drupal::formBuilder()->getForm($this->getContextClass(), $context, $this->getTempstoreId(), $this->machine_name);
$content = $this->formBuilder->getForm($this->getContextClass(), $context, $this->getTempstoreId(), $this->machine_name);
$content['#attached']['library'][] = 'core/drupal.dialog.ajax';
$response = new AjaxResponse();
$response->addCommand(new OpenModalDialogCommand($this->t('Configure Required Context'), $content, array('width' => '700')));
@@ -183,7 +195,7 @@ abstract class RequiredContext extends FormBase {
* Document the route name and parameters for edit/delete context operations.
*
* The route name returned from this method is used as a "base" to which
* ".edit" and ".delete" are appeneded in the getOperations() method.
* ".edit" and ".delete" are appended in the getOperations() method.
* Subclassing '\Drupal\ctools\Form\ContextConfigure' and
* '\Drupal\ctools\Form\RequiredContextDelete' should set you up for using
* this approach quite seamlessly.
@@ -6,7 +6,7 @@ use Drupal\Core\Form\ConfirmFormBase;
use Drupal\Core\Form\ConfirmFormHelper;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\user\SharedTempStoreFactory;
use Drupal\Core\TempStore\SharedTempStoreFactory;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
@@ -15,7 +15,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
abstract class RequiredContextDelete extends ConfirmFormBase {
/**
* @var \Drupal\user\SharedTempStoreFactory
* @var \Drupal\Core\TempStore\SharedTempStoreFactory
*/
protected $tempstore;
@@ -38,11 +38,11 @@ abstract class RequiredContextDelete extends ConfirmFormBase {
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container->get('user.shared_tempstore'));
return new static($container->get('tempstore.shared'));
}
/**
* @param \Drupal\user\SharedTempStoreFactory $tempstore
* @param \Drupal\Core\TempStore\SharedTempStoreFactory $tempstore
*/
function __construct(SharedTempStoreFactory $tempstore) {
$this->tempstore = $tempstore;
@@ -2,19 +2,19 @@
namespace Drupal\ctools\Form;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\CloseModalDialogCommand;
use Drupal\Core\Ajax\RedirectCommand;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\user\SharedTempStoreFactory;
use Drupal\Core\TempStore\SharedTempStoreFactory;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
abstract class ResolverRelationshipConfigure extends FormBase {
/**
* @var \Drupal\user\SharedTempStoreFactory
* @var \Drupal\Core\TempStore\SharedTempStoreFactory
*/
protected $tempstore;
@@ -32,7 +32,7 @@ abstract class ResolverRelationshipConfigure extends FormBase {
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container->get('user.shared_tempstore'));
return new static($container->get('tempstore.shared'));
}
function __construct(SharedTempStoreFactory $tempstore) {
@@ -141,7 +141,8 @@ abstract class ResolverRelationshipConfigure extends FormBase {
$response = new AjaxResponse();
$cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
list($route_name, $route_parameters) = $this->getParentRouteInfo($cached_values);
$response->addCommand(new RedirectCommand($this->url($route_name, $route_parameters)));
$url = Url::fromRoute($route_name, $route_parameters);
$response->addCommand(new RedirectCommand($url->toString()));
$response->addCommand(new CloseModalDialogCommand());
return $response;
}
@@ -2,18 +2,17 @@
namespace Drupal\ctools\Form;
use Drupal\Core\Form\ConfirmFormBase;
use Drupal\Core\Form\ConfirmFormHelper;
use Drupal\Core\Form\FormStateInterface;
use Drupal\ctools\TypedDataResolver;
use Drupal\user\SharedTempStoreFactory;
use Drupal\Core\TempStore\SharedTempStoreFactory;
use Symfony\Component\DependencyInjection\ContainerInterface;
abstract class ResolverRelationshipDelete extends ConfirmFormBase {
/**
* @var \Drupal\user\SharedTempStoreFactory
* @var \Drupal\Core\TempStore\SharedTempStoreFactory
*/
protected $tempstore;
@@ -41,14 +40,14 @@ abstract class ResolverRelationshipDelete extends ConfirmFormBase {
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container->get('user.shared_tempstore'), $container->get('ctools.typed_data.resolver'));
return new static($container->get('tempstore.shared'), $container->get('ctools.typed_data.resolver'));
}
/**
* @param \Drupal\user\SharedTempStoreFactory $tempstore
* @param \Drupal\Core\TempStore\SharedTempStoreFactory $tempstore
* The shared tempstore.
* @param \Drupal\ctools\TypedDataResolver $resolver
* The the typed data resolver.
* The typed data resolver.
*/
public function __construct(SharedTempStoreFactory $tempstore, TypedDataResolver $resolver) {
$this->tempstore = $tempstore;
@@ -3,10 +3,9 @@
namespace Drupal\ctools\ParamConverter;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\ParamConverter\ParamConverterInterface;
use Drupal\user\SharedTempStoreFactory;
use Drupal\Core\TempStore\SharedTempStoreFactory;
use Symfony\Component\Routing\Route;
/**
@@ -83,7 +82,7 @@ class TempstoreConverter implements ParamConverterInterface {
/**
* The tempstore factory.
*
* @var \Drupal\user\SharedTempStoreFactory
* @var \Drupal\Core\TempStore\SharedTempStoreFactory
*/
protected $tempstore;
@@ -97,7 +96,7 @@ class TempstoreConverter implements ParamConverterInterface {
/**
* Constructs a TempstoreConverter.
*
* @param \Drupal\user\SharedTempStoreFactory $tempstore
* @param \Drupal\Core\TempStore\SharedTempStoreFactory $tempstore
*/
public function __construct(SharedTempStoreFactory $tempstore, EntityTypeManagerInterface $entity_type_manager) {
$this->tempstore = $tempstore;
@@ -4,7 +4,8 @@ namespace Drupal\ctools\Plugin\Block;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\ContextAwarePluginInterface;
@@ -21,11 +22,18 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
class EntityView extends BlockBase implements ContextAwarePluginInterface, ContainerFactoryPluginInterface {
/**
* The entity manager.
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityManager;
protected $entityTypeManager;
/**
* The entity display repository.
*
* @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface
*/
protected $entityDisplayRepository;
/**
* Constructs a new EntityView.
@@ -36,13 +44,16 @@ class EntityView extends BlockBase implements ContextAwarePluginInterface, Conta
* The plugin ID for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository
* The entity display repository.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityManagerInterface $entity_manager) {
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityDisplayRepositoryInterface $entity_display_repository) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->entityManager = $entity_manager;
$this->entityTypeManager = $entity_type_manager;
$this->entityDisplayRepository = $entity_display_repository;
}
/**
@@ -53,7 +64,8 @@ class EntityView extends BlockBase implements ContextAwarePluginInterface, Conta
$configuration,
$plugin_id,
$plugin_definition,
$container->get('entity.manager')
$container->get('entity_type.manager'),
$container->get('entity_display.repository')
);
}
@@ -72,7 +84,7 @@ class EntityView extends BlockBase implements ContextAwarePluginInterface, Conta
public function blockForm($form, FormStateInterface $form_state) {
$form['view_mode'] = [
'#type' => 'select',
'#options' => $this->entityManager->getViewModeOptions($this->getDerivativeId()),
'#options' => $this->entityDisplayRepository->getViewModeOptions($this->getDerivativeId()),
'#title' => $this->t('View mode'),
'#default_value' => $this->configuration['view_mode'],
];
@@ -93,7 +105,7 @@ class EntityView extends BlockBase implements ContextAwarePluginInterface, Conta
/** @var $entity \Drupal\Core\Entity\EntityInterface */
$entity = $this->getContextValue('entity');
$view_builder = $this->entityManager->getViewBuilder($entity->getEntityTypeId());
$view_builder = $this->entityTypeManager->getViewBuilder($entity->getEntityTypeId());
$build = $view_builder->view($entity, $this->configuration['view_mode']);
CacheableMetadata::createFromObject($this->getContext('entity'))
@@ -2,6 +2,9 @@
namespace Drupal\ctools\Plugin;
use Drupal\ctools\Event\BlockVariantEvent;
use Drupal\ctools\Event\BlockVariantEvents;
/**
* Provides methods for \Drupal\ctools\Plugin\BlockVariantInterface.
*/
@@ -21,6 +24,13 @@ trait BlockVariantTrait {
*/
protected $blockPluginCollection;
/**
* The event dispatcher.
*
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
*/
protected $eventDispatcher;
/**
* @see \Drupal\ctools\Plugin\BlockVariantInterface::getRegionNames()
*/
@@ -39,6 +49,12 @@ trait BlockVariantTrait {
public function addBlock(array $configuration) {
$configuration['uuid'] = $this->uuidGenerator()->generate();
$this->getBlockCollection()->addInstanceId($configuration['uuid'], $configuration);
$block = $this->getBlock($configuration['uuid']);
// Allow modules to react to the change.
$event = new BlockVariantEvent($block, $this);
$this->eventDispatcher()->dispatch(BlockVariantEvents::ADD_BLOCK, $event);
return $configuration['uuid'];
}
@@ -46,7 +62,13 @@ trait BlockVariantTrait {
* @see \Drupal\ctools\Plugin\BlockVariantInterface::removeBlock()
*/
public function removeBlock($block_id) {
$block = $this->getBlock($block_id);
$this->getBlockCollection()->removeInstanceId($block_id);
// Allow modules to react to the change.
$event = new BlockVariantEvent($block, $this);
$this->eventDispatcher()->dispatch(BlockVariantEvents::DELETE_BLOCK, $event);
return $this;
}
@@ -54,8 +76,14 @@ trait BlockVariantTrait {
* @see \Drupal\ctools\Plugin\BlockVariantInterface::updateBlock()
*/
public function updateBlock($block_id, array $configuration) {
$existing_configuration = $this->getBlock($block_id)->getConfiguration();
$block = $this->getBlock($block_id);
$existing_configuration = $block->getConfiguration();
$this->getBlockCollection()->setInstanceConfiguration($block_id, $configuration + $existing_configuration);
// Allow modules to react to the change.
$event = new BlockVariantEvent($block, $this);
$this->eventDispatcher()->dispatch(BlockVariantEvents::UPDATE_BLOCK, $event);
return $this;
}
@@ -112,6 +140,18 @@ trait BlockVariantTrait {
return $this->blockPluginCollection;
}
/**
* Gets the event dispatcher.
*
* @return \Symfony\Component\EventDispatcher\EventDispatcherInterface
*/
protected function eventDispatcher() {
if (!$this->eventDispatcher) {
$this->eventDispatcher = \Drupal::service('event_dispatcher');
}
return $this->eventDispatcher;
}
/**
* Returns the UUID generator.
*
@@ -13,7 +13,7 @@ class EntityBundle extends EntityDeriverBase {
* {@inheritdoc}
*/
public function getDerivativeDefinitions($base_plugin_definition) {
foreach ($this->entityManager->getDefinitions() as $entity_type_id => $entity_type) {
foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $entity_type) {
if ($entity_type->hasKey('bundle')) {
$this->derivatives[$entity_type_id] = $base_plugin_definition;
$this->derivatives[$entity_type_id]['label'] = $this->getEntityBundleLabel($entity_type);
@@ -43,7 +43,7 @@ class EntityBundle extends EntityDeriverBase {
$fallback = $entity_type->getLabel();
if ($bundle_entity_type = $entity_type->getBundleEntityType()) {
// This is a better fallback.
$fallback = $this->entityManager->getDefinition($bundle_entity_type)->getLabel();
$fallback = $this->entityTypeManager->getDefinition($bundle_entity_type)->getLabel();
}
return $this->t('@label bundle', ['@label' => $fallback]);
@@ -4,7 +4,9 @@ namespace Drupal\ctools\Plugin\Deriver;
use Drupal\Component\Plugin\Derivative\DeriverBase;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeRepositoryInterface;
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
@@ -18,23 +20,43 @@ abstract class EntityDeriverBase extends DeriverBase implements ContainerDeriver
use StringTranslationTrait;
/**
* The entity manager.
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityManager;
protected $entityTypeManager;
/**
* The entity field manager.
*
* @var \Drupal\Core\Entity\EntityFieldManagerInterface
*/
protected $entityFieldManager;
/**
* The entity type repository.
*
* @var \Drupal\Core\Entity\EntityTypeRepositoryInterface
*/
protected $entityTypeRepository;
/**
* Constructs new EntityViewDeriver.
*
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
* The string translation service.
* @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
* The entity field manager.
* @param \Drupal\Core\Entity\EntityTypeRepositoryInterface $entity_type_repository
* The entity type repository.
*/
public function __construct(EntityManagerInterface $entity_manager, TranslationInterface $string_translation) {
$this->entityManager = $entity_manager;
public function __construct(EntityTypeManagerInterface $entity_type_manager, TranslationInterface $string_translation, EntityFieldManagerInterface $entity_field_manager, EntityTypeRepositoryInterface $entity_type_repository) {
$this->entityTypeManager = $entity_type_manager;
$this->stringTranslation = $string_translation;
$this->entityFieldManager = $entity_field_manager;
$this->entityTypeRepository = $entity_type_repository;
}
/**
@@ -42,8 +64,10 @@ abstract class EntityDeriverBase extends DeriverBase implements ContainerDeriver
*/
public static function create(ContainerInterface $container, $base_plugin_id) {
return new static(
$container->get('entity.manager'),
$container->get('string_translation')
$container->get('entity_type.manager'),
$container->get('string_translation'),
$container->get('entity_field.manager'),
$container->get('entity_type.repository')
);
}
@@ -13,7 +13,7 @@ class EntityViewDeriver extends EntityDeriverBase {
* {@inheritdoc}
*/
public function getDerivativeDefinitions($base_plugin_definition) {
foreach ($this->entityManager->getDefinitions() as $entity_type_id => $entity_type) {
foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $entity_type) {
if ($entity_type->hasViewBuilderClass()) {
$this->derivatives[$entity_type_id] = $base_plugin_definition;
$this->derivatives[$entity_type_id]['admin_label'] = $this->t('Entity view (@label)', ['@label' => $entity_type->getLabel()]);
@@ -4,13 +4,11 @@ namespace Drupal\ctools\Plugin\DisplayVariant;
use Drupal\Component\Uuid\UuidInterface;
use Drupal\Core\Block\BlockManager;
use Drupal\Core\Cache\RefinableCacheableDependencyInterface;
use Drupal\Core\Condition\ConditionManager;
use Drupal\Core\Display\VariantBase;
use Drupal\Core\Display\ContextAwareVariantInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\Context\ContextHandlerInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Utility\Token;
use Drupal\ctools\Form\AjaxFormTrait;
@@ -21,7 +19,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides a base class for a display variant that simply contains blocks.
*/
abstract class BlockDisplayVariant extends VariantBase implements ContextAwareVariantInterface, ContainerFactoryPluginInterface, BlockVariantInterface, RefinableCacheableDependencyInterface {
abstract class BlockDisplayVariant extends VariantBase implements ContextAwareVariantInterface, ContainerFactoryPluginInterface, BlockVariantInterface {
use AjaxFormTrait;
use BlockVariantTrait;
@@ -1,6 +1,7 @@
<?php
namespace Drupal\ctools\Plugin\Relationship;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;
@@ -1,6 +1,7 @@
<?php
namespace Drupal\ctools\Plugin\Relationship;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;
@@ -2,9 +2,7 @@
namespace Drupal\ctools\Plugin\Relationship;
use Drupal\Core\Field\FieldItemInterface;
use Drupal\Core\Field\TypedData\FieldItemDataDefinition;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Core\Plugin\Context\ContextInterface;
@@ -1,6 +1,7 @@
<?php
namespace Drupal\ctools\Plugin;
use Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface;
use Drupal\Core\Plugin\Context\ContextAwarePluginManagerInterface;
@@ -2,33 +2,46 @@
namespace Drupal\ctools\Routing\Enhancer;
use Drupal\Core\Routing\Enhancer\RouteEnhancerInterface;
use Drupal\Core\Routing\EnhancerInterface;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Route;
/**
* Sets the request format onto the request object.
*/
class WizardEnhancer implements RouteEnhancerInterface {
/**
* {@inheritdoc}
*/
public function applies(Route $route) {
return !$route->hasDefault('_controller') && ($route->hasDefault('_wizard') || $route->hasDefault('_entity_wizard'));
}
class WizardEnhancer implements EnhancerInterface {
/**
* {@inheritdoc}
*/
public function enhance(array $defaults, Request $request) {
$route = $defaults[RouteObjectInterface::ROUTE_OBJECT];
if (!$this->isApplicable($route)) {
return $defaults;
}
if (!empty($defaults['_wizard'])) {
$defaults['_controller'] = 'ctools.wizard.form:getContentResult';
}
if (!empty($defaults['_entity_wizard'])) {
$defaults['_controller'] = 'ctools.wizard.entity.form:getContentResult';
}
return $defaults;
}
/**
* Returns if current route use ctools default parameters.
*
* @param \Symfony\Component\Routing\Route $route
* The route to check.
*
* @return bool
* TRUE if the route use one of ctools route default parameters or FALSE.
*/
public function isApplicable(Route $route) {
return !$route->hasDefault('_controller') && ($route->hasDefault('_wizard') || $route->hasDefault('_entity_wizard'));
}
}
@@ -3,7 +3,7 @@
namespace Drupal\ctools;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\user\SharedTempStore;
use Drupal\Core\TempStore\SharedTempStore;
/**
* An extension of the SharedTempStore system for serialized data.
@@ -2,25 +2,55 @@
namespace Drupal\ctools;
use Drupal\user\SharedTempStoreFactory;
use Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface;
use Drupal\Core\Lock\LockBackendInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\TempStore\SharedTempStoreFactory;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* A factory for creating SerializableTempStore objects.
*/
class SerializableTempstoreFactory extends SharedTempStoreFactory {
/**
* The current logged user.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected $currentUser;
/**
* Constructs a Drupal\Core\TempStore\SharedTempStoreFactory object.
*
* @param \Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface $storage_factory
* The key/value store factory.
* @param \Drupal\Core\Lock\LockBackendInterface $lock_backend
* The lock object used for this data.
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
* The request stack.
* @param int $expire
* The time to live for items, in seconds.
* @param \Drupal\Core\Session\AccountProxyInterface|null $current_user
* The current logged user.
*/
public function __construct(KeyValueExpirableFactoryInterface $storage_factory, LockBackendInterface $lock_backend, RequestStack $request_stack, $expire = 604800, AccountProxyInterface $current_user = NULL) {
parent::__construct($storage_factory, $lock_backend, $request_stack, $expire);
$this->currentUser = $current_user ?: \Drupal::currentUser();
}
/**
* {@inheritdoc}
*/
function get($collection, $owner = NULL) {
public function get($collection, $owner = NULL) {
// Use the currently authenticated user ID or the active user ID unless the
// owner is overridden.
if (!isset($owner)) {
$owner = \Drupal::currentUser()->id() ?: session_id();
$owner = $this->currentUser->id() ?: session_id();
}
// Store the data for this collection in the database.
$storage = $this->storageFactory->get("user.shared_tempstore.$collection");
$storage = $this->storageFactory->get("tempstore.shared.$collection");
return new SerializableTempstore($storage, $this->lockBackend, $owner, $this->requestStack, $this->expire);
}
@@ -2,7 +2,6 @@
namespace Drupal\ctools\Testing;
use Drupal\Component\Render\FormattableMarkup;
trait EntityCreationTrait {
@@ -1,43 +1,44 @@
<?php
namespace Drupal\ctools\Tests\Wizard;
namespace Drupal\Tests\ctools\Functional;
use Drupal\simpletest\WebTestBase;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Tests\BrowserTestBase;
/**
* Tests basic wizard functionality.
*
* @group ctools
*/
class CToolsWizardTest extends WebTestBase {
class CToolsWizardTest extends BrowserTestBase {
use StringTranslationTrait;
public static $modules = array('ctools', 'ctools_wizard_test');
public static $modules = ['ctools', 'ctools_wizard_test'];
function testWizardSteps() {
/**
* Test wizard Multistep form.
*/
public function testWizardSteps() {
$this->drupalGet('ctools/wizard');
$this->assertText('Form One');
$this->assertSession()->pageTextContains('Form One');
$this->dumpHeaders = TRUE;
// Check that $operations['one']['values'] worked.
$this->assertText('Xylophone');
$this->assertSession()->pageTextContains('Xylophone');
// Submit first step in the wizard.
$edit = [
'one' => 'test',
];
$this->drupalPostForm('ctools/wizard', $edit, $this->t('Next'));
// Redirected to the second step.
$this->assertText('Form Two');
$this->assertText('Dynamic value submitted: Xylophone');
$this->assertSession()->pageTextContains('Form Two');
$this->assertSession()->pageTextContains('Dynamic value submitted: Xylophone');
// Check that $operations['two']['values'] worked.
$this->assertText('Zebra');
$this->assertSession()->pageTextContains('Zebra');
// Hit previous to make sure our form value are preserved.
$this->drupalPostForm(NULL, [], $this->t('Previous'));
// Check the known form values.
$this->assertFieldByName('one', 'test');
$this->assertText('Xylophone');
$this->assertSession()->fieldValueEquals('one', 'test');
$this->assertSession()->pageTextContains('Xylophone');
// Goto next step again and finish this wizard.
$this->drupalPostForm(NULL, [], $this->t('Next'));
$edit = [
@@ -45,44 +46,50 @@ class CToolsWizardTest extends WebTestBase {
];
$this->drupalPostForm(NULL, $edit, $this->t('Finish'));
// Check that the wizard finished properly.
$this->assertText('Value One: test');
$this->assertText('Value Two: Second test');
$this->assertSession()->pageTextContains('Value One: test');
$this->assertSession()->pageTextContains('Value Two: Second test');
}
function testStepValidateAndSubmit() {
/**
* Test wizard validate and submit.
*/
public function testStepValidateAndSubmit() {
$this->drupalGet('ctools/wizard');
$this->assertText('Form One');
$this->assertSession()->pageTextContains('Form One');
// Submit first step in the wizard.
$edit = [
'one' => 'wrong',
];
$this->drupalPostForm('ctools/wizard', $edit, $this->t('Next'));
// We're still on the first form and the error is present.
$this->assertText('Form One');
$this->assertText('Cannot set the value to "wrong".');
$this->assertSession()->pageTextContains('Form One');
$this->assertSession()->pageTextContains('Cannot set the value to "wrong".');
// Try again with the magic value.
$edit = [
'one' => 'magic',
];
$this->drupalPostForm('ctools/wizard', $edit, $this->t('Next'));
// Redirected to the second step.
$this->assertText('Form Two');
$this->assertSession()->pageTextContains('Form Two');
$edit = [
'two' => 'Second test',
];
$this->drupalPostForm(NULL, $edit, $this->t('Finish'));
// Check that the magic value triggered our submit callback.
$this->assertText('Value One: Abraham');
$this->assertText('Value Two: Second test');
$this->assertSession()->pageTextContains('Value One: Abraham');
$this->assertSession()->pageTextContains('Value Two: Second test');
}
function testEntityWizard() {
/**
* Test wizard entity config update.
*/
public function testEntityWizard() {
$this->drupalLogin($this->drupalCreateUser(['administer site configuration']));
// Start adding a new config entity.
$this->drupalGet('admin/structure/ctools_wizard_test_config_entity/add');
$this->assertText('Example entity');
$this->assertNoText('Existing entity');
$this->assertSession()->pageTextContains('Example entity');
$this->assertSession()->pageTextNotContains('Existing entity');
// Submit the general step.
$edit = [
@@ -104,33 +111,32 @@ class CToolsWizardTest extends WebTestBase {
$this->drupalPostForm(NULL, $edit, $this->t('Finish'));
// Now we should be looking at the list of entities.
$this->assertUrl('admin/structure/ctools_wizard_test_config_entity');
$this->assertText('Test Config Entity 123');
$this->assertSession()->addressEquals('admin/structure/ctools_wizard_test_config_entity');
$this->assertSession()->pageTextContains('Test Config Entity 123');
// Edit the entity again and make sure the values are what we expect.
$this->clickLink(t('Edit'));
$this->assertText('Existing entity');
$this->assertFieldByName('label', 'Test Config Entity 123');
$this->assertSession()->pageTextContains('Existing entity');
$this->assertSession()->fieldValueEquals('label', 'Test Config Entity 123');
$this->clickLink(t('Form One'));
$this->assertFieldByName('one', 'The first bit');
$this->assertSession()->fieldValueEquals('one', 'The first bit');
$previous = $this->getUrl();
$this->clickLink(t('Show on dialog'));
$this->assertRaw('Value from one: The first bit');
$this->assertSession()->responseContains('Value from one: The first bit');
$this->drupalGet($previous);
// Change the value for 'one'.
$this->drupalPostForm(NULL, ['one' => 'New value'], $this->t('Next'));
$this->assertFieldByName('two', 'The second bit');
$this->assertSession()->fieldValueEquals('two', 'The second bit');
$this->drupalPostForm(NULL, [], $this->t('Next'));
// Make sure we get the additional step because the entity exists.
$this->assertText('This step only shows if the entity is already existing!');
$this->assertSession()->pageTextContains('This step only shows if the entity is already existing!');
$this->drupalPostForm(NULL, [], $this->t('Finish'));
// Edit the entity again and make sure the change stuck.
$this->assertUrl('admin/structure/ctools_wizard_test_config_entity');
$this->assertSession()->addressEquals('admin/structure/ctools_wizard_test_config_entity');
$this->clickLink(t('Edit'));
$this->drupalPostForm(NULL, [], $this->t('Next'));
$this->assertFieldByName('one', 'New value');
$this->clickLink(t('Form One'));
$this->assertSession()->fieldValueEquals('one', 'New value');
}
}
@@ -2,11 +2,8 @@
namespace Drupal\ctools;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Core\Plugin\Context\ContextDefinitionInterface;
use Drupal\Core\Plugin\Context\ContextInterface;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Core\TypedData\ComplexDataDefinitionInterface;
@@ -2,14 +2,13 @@
namespace Drupal\ctools\Wizard;
use Drupal\Core\DependencyInjection\ClassResolverInterface;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\ctools\Event\WizardEvent;
use Drupal\user\SharedTempStoreFactory;
use Drupal\Core\TempStore\SharedTempStoreFactory;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
@@ -18,14 +17,14 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
abstract class EntityFormWizardBase extends FormWizardBase implements EntityFormWizardInterface {
/**
* The entity manager.
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityManager;
protected $entityTypeManager;
/**
* @param \Drupal\user\SharedTempStoreFactory $tempstore
* @param \Drupal\Core\TempStore\SharedTempStoreFactory $tempstore
* Tempstore Factory for keeping track of values in each step of the
* wizard.
* @param \Drupal\Core\Form\FormBuilderInterface $builder
@@ -34,8 +33,8 @@ abstract class EntityFormWizardBase extends FormWizardBase implements EntityForm
* The class resolver.
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
* The event dispatcher.
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param $tempstore_id
* The shared temp store factory collection name.
* @param null $machine_name
@@ -43,8 +42,8 @@ abstract class EntityFormWizardBase extends FormWizardBase implements EntityForm
* @param null $step
* The current active step of the wizard.
*/
public function __construct(SharedTempStoreFactory $tempstore, FormBuilderInterface $builder, ClassResolverInterface $class_resolver, EventDispatcherInterface $event_dispatcher, EntityManagerInterface $entity_manager, RouteMatchInterface $route_match, $tempstore_id, $machine_name = NULL, $step = NULL) {
$this->entityManager = $entity_manager;
public function __construct(SharedTempStoreFactory $tempstore, FormBuilderInterface $builder, ClassResolverInterface $class_resolver, EventDispatcherInterface $event_dispatcher, EntityTypeManagerInterface $entity_type_manager, RouteMatchInterface $route_match, $tempstore_id, $machine_name = NULL, $step = NULL) {
$this->entityTypeManager = $entity_type_manager;
parent::__construct($tempstore, $builder, $class_resolver, $event_dispatcher, $route_match, $tempstore_id, $machine_name, $step);
}
@@ -53,11 +52,14 @@ abstract class EntityFormWizardBase extends FormWizardBase implements EntityForm
*/
public static function getParameters() {
return [
'tempstore' => \Drupal::service('user.shared_tempstore'),
'tempstore' => \Drupal::service('tempstore.shared'),
'builder' => \Drupal::service('form_builder'),
'class_resolver' => \Drupal::service('class_resolver'),
'event_dispatcher' => \Drupal::service('event_dispatcher'),
// Keep the deprecated entity manager service as a parameter as well for
// BC, so that subclasses still work.
'entity_manager' => \Drupal::service('entity.manager'),
'entity_type_manager' => \Drupal::service('entity_type.manager'),
];
}
@@ -65,7 +67,7 @@ abstract class EntityFormWizardBase extends FormWizardBase implements EntityForm
* {@inheritdoc}
*/
public function initValues() {
$storage = $this->entityManager->getStorage($this->getEntityType());
$storage = $this->entityTypeManager->getStorage($this->getEntityType());
if ($this->getMachineName()) {
$values = $this->getTempstore()->get($this->getMachineName());
if (!$values) {
@@ -89,24 +91,25 @@ abstract class EntityFormWizardBase extends FormWizardBase implements EntityForm
*/
public function finish(array &$form, FormStateInterface $form_state) {
$cached_values = $form_state->getTemporaryValue('wizard');
/** @var $entity \Drupal\Core\Entity\EntityInterface */
/** @var \Drupal\Core\Entity\EntityInterface $entity */
$entity = $cached_values[$this->getEntityType()];
$entity->set('id', $cached_values['id']);
$entity->set('label', $cached_values['label']);
$status = $entity->save();
$definition = $this->entityManager->getDefinition($this->getEntityType());
if ($status) {
drupal_set_message($this->t('Saved the %label @entity_type.', array(
'%label' => $entity->label(),
'@entity_type' => $definition->getLabel(),
)));
$arguments = [
'@entity-type' => $entity->getEntityType()->getLowercaseLabel(),
'%label' => $entity->label(),
];
if ($status === SAVED_UPDATED) {
$this->messenger()->addMessage($this->t('The @entity-type %label has been updated.', $arguments));
$this->logger($entity->getEntityType()->getProvider())->notice('Updated @entity-type %label.', $arguments);
}
else {
drupal_set_message($this->t('The %label @entity_type was not saved.', array(
'%label' => $entity->label(),
'@entity_type' => $definition->getLabel(),
)));
elseif ($status === SAVED_NEW) {
$this->messenger()->addMessage($this->t('The @entity-type %label has been added.', $arguments));
$this->logger($entity->getEntityType()->getProvider())->notice('Added @entity-type %label.', $arguments);
}
$form_state->setRedirectUrl($entity->toUrl('collection'));
parent::finish($form, $form_state);
}
@@ -122,7 +125,7 @@ abstract class EntityFormWizardBase extends FormWizardBase implements EntityForm
protected function customizeForm(array $form, FormStateInterface $form_state) {
$form = parent::customizeForm($form, $form_state);
if ($this->machine_name) {
$entity = $this->entityManager->getStorage($this->getEntityType())
$entity = $this->entityTypeManager->getStorage($this->getEntityType())
->load($this->machine_name);
}
else {
@@ -145,7 +148,7 @@ abstract class EntityFormWizardBase extends FormWizardBase implements EntityForm
$default_operation = reset($operations);
if ($operation['form'] == $default_operation['form']) {
// Get the plugin definition of this entity.
$definition = $this->entityManager->getDefinition($this->getEntityType());
$definition = $this->entityTypeManager->getDefinition($this->getEntityType());
// Create id and label form elements.
$form['name'] = array(
'#type' => 'fieldset',
@@ -13,7 +13,8 @@ use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
use Drupal\ctools\Ajax\OpenModalWizardCommand;
use Drupal\ctools\Event\WizardEvent;
use Drupal\user\SharedTempStoreFactory;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Drupal\Core\TempStore\SharedTempStoreFactory;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
@@ -24,7 +25,7 @@ abstract class FormWizardBase extends FormBase implements FormWizardInterface {
/**
* Tempstore Factory for keeping track of values in each step of the wizard.
*
* @var \Drupal\user\SharedTempStoreFactory
* @var \Drupal\Core\TempStore\SharedTempStoreFactory
*/
protected $tempstore;
@@ -71,7 +72,7 @@ abstract class FormWizardBase extends FormBase implements FormWizardInterface {
protected $step;
/**
* @param \Drupal\user\SharedTempStoreFactory $tempstore
* @param \Drupal\Core\TempStore\SharedTempStoreFactory $tempstore
* Tempstore Factory for keeping track of values in each step of the
* wizard.
* @param \Drupal\Core\Form\FormBuilderInterface $builder
@@ -103,7 +104,7 @@ abstract class FormWizardBase extends FormBase implements FormWizardInterface {
*/
public static function getParameters() {
return [
'tempstore' => \Drupal::service('user.shared_tempstore'),
'tempstore' => \Drupal::service('tempstore.shared'),
'builder' => \Drupal::service('form_builder'),
'class_resolver' => \Drupal::service('class_resolver'),
'event_dispatcher' => \Drupal::service('event_dispatcher'),
@@ -131,7 +132,8 @@ abstract class FormWizardBase extends FormBase implements FormWizardInterface {
* {@inheritdoc}
*/
public function getTempstore() {
return $this->tempstore->get($this->getTempstoreId());
$tempstore = $this->tempstore->get($this->getTempstoreId());
return $tempstore;
}
/**
@@ -393,7 +395,7 @@ abstract class FormWizardBase extends FormBase implements FormWizardInterface {
$actions['submit']['#ajax'] = [
'callback' => '::ajaxSubmit',
'url' => Url::fromRoute($this->getRouteName(), $parameters),
'options' => ['query' => \Drupal::request()->query->all() + [FormBuilderInterface::AJAX_FORM_REQUEST => TRUE]],
'options' => ['query' => $this->getRequest()->query->all() + [FormBuilderInterface::AJAX_FORM_REQUEST => TRUE]],
];
}
@@ -419,7 +421,7 @@ abstract class FormWizardBase extends FormBase implements FormWizardInterface {
$actions['previous']['#ajax'] = [
'callback' => '::ajaxPrevious',
'url' => Url::fromRoute($this->getRouteName(), $parameters),
'options' => ['query' => \Drupal::request()->query->all() + [FormBuilderInterface::AJAX_FORM_REQUEST => TRUE]],
'options' => ['query' => $this->getRequest()->query->all() + [FormBuilderInterface::AJAX_FORM_REQUEST => TRUE]],
];
}
}
@@ -39,7 +39,7 @@ interface FormWizardInterface extends FormInterface {
/**
* The active SharedTempStore for this wizard.
*
* @return \Drupal\user\SharedTempStore
* @return \Drupal\Core\TempStore\SharedTempStore
*/
public function getTempstore();
@@ -5,6 +5,7 @@ namespace Drupal\ctools\Wizard;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormState;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Drupal\Core\Render\Renderer;
class WizardFactory implements WizardFactoryInterface {
@@ -23,14 +24,26 @@ class WizardFactory implements WizardFactoryInterface {
protected $dispatcher;
/**
* The object renderer.
*
* @var \Drupal\Core\Render\Renderer
*/
protected $renderer;
/**
* The construct method.
*
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
* The form builder.
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
* The event dispatcher.
* @param \Drupal\Core\Render\Renderer $renderer
* The object renderer.
*/
public function __construct(FormBuilderInterface $form_builder, EventDispatcherInterface $event_dispatcher) {
public function __construct(FormBuilderInterface $form_builder, EventDispatcherInterface $event_dispatcher, Renderer $renderer) {
$this->builder = $form_builder;
$this->dispatcher = $event_dispatcher;
$this->renderer = $renderer;
}
/**
@@ -42,9 +55,8 @@ class WizardFactory implements WizardFactoryInterface {
if ($ajax) {
$form['#attached']['library'][] = 'core/drupal.dialog.ajax';
$status_messages = array('#type' => 'status_messages');
// @todo properly inject the renderer. Core should really be doing this work.
if ($messages = \Drupal::service('renderer')->renderRoot($status_messages)) {
$status_messages = ['#type' => 'status_messages'];
if ($messages = $this->renderer->renderRoot($status_messages)) {
if (!empty($form['#prefix'])) {
// Form prefix is expected to be a string. Prepend the messages to
// that string.
@@ -1,4 +1,5 @@
<?php
namespace Drupal\ctools\Wizard;
interface WizardFactoryInterface {
@@ -0,0 +1,14 @@
name: Block Display Variant Test
type: module
description: 'Testing infrastructure for CTools block display variants.'
package: Testing
# version: 3.x
# core: 8.x
dependencies:
- ctools:ctools
# Information added by Drupal.org packaging script on 2019-02-21
version: '8.x-3.2'
core: '8.x'
project: 'ctools'
datestamp: 1550728390
@@ -0,0 +1,23 @@
<?php
namespace Drupal\ctools_block_display_test\Plugin\DisplayVariant;
use Drupal\ctools\Plugin\DisplayVariant\BlockDisplayVariant as BaseBlockDisplayVariant;
class BlockDisplayVariant extends BaseBlockDisplayVariant {
/**
* {@inheritdoc}
*/
public function getRegionNames() {
return [];
}
/**
* {@inheritdoc}
*/
public function build() {
return [];
}
}
@@ -5,8 +5,8 @@ package: Testing
# version: 3.x
# core: 8.x
# Information added by Drupal.org packaging script on 2017-04-28
version: '8.x-3.0'
# Information added by Drupal.org packaging script on 2019-02-21
version: '8.x-3.2'
core: '8.x'
project: 'ctools'
datestamp: 1493401747
datestamp: 1550728390
@@ -22,7 +22,7 @@ class ExampleConfigEntityListBuilder extends ConfigEntityListBuilder {
* {@inheritdoc}
*/
public function buildRow(EntityInterface $entity) {
$row['label'] = $this->getLabel($entity);
$row['label'] = $entity->label();
$row['id'] = $entity->id();
// You probably want a few more properties here...
return $row + parent::buildRow($entity);
@@ -36,8 +36,7 @@ class ExampleConfigEntityDeleteForm extends EntityConfirmFormBase {
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$this->entity->delete();
drupal_set_message(
$this->messenger()->addMessage(
$this->t('content @type: deleted @label.',
[
'@type' => $this->entity->bundle(),
@@ -2,18 +2,20 @@
namespace Drupal\ctools_wizard_test\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\user\SharedTempStoreFactory;
use Drupal\Core\TempStore\SharedTempStoreFactory;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Example form config entity.
*/
class ExampleConfigEntityExternalForm extends FormBase {
/**
* Tempstore factory.
*
* @var \Drupal\user\SharedTempStoreFactory
* @var \Drupal\Core\TempStore\SharedTempStoreFactory
*/
protected $tempstore;
@@ -21,8 +23,9 @@ class ExampleConfigEntityExternalForm extends FormBase {
* Constructs a new ExampleConfigEntityExternalForm.
*
* @param \Drupal\ctools_wizard_test\Form\SharedTempStoreFactory $tempstore
* Creates a shared temporary storage for a collection.
*/
function __construct(SharedTempStoreFactory $tempstore) {
public function __construct(SharedTempStoreFactory $tempstore) {
$this->tempstore = $tempstore;
}
@@ -30,7 +33,7 @@ class ExampleConfigEntityExternalForm extends FormBase {
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container->get('user.shared_tempstore'));
return new static($container->get('tempstore.shared'));
}
/**
@@ -63,4 +66,3 @@ class ExampleConfigEntityExternalForm extends FormBase {
}
}
@@ -64,8 +64,7 @@ class OneForm extends FormBase {
$cached_values[$key] = $form_state->getValue($key);
}
$form_state->setTemporaryValue('wizard', $cached_values);
drupal_set_message($this->t('Dynamic value submitted: @value', ['@value' => $cached_values['dynamic']]));;
$this->messenger()->addMessage($this->t('Dynamic value submitted: @value', ['@value' => $cached_values['dynamic']]));
}
}
@@ -74,8 +74,8 @@ class WizardTest extends FormWizardBase {
*/
public function finish(array &$form, FormStateInterface $form_state) {
$cached_values = $form_state->getTemporaryValue('wizard');
drupal_set_message($this->t('Value One: @one', ['@one' => $cached_values['one']]));
drupal_set_message($this->t('Value Two: @two', ['@two' => $cached_values['two']]));
$this->messenger()->addMessage($this->t('Value One: @one', ['@one' => $cached_values['one']]));
$this->messenger()->addMessage($this->t('Value Two: @two', ['@two' => $cached_values['two']]));
parent::finish($form, $form_state);
}
@@ -0,0 +1,53 @@
<?php
namespace Drupal\Tests\ctools\Kernel;
use Drupal\ctools\Event\BlockVariantEvent;
use Drupal\ctools\Event\BlockVariantEvents;
use Drupal\ctools_block_display_test\Plugin\DisplayVariant\BlockDisplayVariant;
use Drupal\KernelTests\KernelTestBase;
use Prophecy\Argument;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* @coversDefaultClass \Drupal\ctools\Plugin\DisplayVariant\BlockDisplayVariant
* @group CTools
*/
class BlockDisplayVariantTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['ctools', 'ctools_block_display_test', 'system', 'user'];
/**
* Tests that events are fired when manipulating a block variant.
*/
public function testBlockDisplayVariantEvents() {
/** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher */
$event_dispatcher = $this->prophesize(EventDispatcherInterface::class);
// Swap in a mock event dispatcher so we can spy on method calls.
$this->container->set('event_dispatcher', $event_dispatcher->reveal());
$variant = BlockDisplayVariant::create(
$this->container,
[],
'foobar',
[]
);
// Set up the expected calls to the event dispatcher.
$event = Argument::type(BlockVariantEvent::class);
$event_dispatcher->dispatch(BlockVariantEvents::ADD_BLOCK, $event)
->shouldBeCalled();
$event_dispatcher->dispatch(BlockVariantEvents::UPDATE_BLOCK, $event)
->shouldBeCalled();
$event_dispatcher->dispatch(BlockVariantEvents::DELETE_BLOCK, $event)
->shouldBeCalled();
$block_id = $variant->addBlock(['id' => 'system_powered_by_block']);
$variant->updateBlock($block_id, []);
$variant->removeBlock($block_id);
}
}
@@ -6,7 +6,7 @@ use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;
/**
* @coversDefaultClass \Drupal\ctools\Plugin\RelationshipManagerInterface
* @coversDefaultClass \Drupal\ctools\Plugin\RelationshipManager
* @group CTools
*/
class RelationshipManagerTest extends RelationshipsTestBase {
@@ -0,0 +1,6 @@
<?php
/**
* @file
* File for admin helper functions for views_content module.
*/