Pathauto and dependencies
This commit is contained in:
parent
4b1a293d57
commit
24ffcb956b
257 changed files with 29510 additions and 0 deletions
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Access;
|
||||
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
||||
interface AccessInterface {
|
||||
public function access(AccountInterface $account);
|
||||
}
|
51
web/modules/contrib/ctools/src/Access/TempstoreAccess.php
Normal file
51
web/modules/contrib/ctools/src/Access/TempstoreAccess.php
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
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 Symfony\Component\Routing\Route;
|
||||
|
||||
class TempstoreAccess implements CoreAccessInterface {
|
||||
|
||||
/**
|
||||
* The shared tempstore factory.
|
||||
*
|
||||
* @var \Drupal\user\SharedTempStoreFactory
|
||||
*/
|
||||
protected $tempstore;
|
||||
|
||||
public function __construct(SharedTempStoreFactory $tempstore) {
|
||||
$this->tempstore = $tempstore;
|
||||
}
|
||||
|
||||
protected function getTempstore() {
|
||||
return $this->tempstore;
|
||||
}
|
||||
|
||||
public function access(Route $route, RouteMatch $match, AccountInterface $account) {
|
||||
$tempstore_id = $match->getParameter('tempstore_id') ? $match->getParameter('tempstore_id') : $route->getDefault('tempstore_id');
|
||||
$id = $match->getParameter($route->getRequirement('_ctools_access'));
|
||||
if ($tempstore_id && $id) {
|
||||
$cached_values = $this->getTempstore()->get($tempstore_id)->get($id);
|
||||
if (!empty($cached_values['access']) && ($cached_values['access'] instanceof CToolsAccessInterface)) {
|
||||
$access = $cached_values['access']->access($account);
|
||||
}
|
||||
else {
|
||||
$access = AccessResult::allowed();
|
||||
}
|
||||
}
|
||||
else {
|
||||
$access = AccessResult::forbidden();
|
||||
}
|
||||
// The different wizards will have different tempstore ids and adding this
|
||||
// cache context allows us to nuance the access per wizard.
|
||||
$access->addCacheContexts(['url.query_args:tempstore_id']);
|
||||
return $access;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Ajax;
|
||||
|
||||
use Drupal\Core\Ajax\OpenModalDialogCommand;
|
||||
|
||||
class OpenModalWizardCommand extends OpenModalDialogCommand {
|
||||
|
||||
public function __construct($object, $tempstore_id, array $parameters = array(), array $dialog_options = array(), $settings = NULL) {
|
||||
// Instantiate the wizard class properly.
|
||||
$parameters += [
|
||||
'tempstore_id' => $tempstore_id,
|
||||
'machine_name' => NULL,
|
||||
'step' => NULL,
|
||||
];
|
||||
$form = \Drupal::service('ctools.wizard.factory')->getWizardForm($object, $parameters, TRUE);
|
||||
$title = isset($form['#title']) ? $form['#title'] : '';
|
||||
$content = $form;
|
||||
|
||||
parent::__construct($title, $content, $dialog_options, $settings);
|
||||
}
|
||||
|
||||
}
|
54
web/modules/contrib/ctools/src/Annotation/Relationship.php
Normal file
54
web/modules/contrib/ctools/src/Annotation/Relationship.php
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Annotation;
|
||||
|
||||
use Drupal\Component\Annotation\Plugin;
|
||||
|
||||
/**
|
||||
* Defines a Relationship item annotation object.
|
||||
*
|
||||
* @see \Drupal\ctools\Plugin\RelationshipManager
|
||||
* @see plugin_api
|
||||
*
|
||||
* @Annotation
|
||||
*/
|
||||
class Relationship extends Plugin {
|
||||
|
||||
/**
|
||||
* The plugin ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* The label of the plugin.
|
||||
*
|
||||
* @var \Drupal\Core\Annotation\Translation
|
||||
*
|
||||
* @ingroup plugin_translatable
|
||||
*/
|
||||
public $label;
|
||||
|
||||
/**
|
||||
* The returned data type of this relationship
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $data_type;
|
||||
|
||||
/**
|
||||
* The name of the property from which this relationship is derived.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $property_name;
|
||||
|
||||
/**
|
||||
* The array of contexts requires or optional for this plugin.
|
||||
*
|
||||
* @var \Drupal\Core\Plugin\Context\ContextInterface[]
|
||||
*/
|
||||
public $context;
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools;
|
||||
|
||||
|
||||
interface ConstraintConditionInterface {
|
||||
|
||||
/**
|
||||
* Applies relevant constraints for this condition to the injected contexts.
|
||||
*
|
||||
* @param \Drupal\Core\Plugin\Context\ContextInterface[] $contexts
|
||||
*
|
||||
* @return NULL
|
||||
*/
|
||||
public function applyConstraints(array $contexts = array());
|
||||
|
||||
/**
|
||||
* Removes constraints for this condition from the injected contexts.
|
||||
*
|
||||
* @param \Drupal\Core\Plugin\Context\ContextInterface[] $contexts
|
||||
*
|
||||
* @return NULL
|
||||
*/
|
||||
public function removeConstraints(array $contexts = array());
|
||||
|
||||
}
|
25
web/modules/contrib/ctools/src/Context/AutomaticContext.php
Normal file
25
web/modules/contrib/ctools/src/Context/AutomaticContext.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Context;
|
||||
|
||||
use Drupal\Core\Plugin\Context\Context;
|
||||
|
||||
/**
|
||||
* Provides a class to indicate that this context is always present.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @todo Move into core.
|
||||
*/
|
||||
class AutomaticContext extends Context {
|
||||
|
||||
/**
|
||||
* Returns TRUE if this context is automatic and always available.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isAutomatic() {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Context;
|
||||
|
||||
use Drupal\Core\Entity\EntityRepositoryInterface;
|
||||
use Drupal\Core\Plugin\Context\Context;
|
||||
use Drupal\Core\Plugin\Context\ContextDefinitionInterface;
|
||||
|
||||
/**
|
||||
* @todo.
|
||||
*/
|
||||
class EntityLazyLoadContext extends Context {
|
||||
|
||||
/**
|
||||
* The entity UUID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $uuid;
|
||||
|
||||
/**
|
||||
* The entity repository.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityRepositoryInterface
|
||||
*/
|
||||
protected $entityRepository;
|
||||
|
||||
/**
|
||||
* Construct an EntityLazyLoadContext object.
|
||||
*
|
||||
* @param \Drupal\Core\Plugin\Context\ContextDefinitionInterface $context_definition
|
||||
* The context definition.
|
||||
* @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
|
||||
* The entity repository.
|
||||
* @param string $uuid
|
||||
* The UUID of the entity.
|
||||
*/
|
||||
public function __construct(ContextDefinitionInterface $context_definition, EntityRepositoryInterface $entity_repository, $uuid) {
|
||||
parent::__construct($context_definition);
|
||||
$this->entityRepository = $entity_repository;
|
||||
$this->uuid = $uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContextValue() {
|
||||
if (!$this->contextData) {
|
||||
$entity_type_id = substr($this->contextDefinition->getDataType(), 7);
|
||||
$this->setContextValue($this->entityRepository->loadEntityByUuid($entity_type_id, $this->uuid));
|
||||
}
|
||||
return parent::getContextValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasContextValue() {
|
||||
// Ensure that the entity is loaded before checking if it exists.
|
||||
if (!$this->contextData) {
|
||||
$this->getContextValue();
|
||||
}
|
||||
return parent::hasContextValue();
|
||||
}
|
||||
|
||||
}
|
50
web/modules/contrib/ctools/src/ContextMapper.php
Normal file
50
web/modules/contrib/ctools/src/ContextMapper.php
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools;
|
||||
|
||||
use Drupal\Core\Entity\EntityRepositoryInterface;
|
||||
use Drupal\Core\Plugin\Context\Context;
|
||||
use Drupal\Core\Plugin\Context\ContextDefinition;
|
||||
use Drupal\ctools\Context\EntityLazyLoadContext;
|
||||
|
||||
/**
|
||||
* Maps context configurations to context objects.
|
||||
*/
|
||||
class ContextMapper implements ContextMapperInterface {
|
||||
|
||||
/**
|
||||
* The entity repository.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityRepositoryInterface
|
||||
*/
|
||||
protected $entityRepository;
|
||||
|
||||
/**
|
||||
* Constructs a new ContextMapper.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
|
||||
* The entity repository.
|
||||
*/
|
||||
public function __construct(EntityRepositoryInterface $entity_repository) {
|
||||
$this->entityRepository = $entity_repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContextValues(array $context_configurations) {
|
||||
$contexts = [];
|
||||
foreach ($context_configurations as $name => $context_configuration) {
|
||||
$context_definition = new ContextDefinition($context_configuration['type'], $context_configuration['label'], TRUE, FALSE, $context_configuration['description']);
|
||||
if (strpos($context_configuration['type'], 'entity:') === 0) {
|
||||
$context = new EntityLazyLoadContext($context_definition, $this->entityRepository, $context_configuration['value']);
|
||||
}
|
||||
else {
|
||||
$context = new Context($context_definition, $context_configuration['value']);
|
||||
}
|
||||
$contexts[$name] = $context;
|
||||
}
|
||||
return $contexts;
|
||||
}
|
||||
|
||||
}
|
21
web/modules/contrib/ctools/src/ContextMapperInterface.php
Normal file
21
web/modules/contrib/ctools/src/ContextMapperInterface.php
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools;
|
||||
|
||||
/**
|
||||
* Provides an interface for mapping context configurations to context objects.
|
||||
*/
|
||||
interface ContextMapperInterface {
|
||||
|
||||
/**
|
||||
* Gathers the static context values.
|
||||
*
|
||||
* @param array[] $static_context_configurations
|
||||
* An array of static context configurations.
|
||||
*
|
||||
* @return \Drupal\Component\Plugin\Context\ContextInterface[]
|
||||
* An array of set context values, keyed by context name.
|
||||
*/
|
||||
public function getContextValues(array $static_context_configurations);
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools;
|
||||
|
||||
|
||||
class ContextNotFoundException extends \Exception {}
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Controller;
|
||||
|
||||
use Drupal\Core\Controller\ControllerResolverInterface;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Form\FormBuilderInterface;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\ctools\Wizard\WizardFactoryInterface;
|
||||
|
||||
/**
|
||||
* Wrapping controller for wizard forms that serve as the main page body.
|
||||
*/
|
||||
class WizardEntityFormController extends WizardFormController {
|
||||
|
||||
/**
|
||||
* The entity manager service.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityManagerInterface
|
||||
*/
|
||||
protected $entityManager;
|
||||
|
||||
/**
|
||||
* @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver
|
||||
* The controller resolver.
|
||||
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
|
||||
* The form builder.
|
||||
* @param \Drupal\ctools\Wizard\WizardFactoryInterface $wizard_factory
|
||||
* The wizard factory.
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $manager
|
||||
* The entity manager.
|
||||
*/
|
||||
public function __construct(ControllerResolverInterface $controller_resolver, FormBuilderInterface $form_builder, WizardFactoryInterface $wizard_factory, EntityManagerInterface $manager) {
|
||||
parent::__construct($controller_resolver, $form_builder, $wizard_factory);
|
||||
$this->entityManager = $manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
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);
|
||||
$handlers = $definition->getHandlerClasses();
|
||||
if (empty($handlers['wizard'][$operation])) {
|
||||
throw new \Exception(sprintf('Unsupported wizard operation %s', $operation));
|
||||
}
|
||||
return $handlers['wizard'][$operation];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Controller;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Wrapping controller for wizard forms that serve as the main page body.
|
||||
*/
|
||||
class WizardFormController extends FormController {
|
||||
|
||||
/**
|
||||
* The class resolver.
|
||||
*
|
||||
* @var \Drupal\Core\DependencyInjection\ClassResolverInterface;
|
||||
*/
|
||||
protected $classResolver;
|
||||
|
||||
/**
|
||||
* Tempstore Factory for keeping track of values in each step of the wizard.
|
||||
*
|
||||
* @var \Drupal\user\SharedTempStoreFactory
|
||||
*/
|
||||
protected $tempstore;
|
||||
|
||||
/**
|
||||
* The event dispatcher.
|
||||
*
|
||||
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
|
||||
*/
|
||||
protected $dispatcher;
|
||||
|
||||
/**
|
||||
* @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver
|
||||
* The controller resolver.
|
||||
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
|
||||
* The form builder.
|
||||
* @param \Drupal\ctools\Wizard\WizardFactoryInterface $wizard_factory
|
||||
* The wizard factory.
|
||||
*/
|
||||
public function __construct(ControllerResolverInterface $controller_resolver, FormBuilderInterface $form_builder, WizardFactoryInterface $wizard_factory) {
|
||||
parent::__construct($controller_resolver, $form_builder);
|
||||
$this->wizardFactory = $wizard_factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getFormArgument(RouteMatchInterface $route_match) {
|
||||
return $route_match->getRouteObject()->getDefault('_wizard');
|
||||
}
|
||||
|
||||
/**
|
||||
* Wizards are not instantiated as simply as forms, so this method is unused.
|
||||
*/
|
||||
protected function getFormObject(RouteMatchInterface $route_match, $form_arg) {
|
||||
if (!is_subclass_of($form_arg, '\Drupal\ctools\Wizard\FormWizardInterface')) {
|
||||
throw new \Exception("The _wizard default must reference a class instance of \\Drupal\\ctools\\Wizard\\FormWizardInterface.");
|
||||
}
|
||||
$parameters = $route_match->getParameters()->all();
|
||||
$parameters += $form_arg::getParameters();
|
||||
$parameters['route_match'] = $route_match;
|
||||
return $this->wizardFactory->createWizard($form_arg, $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContentResult(Request $request, RouteMatchInterface $route_match) {
|
||||
$wizard = $this->getFormObject($route_match, $this->getFormArgument($route_match));
|
||||
$ajax = $request->attributes->get('js') == 'ajax' ? TRUE : FALSE;
|
||||
|
||||
return $this->wizardFactory->getWizardForm($wizard, $request->attributes->all(), $ajax);
|
||||
}
|
||||
|
||||
}
|
41
web/modules/contrib/ctools/src/Event/WizardEvent.php
Normal file
41
web/modules/contrib/ctools/src/Event/WizardEvent.php
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Event;
|
||||
|
||||
use Drupal\ctools\Wizard\FormWizardInterface;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* An event for altering form wizard values.
|
||||
*/
|
||||
class WizardEvent extends Event {
|
||||
|
||||
/**
|
||||
* @var \Drupal\ctools\Wizard\FormWizardInterface
|
||||
*/
|
||||
protected $wizard;
|
||||
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
protected $values;
|
||||
|
||||
function __construct(FormWizardInterface $wizard, $values) {
|
||||
$this->wizard = $wizard;
|
||||
$this->values = $values;
|
||||
}
|
||||
|
||||
public function getWizard() {
|
||||
return $this->wizard;
|
||||
}
|
||||
|
||||
public function getValues() {
|
||||
return $this->values;
|
||||
}
|
||||
|
||||
public function setValues($values) {
|
||||
$this->values = $values;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
43
web/modules/contrib/ctools/src/Form/AjaxFormTrait.php
Normal file
43
web/modules/contrib/ctools/src/Form/AjaxFormTrait.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Form;
|
||||
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\Component\Utility\NestedArray;
|
||||
|
||||
/**
|
||||
* Provides helper methods for using an AJAX modal.
|
||||
*/
|
||||
trait AjaxFormTrait {
|
||||
|
||||
/**
|
||||
* Gets attributes for use with an AJAX modal.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getAjaxAttributes() {
|
||||
return [
|
||||
'class' => ['use-ajax'],
|
||||
'data-dialog-type' => 'modal',
|
||||
'data-dialog-options' => Json::encode([
|
||||
'width' => 'auto',
|
||||
]),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets attributes for use with an add button AJAX modal.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getAjaxButtonAttributes() {
|
||||
return NestedArray::mergeDeep(AjaxFormTrait::getAjaxAttributes(), [
|
||||
'class' => [
|
||||
'button',
|
||||
'button--small',
|
||||
'button-action',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
182
web/modules/contrib/ctools/src/Form/ConditionConfigure.php
Normal file
182
web/modules/contrib/ctools/src/Form/ConditionConfigure.php
Normal file
|
@ -0,0 +1,182 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Form;
|
||||
|
||||
|
||||
use Drupal\Component\Plugin\PluginManagerInterface;
|
||||
use Drupal\Component\Uuid\Uuid;
|
||||
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\Core\Plugin\ContextAwarePluginInterface;
|
||||
use Drupal\ctools\ConstraintConditionInterface;
|
||||
use Drupal\user\SharedTempStoreFactory;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Base class for condition configur operations.
|
||||
*/
|
||||
abstract class ConditionConfigure extends FormBase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\user\SharedTempStoreFactory
|
||||
*/
|
||||
protected $tempstore;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Condition\ConditionManager
|
||||
*/
|
||||
protected $manager;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $tempstore_id;
|
||||
|
||||
/**
|
||||
* @var string;
|
||||
*/
|
||||
protected $machine_name;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static($container->get('user.shared_tempstore'), $container->get('plugin.manager.condition'));
|
||||
}
|
||||
|
||||
function __construct(SharedTempStoreFactory $tempstore, PluginManagerInterface $manager) {
|
||||
$this->tempstore = $tempstore;
|
||||
$this->manager = $manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'ctools_condition_configure';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state, $condition = NULL, $tempstore_id = NULL, $machine_name = NULL) {
|
||||
$this->tempstore_id = $tempstore_id;
|
||||
$this->machine_name = $machine_name;
|
||||
$cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
|
||||
if (is_numeric($condition) || Uuid::isValid($condition)) {
|
||||
$id = $condition;
|
||||
$condition = $this->getConditions($cached_values)[$id];
|
||||
$instance = $this->manager->createInstance($condition['id'], $condition);
|
||||
}
|
||||
else {
|
||||
$instance = $this->manager->createInstance($condition, []);
|
||||
}
|
||||
$form_state->setTemporaryValue('gathered_contexts', $this->getContexts($cached_values));
|
||||
/** @var $instance \Drupal\Core\Condition\ConditionInterface */
|
||||
$form = $instance->buildConfigurationForm($form, $form_state);
|
||||
if (isset($id)) {
|
||||
// Conditionally set this form element so that we can update or add.
|
||||
$form['id'] = [
|
||||
'#type' => 'value',
|
||||
'#value' => $id
|
||||
];
|
||||
}
|
||||
$form['instance'] = [
|
||||
'#type' => 'value',
|
||||
'#value' => $instance
|
||||
];
|
||||
$form['submit'] = [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Save'),
|
||||
'#ajax' => [
|
||||
'callback' => [$this, 'ajaxSave'],
|
||||
]
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
|
||||
/** @var $instance \Drupal\Core\Condition\ConditionInterface */
|
||||
$instance = $form_state->getValue('instance');
|
||||
$instance->submitConfigurationForm($form, $form_state);
|
||||
$conditions = $this->getConditions($cached_values);
|
||||
if ($instance instanceof ContextAwarePluginInterface) {
|
||||
/** @var $instance \Drupal\Core\Plugin\ContextAwarePluginInterface */
|
||||
$context_mapping = $form_state->hasValue('context_mapping')? $form_state->getValue('context_mapping') : [];
|
||||
$instance->setContextMapping($context_mapping);
|
||||
}
|
||||
if ($instance instanceof ConstraintConditionInterface) {
|
||||
/** @var $instance \Drupal\ctools\ConstraintConditionInterface */
|
||||
$instance->applyConstraints($this->getContexts($cached_values));
|
||||
}
|
||||
if ($form_state->hasValue('id')) {
|
||||
$conditions[$form_state->getValue('id')] = $instance->getConfiguration();
|
||||
}
|
||||
else {
|
||||
$conditions[] = $instance->getConfiguration();
|
||||
}
|
||||
$cached_values = $this->setConditions($cached_values, $conditions);
|
||||
$this->tempstore->get($this->tempstore_id)->set($this->machine_name, $cached_values);
|
||||
list($route_name, $route_parameters) = $this->getParentRouteInfo($cached_values);
|
||||
$form_state->setRedirect($route_name, $route_parameters);
|
||||
}
|
||||
|
||||
public function ajaxSave(array &$form, FormStateInterface $form_state) {
|
||||
$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)));
|
||||
$response->addCommand(new CloseModalDialogCommand());
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Document the route name and parameters for redirect after submission.
|
||||
*
|
||||
* @param $cached_values
|
||||
*
|
||||
* @return array
|
||||
* In the format of
|
||||
* return ['route.name', ['machine_name' => $this->machine_name, 'step' => 'step_name']];
|
||||
*/
|
||||
abstract protected function getParentRouteInfo($cached_values);
|
||||
|
||||
/**
|
||||
* Custom logic for retrieving the conditions array from cached_values.
|
||||
*
|
||||
* @param $cached_values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract protected function getConditions($cached_values);
|
||||
|
||||
/**
|
||||
* Custom logic for setting the conditions array in cached_values.
|
||||
*
|
||||
* @param $cached_values
|
||||
*
|
||||
* @param $conditions
|
||||
* The conditions to set within the cached values.
|
||||
*
|
||||
* @return mixed
|
||||
* Return the $cached_values
|
||||
*/
|
||||
abstract protected function setConditions($cached_values, $conditions);
|
||||
|
||||
/**
|
||||
* Custom logic for retrieving the contexts array from cached_values.
|
||||
*
|
||||
* @param $cached_values
|
||||
*
|
||||
* @return \Drupal\Core\Plugin\Context\ContextInterface[]
|
||||
*/
|
||||
abstract protected function getContexts($cached_values);
|
||||
|
||||
}
|
210
web/modules/contrib/ctools/src/Form/ConditionDelete.php
Normal file
210
web/modules/contrib/ctools/src/Form/ConditionDelete.php
Normal file
|
@ -0,0 +1,210 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Form;
|
||||
|
||||
use Drupal\Component\Plugin\PluginManagerInterface;
|
||||
use Drupal\Core\Form\ConfirmFormBase;
|
||||
use Drupal\Core\Form\ConfirmFormHelper;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\ctools\ConstraintConditionInterface;
|
||||
use Drupal\user\SharedTempStoreFactory;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
abstract class ConditionDelete extends ConfirmFormBase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\user\SharedTempStoreFactory
|
||||
*/
|
||||
protected $tempstore;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Condition\ConditionManager
|
||||
*/
|
||||
protected $manager;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $tempstore_id;
|
||||
|
||||
/**
|
||||
* @var string;
|
||||
*/
|
||||
protected $machine_name;
|
||||
|
||||
/**
|
||||
* @var int;
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static($container->get('user.shared_tempstore'), $container->get('plugin.manager.condition'));
|
||||
}
|
||||
|
||||
function __construct(SharedTempStoreFactory $tempstore, PluginManagerInterface $manager) {
|
||||
$this->tempstore = $tempstore;
|
||||
$this->manager = $manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'ctools_condition_delete';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state, $id = NULL, $tempstore_id = NULL, $machine_name = NULL) {
|
||||
$this->tempstore_id = $tempstore_id;
|
||||
$this->machine_name = $machine_name;
|
||||
$this->id = $id;
|
||||
|
||||
$cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
|
||||
$form ['#title'] = $this->getQuestion($id, $cached_values);
|
||||
|
||||
$form ['#attributes']['class'][] = 'confirmation';
|
||||
$form ['description'] = array('#markup' => $this->getDescription());
|
||||
$form [$this->getFormName()] = array('#type' => 'hidden', '#value' => 1);
|
||||
|
||||
// By default, render the form using theme_confirm_form().
|
||||
if (!isset($form ['#theme'])) {
|
||||
$form ['#theme'] = 'confirm_form';
|
||||
}
|
||||
$form['actions'] = array('#type' => 'actions');
|
||||
$form['actions'] += $this->actions($form, $form_state);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
|
||||
$conditions = $this->getConditions($cached_values);
|
||||
/** @var $instance \Drupal\ctools\ConstraintConditionInterface */
|
||||
$instance = $this->manager->createInstance($conditions[$this->id]['id'], $conditions[$this->id]);
|
||||
if ($instance instanceof ConstraintConditionInterface) {
|
||||
$instance->removeConstraints($this->getContexts($cached_values));
|
||||
}
|
||||
unset($conditions[$this->id]);
|
||||
$cached_values = $this->setConditions($cached_values, $conditions);
|
||||
$this->tempstore->get($this->tempstore_id)->set($this->machine_name, $cached_values);
|
||||
list($route_name, $route_parameters) = $this->getParentRouteInfo($cached_values);
|
||||
$form_state->setRedirect($route_name, $route_parameters);
|
||||
}
|
||||
|
||||
public function getQuestion($id = NULL, $cached_values = NULL) {
|
||||
$condition = $this->getConditions($cached_values)[$id];
|
||||
return $this->t('Are you sure you want to delete the @label condition?', array(
|
||||
'@label' => $condition['id'],
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDescription() {
|
||||
return $this->t('This action cannot be undone.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormName() {
|
||||
return 'confirm';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function actions(array $form, FormStateInterface $form_state) {
|
||||
return array(
|
||||
'submit' => array(
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->getConfirmText(),
|
||||
'#validate' => array(
|
||||
array($this, 'validateForm'),
|
||||
),
|
||||
'#submit' => array(
|
||||
array($this, 'submitForm'),
|
||||
),
|
||||
),
|
||||
'cancel' => ConfirmFormHelper::buildCancelLink($this, $this->getRequest()),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the route to go to if the user cancels the action.
|
||||
*
|
||||
* @return \Drupal\Core\Url
|
||||
* A URL object.
|
||||
*/
|
||||
public function getCancelUrl() {
|
||||
$cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
|
||||
list($route_name, $route_parameters) = $this->getParentRouteInfo($cached_values);
|
||||
return new Url($route_name, $route_parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getConfirmText() {
|
||||
return $this->t('Delete');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCancelText() {
|
||||
return $this->t('Cancel');
|
||||
}
|
||||
|
||||
/**
|
||||
* Document the route name and parameters for redirect after submission.
|
||||
*
|
||||
* @param $cached_values
|
||||
*
|
||||
* @return array
|
||||
* In the format of
|
||||
* return ['route.name', ['machine_name' => $this->machine_name, 'step' => 'step_name]];
|
||||
*/
|
||||
abstract protected function getParentRouteInfo($cached_values);
|
||||
|
||||
/**
|
||||
* Custom logic for retrieving the conditions array from cached_values.
|
||||
*
|
||||
* @param $cached_values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract protected function getConditions($cached_values);
|
||||
|
||||
/**
|
||||
* Custom logic for setting the conditions array in cached_values.
|
||||
*
|
||||
* @param $cached_values
|
||||
*
|
||||
* @param $conditions
|
||||
* The conditions to set within the cached values.
|
||||
*
|
||||
* @return mixed
|
||||
* Return the $cached_values
|
||||
*/
|
||||
abstract protected function setConditions($cached_values, $conditions);
|
||||
|
||||
/**
|
||||
* Custom logic for retrieving the contexts array from cached_values.
|
||||
*
|
||||
* @param $cached_values
|
||||
*
|
||||
* @return \Drupal\Core\Plugin\Context\ContextInterface[]
|
||||
*/
|
||||
abstract protected function getContexts($cached_values);
|
||||
|
||||
}
|
254
web/modules/contrib/ctools/src/Form/ContextConfigure.php
Normal file
254
web/modules/contrib/ctools/src/Form/ContextConfigure.php
Normal file
|
@ -0,0 +1,254 @@
|
|||
<?php
|
||||
|
||||
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;
|
||||
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 Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
abstract class ContextConfigure extends FormBase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\user\SharedTempStoreFactory
|
||||
*/
|
||||
protected $tempstore;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $tempstore_id;
|
||||
|
||||
/**
|
||||
* @var string;
|
||||
*/
|
||||
protected $machine_name;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static($container->get('user.shared_tempstore'));
|
||||
}
|
||||
|
||||
function __construct(SharedTempStoreFactory $tempstore) {
|
||||
$this->tempstore = $tempstore;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'ctools_context_configure';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state, $context_id = NULL, $tempstore_id = NULL, $machine_name = NULL) {
|
||||
$this->tempstore_id = $tempstore_id;
|
||||
$this->machine_name = $machine_name;
|
||||
$cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
|
||||
$contexts = $this->getContexts($cached_values);
|
||||
$edit = FALSE;
|
||||
if (!empty($contexts[$context_id])) {
|
||||
$context = $contexts[$context_id];
|
||||
$machine_name = $context_id;
|
||||
$edit = TRUE;
|
||||
}
|
||||
else {
|
||||
$context_definition = new ContextDefinition($context_id);
|
||||
$context = new Context($context_definition);
|
||||
$machine_name = '';
|
||||
}
|
||||
$label = $context->getContextDefinition()->getLabel();
|
||||
$description = $context->getContextDefinition()->getDescription();
|
||||
$data_type = $context->getContextDefinition()->getDataType();
|
||||
$form['#attached']['library'][] = 'core/drupal.dialog.ajax';
|
||||
$form['context_id'] = [
|
||||
'#type' => 'value',
|
||||
'#value' => $context_id
|
||||
];
|
||||
$form['label'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Label'),
|
||||
'#default_value' => $label,
|
||||
'#required' => TRUE,
|
||||
];
|
||||
$form['machine_name'] = [
|
||||
'#type' => 'machine_name',
|
||||
'#title' => $this->t('Machine Name'),
|
||||
'#default_value' => $machine_name,
|
||||
'#required' => TRUE,
|
||||
'#maxlength' => 128,
|
||||
'#machine_name' => [
|
||||
'source' => ['label'],
|
||||
'exists' => [$this, 'contextExists'],
|
||||
],
|
||||
'#disabled' => $this->disableMachineName($cached_values, $machine_name),
|
||||
];
|
||||
$form['description'] = [
|
||||
'#type' => 'textarea',
|
||||
'#title' => $this->t('Description'),
|
||||
'#default_value' => $description,
|
||||
];
|
||||
if (strpos($data_type, 'entity:') === 0) {
|
||||
list(, $entity_type) = explode(':', $data_type);
|
||||
/** @var EntityAdapter $entity */
|
||||
$entity = $edit ? $context->getContextValue() : NULL;
|
||||
$form['context_value'] = [
|
||||
'#type' => 'entity_autocomplete',
|
||||
'#required' => TRUE,
|
||||
'#target_type' => $entity_type,
|
||||
'#default_value' => $entity,
|
||||
'#title' => $this->t('Select entity'),
|
||||
];
|
||||
}
|
||||
else {
|
||||
$value = $context->getContextData()->getValue();
|
||||
$form['context_value'] = [
|
||||
'#title' => $this->t('Set a context value'),
|
||||
'#type' => 'textfield',
|
||||
'#required' => TRUE,
|
||||
'#default_value' => $value,
|
||||
];
|
||||
}
|
||||
$form['submit'] = [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Save'),
|
||||
'#ajax' => [
|
||||
'callback' => [$this, 'ajaxSave'],
|
||||
]
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateForm(array &$form, FormStateInterface $form_state) {
|
||||
// If these are not equal, then we're adding a new context and should not override an existing context.
|
||||
if ($form_state->getValue('machine_name') != $form_state->getValue('context_id')) {
|
||||
$machine_name = $form_state->getValue('machine_name');
|
||||
$cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
|
||||
if (!empty($this->getContexts($cached_values)[$machine_name])) {
|
||||
$form_state->setError($form['machine_name'], $this->t('That machine name is in use by another context definition.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
|
||||
$contexts = $this->getContexts($cached_values);
|
||||
if ($form_state->getValue('machine_name') != $form_state->getValue('context_id')) {
|
||||
$data_type = $form_state->getValue('context_id');
|
||||
$context_definition = new ContextDefinition($data_type, $form_state->getValue('label'), TRUE, FALSE, $form_state->getValue('description'));
|
||||
}
|
||||
else {
|
||||
$context = $contexts[$form_state->getValue('machine_name')];
|
||||
$context_definition = $context->getContextDefinition();
|
||||
$context_definition->setLabel($form_state->getValue('label'));
|
||||
$context_definition->setDescription($form_state->getValue('description'));
|
||||
}
|
||||
// We're dealing with an entity and should make sure it's loaded.
|
||||
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'));
|
||||
}
|
||||
}
|
||||
// No loading required for non-entity values.
|
||||
else {
|
||||
$value = $form_state->getValue('context_value');
|
||||
}
|
||||
$context = new Context($context_definition, $value);
|
||||
|
||||
$cached_values = $this->addContext($cached_values, $form_state->getValue('machine_name'), $context);
|
||||
$this->tempstore->get($this->tempstore_id)->set($this->machine_name, $cached_values);
|
||||
list($route_name, $route_parameters) = $this->getParentRouteInfo($cached_values);
|
||||
$form_state->setRedirect($route_name, $route_parameters);
|
||||
}
|
||||
|
||||
public function ajaxSave(array &$form, FormStateInterface $form_state) {
|
||||
$response = new AjaxResponse();
|
||||
$cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
|
||||
list($route_name, $route_parameters) = $this->getParentRouteInfo($cached_values);
|
||||
$url = new Url($route_name, $route_parameters);
|
||||
$response->addCommand(new RedirectCommand($url->toString()));
|
||||
$response->addCommand(new CloseModalDialogCommand());
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Document the route name and parameters for redirect after submission.
|
||||
*
|
||||
* @param $cached_values
|
||||
*
|
||||
* @return array
|
||||
* In the format of
|
||||
* return ['route.name', ['machine_name' => $this->machine_name, 'step' => 'step_name]];
|
||||
*/
|
||||
abstract protected function getParentRouteInfo($cached_values);
|
||||
|
||||
/**
|
||||
* Custom logic for retrieving the contexts array from cached_values.
|
||||
*
|
||||
* @param $cached_values
|
||||
*
|
||||
* @return \Drupal\Core\Plugin\Context\ContextInterface[]
|
||||
*/
|
||||
abstract protected function getContexts($cached_values);
|
||||
|
||||
/**
|
||||
* Custom logic for adding a context to the cached_values contexts array.
|
||||
*
|
||||
* @param array $cached_values
|
||||
* The cached_values currently in use.
|
||||
* @param string $context_id
|
||||
* The context identifier.
|
||||
* @param \Drupal\Core\Plugin\Context\ContextInterface $context
|
||||
* The context to add or update within the cached values.
|
||||
*
|
||||
* @return mixed
|
||||
* Return the $cached_values
|
||||
*/
|
||||
abstract protected function addContext($cached_values, $context_id, ContextInterface $context);
|
||||
|
||||
/**
|
||||
* Custom "exists" logic for the context to be created.
|
||||
*
|
||||
* @param string $value
|
||||
* The name of the context.
|
||||
* @param $element
|
||||
* The machine_name element
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The form state.
|
||||
*
|
||||
* @return bool
|
||||
* Return true if a context of this name exists.
|
||||
*/
|
||||
abstract public function contextExists($value, $element, $form_state);
|
||||
|
||||
/**
|
||||
* Determines if the machine_name should be disabled.
|
||||
*
|
||||
* @param $cached_values
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
abstract protected function disableMachineName($cached_values, $machine_name);
|
||||
|
||||
}
|
85
web/modules/contrib/ctools/src/Form/ContextDelete.php
Normal file
85
web/modules/contrib/ctools/src/Form/ContextDelete.php
Normal file
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Form;
|
||||
|
||||
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Form\ConfirmFormBase;
|
||||
use Drupal\user\SharedTempStoreFactory;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides a form for deleting an contexts and relationships.
|
||||
*/
|
||||
abstract class ContextDelete extends ConfirmFormBase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\user\SharedTempStoreFactory
|
||||
*/
|
||||
protected $tempstore;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $tempstore_id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $machine_name;
|
||||
|
||||
/**
|
||||
* The static context's machine name.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $context_id;
|
||||
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static($container->get('user.shared_tempstore'));
|
||||
}
|
||||
|
||||
public function __construct(SharedTempStoreFactory $tempstore) {
|
||||
$this->tempstore = $tempstore;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'ctools_context_delete_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getConfirmText() {
|
||||
return $this->t('Delete');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state, $tempstore_id = NULL, $machine_name = NULL, $context_id = NULL) {
|
||||
$this->tempstore_id = $tempstore_id;
|
||||
$this->machine_name = $machine_name;
|
||||
$this->context_id = $context_id;
|
||||
return parent::buildForm($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$form_state->setRedirectUrl($this->getCancelUrl());
|
||||
}
|
||||
|
||||
protected function getTempstore() {
|
||||
return $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
|
||||
}
|
||||
|
||||
protected function setTempstore($cached_values) {
|
||||
$this->tempstore->get($this->tempstore_id)->set($this->machine_name, $cached_values);
|
||||
}
|
||||
|
||||
}
|
224
web/modules/contrib/ctools/src/Form/ManageConditions.php
Normal file
224
web/modules/contrib/ctools/src/Form/ManageConditions.php
Normal file
|
@ -0,0 +1,224 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Form;
|
||||
|
||||
|
||||
use Drupal\Component\Plugin\PluginManagerInterface;
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\Core\Ajax\AjaxResponse;
|
||||
use Drupal\Core\Ajax\OpenModalDialogCommand;
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormBuilderInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
abstract class ManageConditions extends FormBase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Condition\ConditionManager
|
||||
*/
|
||||
protected $manager;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $machine_name;
|
||||
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static($container->get('plugin.manager.condition'));
|
||||
}
|
||||
|
||||
function __construct(PluginManagerInterface $manager) {
|
||||
$this->manager = $manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'ctools_manage_conditions_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$cached_values = $form_state->getTemporaryValue('wizard');
|
||||
$this->machine_name = $cached_values['id'];
|
||||
$form['#attached']['library'][] = 'core/drupal.dialog.ajax';
|
||||
$options = [];
|
||||
$contexts = $this->getContexts($cached_values);
|
||||
foreach ($this->manager->getDefinitionsForContexts($contexts) as $plugin_id => $definition) {
|
||||
$options[$plugin_id] = (string) $definition['label'];
|
||||
}
|
||||
$form['items'] = array(
|
||||
'#type' => 'markup',
|
||||
'#prefix' => '<div id="configured-conditions">',
|
||||
'#suffix' => '</div>',
|
||||
'#theme' => 'table',
|
||||
'#header' => array($this->t('Plugin Id'), $this->t('Summary'), $this->t('Operations')),
|
||||
'#rows' => $this->renderRows($cached_values),
|
||||
'#empty' => $this->t('No required conditions have been configured.')
|
||||
);
|
||||
$form['conditions'] = [
|
||||
'#type' => 'select',
|
||||
'#options' => $options,
|
||||
];
|
||||
$form['add'] = [
|
||||
'#type' => 'submit',
|
||||
'#name' => 'add',
|
||||
'#value' => $this->t('Add Condition'),
|
||||
'#ajax' => [
|
||||
'callback' => [$this, 'add'],
|
||||
'event' => 'click',
|
||||
],
|
||||
'#submit' => [
|
||||
'callback' => [$this, 'submitForm'],
|
||||
]
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$cached_values = $form_state->getTemporaryValue('wizard');
|
||||
list(, $route_parameters) = $this->getOperationsRouteInfo($cached_values, $this->machine_name, $form_state->getValue('conditions'));
|
||||
$form_state->setRedirect($this->getAddRoute($cached_values), $route_parameters);
|
||||
}
|
||||
|
||||
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['#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]]);
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new OpenModalDialogCommand($this->t('Configure Required Context'), $content, array('width' => '700')));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cached_values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function renderRows($cached_values) {
|
||||
$configured_conditions = array();
|
||||
foreach ($this->getConditions($cached_values) as $row => $condition) {
|
||||
/** @var $instance \Drupal\Core\Condition\ConditionInterface */
|
||||
$instance = $this->manager->createInstance($condition['id'], $condition);
|
||||
list($route_name, $route_parameters) = $this->getOperationsRouteInfo($cached_values, $cached_values['id'], $row);
|
||||
$build = array(
|
||||
'#type' => 'operations',
|
||||
'#links' => $this->getOperations($route_name, $route_parameters),
|
||||
);
|
||||
$configured_conditions[] = array(
|
||||
$instance->getPluginId(),
|
||||
$instance->summary(),
|
||||
'operations' => [
|
||||
'data' => $build,
|
||||
],
|
||||
);
|
||||
}
|
||||
return $configured_conditions;
|
||||
}
|
||||
|
||||
protected function getOperations($route_name_base, array $route_parameters = array()) {
|
||||
$operations['edit'] = array(
|
||||
'title' => $this->t('Edit'),
|
||||
'url' => new Url($route_name_base . '.edit', $route_parameters),
|
||||
'weight' => 10,
|
||||
'attributes' => array(
|
||||
'class' => ['use-ajax'],
|
||||
'data-dialog-type' => 'modal',
|
||||
'data-dialog-options' => Json::encode([
|
||||
'width' => 700,
|
||||
]),
|
||||
),
|
||||
);
|
||||
$route_parameters['id'] = $route_parameters['condition'];
|
||||
$operations['delete'] = array(
|
||||
'title' => $this->t('Delete'),
|
||||
'url' => new Url($route_name_base . '.delete', $route_parameters),
|
||||
'weight' => 100,
|
||||
'attributes' => array(
|
||||
'class' => array('use-ajax'),
|
||||
'data-dialog-type' => 'modal',
|
||||
'data-dialog-options' => Json::encode([
|
||||
'width' => 700,
|
||||
]),
|
||||
),
|
||||
);
|
||||
return $operations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a subclass of '\Drupal\ctools\Form\ConditionConfigure'.
|
||||
*
|
||||
* The ConditionConfigure class is designed to be subclassed with custom
|
||||
* route information to control the modal/redirect needs of your use case.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getConditionClass();
|
||||
|
||||
/**
|
||||
* The route to which condition 'add' actions should submit.
|
||||
*
|
||||
* @param mixed $cached_values
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getAddRoute($cached_values);
|
||||
|
||||
/**
|
||||
* Provide the tempstore id for your specified use case.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getTempstoreId();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Subclassing '\Drupal\ctools\Form\ConditionConfigure' and
|
||||
* '\Drupal\ctools\Form\ConditionDelete' should set you up for using this
|
||||
* approach quite seamlessly.
|
||||
*
|
||||
* @param mixed $cached_values
|
||||
*
|
||||
* @param string $machine_name
|
||||
*
|
||||
* @param string $row
|
||||
*
|
||||
* @return array
|
||||
* In the format of
|
||||
* return ['route.base.name', ['machine_name' => $machine_name, 'context' => $row]];
|
||||
*/
|
||||
abstract protected function getOperationsRouteInfo($cached_values, $machine_name, $row);
|
||||
|
||||
/**
|
||||
* Custom logic for retrieving the conditions array from cached_values.
|
||||
*
|
||||
* @param $cached_values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract protected function getConditions($cached_values);
|
||||
|
||||
/**
|
||||
* Custom logic for retrieving the contexts array from cached_values.
|
||||
*
|
||||
* @param $cached_values
|
||||
*
|
||||
* @return \Drupal\Core\Plugin\Context\ContextInterface[]
|
||||
*/
|
||||
abstract protected function getContexts($cached_values);
|
||||
|
||||
}
|
327
web/modules/contrib/ctools/src/Form/ManageContext.php
Normal file
327
web/modules/contrib/ctools/src/Form/ManageContext.php
Normal file
|
@ -0,0 +1,327 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Form;
|
||||
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\Core\Ajax\AjaxResponse;
|
||||
use Drupal\Core\Ajax\OpenModalDialogCommand;
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormBuilderInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\TypedData\TypedDataManagerInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
abstract class ManageContext extends FormBase {
|
||||
|
||||
/**
|
||||
* The machine name of the wizard we're working with.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $machine_name;
|
||||
|
||||
/**
|
||||
* The typed data manager.
|
||||
*
|
||||
* @var \Drupal\Core\TypedData\TypedDataManagerInterface
|
||||
*/
|
||||
protected $typedDataManager;
|
||||
|
||||
/**
|
||||
* The form builder.
|
||||
*
|
||||
* @var \Drupal\Core\Form\FormBuilderInterface
|
||||
*/
|
||||
protected $formBuilder;
|
||||
|
||||
/**
|
||||
* An array of property types that are eligible as relationships.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $property_types = [];
|
||||
|
||||
/**
|
||||
* A property for controlling usage of relationships in an implementation.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $relationships = TRUE;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static($container->get('typed_data_manager'), $container->get('form_builder'));
|
||||
}
|
||||
|
||||
/**
|
||||
* ManageContext constructor.
|
||||
*
|
||||
* @param \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data_manager
|
||||
* The typed data manager.
|
||||
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
|
||||
* The form builder.
|
||||
*/
|
||||
public function __construct(TypedDataManagerInterface $typed_data_manager, FormBuilderInterface $form_builder) {
|
||||
$this->typedDataManager = $typed_data_manager;
|
||||
$this->formBuilder = $form_builder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'ctools_manage_context_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$cached_values = $form_state->getTemporaryValue('wizard');
|
||||
$this->machine_name = $cached_values['id'];
|
||||
$form['items'] = array(
|
||||
'#type' => 'markup',
|
||||
'#prefix' => '<div id="configured-contexts">',
|
||||
'#suffix' => '</div>',
|
||||
'#theme' => 'table',
|
||||
'#header' => array($this->t('Context ID'), $this->t('Label'), $this->t('Data Type'), $this->t('Options')),
|
||||
'#rows' => $this->renderRows($cached_values),
|
||||
'#empty' => $this->t('No contexts or relationships have been added.')
|
||||
);
|
||||
foreach ($this->typedDataManager->getDefinitions() as $type => $definition) {
|
||||
$types[$type] = $definition['label'];
|
||||
}
|
||||
if (isset($types['entity'])) {
|
||||
unset($types['entity']);
|
||||
}
|
||||
asort($types);
|
||||
$form['context'] = [
|
||||
'#type' => 'select',
|
||||
'#options' => $types,
|
||||
];
|
||||
$form['add'] = [
|
||||
'#type' => 'submit',
|
||||
'#name' => 'add',
|
||||
'#value' => $this->t('Add new context'),
|
||||
'#ajax' => [
|
||||
'callback' => [$this, 'addContext'],
|
||||
'event' => 'click',
|
||||
],
|
||||
'#submit' => [
|
||||
'callback' => [$this, 'submitForm'],
|
||||
]
|
||||
];
|
||||
|
||||
$form['relationships'] = [
|
||||
'#type' => 'select',
|
||||
'#title' => $this->t('Add a relationship'),
|
||||
'#options' => $this->getAvailableRelationships($cached_values),
|
||||
'#access' => $this->relationships,
|
||||
];
|
||||
$form['add_relationship'] = [
|
||||
'#type' => 'submit',
|
||||
'#name' => 'add_relationship',
|
||||
'#value' => $this->t('Add Relationship'),
|
||||
'#ajax' => [
|
||||
'callback' => [$this, 'addRelationship'],
|
||||
'event' => 'click',
|
||||
],
|
||||
'#submit' => [
|
||||
'callback' => [$this, 'submitForm'],
|
||||
],
|
||||
'#access' => $this->relationships,
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
if ($form_state->getTriggeringElement()['#name'] == 'add') {
|
||||
$cached_values = $form_state->getTemporaryValue('wizard');
|
||||
list(, $route_parameters) = $this->getContextOperationsRouteInfo($cached_values, $this->machine_name, $form_state->getValue('context'));
|
||||
$form_state->setRedirect($this->getContextAddRoute($cached_values), $route_parameters);
|
||||
}
|
||||
if ($form_state->getTriggeringElement()['#name'] == 'add_relationship') {
|
||||
$cached_values = $form_state->getTemporaryValue('wizard');
|
||||
list(, $route_parameters) = $this->getRelationshipOperationsRouteInfo($cached_values, $this->machine_name, $form_state->getValue('relationships'));
|
||||
$form_state->setRedirect($this->getRelationshipAddRoute($cached_values), $route_parameters);
|
||||
}
|
||||
}
|
||||
|
||||
public function addContext(array &$form, FormStateInterface $form_state) {
|
||||
$context = $form_state->getValue('context');
|
||||
$content = $this->formBuilder->getForm($this->getContextClass(), $context, $this->getTempstoreId(), $this->machine_name);
|
||||
$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]]);
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new OpenModalDialogCommand($this->t('Add new context'), $content, array('width' => '700')));
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function addRelationship(array &$form, FormStateInterface $form_state) {
|
||||
$relationship = $form_state->getValue('relationships');
|
||||
$content = $this->formBuilder->getForm($this->getRelationshipClass(), $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->getRelationshipAddRoute($cached_values), $route_parameters, ['query' => [FormBuilderInterface::AJAX_FORM_REQUEST => TRUE]]);
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new OpenModalDialogCommand($this->t('Configure Relationship'), $content, array('width' => '700')));
|
||||
return $response;
|
||||
}
|
||||
|
||||
protected function getAvailableRelationships($cached_values) {
|
||||
/** @var \Drupal\ctools\TypedDataResolver $resolver */
|
||||
$resolver = \Drupal::service('ctools.typed_data.resolver');
|
||||
return $resolver->getTokensForContexts($this->getContexts($cached_values));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cached_values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function renderRows($cached_values) {
|
||||
$contexts = array();
|
||||
foreach ($this->getContexts($cached_values) as $row => $context) {
|
||||
list($route_name, $route_parameters) = $this->getContextOperationsRouteInfo($cached_values, $this->machine_name, $row);
|
||||
$build = array(
|
||||
'#type' => 'operations',
|
||||
'#links' => $this->getOperations($cached_values, $row, $route_name, $route_parameters),
|
||||
);
|
||||
$contexts[$row] = array(
|
||||
$row,
|
||||
$context->getContextDefinition()->getLabel(),
|
||||
$context->getContextDefinition()->getDataType(),
|
||||
'operations' => [
|
||||
'data' => $build,
|
||||
],
|
||||
);
|
||||
}
|
||||
return $contexts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $cached_values
|
||||
* @param string $row
|
||||
* @param string $route_name_base
|
||||
* @param array $route_parameters
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getOperations($cached_values, $row, $route_name_base, array $route_parameters = array()) {
|
||||
$operations = [];
|
||||
if ($this->isEditableContext($cached_values, $row)) {
|
||||
$operations['edit'] = array(
|
||||
'title' => $this->t('Edit'),
|
||||
'url' => new Url($route_name_base . '.edit', $route_parameters),
|
||||
'weight' => 10,
|
||||
'attributes' => array(
|
||||
'class' => ['use-ajax'],
|
||||
'data-dialog-type' => 'modal',
|
||||
'data-dialog-options' => Json::encode([
|
||||
'width' => 700,
|
||||
]),
|
||||
),
|
||||
);
|
||||
$operations['delete'] = array(
|
||||
'title' => $this->t('Delete'),
|
||||
'url' => new Url($route_name_base . '.delete', $route_parameters),
|
||||
'weight' => 100,
|
||||
'attributes' => array(
|
||||
'class' => array('use-ajax'),
|
||||
'data-dialog-type' => 'modal',
|
||||
'data-dialog-options' => Json::encode([
|
||||
'width' => 700,
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
return $operations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a subclass of '\Drupal\ctools\Form\ContextConfigure'.
|
||||
*
|
||||
* The ContextConfigure class is designed to be subclassed with custom
|
||||
* route information to control the modal/redirect needs of your use case.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getContextClass($cached_values);
|
||||
|
||||
/**
|
||||
* Return a subclass of '\Drupal\ctools\Form\RelationshipConfigure'.
|
||||
*
|
||||
* The RelationshipConfigure class is designed to be subclassed with custom
|
||||
* route information to control the modal/redirect needs of your use case.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getRelationshipClass($cached_values);
|
||||
|
||||
/**
|
||||
* The route to which context 'add' actions should submit.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getContextAddRoute($cached_values);
|
||||
|
||||
/**
|
||||
* The route to which relationship 'add' actions should submit.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getRelationshipAddRoute($cached_values);
|
||||
|
||||
/**
|
||||
* Provide the tempstore id for your specified use case.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getTempstoreId();
|
||||
|
||||
/**
|
||||
* Returns the contexts already available in the wizard.
|
||||
*
|
||||
* @param mixed $cached_values
|
||||
*
|
||||
* @return \Drupal\Core\Plugin\Context\ContextInterface[]
|
||||
*/
|
||||
abstract protected function getContexts($cached_values);
|
||||
|
||||
/**
|
||||
* @param mixed $cached_values
|
||||
* @param string $machine_name
|
||||
* @param string $row
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract protected function getContextOperationsRouteInfo($cached_values, $machine_name, $row);
|
||||
|
||||
/**
|
||||
* @param mixed $cached_values
|
||||
* @param string $machine_name
|
||||
* @param string $row
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract protected function getRelationshipOperationsRouteInfo($cached_values, $machine_name, $row);
|
||||
|
||||
/**
|
||||
* @param mixed $cached_values
|
||||
* @param string $row
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
abstract protected function isEditableContext($cached_values, $row);
|
||||
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Form;
|
||||
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\Core\Ajax\AjaxResponse;
|
||||
use Drupal\Core\Ajax\OpenModalDialogCommand;
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormBuilderInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Url;
|
||||
|
||||
abstract class ManageResolverRelationships extends FormBase {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $machine_name;
|
||||
|
||||
/**
|
||||
* An array of property types that are eligible as relationships.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $property_types = [];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'ctools_manage_resolver_relationships_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$cached_values = $form_state->getTemporaryValue('wizard');
|
||||
$this->machine_name = $cached_values['id'];
|
||||
$form['items'] = array(
|
||||
'#type' => 'markup',
|
||||
'#prefix' => '<div id="configured-relationships">',
|
||||
'#suffix' => '</div>',
|
||||
'#theme' => 'table',
|
||||
'#header' => array($this->t('Context ID'), $this->t('Label'), $this->t('Data Type'), $this->t('Options')),
|
||||
'#rows' => $this->renderRows($cached_values),
|
||||
'#empty' => $this->t('No relationships have been added.')
|
||||
);
|
||||
|
||||
$form['relationships'] = [
|
||||
'#type' => 'select',
|
||||
'#title' => $this->t('Add a relationship'),
|
||||
'#options' => $this->getAvailableRelationships($cached_values),
|
||||
];
|
||||
$form['add_relationship'] = [
|
||||
'#type' => 'submit',
|
||||
'#name' => 'add',
|
||||
'#value' => $this->t('Add Relationship'),
|
||||
'#ajax' => [
|
||||
'callback' => [$this, 'addRelationship'],
|
||||
'event' => 'click',
|
||||
],
|
||||
'#submit' => [
|
||||
'callback' => [$this, 'submitForm'],
|
||||
]
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
if ($form_state->getTriggeringElement()['#name'] == 'add') {
|
||||
$cached_values = $form_state->getTemporaryValue('wizard');
|
||||
list(, $route_parameters) = $this->getRelationshipOperationsRouteInfo($cached_values, $this->machine_name, $form_state->getValue('relationships'));
|
||||
$form_state->setRedirect($this->getAddRoute($cached_values), $route_parameters);
|
||||
}
|
||||
}
|
||||
|
||||
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['#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]]);
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new OpenModalDialogCommand($this->t('Configure Relationship'), $content, array('width' => '700')));
|
||||
return $response;
|
||||
}
|
||||
|
||||
protected function getAvailableRelationships($cached_values) {
|
||||
/** @var \Drupal\ctools\TypedDataResolver $resolver */
|
||||
$resolver = \Drupal::service('ctools.typed_data.resolver');
|
||||
return $resolver->getTokensForContexts($this->getContexts($cached_values));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cached_values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function renderRows($cached_values) {
|
||||
$contexts = array();
|
||||
foreach ($this->getContexts($cached_values) as $row => $context) {
|
||||
list($route_name, $route_parameters) = $this->getRelationshipOperationsRouteInfo($cached_values, $this->machine_name, $row);
|
||||
$build = array(
|
||||
'#type' => 'operations',
|
||||
'#links' => $this->getOperations($cached_values, $row, $route_name, $route_parameters),
|
||||
);
|
||||
$contexts[$row] = array(
|
||||
$row,
|
||||
$context->getContextDefinition()->getLabel(),
|
||||
$context->getContextDefinition()->getDataType(),
|
||||
'operations' => [
|
||||
'data' => $build,
|
||||
],
|
||||
);
|
||||
}
|
||||
return $contexts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $cached_values
|
||||
* @param string $row
|
||||
* @param string $route_name_base
|
||||
* @param array $route_parameters
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getOperations($cached_values, $row, $route_name_base, array $route_parameters = array()) {
|
||||
// Base contexts will not be a : separated and generated relationships should have 3 parts.
|
||||
if (count(explode(':', $row)) < 2) {
|
||||
return [];
|
||||
}
|
||||
$operations['edit'] = array(
|
||||
'title' => $this->t('Edit'),
|
||||
'url' => new Url($route_name_base . '.edit', $route_parameters),
|
||||
'weight' => 10,
|
||||
'attributes' => array(
|
||||
'class' => ['use-ajax'],
|
||||
'data-dialog-type' => 'modal',
|
||||
'data-dialog-options' => Json::encode([
|
||||
'width' => 700,
|
||||
]),
|
||||
),
|
||||
);
|
||||
$route_parameters['id'] = $route_parameters['context'];
|
||||
$operations['delete'] = array(
|
||||
'title' => $this->t('Delete'),
|
||||
'url' => new Url($route_name_base . '.delete', $route_parameters),
|
||||
'weight' => 100,
|
||||
'attributes' => array(
|
||||
'class' => array('use-ajax'),
|
||||
'data-dialog-type' => 'modal',
|
||||
'data-dialog-options' => Json::encode([
|
||||
'width' => 700,
|
||||
]),
|
||||
),
|
||||
);
|
||||
return $operations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a subclass of '\Drupal\ctools\Form\ResolverRelationshipConfigure'.
|
||||
*
|
||||
* The ConditionConfigure class is designed to be subclassed with custom
|
||||
* route information to control the modal/redirect needs of your use case.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getContextClass($cached_values);
|
||||
|
||||
/**
|
||||
* The route to which relationship 'add' actions should submit.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getAddRoute($cached_values);
|
||||
|
||||
/**
|
||||
* Provide the tempstore id for your specified use case.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getTempstoreId();
|
||||
|
||||
/**
|
||||
* @param $cached_values
|
||||
*
|
||||
* @return \Drupal\Core\Plugin\Context\ContextInterface[]
|
||||
*/
|
||||
abstract protected function getContexts($cached_values);
|
||||
|
||||
/**
|
||||
* @param string $cached_values
|
||||
* @param string $machine_name
|
||||
* @param string $row
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract protected function getRelationshipOperationsRouteInfo($cached_values, $machine_name, $row);
|
||||
|
||||
}
|
152
web/modules/contrib/ctools/src/Form/RelationshipConfigure.php
Normal file
152
web/modules/contrib/ctools/src/Form/RelationshipConfigure.php
Normal file
|
@ -0,0 +1,152 @@
|
|||
<?php
|
||||
|
||||
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\ctools\TypedDataResolver;
|
||||
use Drupal\user\SharedTempStoreFactory;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
abstract class RelationshipConfigure extends FormBase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\user\SharedTempStoreFactory
|
||||
*/
|
||||
protected $tempstore;
|
||||
|
||||
/**
|
||||
* @var \Drupal\ctools\TypedDataResolver
|
||||
*/
|
||||
protected $resolver;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $tempstore_id;
|
||||
|
||||
/**
|
||||
* @var string;
|
||||
*/
|
||||
protected $machine_name;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static($container->get('user.shared_tempstore'), $container->get('ctools.typed_data.resolver'));
|
||||
}
|
||||
|
||||
public function __construct(SharedTempStoreFactory $tempstore, TypedDataResolver $resolver) {
|
||||
$this->tempstore = $tempstore;
|
||||
$this->resolver = $resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'ctools_relationship_configure';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state, $context_id = NULL, $tempstore_id = NULL, $machine_name = NULL) {
|
||||
$this->tempstore_id = $tempstore_id;
|
||||
$this->machine_name = $machine_name;
|
||||
$cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
|
||||
|
||||
/** @var \Drupal\Core\Plugin\Context\ContextInterface[] $contexts */
|
||||
$contexts = $this->getContexts($cached_values);
|
||||
$context_object = $this->resolver->convertTokenToContext($context_id, $contexts);
|
||||
$form['id'] = [
|
||||
'#type' => 'value',
|
||||
'#value' => $context_id
|
||||
];
|
||||
$form['context_object'] = [
|
||||
'#type' => 'value',
|
||||
'#value' => $context_object,
|
||||
];
|
||||
$form['label'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Context label'),
|
||||
'#default_value' => !empty($contexts[$context_id]) ? $contexts[$context_id]->getContextDefinition()->getLabel() : $this->resolver->getLabelByToken($context_id, $contexts),
|
||||
'#required' => TRUE,
|
||||
];
|
||||
$form['context_data'] = [
|
||||
'#type' => 'item',
|
||||
'#title' => $this->t('Data type'),
|
||||
'#markup' => $context_object->getContextDefinition()->getDataType(),
|
||||
];
|
||||
$form['submit'] = [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Save'),
|
||||
'#ajax' => [
|
||||
'callback' => [$this, 'ajaxSave'],
|
||||
]
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
|
||||
list($route_name, $route_options) = $this->getParentRouteInfo($cached_values);
|
||||
$form_state->setRedirect($route_name, $route_options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $form
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
*
|
||||
* @return \Drupal\Core\Ajax\AjaxResponse
|
||||
*/
|
||||
public function ajaxSave(array &$form, FormStateInterface $form_state) {
|
||||
$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)));
|
||||
$response->addCommand(new CloseModalDialogCommand());
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Document the route name and parameters for redirect after submission.
|
||||
*
|
||||
* @param array $cached_values
|
||||
*
|
||||
* @return array In the format of
|
||||
* In the format of
|
||||
* return ['route.name', ['machine_name' => $this->machine_name, 'step' => 'step_name']];
|
||||
*/
|
||||
abstract protected function getParentRouteInfo($cached_values);
|
||||
|
||||
/**
|
||||
* Custom logic for setting the conditions array in cached_values.
|
||||
*
|
||||
* @param $cached_values
|
||||
*
|
||||
* @param $contexts
|
||||
* The conditions to set within the cached values.
|
||||
*
|
||||
* @return mixed
|
||||
* Return the $cached_values
|
||||
*/
|
||||
abstract protected function setContexts($cached_values, $contexts);
|
||||
|
||||
/**
|
||||
* Custom logic for retrieving the contexts array from cached_values.
|
||||
*
|
||||
* @param $cached_values
|
||||
*
|
||||
* @return \Drupal\Core\Plugin\Context\ContextInterface[]
|
||||
*/
|
||||
abstract protected function getContexts($cached_values);
|
||||
|
||||
}
|
212
web/modules/contrib/ctools/src/Form/RequiredContext.php
Normal file
212
web/modules/contrib/ctools/src/Form/RequiredContext.php
Normal file
|
@ -0,0 +1,212 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Form;
|
||||
|
||||
use Drupal\Component\Plugin\PluginManagerInterface;
|
||||
use Drupal\Core\Ajax\AjaxResponse;
|
||||
use Drupal\Core\Ajax\OpenModalDialogCommand;
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
abstract class RequiredContext extends FormBase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\TypedData\TypedDataManager
|
||||
*/
|
||||
protected $typedDataManager;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $machine_name;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static($container->get('typed_data_manager'));
|
||||
}
|
||||
|
||||
public function __construct(PluginManagerInterface $typed_data_manager) {
|
||||
$this->typedDataManager = $typed_data_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'ctools_required_context_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$cached_values = $form_state->getTemporaryValue('wizard');
|
||||
$this->machine_name = $cached_values['id'];
|
||||
$form['#attached']['library'][] = 'core/drupal.dialog.ajax';
|
||||
$options = [];
|
||||
foreach ($this->typedDataManager->getDefinitions() as $plugin_id => $definition) {
|
||||
$options[$plugin_id] = (string) $definition['label'];
|
||||
}
|
||||
$form['items'] = array(
|
||||
'#type' => 'markup',
|
||||
'#prefix' => '<div id="configured-contexts">',
|
||||
'#suffix' => '</div>',
|
||||
'#theme' => 'table',
|
||||
'#header' => array($this->t('Information'), $this->t('Description'), $this->t('Operations')),
|
||||
'#rows' => $this->renderContexts($cached_values),
|
||||
'#empty' => $this->t('No required contexts have been configured.')
|
||||
);
|
||||
$form['contexts'] = [
|
||||
'#type' => 'select',
|
||||
'#options' => $options,
|
||||
];
|
||||
$form['add'] = [
|
||||
'#type' => 'submit',
|
||||
'#name' => 'add',
|
||||
'#value' => $this->t('Add required context'),
|
||||
'#ajax' => [
|
||||
'callback' => [$this, 'add'],
|
||||
'event' => 'click',
|
||||
],
|
||||
'#submit' => [
|
||||
'callback' => [$this, 'submitform'],
|
||||
]
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$cached_values = $form_state->getTemporaryValue('wizard');
|
||||
list($route_name, $route_parameters) = $this->getOperationsRouteInfo($cached_values, $this->machine_name, $form_state->getValue('contexts'));
|
||||
$form_state->setRedirect($route_name . '.edit', $route_parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom ajax form submission handler.
|
||||
*
|
||||
* @param array $form
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
*
|
||||
* @return \Drupal\Core\Ajax\AjaxResponse
|
||||
*/
|
||||
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['#attached']['library'][] = 'core/drupal.dialog.ajax';
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new OpenModalDialogCommand($this->t('Configure Required Context'), $content, array('width' => '700')));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cached_values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function renderContexts($cached_values) {
|
||||
$configured_contexts = array();
|
||||
foreach ($this->getContexts($cached_values) as $row => $context) {
|
||||
list($plugin_id, $label, $machine_name, $description) = array_values($context);
|
||||
list($route_name, $route_parameters) = $this->getOperationsRouteInfo($cached_values, $cached_values['id'], $row);
|
||||
$build = array(
|
||||
'#type' => 'operations',
|
||||
'#links' => $this->getOperations($route_name, $route_parameters),
|
||||
);
|
||||
$configured_contexts[] = array(
|
||||
$this->t('<strong>Label:</strong> @label<br /> <strong>Type:</strong> @type', ['@label' => $label, '@type' => $plugin_id]),
|
||||
$this->t('@description', ['@description' => $description]),
|
||||
'operations' => [
|
||||
'data' => $build,
|
||||
],
|
||||
);
|
||||
}
|
||||
return $configured_contexts;
|
||||
}
|
||||
|
||||
protected function getOperations($route_name_base, array $route_parameters = array()) {
|
||||
$operations['edit'] = array(
|
||||
'title' => $this->t('Edit'),
|
||||
'url' => new Url($route_name_base . '.edit', $route_parameters),
|
||||
'weight' => 10,
|
||||
'attributes' => array(
|
||||
'class' => array('use-ajax'),
|
||||
'data-accepts' => 'application/vnd.drupal-modal',
|
||||
'data-dialog-options' => json_encode(array(
|
||||
'width' => 700,
|
||||
)),
|
||||
),
|
||||
'ajax' => [
|
||||
''
|
||||
],
|
||||
);
|
||||
$route_parameters['id'] = $route_parameters['context'];
|
||||
$operations['delete'] = array(
|
||||
'title' => $this->t('Delete'),
|
||||
'url' => new Url($route_name_base . '.delete', $route_parameters),
|
||||
'weight' => 100,
|
||||
'attributes' => array(
|
||||
'class' => array('use-ajax'),
|
||||
'data-accepts' => 'application/vnd.drupal-modal',
|
||||
'data-dialog-options' => json_encode(array(
|
||||
'width' => 700,
|
||||
)),
|
||||
),
|
||||
);
|
||||
return $operations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a subclass of '\Drupal\ctools\Form\ContextConfigure'.
|
||||
*
|
||||
* The ContextConfigure class is designed to be subclassed with custom route
|
||||
* information to control the modal/redirect needs of your use case.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getContextClass();
|
||||
|
||||
/**
|
||||
* Provide the tempstore id for your specified use case.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getTempstoreId();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Subclassing '\Drupal\ctools\Form\ContextConfigure' and
|
||||
* '\Drupal\ctools\Form\RequiredContextDelete' should set you up for using
|
||||
* this approach quite seamlessly.
|
||||
*
|
||||
* @param mixed $cached_values
|
||||
*
|
||||
* @param string $machine_name
|
||||
*
|
||||
* @param string $row
|
||||
*
|
||||
* @return array
|
||||
* In the format of
|
||||
* return ['route.base.name', ['machine_name' => $machine_name, 'context' => $row]];
|
||||
*/
|
||||
abstract protected function getOperationsRouteInfo($cached_values, $machine_name, $row);
|
||||
|
||||
/**
|
||||
* Custom logic for retrieving the contexts array from cached_values.
|
||||
*
|
||||
* @param $cached_values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract protected function getContexts($cached_values);
|
||||
|
||||
}
|
194
web/modules/contrib/ctools/src/Form/RequiredContextDelete.php
Normal file
194
web/modules/contrib/ctools/src/Form/RequiredContextDelete.php
Normal file
|
@ -0,0 +1,194 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Form;
|
||||
|
||||
use Drupal\Core\Form\ConfirmFormBase;
|
||||
use Drupal\Core\Form\ConfirmFormHelper;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\user\SharedTempStoreFactory;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Base class for adding a required contexts step to your wizard.
|
||||
*/
|
||||
abstract class RequiredContextDelete extends ConfirmFormBase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\user\SharedTempStoreFactory
|
||||
*/
|
||||
protected $tempstore;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $tempstore_id;
|
||||
|
||||
/**
|
||||
* @var string;
|
||||
*/
|
||||
protected $machine_name;
|
||||
|
||||
/**
|
||||
* @var int;
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static($container->get('user.shared_tempstore'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Drupal\user\SharedTempStoreFactory $tempstore
|
||||
*/
|
||||
function __construct(SharedTempStoreFactory $tempstore) {
|
||||
$this->tempstore = $tempstore;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'ctools_required_context_delete';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state, $id = NULL, $tempstore_id = NULL, $machine_name = NULL) {
|
||||
$this->tempstore_id = $tempstore_id;
|
||||
$this->machine_name = $machine_name;
|
||||
$this->id = $id;
|
||||
|
||||
$cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
|
||||
$form ['#title'] = $this->getQuestion($id, $cached_values);
|
||||
|
||||
$form ['#attributes']['class'][] = 'confirmation';
|
||||
$form ['description'] = array('#markup' => $this->getDescription());
|
||||
$form [$this->getFormName()] = array('#type' => 'hidden', '#value' => 1);
|
||||
|
||||
// By default, render the form using theme_confirm_form().
|
||||
if (!isset($form ['#theme'])) {
|
||||
$form ['#theme'] = 'confirm_form';
|
||||
}
|
||||
$form['actions'] = array('#type' => 'actions');
|
||||
$form['actions'] += $this->actions($form, $form_state);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
|
||||
$contexts = $this->getContexts($cached_values);
|
||||
unset($contexts[$this->id]);
|
||||
$cached_values = $this->setContexts($cached_values, $contexts);
|
||||
$this->tempstore->get($this->tempstore_id)->set($this->machine_name, $cached_values);
|
||||
list($route_name, $route_parameters) = $this->getParentRouteInfo($cached_values);
|
||||
$form_state->setRedirect($route_name, $route_parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getQuestion($id = NULL, $cached_values = NULL) {
|
||||
$context = $this->getContexts($cached_values)[$id];
|
||||
return $this->t('Are you sure you want to delete the @label context?', array(
|
||||
'@label' => $context['label'],
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDescription() {
|
||||
return $this->t('This action cannot be undone.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormName() {
|
||||
return 'confirm';
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the action buttons for submitting this form.
|
||||
*/
|
||||
protected function actions(array $form, FormStateInterface $form_state) {
|
||||
return array(
|
||||
'submit' => array(
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->getConfirmText(),
|
||||
'#validate' => array(
|
||||
array($this, 'validate'),
|
||||
),
|
||||
'#submit' => array(
|
||||
array($this, 'submitForm'),
|
||||
),
|
||||
),
|
||||
'cancel' => ConfirmFormHelper::buildCancelLink($this, $this->getRequest()),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCancelUrl() {
|
||||
$cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
|
||||
list($route_name, $route_parameters) = $this->getParentRouteInfo($cached_values);
|
||||
return new Url($route_name, $route_parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getConfirmText() {
|
||||
return $this->t('Delete');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCancelText() {
|
||||
return $this->t('Cancel');
|
||||
}
|
||||
|
||||
/**
|
||||
* Document the route name and parameters for redirect after submission.
|
||||
*
|
||||
* @param $cached_values
|
||||
*
|
||||
* @return array
|
||||
* In the format of
|
||||
* return ['route.name', ['machine_name' => $this->machine_name, 'step' => 'step_name]];
|
||||
*/
|
||||
abstract protected function getParentRouteInfo($cached_values);
|
||||
|
||||
/**
|
||||
* Custom logic for retrieving the contexts array from cached_values.
|
||||
*
|
||||
* @param $cached_values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract protected function getContexts($cached_values);
|
||||
|
||||
/**
|
||||
* Custom logic for setting the contexts array in cached_values.
|
||||
*
|
||||
* @param $cached_values
|
||||
*
|
||||
* @param $contexts
|
||||
* The contexts to set within the cached values.
|
||||
*
|
||||
* @return mixed
|
||||
* Return the $cached_values
|
||||
*/
|
||||
abstract protected function setContexts($cached_values, $contexts);
|
||||
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
<?php
|
||||
|
||||
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 Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
abstract class ResolverRelationshipConfigure extends FormBase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\user\SharedTempStoreFactory
|
||||
*/
|
||||
protected $tempstore;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $tempstore_id;
|
||||
|
||||
/**
|
||||
* @var string;
|
||||
*/
|
||||
protected $machine_name;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static($container->get('user.shared_tempstore'));
|
||||
}
|
||||
|
||||
function __construct(SharedTempStoreFactory $tempstore) {
|
||||
$this->tempstore = $tempstore;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'ctools_context_configure';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state, $context = NULL, $tempstore_id = NULL, $machine_name = NULL) {
|
||||
$this->tempstore_id = $tempstore_id;
|
||||
$this->machine_name = $machine_name;
|
||||
$cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
|
||||
if (is_numeric($context)) {
|
||||
$id = $context;
|
||||
$contexts = $this->getContexts($cached_values);
|
||||
$context = $contexts[$id]['context'];
|
||||
$label = $contexts[$id]['label'];
|
||||
$machine_name = $contexts[$id]['machine_name'];
|
||||
$description = $contexts[$id]['description'];
|
||||
// Conditionally set this form element so that we can update or add.
|
||||
$form['id'] = [
|
||||
'#type' => 'value',
|
||||
'#value' => $id
|
||||
];
|
||||
}
|
||||
else {
|
||||
$label = '';
|
||||
$machine_name = '';
|
||||
$description = '';
|
||||
}
|
||||
$form['#attached']['library'][] = 'core/drupal.dialog.ajax';
|
||||
$form['context'] = [
|
||||
'#type' => 'value',
|
||||
'#value' => $context
|
||||
];
|
||||
$form['label'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Label'),
|
||||
'#default_value' => $label,
|
||||
'#required' => TRUE,
|
||||
];
|
||||
$form['machine_name'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Machine Name'),
|
||||
'#default_value' => $machine_name,
|
||||
'#required' => TRUE,
|
||||
];
|
||||
$form['description'] = [
|
||||
'#type' => 'textarea',
|
||||
'#title' => $this->t('Description'),
|
||||
'#default_value' => $description,
|
||||
];
|
||||
$form['submit'] = [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Save'),
|
||||
'#ajax' => [
|
||||
'callback' => [$this, 'ajaxSave'],
|
||||
]
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
public function validateForm(array &$form, FormStateInterface $form_state) {
|
||||
$machine_name = $form_state->getValue('machine_name');
|
||||
$cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
|
||||
foreach ($this->getContexts($cached_values) as $id => $context) {
|
||||
if ($context['machine_name'] == $machine_name) {
|
||||
$form_state->setError($form['machine_name'], $this->t('That machine name is in use by another context definition.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
|
||||
$contexts = $this->getContexts($cached_values);
|
||||
$context = [
|
||||
'context' => $form_state->getValue('context'),
|
||||
'label' => $form_state->getValue('label'),
|
||||
'machine_name' => $form_state->getValue('machine_name'),
|
||||
'description' => $form_state->getValue('description'),
|
||||
];
|
||||
if ($form_state->hasValue('id')) {
|
||||
$contexts[$form_state->getValue('id')] = $context;
|
||||
}
|
||||
else {
|
||||
$contexts[] = $context;
|
||||
}
|
||||
$cached_values = $this->setContexts($cached_values, $contexts);
|
||||
$this->tempstore->get($this->tempstore_id)->set($this->machine_name, $cached_values);
|
||||
list($route_name, $route_parameters) = $this->getParentRouteInfo($cached_values);
|
||||
$form_state->setRedirect($route_name, $route_parameters);
|
||||
}
|
||||
|
||||
public function ajaxSave(array &$form, FormStateInterface $form_state) {
|
||||
$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)));
|
||||
$response->addCommand(new CloseModalDialogCommand());
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Document the route name and parameters for redirect after submission.
|
||||
*
|
||||
* @param $cached_values
|
||||
*
|
||||
* @return array
|
||||
* In the format of
|
||||
* return ['route.name', ['machine_name' => $this->machine_name, 'step' => 'step_name]];
|
||||
*/
|
||||
abstract protected function getParentRouteInfo($cached_values);
|
||||
|
||||
/**
|
||||
* Custom logic for retrieving the contexts array from cached_values.
|
||||
*
|
||||
* @param $cached_values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract protected function getContexts($cached_values);
|
||||
|
||||
/**
|
||||
* Custom logic for setting the contexts array in cached_values.
|
||||
*
|
||||
* @param $cached_values
|
||||
*
|
||||
* @param $contexts
|
||||
* The contexts to set within the cached values.
|
||||
*
|
||||
* @return mixed
|
||||
* Return the $cached_values
|
||||
*/
|
||||
abstract protected function setContexts($cached_values, $contexts);
|
||||
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
<?php
|
||||
|
||||
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 Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
abstract class ResolverRelationshipDelete extends ConfirmFormBase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\user\SharedTempStoreFactory
|
||||
*/
|
||||
protected $tempstore;
|
||||
|
||||
/**
|
||||
* @var \Drupal\ctools\TypedDataResolver
|
||||
*/
|
||||
protected $resolver;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $tempstore_id;
|
||||
|
||||
/**
|
||||
* @var string;
|
||||
*/
|
||||
protected $machine_name;
|
||||
|
||||
/**
|
||||
* @var string;
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static($container->get('user.shared_tempstore'), $container->get('ctools.typed_data.resolver'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Drupal\user\SharedTempStoreFactory $tempstore
|
||||
* The shared tempstore.
|
||||
* @param \Drupal\ctools\TypedDataResolver $resolver
|
||||
* The the typed data resolver.
|
||||
*/
|
||||
public function __construct(SharedTempStoreFactory $tempstore, TypedDataResolver $resolver) {
|
||||
$this->tempstore = $tempstore;
|
||||
$this->resolver = $resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'ctools_resolver_relationship_delete';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getQuestion($id = NULL, $cached_values = []) {
|
||||
$context = $this->getContexts($cached_values)[$id];
|
||||
return $this->t('Are you sure you want to delete the @label relationship?', [
|
||||
'@label' => $context->getContextDefinition()->getLabel(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
abstract public function getCancelUrl($cached_values = []);
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state, $id = NULL, $tempstore_id = NULL, $machine_name = NULL) {
|
||||
$this->tempstore_id = $tempstore_id;
|
||||
$this->machine_name = $machine_name;
|
||||
$this->id = $id;
|
||||
|
||||
$cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
|
||||
$form ['#title'] = $this->getQuestion($id, $cached_values);
|
||||
|
||||
$form ['#attributes']['class'][] = 'confirmation';
|
||||
$form ['description'] = array('#markup' => $this->getDescription());
|
||||
$form [$this->getFormName()] = array('#type' => 'hidden', '#value' => 1);
|
||||
|
||||
// By default, render the form using theme_confirm_form().
|
||||
if (!isset($form ['#theme'])) {
|
||||
$form ['#theme'] = 'confirm_form';
|
||||
}
|
||||
$form['actions'] = array('#type' => 'actions');
|
||||
$form['actions'] += $this->actions($form, $form_state, $cached_values);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
|
||||
$form_state->setRedirectUrl($this->getCancelUrl($cached_values));
|
||||
}
|
||||
|
||||
/**
|
||||
* A custom form actions method.
|
||||
*
|
||||
* @param array $form
|
||||
* The form array.
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The current form state.
|
||||
* @param $cached_values
|
||||
* The current wizard cached values.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function actions(array $form, FormStateInterface $form_state, $cached_values) {
|
||||
return array(
|
||||
'submit' => array(
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->getConfirmText(),
|
||||
'#validate' => array(
|
||||
array($this, 'validate'),
|
||||
),
|
||||
'#submit' => array(
|
||||
array($this, 'submitForm'),
|
||||
),
|
||||
),
|
||||
'cancel' => ConfirmFormHelper::buildCancelLink($this, $this->getRequest()),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract contexts from the cached values.
|
||||
*
|
||||
* @param array $cached_values
|
||||
* The cached values.
|
||||
*
|
||||
* @return \Drupal\Core\Plugin\Context\ContextInterface[]
|
||||
*/
|
||||
abstract public function getContexts($cached_values);
|
||||
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
<?php
|
||||
|
||||
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 Symfony\Component\Routing\Route;
|
||||
|
||||
/**
|
||||
* Parameter converter for pulling entities out of the tempstore.
|
||||
*
|
||||
* This is particularly useful when building non-wizard forms (like dialogs)
|
||||
* that operate on data in the wizard and getting the route access correct.
|
||||
*
|
||||
* There are four different ways to use this!
|
||||
*
|
||||
* In the most basic way, you specify the 'tempstore_id' in the defaults (so
|
||||
* that the form/controller has access to it as well) and in the parameter type
|
||||
* we simply give 'tempstore'. This assumes the entity is the full value
|
||||
* returned from the tempstore.
|
||||
*
|
||||
* @code
|
||||
* example.route:
|
||||
* path: foo/{example}
|
||||
* defaults:
|
||||
* tempstore_id: example.foo
|
||||
* options:
|
||||
* parameters:
|
||||
* example:
|
||||
* type: tempstore
|
||||
* @endcode
|
||||
*
|
||||
* If the value returned from the tempstore is an array, and the entity is
|
||||
* one of the keys, then we specify that after 'tempstore:', for example:
|
||||
*
|
||||
* @code
|
||||
* example.route:
|
||||
* path: foo/{example}
|
||||
* defaults:
|
||||
* tempstore_id: example.foo
|
||||
* options:
|
||||
* parameters:
|
||||
* example:
|
||||
* # Get the 'foo' key from the array returned by the tempstore.
|
||||
* type: tempstore:foo
|
||||
* @endcode
|
||||
*
|
||||
* You can also specify the 'tempstore_id' under the parameter rather than in
|
||||
* the defaults, for example:
|
||||
*
|
||||
* @code
|
||||
* example.route:
|
||||
* path: foo/{example}
|
||||
* options:
|
||||
* parameters:
|
||||
* example:
|
||||
* type: tempstore:foo
|
||||
* tempstore_id: example.foo
|
||||
* @endcode
|
||||
*
|
||||
* Or, if you have two parameters which are represented by two keys on the same
|
||||
* array from the tempstore, put the slug which represents the id for the
|
||||
* tempstore in the 2nd key. For example:
|
||||
*
|
||||
* @code
|
||||
* example.route:
|
||||
* path: foo/{example}/{other}
|
||||
* defaults:
|
||||
* tempstore_id: example.foo
|
||||
* options:
|
||||
* parameters:
|
||||
* example:
|
||||
* type: tempstore:foo
|
||||
* other:
|
||||
* type: tempstore:{example}:other
|
||||
* @endcode
|
||||
*/
|
||||
class TempstoreConverter implements ParamConverterInterface {
|
||||
|
||||
/**
|
||||
* The tempstore factory.
|
||||
*
|
||||
* @var \Drupal\user\SharedTempStoreFactory
|
||||
*/
|
||||
protected $tempstore;
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* Constructs a TempstoreConverter.
|
||||
*
|
||||
* @param \Drupal\user\SharedTempStoreFactory $tempstore
|
||||
*/
|
||||
public function __construct(SharedTempStoreFactory $tempstore, EntityTypeManagerInterface $entity_type_manager) {
|
||||
$this->tempstore = $tempstore;
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function convert($value, $definition, $name, array $defaults) {
|
||||
$tempstore_id = !empty($definition['tempstore_id']) ? $definition['tempstore_id'] : $defaults['tempstore_id'];
|
||||
$machine_name = $this->convertVariable($value, $defaults);
|
||||
|
||||
list(, $parts) = explode(':', $definition['type'], 2);
|
||||
$parts = explode(':', $parts);
|
||||
foreach ($parts as $key => $part) {
|
||||
$parts[$key] = $this->convertVariable($part, $defaults);
|
||||
}
|
||||
$cached_values = $this->tempstore->get($tempstore_id)->get($machine_name);
|
||||
// Entity type upcasting is most common, so we just assume that here.
|
||||
// @todo see if there's a better way to do this.
|
||||
if (!$cached_values && $this->entityTypeManager->hasDefinition($name)) {
|
||||
$value = $this->entityTypeManager->getStorage($name)->load($machine_name);
|
||||
return $value;
|
||||
}
|
||||
elseif (!$cached_values) {
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
$value = NestedArray::getValue($cached_values, $parts, $key_exists);
|
||||
return $key_exists ? $value : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function for converting string variable names from the defaults.
|
||||
*
|
||||
* @param mixed $name
|
||||
* If name is a string in the format of {var} it will parse the defaults
|
||||
* for a 'var' default. If $name isn't a string or isn't a slug, it will
|
||||
* return the raw $name value. If no default is found, it will return NULL
|
||||
* @param array $defaults
|
||||
* The route defaults array.
|
||||
*
|
||||
* @return mixed
|
||||
* The value of a variable in defaults.
|
||||
*/
|
||||
protected function convertVariable($name, $defaults) {
|
||||
if (is_string($name) && strpos($name, '{') === 0) {
|
||||
$length = strlen($name);
|
||||
$name = substr($name, 1, $length -2);
|
||||
return isset($defaults[$name]) ? $defaults[$name] : NULL;
|
||||
}
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function applies($definition, $name, Route $route) {
|
||||
if (!empty($definition['type']) && ($definition['type'] == 'tempstore' || strpos($definition['type'], 'tempstore:') === 0)) {
|
||||
if (!empty($definition['tempstore_id']) || $route->hasDefault('tempstore_id')) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}
|
105
web/modules/contrib/ctools/src/Plugin/Block/EntityView.php
Normal file
105
web/modules/contrib/ctools/src/Plugin/Block/EntityView.php
Normal file
|
@ -0,0 +1,105 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin\Block;
|
||||
|
||||
use Drupal\Core\Block\BlockBase;
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Plugin\ContextAwarePluginInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides a block to view a specific entity.
|
||||
*
|
||||
* @Block(
|
||||
* id = "entity_view",
|
||||
* deriver = "Drupal\ctools\Plugin\Deriver\EntityViewDeriver",
|
||||
* )
|
||||
*/
|
||||
class EntityView extends BlockBase implements ContextAwarePluginInterface, ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* The entity manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityManagerInterface
|
||||
*/
|
||||
protected $entityManager;
|
||||
|
||||
/**
|
||||
* Constructs a new EntityView.
|
||||
*
|
||||
* @param array $configuration
|
||||
* A configuration array containing information about the plugin instance.
|
||||
* @param string $plugin_id
|
||||
* The plugin ID for the plugin instance.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityManagerInterface $entity_manager) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
|
||||
$this->entityManager = $entity_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('entity.manager')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defaultConfiguration() {
|
||||
return [
|
||||
'view_mode' => 'default',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function blockForm($form, FormStateInterface $form_state) {
|
||||
$form['view_mode'] = [
|
||||
'#type' => 'select',
|
||||
'#options' => $this->entityManager->getViewModeOptions($this->getDerivativeId()),
|
||||
'#title' => $this->t('View mode'),
|
||||
'#default_value' => $this->configuration['view_mode'],
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function blockSubmit($form, FormStateInterface $form_state) {
|
||||
$this->configuration['view_mode'] = $form_state->getValue('view_mode');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function build() {
|
||||
/** @var $entity \Drupal\Core\Entity\EntityInterface */
|
||||
$entity = $this->getContextValue('entity');
|
||||
|
||||
$view_builder = $this->entityManager->getViewBuilder($entity->getEntityTypeId());
|
||||
$build = $view_builder->view($entity, $this->configuration['view_mode']);
|
||||
|
||||
CacheableMetadata::createFromObject($this->getContext('entity'))
|
||||
->applyTo($build);
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin;
|
||||
|
||||
use Drupal\Core\Block\BlockPluginInterface;
|
||||
use Drupal\Core\Plugin\DefaultLazyPluginCollection;
|
||||
|
||||
/**
|
||||
* Provides a collection of block plugins.
|
||||
*/
|
||||
class BlockPluginCollection extends DefaultLazyPluginCollection {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return \Drupal\Core\Block\BlockPluginInterface
|
||||
*/
|
||||
public function &get($instance_id) {
|
||||
return parent::get($instance_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all blocks keyed by their region.
|
||||
*
|
||||
* @return array
|
||||
* An associative array keyed by region, containing an associative array of
|
||||
* block plugins.
|
||||
*/
|
||||
public function getAllByRegion() {
|
||||
$region_assignments = [];
|
||||
foreach ($this as $block_id => $block) {
|
||||
$configuration = $block->getConfiguration();
|
||||
$region = isset($configuration['region']) ? $configuration['region'] : NULL;
|
||||
$region_assignments[$region][$block_id] = $block;
|
||||
}
|
||||
foreach ($region_assignments as $region => $region_assignment) {
|
||||
// @todo Determine the reason this needs error suppression.
|
||||
@uasort($region_assignment, function (BlockPluginInterface $a, BlockPluginInterface $b) {
|
||||
$a_config = $a->getConfiguration();
|
||||
$a_weight = isset($a_config['weight']) ? $a_config['weight'] : 0;
|
||||
$b_config = $b->getConfiguration();
|
||||
$b_weight = isset($b_config['weight']) ? $b_config['weight'] : 0;
|
||||
if ($a_weight == $b_weight) {
|
||||
return strcmp($a->label(), $b->label());
|
||||
}
|
||||
return $a_weight > $b_weight ? 1 : -1;
|
||||
});
|
||||
$region_assignments[$region] = $region_assignment;
|
||||
}
|
||||
return $region_assignments;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin;
|
||||
|
||||
use Drupal\Core\Display\VariantInterface;
|
||||
|
||||
/**
|
||||
* Provides an interface for variant plugins that use block plugins.
|
||||
*/
|
||||
interface BlockVariantInterface extends VariantInterface {
|
||||
|
||||
/**
|
||||
* Returns the human-readable list of regions keyed by machine name.
|
||||
*
|
||||
* @return array
|
||||
* An array of human-readable region names keyed by machine name.
|
||||
*/
|
||||
public function getRegionNames();
|
||||
|
||||
/**
|
||||
* Returns the human-readable name of a specific region.
|
||||
*
|
||||
* @param string $region
|
||||
* The machine name of a region.
|
||||
*
|
||||
* @return string
|
||||
* The human-readable name of a region.
|
||||
*/
|
||||
public function getRegionName($region);
|
||||
|
||||
/**
|
||||
* Adds a block to this display variant.
|
||||
*
|
||||
* @param array $configuration
|
||||
* An array of block configuration.
|
||||
*
|
||||
* @return string
|
||||
* The block ID.
|
||||
*/
|
||||
public function addBlock(array $configuration);
|
||||
|
||||
/**
|
||||
* Returns the region a specific block is assigned to.
|
||||
*
|
||||
* @param string $block_id
|
||||
* The block ID.
|
||||
*
|
||||
* @return string
|
||||
* The machine name of the region this block is assigned to.
|
||||
*/
|
||||
public function getRegionAssignment($block_id);
|
||||
|
||||
/**
|
||||
* Returns an array of regions and their block plugins.
|
||||
*
|
||||
* @return array
|
||||
* The array is first keyed by region machine name, with the values
|
||||
* containing an array keyed by block ID, with block plugin instances as the
|
||||
* values.
|
||||
*/
|
||||
public function getRegionAssignments();
|
||||
|
||||
/**
|
||||
* Returns a specific block plugin.
|
||||
*
|
||||
* @param string $block_id
|
||||
* The block ID.
|
||||
*
|
||||
* @return \Drupal\Core\Block\BlockPluginInterface
|
||||
* The block plugin.
|
||||
*/
|
||||
public function getBlock($block_id);
|
||||
|
||||
/**
|
||||
* Updates the configuration of a specific block plugin.
|
||||
*
|
||||
* @param string $block_id
|
||||
* The block ID.
|
||||
* @param array $configuration
|
||||
* The array of configuration to set.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function updateBlock($block_id, array $configuration);
|
||||
|
||||
/**
|
||||
* Removes a specific block from this display variant.
|
||||
*
|
||||
* @param string $block_id
|
||||
* The block ID.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function removeBlock($block_id);
|
||||
|
||||
}
|
130
web/modules/contrib/ctools/src/Plugin/BlockVariantTrait.php
Normal file
130
web/modules/contrib/ctools/src/Plugin/BlockVariantTrait.php
Normal file
|
@ -0,0 +1,130 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin;
|
||||
|
||||
/**
|
||||
* Provides methods for \Drupal\ctools\Plugin\BlockVariantInterface.
|
||||
*/
|
||||
trait BlockVariantTrait {
|
||||
|
||||
/**
|
||||
* The block manager.
|
||||
*
|
||||
* @var \Drupal\Core\Block\BlockManager
|
||||
*/
|
||||
protected $blockManager;
|
||||
|
||||
/**
|
||||
* The plugin collection that holds the block plugins.
|
||||
*
|
||||
* @var \Drupal\ctools\Plugin\BlockPluginCollection
|
||||
*/
|
||||
protected $blockPluginCollection;
|
||||
|
||||
/**
|
||||
* @see \Drupal\ctools\Plugin\BlockVariantInterface::getRegionNames()
|
||||
*/
|
||||
abstract public function getRegionNames();
|
||||
|
||||
/**
|
||||
* @see \Drupal\ctools\Plugin\BlockVariantInterface::getBlock()
|
||||
*/
|
||||
public function getBlock($block_id) {
|
||||
return $this->getBlockCollection()->get($block_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \Drupal\ctools\Plugin\BlockVariantInterface::addBlock()
|
||||
*/
|
||||
public function addBlock(array $configuration) {
|
||||
$configuration['uuid'] = $this->uuidGenerator()->generate();
|
||||
$this->getBlockCollection()->addInstanceId($configuration['uuid'], $configuration);
|
||||
return $configuration['uuid'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \Drupal\ctools\Plugin\BlockVariantInterface::removeBlock()
|
||||
*/
|
||||
public function removeBlock($block_id) {
|
||||
$this->getBlockCollection()->removeInstanceId($block_id);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \Drupal\ctools\Plugin\BlockVariantInterface::updateBlock()
|
||||
*/
|
||||
public function updateBlock($block_id, array $configuration) {
|
||||
$existing_configuration = $this->getBlock($block_id)->getConfiguration();
|
||||
$this->getBlockCollection()->setInstanceConfiguration($block_id, $configuration + $existing_configuration);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \Drupal\ctools\Plugin\BlockVariantInterface::getRegionAssignment()
|
||||
*/
|
||||
public function getRegionAssignment($block_id) {
|
||||
$configuration = $this->getBlock($block_id)->getConfiguration();
|
||||
return isset($configuration['region']) ? $configuration['region'] : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \Drupal\ctools\Plugin\BlockVariantInterface::getRegionAssignments()
|
||||
*/
|
||||
public function getRegionAssignments() {
|
||||
// Build an array of the region names in the right order.
|
||||
$empty = array_fill_keys(array_keys($this->getRegionNames()), []);
|
||||
$full = $this->getBlockCollection()->getAllByRegion();
|
||||
// Merge it with the actual values to maintain the ordering.
|
||||
return array_intersect_key(array_merge($empty, $full), $empty);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \Drupal\ctools\Plugin\BlockVariantInterface::getRegionName()
|
||||
*/
|
||||
public function getRegionName($region) {
|
||||
$regions = $this->getRegionNames();
|
||||
return isset($regions[$region]) ? $regions[$region] : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the block plugin manager.
|
||||
*
|
||||
* @return \Drupal\Core\Block\BlockManager
|
||||
* The block plugin manager.
|
||||
*/
|
||||
protected function getBlockManager() {
|
||||
if (!$this->blockManager) {
|
||||
$this->blockManager = \Drupal::service('plugin.manager.block');
|
||||
}
|
||||
return $this->blockManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the block plugins used for this display variant.
|
||||
*
|
||||
* @return \Drupal\Core\Block\BlockPluginInterface[]|\Drupal\ctools\Plugin\BlockPluginCollection
|
||||
* An array or collection of configured block plugins.
|
||||
*/
|
||||
protected function getBlockCollection() {
|
||||
if (!$this->blockPluginCollection) {
|
||||
$this->blockPluginCollection = new BlockPluginCollection($this->getBlockManager(), $this->getBlockConfig());
|
||||
}
|
||||
return $this->blockPluginCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the UUID generator.
|
||||
*
|
||||
* @return \Drupal\Component\Uuid\UuidInterface
|
||||
*/
|
||||
abstract protected function uuidGenerator();
|
||||
|
||||
/**
|
||||
* Returns the configuration for stored blocks.
|
||||
*
|
||||
* @return array
|
||||
* An array of block configuration, keyed by the unique block ID.
|
||||
*/
|
||||
abstract protected function getBlockConfig();
|
||||
|
||||
}
|
160
web/modules/contrib/ctools/src/Plugin/Condition/EntityBundle.php
Normal file
160
web/modules/contrib/ctools/src/Plugin/Condition/EntityBundle.php
Normal file
|
@ -0,0 +1,160 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin\Condition;
|
||||
|
||||
use Drupal\Core\Condition\ConditionPluginBase;
|
||||
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\ctools\ConstraintConditionInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides a 'Entity Bundle' condition.
|
||||
*
|
||||
* @Condition(
|
||||
* id = "entity_bundle",
|
||||
* deriver = "\Drupal\ctools\Plugin\Deriver\EntityBundle"
|
||||
* )
|
||||
*
|
||||
*/
|
||||
class EntityBundle extends ConditionPluginBase implements ConstraintConditionInterface, ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* The entity type bundle info service.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
|
||||
*/
|
||||
protected $entityTypeBundleInfo;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Entity\EntityTypeInterface|null
|
||||
*/
|
||||
protected $bundleOf;
|
||||
|
||||
/**
|
||||
* Creates a new EntityBundle instance.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
||||
* The entity type manager.
|
||||
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
|
||||
* The entity type bundle info service.
|
||||
* @param array $configuration
|
||||
* The plugin configuration, i.e. an array with configuration values keyed
|
||||
* by configuration option name. The special key 'context' may be used to
|
||||
* initialize the defined contexts by setting it to an array of context
|
||||
* values keyed by context names.
|
||||
* @param string $plugin_id
|
||||
* The plugin_id for the plugin instance.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
*/
|
||||
public function __construct(EntityTypeManagerInterface $entity_type_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info, array $configuration, $plugin_id, $plugin_definition) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->entityTypeBundleInfo = $entity_type_bundle_info;
|
||||
$this->bundleOf = $entity_type_manager->getDefinition($this->getDerivativeId());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$container->get('entity_type.manager'),
|
||||
$container->get('entity_type.bundle.info'),
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
$options = array();
|
||||
$bundles = $this->entityTypeBundleInfo->getBundleInfo($this->bundleOf->id());
|
||||
foreach ($bundles as $id => $info) {
|
||||
$options[$id] = $info['label'];
|
||||
}
|
||||
$form['bundles'] = array(
|
||||
'#title' => $this->pluginDefinition['label'],
|
||||
'#type' => 'checkboxes',
|
||||
'#options' => $options,
|
||||
'#default_value' => $this->configuration['bundles'],
|
||||
);
|
||||
return parent::buildConfigurationForm($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
|
||||
$this->configuration['bundles'] = array_filter($form_state->getValue('bundles'));
|
||||
parent::submitConfigurationForm($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function evaluate() {
|
||||
if (empty($this->configuration['bundles']) && !$this->isNegated()) {
|
||||
return TRUE;
|
||||
}
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
|
||||
$entity = $this->getContextValue($this->bundleOf->id());
|
||||
return !empty($this->configuration['bundles'][$entity->bundle()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function summary() {
|
||||
if (count($this->configuration['bundles']) > 1) {
|
||||
$bundles = $this->configuration['bundles'];
|
||||
$last = array_pop($bundles);
|
||||
$bundles = implode(', ', $bundles);
|
||||
return $this->t('@bundle_type is @bundles or @last', array('@bundle_type' => $this->bundleOf->getBundleLabel(), '@bundles' => $bundles, '@last' => $last));
|
||||
}
|
||||
$bundle = reset($this->configuration['bundles']);
|
||||
return $this->t('@bundle_type is @bundle', array('@bundle_type' => $this->bundleOf->getBundleLabel(), '@bundle' => $bundle));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defaultConfiguration() {
|
||||
return array('bundles' => array()) + parent::defaultConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param \Drupal\Core\Plugin\Context\ContextInterface[] $contexts
|
||||
*/
|
||||
public function applyConstraints(array $contexts = array()) {
|
||||
// Nullify any bundle constraints on contexts we care about.
|
||||
$this->removeConstraints($contexts);
|
||||
$bundle = array_values($this->configuration['bundles']);
|
||||
// There's only one expected context for this plugint type.
|
||||
foreach ($this->getContextMapping() as $definition_id => $context_id) {
|
||||
$contexts[$context_id]->getContextDefinition()->addConstraint('Bundle', ['value' => $bundle]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param \Drupal\Core\Plugin\Context\ContextInterface[] $contexts
|
||||
*/
|
||||
public function removeConstraints(array $contexts = array()) {
|
||||
// Reset the bundle constraint for any context we've mapped.
|
||||
foreach ($this->getContextMapping() as $definition_id => $context_id) {
|
||||
$constraints = $contexts[$context_id]->getContextDefinition()->getConstraints();
|
||||
unset($constraints['Bundle']);
|
||||
$contexts[$context_id]->getContextDefinition()->setConstraints($constraints);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
41
web/modules/contrib/ctools/src/Plugin/Condition/NodeType.php
Normal file
41
web/modules/contrib/ctools/src/Plugin/Condition/NodeType.php
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin\Condition;
|
||||
|
||||
use Drupal\node\Plugin\Condition\NodeType as CoreNodeType;
|
||||
use Drupal\ctools\ConstraintConditionInterface;
|
||||
|
||||
class NodeType extends CoreNodeType implements ConstraintConditionInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param \Drupal\Core\Plugin\Context\ContextInterface[] $contexts
|
||||
*/
|
||||
public function applyConstraints(array $contexts = array()) {
|
||||
// Nullify any bundle constraints on contexts we care about.
|
||||
$this->removeConstraints($contexts);
|
||||
// If a single bundle is configured, we can set a proper constraint.
|
||||
if (count($this->configuration['bundles']) == 1) {
|
||||
$bundle = array_values($this->configuration['bundles']);
|
||||
foreach ($this->getContextMapping() as $definition_id => $context_id) {
|
||||
$contexts[$context_id]->getContextDefinition()->addConstraint('Bundle', ['value' => $bundle[0]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param \Drupal\Core\Plugin\Context\ContextInterface[] $contexts
|
||||
*/
|
||||
public function removeConstraints(array $contexts = array()) {
|
||||
// Reset the bundle constraint for any context we've mapped.
|
||||
foreach ($this->getContextMapping() as $definition_id => $context_id) {
|
||||
$constraints = $contexts[$context_id]->getContextDefinition()->getConstraints();
|
||||
unset($constraints['Bundle']);
|
||||
$contexts[$context_id]->getContextDefinition()->setConstraints($constraints);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin\Deriver;
|
||||
|
||||
use Drupal\Core\Plugin\Context\ContextDefinition;
|
||||
|
||||
/**
|
||||
* Deriver that creates a condition for each entity type with bundles.
|
||||
*/
|
||||
class EntityBundle extends EntityDeriverBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDerivativeDefinitions($base_plugin_definition) {
|
||||
foreach ($this->entityManager->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);
|
||||
$this->derivatives[$entity_type_id]['context'] = [
|
||||
"$entity_type_id" => new ContextDefinition('entity:' . $entity_type_id),
|
||||
];
|
||||
}
|
||||
}
|
||||
return $this->derivatives;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the bundle label with a fallback when not defined.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type we are looking the bundle label for.
|
||||
*
|
||||
* @return \Drupal\Core\StringTranslation\TranslatableMarkup
|
||||
* The entity bundle label or a fallback label.
|
||||
*/
|
||||
protected function getEntityBundleLabel($entity_type) {
|
||||
|
||||
if ($label = $entity_type->getBundleLabel()) {
|
||||
return $this->t('@label', ['@label' => $label]);
|
||||
}
|
||||
|
||||
$fallback = $entity_type->getLabel();
|
||||
if ($bundle_entity_type = $entity_type->getBundleEntityType()) {
|
||||
// This is a better fallback.
|
||||
$fallback = $this->entityManager->getDefinition($bundle_entity_type)->getLabel();
|
||||
}
|
||||
|
||||
return $this->t('@label bundle', ['@label' => $fallback]);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin\Deriver;
|
||||
|
||||
|
||||
use Drupal\Component\Plugin\Derivative\DeriverBase;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\Core\StringTranslation\TranslationInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* An abstract base class that sets up the needs of entity specific derivers.
|
||||
*/
|
||||
abstract class EntityDeriverBase extends DeriverBase implements ContainerDeriverInterface {
|
||||
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* The entity manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityManagerInterface
|
||||
*/
|
||||
protected $entityManager;
|
||||
|
||||
/**
|
||||
* Constructs new EntityViewDeriver.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
|
||||
* The string translation service.
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $entity_manager, TranslationInterface $string_translation) {
|
||||
$this->entityManager = $entity_manager;
|
||||
$this->stringTranslation = $string_translation;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, $base_plugin_id) {
|
||||
return new static(
|
||||
$container->get('entity.manager'),
|
||||
$container->get('string_translation')
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin\Deriver;
|
||||
|
||||
use Drupal\Core\Plugin\Context\ContextDefinition;
|
||||
|
||||
/**
|
||||
* Provides entity view block definitions for each entity type.
|
||||
*/
|
||||
class EntityViewDeriver extends EntityDeriverBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDerivativeDefinitions($base_plugin_definition) {
|
||||
foreach ($this->entityManager->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()]);
|
||||
$this->derivatives[$entity_type_id]['context'] = [
|
||||
'entity' => new ContextDefinition('entity:' . $entity_type_id),
|
||||
];
|
||||
}
|
||||
}
|
||||
return $this->derivatives;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin\Deriver;
|
||||
|
||||
|
||||
use Drupal\Core\TypedData\DataDefinitionInterface;
|
||||
|
||||
class TypedDataEntityRelationshipDeriver extends TypedDataRelationshipDeriver {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $label = '@property Entity from @base';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generateDerivativeDefinition($base_plugin_definition, $data_type_id, $data_type_definition, DataDefinitionInterface $base_definition, $property_name, DataDefinitionInterface $property_definition) {
|
||||
if (method_exists($property_definition, 'getType') && $property_definition->getType() == 'entity_reference') {
|
||||
parent::generateDerivativeDefinition($base_plugin_definition, $data_type_id, $data_type_definition, $base_definition, $property_name, $property_definition);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin\Deriver;
|
||||
|
||||
|
||||
use Drupal\Core\TypedData\DataDefinitionInterface;
|
||||
|
||||
class TypedDataLanguageRelationshipDeriver extends TypedDataRelationshipDeriver {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @todo this results in awful labels like "Language Language from Content"
|
||||
* Fix it.
|
||||
*/
|
||||
protected $label = '@property Language from @base';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generateDerivativeDefinition($base_plugin_definition, $data_type_id, $data_type_definition, DataDefinitionInterface $base_definition, $property_name, DataDefinitionInterface $property_definition) {
|
||||
if (method_exists($property_definition, 'getType') && $property_definition->getType() == 'language') {
|
||||
parent::generateDerivativeDefinition($base_plugin_definition, $data_type_id, $data_type_definition, $base_definition, $property_name, $property_definition);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDerivativeDefinitions($base_plugin_definition) {
|
||||
parent::getDerivativeDefinitions($base_plugin_definition);
|
||||
// The data types will all be set to string since language extends string
|
||||
// and the parent class finds the related primitive.
|
||||
foreach ($this->derivatives as $plugin_id => $derivative) {
|
||||
$this->derivatives[$plugin_id]['data_type'] = 'language';
|
||||
}
|
||||
return $this->derivatives;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin\Deriver;
|
||||
|
||||
|
||||
use Drupal\Component\Plugin\Derivative\DeriverBase;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\Core\StringTranslation\TranslationInterface;
|
||||
use Drupal\Core\TypedData\ComplexDataInterface;
|
||||
use Drupal\Core\TypedData\DataDefinitionInterface;
|
||||
use Drupal\Core\TypedData\DataReferenceDefinitionInterface;
|
||||
use Drupal\Core\TypedData\ListDataDefinitionInterface;
|
||||
use Drupal\Core\TypedData\TypedDataManagerInterface;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
abstract class TypedDataPropertyDeriverBase extends DeriverBase implements ContainerDeriverInterface {
|
||||
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\TypedData\TypedDataManagerInterface
|
||||
*/
|
||||
protected $typedDataManager;
|
||||
|
||||
/**
|
||||
* The label string for use with derivative labels.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $label = '@property from @base';
|
||||
|
||||
/**
|
||||
* TypedDataPropertyDeriverBase constructor.
|
||||
*
|
||||
* @param \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data_manager
|
||||
* The typed data manager.
|
||||
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
|
||||
* The string translation service.
|
||||
*/
|
||||
public function __construct(TypedDataManagerInterface $typed_data_manager, TranslationInterface $string_translation) {
|
||||
$this->typedDataManager = $typed_data_manager;
|
||||
$this->stringTranslation = $string_translation;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, $base_plugin_id) {
|
||||
return new static(
|
||||
$container->get('typed_data_manager'),
|
||||
$container->get('string_translation')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDerivativeDefinitions($base_plugin_definition) {
|
||||
foreach ($this->typedDataManager->getDefinitions() as $data_type_id => $data_type_definition) {
|
||||
if (is_subclass_of($data_type_definition['class'], ComplexDataInterface::class, TRUE)) {
|
||||
/** @var \Drupal\Core\TypedData\ComplexDataDefinitionInterface $base_definition */
|
||||
$base_definition = $this->typedDataManager->createDataDefinition($data_type_id);
|
||||
foreach ($base_definition->getPropertyDefinitions() as $property_name => $property_definition) {
|
||||
if ($property_definition instanceof BaseFieldDefinition || $property_definition instanceof FieldConfig) {
|
||||
$this->generateDerivativeDefinition($base_plugin_definition, $data_type_id, $data_type_definition, $base_definition, $property_name, $property_definition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->derivatives;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $property_definition
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getDataType($property_definition) {
|
||||
if ($property_definition instanceof DataReferenceDefinitionInterface) {
|
||||
return $property_definition->getTargetDefinition()->getDataType();
|
||||
}
|
||||
if ($property_definition instanceof ListDataDefinitionInterface) {
|
||||
return $property_definition->getItemDefinition()->getDataType();
|
||||
}
|
||||
return $property_definition->getDataType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates and maintains a derivative definition.
|
||||
*
|
||||
* This method should directly manipulate $this->derivatives and not return
|
||||
* values. This allows implementations control over the derivative names.
|
||||
*
|
||||
* @param $base_plugin_definition
|
||||
* The base plugin definition.
|
||||
* @param string $data_type_id
|
||||
* The plugin id of the data type.
|
||||
* @param mixed $data_type_definition
|
||||
* The plugin definition of the data type.
|
||||
* @param \Drupal\Core\TypedData\DataDefinitionInterface $base_definition
|
||||
* The data type definition of a complex data object.
|
||||
* @param string $property_name
|
||||
* The name of the property
|
||||
* @param \Drupal\Core\TypedData\DataDefinitionInterface $property_definition
|
||||
* The property definition.
|
||||
*
|
||||
*/
|
||||
abstract protected function generateDerivativeDefinition($base_plugin_definition, $data_type_id, $data_type_definition, DataDefinitionInterface $base_definition, $property_name, DataDefinitionInterface $property_definition);
|
||||
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin\Deriver;
|
||||
|
||||
|
||||
use Drupal\Core\Plugin\Context\ContextDefinition;
|
||||
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
|
||||
use Drupal\Core\TypedData\DataDefinitionInterface;
|
||||
use Drupal\field\FieldConfigInterface;
|
||||
|
||||
class TypedDataRelationshipDeriver extends TypedDataPropertyDeriverBase implements ContainerDeriverInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generateDerivativeDefinition($base_plugin_definition, $data_type_id, $data_type_definition, DataDefinitionInterface $base_definition, $property_name, DataDefinitionInterface $property_definition) {
|
||||
$bundle_info = $base_definition->getConstraint('Bundle');
|
||||
// Identify base definitions that appear on bundle-able entities.
|
||||
if ($bundle_info && array_filter($bundle_info) && $base_definition->getConstraint('EntityType')) {
|
||||
$base_data_type = 'entity:' . $base_definition->getConstraint('EntityType');
|
||||
}
|
||||
// Otherwise, just use the raw data type identifier.
|
||||
else {
|
||||
$base_data_type = $data_type_id;
|
||||
}
|
||||
// If we've not processed this thing before.
|
||||
if (!isset($this->derivatives[$base_data_type . ':' . $property_name])) {
|
||||
$derivative = $base_plugin_definition;
|
||||
|
||||
$derivative['label'] = $this->t($this->label, [
|
||||
'@property' => $property_definition->getLabel(),
|
||||
'@base' => $data_type_definition['label'],
|
||||
]);
|
||||
$derivative['data_type'] = $property_definition->getFieldStorageDefinition()->getPropertyDefinition($property_definition->getFieldStorageDefinition()->getMainPropertyName())->getDataType();
|
||||
$derivative['property_name'] = $property_name;
|
||||
$context_definition = new ContextDefinition($base_data_type, $this->typedDataManager->createDataDefinition($base_data_type));
|
||||
// Add the constraints of the base definition to the context definition.
|
||||
if ($base_definition->getConstraint('Bundle')) {
|
||||
$context_definition->addConstraint('Bundle', $base_definition->getConstraint('Bundle'));
|
||||
}
|
||||
$derivative['context'] = [
|
||||
'base' => $context_definition,
|
||||
];
|
||||
$derivative['property_name'] = $property_name;
|
||||
|
||||
$this->derivatives[$base_data_type . ':' . $property_name] = $derivative;
|
||||
}
|
||||
// Individual fields can be on multiple bundles.
|
||||
elseif ($property_definition instanceof FieldConfigInterface) {
|
||||
// We should only end up in here on entity bundles.
|
||||
$derivative = $this->derivatives[$base_data_type . ':' . $property_name];
|
||||
// Update label
|
||||
/** @var \Drupal\Core\StringTranslation\TranslatableMarkup $label */
|
||||
$label = $derivative['label'];
|
||||
list(,, $argument_name) = explode(':', $data_type_id);
|
||||
$arguments = $label->getArguments();
|
||||
$arguments['@'. $argument_name] = $data_type_definition['label'];
|
||||
$string_args = $arguments;
|
||||
array_shift($string_args);
|
||||
$last = array_slice($string_args, -1);
|
||||
// The slice doesn't remove, so do that now.
|
||||
array_pop($string_args);
|
||||
$string = count($string_args) >= 2 ? '@property from '. implode(', ', array_keys($string_args)) .' and '. array_keys($last)[0] : '@property from @base and '. array_keys($last)[0];
|
||||
$this->derivatives[$base_data_type . ':' . $property_name]['label'] = $this->t($string, $arguments);
|
||||
if ($base_definition->getConstraint('Bundle')) {
|
||||
// Add bundle constraints
|
||||
$context_definition = $derivative['context']['base'];
|
||||
$bundles = $context_definition->getConstraint('Bundle') ?: [];
|
||||
$bundles = array_merge($bundles, $base_definition->getConstraint('Bundle'));
|
||||
$context_definition->addConstraint('Bundle', $bundles);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,226 @@
|
|||
<?php
|
||||
|
||||
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;
|
||||
use Drupal\ctools\Plugin\BlockVariantInterface;
|
||||
use Drupal\ctools\Plugin\BlockVariantTrait;
|
||||
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 {
|
||||
|
||||
use AjaxFormTrait;
|
||||
use BlockVariantTrait;
|
||||
|
||||
/**
|
||||
* The context handler.
|
||||
*
|
||||
* @var \Drupal\Core\Plugin\Context\ContextHandlerInterface
|
||||
*/
|
||||
protected $contextHandler;
|
||||
|
||||
/**
|
||||
* The UUID generator.
|
||||
*
|
||||
* @var \Drupal\Component\Uuid\UuidInterface
|
||||
*/
|
||||
protected $uuidGenerator;
|
||||
|
||||
/**
|
||||
* The current user.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $account;
|
||||
|
||||
/**
|
||||
* The token service.
|
||||
*
|
||||
* @var \Drupal\Core\Utility\Token
|
||||
*/
|
||||
protected $token;
|
||||
|
||||
/**
|
||||
* An array of collected contexts.
|
||||
*
|
||||
* This is only used on runtime, and is not stored.
|
||||
*
|
||||
* @var \Drupal\Component\Plugin\Context\ContextInterface[]
|
||||
*/
|
||||
protected $contexts = [];
|
||||
|
||||
/**
|
||||
* Constructs a new BlockDisplayVariant.
|
||||
*
|
||||
* @param array $configuration
|
||||
* A configuration array containing information about the plugin instance.
|
||||
* @param string $plugin_id
|
||||
* The plugin ID for the plugin instance.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
* @param \Drupal\Core\Plugin\Context\ContextHandlerInterface $context_handler
|
||||
* The context handler.
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The current user.
|
||||
* @param \Drupal\Component\Uuid\UuidInterface $uuid_generator
|
||||
* The UUID generator.
|
||||
* @param \Drupal\Core\Utility\Token $token
|
||||
* The token service.
|
||||
* @param \Drupal\Core\Block\BlockManager $block_manager
|
||||
* The block manager.
|
||||
* @param \Drupal\Core\Condition\ConditionManager $condition_manager
|
||||
* The condition manager.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, ContextHandlerInterface $context_handler, AccountInterface $account, UuidInterface $uuid_generator, Token $token, BlockManager $block_manager, ConditionManager $condition_manager) {
|
||||
// Inject dependencies as early as possible, so they can be used in
|
||||
// configuration.
|
||||
$this->contextHandler = $context_handler;
|
||||
$this->account = $account;
|
||||
$this->uuidGenerator = $uuid_generator;
|
||||
$this->token = $token;
|
||||
$this->blockManager = $block_manager;
|
||||
$this->conditionManager = $condition_manager;
|
||||
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('context.handler'),
|
||||
$container->get('current_user'),
|
||||
$container->get('uuid'),
|
||||
$container->get('token'),
|
||||
$container->get('plugin.manager.block'),
|
||||
$container->get('plugin.manager.condition')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defaultConfiguration() {
|
||||
return parent::defaultConfiguration() + [
|
||||
'blocks' => []
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function calculateDependencies() {
|
||||
foreach ($this->getBlockCollection() as $instance) {
|
||||
$this->calculatePluginDependencies($instance);
|
||||
}
|
||||
return $this->dependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getConfiguration() {
|
||||
return [
|
||||
'blocks' => $this->getBlockCollection()->getConfiguration(),
|
||||
] + parent::getConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setConfiguration(array $configuration) {
|
||||
// preserve the uuid.
|
||||
if ($this->configuration && !empty($this->configuration['uuid'])) {
|
||||
$configuration['uuid'] = $this->configuration['uuid'];
|
||||
}
|
||||
parent::setConfiguration($configuration);
|
||||
$this->getBlockCollection()->setConfiguration($this->configuration['blocks']);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the contexts.
|
||||
*
|
||||
* @return \Drupal\Component\Plugin\Context\ContextInterface[]
|
||||
* An array of set contexts, keyed by context name.
|
||||
*/
|
||||
public function getContexts() {
|
||||
return $this->contexts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the contexts.
|
||||
*
|
||||
* @param \Drupal\Component\Plugin\Context\ContextInterface[] $contexts
|
||||
* An array of contexts, keyed by context name.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setContexts(array $contexts) {
|
||||
$this->contexts = $contexts;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function contextHandler() {
|
||||
return $this->contextHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getBlockConfig() {
|
||||
return $this->configuration['blocks'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function uuidGenerator() {
|
||||
return $this->uuidGenerator;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __sleep() {
|
||||
$vars = parent::__sleep();
|
||||
|
||||
// Gathered contexts objects should not be serialized.
|
||||
if (($key = array_search('contexts', $vars)) !== FALSE) {
|
||||
unset($vars[$key]);
|
||||
}
|
||||
|
||||
// The block plugin collection should also not be serialized, ensure that
|
||||
// configuration is synced back.
|
||||
if (($key = array_search('blockPluginCollection', $vars)) !== FALSE) {
|
||||
if ($this->blockPluginCollection) {
|
||||
$this->configuration['blocks'] = $this->blockPluginCollection->getConfiguration();
|
||||
}
|
||||
unset($vars[$key]);
|
||||
}
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin;
|
||||
|
||||
/**
|
||||
* Provides an interface for configuring a plugin via wizard steps.
|
||||
*/
|
||||
interface PluginWizardInterface {
|
||||
|
||||
/**
|
||||
* Retrieve a list of FormInterface classes by their step key in the wizard.
|
||||
*
|
||||
* @param mixed $cached_values
|
||||
* The cached values used in the wizard. The plugin we're editing will
|
||||
* always be assigned to the 'plugin' key.
|
||||
*
|
||||
* @return array
|
||||
* An associative array keyed on the step name with an array value with the
|
||||
* following keys:
|
||||
* - title (string): Human-readable title of the step.
|
||||
* - form (string): Fully-qualified class name of the form for this step.
|
||||
*/
|
||||
public function getWizardOperations($cached_values);
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin\Relationship;
|
||||
use Drupal\Core\Plugin\Context\Context;
|
||||
use Drupal\Core\Plugin\Context\ContextDefinition;
|
||||
|
||||
/**
|
||||
* @Relationship(
|
||||
* id = "typed_data_entity_relationship",
|
||||
* deriver = "\Drupal\ctools\Plugin\Deriver\TypedDataEntityRelationshipDeriver"
|
||||
* )
|
||||
*/
|
||||
class TypedDataEntityRelationship extends TypedDataRelationship {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRelationship() {
|
||||
$plugin_definition = $this->getPluginDefinition();
|
||||
|
||||
$entity_type = $this->getData($this->getContext('base'))->getDataDefinition()->getSetting('target_type');
|
||||
$context_definition = new ContextDefinition("entity:$entity_type", $plugin_definition['label']);
|
||||
$context_value = NULL;
|
||||
|
||||
// If the 'base' context has a value, then get the property value to put on
|
||||
// the context (otherwise, mapping hasn't occurred yet and we just want to
|
||||
// return the context with the right definition and no value).
|
||||
if ($this->getContext('base')->hasContextValue()) {
|
||||
$context_value = $this->getData($this->getContext('base'))->entity;
|
||||
}
|
||||
|
||||
$context_definition->setDefaultValue($context_value);
|
||||
return new Context($context_definition, $context_value);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin\Relationship;
|
||||
use Drupal\Core\Plugin\Context\Context;
|
||||
use Drupal\Core\Plugin\Context\ContextDefinition;
|
||||
|
||||
/**
|
||||
* @Relationship(
|
||||
* id = "typed_data_language_relationship",
|
||||
* deriver = "\Drupal\ctools\Plugin\Deriver\TypedDataLanguageRelationshipDeriver"
|
||||
* )
|
||||
*/
|
||||
class TypedDataLanguageRelationship extends TypedDataRelationship {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRelationship() {
|
||||
$plugin_definition = $this->getPluginDefinition();
|
||||
|
||||
$context_definition = new ContextDefinition("language", $plugin_definition['label']);
|
||||
$context_value = NULL;
|
||||
|
||||
// If the 'base' context has a value, then get the property value to put on
|
||||
// the context (otherwise, mapping hasn't occurred yet and we just want to
|
||||
// return the context with the right definition and no value).
|
||||
if ($this->getContext('base')->hasContextValue()) {
|
||||
$context_value = $this->getData($this->getContext('base'))->language;
|
||||
}
|
||||
|
||||
$context_definition->setDefaultValue($context_value);
|
||||
return new Context($context_definition, $context_value);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
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;
|
||||
use Drupal\Core\TypedData\DataReferenceInterface;
|
||||
use Drupal\Core\TypedData\ListInterface;
|
||||
use Drupal\ctools\Annotation\Relationship;
|
||||
use Drupal\ctools\Plugin\RelationshipBase;
|
||||
|
||||
/**
|
||||
* @Relationship(
|
||||
* id = "typed_data_relationship",
|
||||
* deriver = "\Drupal\ctools\Plugin\Deriver\TypedDataRelationshipDeriver"
|
||||
* )
|
||||
*/
|
||||
class TypedDataRelationship extends RelationshipBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRelationship() {
|
||||
$plugin_definition = $this->getPluginDefinition();
|
||||
|
||||
$data_type = $plugin_definition['data_type'];
|
||||
$context_definition = new ContextDefinition($data_type, $plugin_definition['label']);
|
||||
$context_value = NULL;
|
||||
|
||||
// If the 'base' context has a value, then get the property value to put on
|
||||
// the context (otherwise, mapping hasn't occurred yet and we just want to
|
||||
// return the context with the right definition and no value).
|
||||
if ($this->getContext('base')->hasContextValue()) {
|
||||
$data = $this->getData($this->getContext('base'));
|
||||
$property = $this->getMainPropertyName($data);
|
||||
$context_value = $data->get($property)->getValue();
|
||||
}
|
||||
|
||||
$context_definition->setDefaultValue($context_value);
|
||||
return new Context($context_definition, $context_value);
|
||||
}
|
||||
|
||||
public function getName() {
|
||||
return $this->getPluginDefinition()['property_name'];
|
||||
}
|
||||
|
||||
protected function getData(ContextInterface $context) {
|
||||
/** @var \Drupal\Core\TypedData\ComplexDataInterface $base */
|
||||
$base = $context->getContextValue();
|
||||
$name = $this->getPluginDefinition()['property_name'];
|
||||
$data = $base->get($name);
|
||||
// @todo add configuration to get N instead of first.
|
||||
if ($data instanceof ListInterface) {
|
||||
$data = $data->first();
|
||||
}
|
||||
if ($data instanceof DataReferenceInterface) {
|
||||
$data = $data->getTarget();
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function getMainPropertyName(FieldItemInterface $data) {
|
||||
return $data->getFieldDefinition()->getFieldStorageDefinition()->getMainPropertyName();
|
||||
}
|
||||
|
||||
public function getRelationshipValue() {
|
||||
$property = $this->getMainPropertyName();
|
||||
/** @var \Drupal\Core\TypedData\ComplexDataInterface $data */
|
||||
$data = $this->getRelationship()->getContextData();
|
||||
$data->get($property)->getValue();
|
||||
}
|
||||
|
||||
}
|
10
web/modules/contrib/ctools/src/Plugin/RelationshipBase.php
Normal file
10
web/modules/contrib/ctools/src/Plugin/RelationshipBase.php
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin;
|
||||
|
||||
use Drupal\Core\Plugin\ContextAwarePluginBase;
|
||||
|
||||
/**
|
||||
* Base class for Relationship plugins.
|
||||
*/
|
||||
abstract class RelationshipBase extends ContextAwarePluginBase implements RelationshipInterface {}
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin;
|
||||
|
||||
use Drupal\Component\Plugin\DerivativeInspectionInterface;
|
||||
use Drupal\Core\Plugin\ContextAwarePluginInterface;
|
||||
|
||||
/**
|
||||
* Defines an interface for Relationship plugins.
|
||||
*/
|
||||
interface RelationshipInterface extends ContextAwarePluginInterface, DerivativeInspectionInterface {
|
||||
|
||||
/**
|
||||
* Generates a context based on this plugin's configuration.
|
||||
*
|
||||
* @return \Drupal\Core\Plugin\Context\ContextInterface
|
||||
*/
|
||||
public function getRelationship();
|
||||
|
||||
/**
|
||||
* The name of the property used to get this relationship.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName();
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin;
|
||||
|
||||
use Drupal\Core\Plugin\Context\ContextAwarePluginManagerTrait;
|
||||
use Drupal\Core\Plugin\DefaultPluginManager;
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
|
||||
/**
|
||||
* Provides the Relationship plugin manager.
|
||||
*/
|
||||
class RelationshipManager extends DefaultPluginManager implements RelationshipManagerInterface {
|
||||
|
||||
use ContextAwarePluginManagerTrait;
|
||||
|
||||
/**
|
||||
* Constructor for RelationshipManager objects.
|
||||
*
|
||||
* @param \Traversable $namespaces
|
||||
* An object that implements \Traversable which contains the root paths
|
||||
* keyed by the corresponding namespace to look for plugin implementations.
|
||||
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
|
||||
* Cache backend instance to use.
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler to invoke the alter hook with.
|
||||
*/
|
||||
public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
|
||||
parent::__construct('Plugin/Relationship', $namespaces, $module_handler, 'Drupal\ctools\Plugin\RelationshipInterface', 'Drupal\ctools\Annotation\Relationship');
|
||||
|
||||
$this->alterInfo('ctools_relationship_info');
|
||||
$this->setCacheBackend($cache_backend, 'ctools_relationship_plugins');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin;
|
||||
use Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface;
|
||||
use Drupal\Core\Plugin\Context\ContextAwarePluginManagerInterface;
|
||||
|
||||
/**
|
||||
* Provides the Relationship plugin manager.
|
||||
*/
|
||||
interface RelationshipManagerInterface extends ContextAwarePluginManagerInterface, CachedDiscoveryInterface {}
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin;
|
||||
|
||||
/**
|
||||
* Provides an interface for objects that have variants e.g. Pages.
|
||||
*/
|
||||
interface VariantCollectionInterface {
|
||||
|
||||
/**
|
||||
* Adds a new variant to the entity.
|
||||
*
|
||||
* @param array $configuration
|
||||
* An array of configuration for the new variant.
|
||||
*
|
||||
* @return string
|
||||
* The variant ID.
|
||||
*/
|
||||
public function addVariant(array $configuration);
|
||||
|
||||
/**
|
||||
* Retrieves a specific variant.
|
||||
*
|
||||
* @param string $variant_id
|
||||
* The variant ID.
|
||||
*
|
||||
* @return \Drupal\Core\Display\VariantInterface
|
||||
* The variant object.
|
||||
*/
|
||||
public function getVariant($variant_id);
|
||||
|
||||
/**
|
||||
* Removes a specific variant.
|
||||
*
|
||||
* @param string $variant_id
|
||||
* The variant ID.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function removeVariant($variant_id);
|
||||
|
||||
/**
|
||||
* Returns the variants available for the entity.
|
||||
*
|
||||
* @return \Drupal\Core\Display\VariantInterface[]
|
||||
* An array of the variants.
|
||||
*/
|
||||
public function getVariants();
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin;
|
||||
|
||||
/**
|
||||
* Provides methods for VariantCollectionInterface.
|
||||
*/
|
||||
trait VariantCollectionTrait {
|
||||
|
||||
/**
|
||||
* The plugin collection that holds the variants.
|
||||
*
|
||||
* @var \Drupal\ctools\Plugin\VariantPluginCollection
|
||||
*/
|
||||
protected $variantCollection;
|
||||
|
||||
/**
|
||||
* @see \Drupal\ctools\Plugin\VariantCollectionInterface::addVariant()
|
||||
*/
|
||||
public function addVariant(array $configuration) {
|
||||
$configuration['uuid'] = $this->uuidGenerator()->generate();
|
||||
$this->getVariants()->addInstanceId($configuration['uuid'], $configuration);
|
||||
return $configuration['uuid'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \Drupal\ctools\Plugin\VariantCollectionInterface::getVariant()
|
||||
*/
|
||||
public function getVariant($variant_id) {
|
||||
return $this->getVariants()->get($variant_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \Drupal\ctools\Plugin\VariantCollectionInterface::removeVariant()
|
||||
*/
|
||||
public function removeVariant($variant_id) {
|
||||
$this->getVariants()->removeInstanceId($variant_id);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \Drupal\ctools\Plugin\VariantCollectionInterface::getVariants()
|
||||
*/
|
||||
public function getVariants() {
|
||||
if (!$this->variantCollection) {
|
||||
$this->variantCollection = new VariantPluginCollection(\Drupal::service('plugin.manager.display_variant'), $this->getVariantConfig());
|
||||
$this->variantCollection->sort();
|
||||
}
|
||||
return $this->variantCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configuration for stored variants.
|
||||
*
|
||||
* @return array
|
||||
* An array of variant configuration, keyed by the unique variant ID.
|
||||
*/
|
||||
abstract protected function getVariantConfig();
|
||||
|
||||
/**
|
||||
* Returns the UUID generator.
|
||||
*
|
||||
* @return \Drupal\Component\Uuid\UuidInterface
|
||||
*/
|
||||
abstract protected function uuidGenerator();
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Plugin;
|
||||
|
||||
use Drupal\Core\Plugin\DefaultLazyPluginCollection;
|
||||
|
||||
/**
|
||||
* Provides a collection of variants plugins.
|
||||
*/
|
||||
class VariantPluginCollection extends DefaultLazyPluginCollection {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return \Drupal\Core\Display\VariantInterface
|
||||
*/
|
||||
public function &get($instance_id) {
|
||||
return parent::get($instance_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function sort() {
|
||||
// @todo Determine the reason this needs error suppression.
|
||||
@uasort($this->instanceIDs, [$this, 'sortHelper']);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function sortHelper($aID, $bID) {
|
||||
$a_weight = $this->get($aID)->getWeight();
|
||||
$b_weight = $this->get($bID)->getWeight();
|
||||
if ($a_weight == $b_weight) {
|
||||
return strcmp($aID, $bID);
|
||||
}
|
||||
|
||||
return ($a_weight < $b_weight) ? -1 : 1;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Routing\Enhancer;
|
||||
|
||||
use Drupal\Core\Routing\Enhancer\RouteEnhancerInterface;
|
||||
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'));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function enhance(array $defaults, Request $request) {
|
||||
if (!empty($defaults['_wizard'])) {
|
||||
$defaults['_controller'] = 'ctools.wizard.form:getContentResult';
|
||||
}
|
||||
if (!empty($defaults['_entity_wizard'])) {
|
||||
$defaults['_controller'] = 'ctools.wizard.entity.form:getContentResult';
|
||||
}
|
||||
return $defaults;
|
||||
}
|
||||
|
||||
}
|
13
web/modules/contrib/ctools/src/SerializableTempstore.php
Normal file
13
web/modules/contrib/ctools/src/SerializableTempstore.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools;
|
||||
|
||||
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
|
||||
use Drupal\user\SharedTempStore;
|
||||
|
||||
/**
|
||||
* An extension of the SharedTempStore system for serialized data.
|
||||
*/
|
||||
class SerializableTempstore extends SharedTempStore {
|
||||
use DependencySerializationTrait;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools;
|
||||
|
||||
use Drupal\user\SharedTempStoreFactory;
|
||||
|
||||
/**
|
||||
* A factory for creating SerializableTempStore objects.
|
||||
*/
|
||||
class SerializableTempstoreFactory extends SharedTempStoreFactory {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
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();
|
||||
}
|
||||
|
||||
// Store the data for this collection in the database.
|
||||
$storage = $this->storageFactory->get("user.shared_tempstore.$collection");
|
||||
return new SerializableTempstore($storage, $this->lockBackend, $owner, $this->requestStack, $this->expire);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Testing;
|
||||
|
||||
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
|
||||
trait EntityCreationTrait {
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* Creates a custom content type based on default settings.
|
||||
*
|
||||
* @param string $entity_type
|
||||
* The type of entity to create.
|
||||
* @param array $values
|
||||
* An array of settings to change from the defaults.
|
||||
* Example: 'type' => 'foo'.
|
||||
*
|
||||
* @return \Drupal\Core\Entity\EntityInterface
|
||||
* Created entity.
|
||||
*/
|
||||
protected function createEntity($entity_type, array $values = array()) {
|
||||
$storage = $this->getEntityTypeManager()->getStorage($entity_type);
|
||||
$entity = $storage->create($values);
|
||||
$status = $entity->save();
|
||||
\Drupal::service('router.builder')->rebuild();
|
||||
|
||||
if ($this instanceof \PHPUnit_Framework_TestCase) {
|
||||
$this->assertSame($status, SAVED_NEW, (new FormattableMarkup('Created entity %id of type %type.', ['%id' => $entity->id(), '%type' => $entity_type]))->__toString());
|
||||
}
|
||||
else {
|
||||
$this->assertEqual($status, SAVED_NEW, (new FormattableMarkup('Created entity %id of type %type.', ['%id' => $entity->id(), '%type' => $entity_type]))->__toString());
|
||||
}
|
||||
|
||||
return $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected function getEntityTypeManager() {
|
||||
if (!isset($this->entityTypeManager)) {
|
||||
$this->entityTypeManager = $this->container->get('entity_type.manager');
|
||||
}
|
||||
return $this->entityTypeManager;
|
||||
}
|
||||
|
||||
}
|
136
web/modules/contrib/ctools/src/Tests/Wizard/CToolsWizardTest.php
Normal file
136
web/modules/contrib/ctools/src/Tests/Wizard/CToolsWizardTest.php
Normal file
|
@ -0,0 +1,136 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Tests\Wizard;
|
||||
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
|
||||
|
||||
/**
|
||||
* Tests basic wizard functionality.
|
||||
*
|
||||
* @group ctools
|
||||
*/
|
||||
class CToolsWizardTest extends WebTestBase {
|
||||
|
||||
use StringTranslationTrait;
|
||||
public static $modules = array('ctools', 'ctools_wizard_test');
|
||||
|
||||
function testWizardSteps() {
|
||||
$this->drupalGet('ctools/wizard');
|
||||
$this->assertText('Form One');
|
||||
$this->dumpHeaders = TRUE;
|
||||
// Check that $operations['one']['values'] worked.
|
||||
$this->assertText('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');
|
||||
// Check that $operations['two']['values'] worked.
|
||||
$this->assertText('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');
|
||||
// Goto next step again and finish this wizard.
|
||||
$this->drupalPostForm(NULL, [], $this->t('Next'));
|
||||
$edit = [
|
||||
'two' => 'Second test',
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, $this->t('Finish'));
|
||||
// Check that the wizard finished properly.
|
||||
$this->assertText('Value One: test');
|
||||
$this->assertText('Value Two: Second test');
|
||||
}
|
||||
|
||||
function testStepValidateAndSubmit() {
|
||||
$this->drupalGet('ctools/wizard');
|
||||
$this->assertText('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".');
|
||||
// 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');
|
||||
$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');
|
||||
}
|
||||
|
||||
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');
|
||||
|
||||
// Submit the general step.
|
||||
$edit = [
|
||||
'id' => 'test123',
|
||||
'label' => 'Test Config Entity 123',
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, $this->t('Next'));
|
||||
|
||||
// Submit the first step.
|
||||
$edit = [
|
||||
'one' => 'The first bit',
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, $this->t('Next'));
|
||||
|
||||
// Submit the second step.
|
||||
$edit = [
|
||||
'two' => 'The second bit',
|
||||
];
|
||||
$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');
|
||||
|
||||
// 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->clickLink(t('Form One'));
|
||||
$this->assertFieldByName('one', 'The first bit');
|
||||
$previous = $this->getUrl();
|
||||
$this->clickLink(t('Show on dialog'));
|
||||
$this->assertRaw('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->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->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->clickLink(t('Edit'));
|
||||
$this->drupalPostForm(NULL, [], $this->t('Next'));
|
||||
$this->assertFieldByName('one', 'New value');
|
||||
}
|
||||
|
||||
}
|
||||
|
253
web/modules/contrib/ctools/src/TypedDataResolver.php
Normal file
253
web/modules/contrib/ctools/src/TypedDataResolver.php
Normal file
|
@ -0,0 +1,253 @@
|
|||
<?php
|
||||
|
||||
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;
|
||||
use Drupal\Core\TypedData\DataReferenceDefinitionInterface;
|
||||
use Drupal\Core\TypedData\DataReferenceInterface;
|
||||
use Drupal\Core\TypedData\ListDataDefinitionInterface;
|
||||
use Drupal\Core\TypedData\ListInterface;
|
||||
use Drupal\Core\TypedData\TypedDataManagerInterface;
|
||||
|
||||
class TypedDataResolver {
|
||||
|
||||
/**
|
||||
* The typed data manager.
|
||||
*
|
||||
* @var \Drupal\Core\TypedData\TypedDataManagerInterface
|
||||
*/
|
||||
protected $manager;
|
||||
|
||||
/**
|
||||
* The string translation service.
|
||||
*
|
||||
* @var \Drupal\Core\StringTranslation\TranslationInterface
|
||||
*/
|
||||
protected $translation;
|
||||
|
||||
/**
|
||||
* @param \Drupal\Core\TypedData\TypedDataManagerInterface $manager
|
||||
* The typed data manager.
|
||||
* @param \Drupal\Core\StringTranslation\TranslationInterface $translation
|
||||
* The string translation service.
|
||||
*/
|
||||
public function __construct(TypedDataManagerInterface $manager, TranslationInterface $translation) {
|
||||
$this->manager = $manager;
|
||||
$this->translation = $translation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a property to a context.
|
||||
*
|
||||
* This method will respect the value of contexts as well, so if a context
|
||||
* object is pass that contains a value, the appropriate value will be
|
||||
* extracted and injected into the resulting context object if available.
|
||||
*
|
||||
* @param string $property_path
|
||||
* The name of the property.
|
||||
* @param \Drupal\Core\Plugin\Context\ContextInterface $context
|
||||
* The context from which we will extract values if available.
|
||||
*
|
||||
* @return \Drupal\Core\Plugin\Context\Context
|
||||
* A context object that represents the definition & value of the property.
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getContextFromProperty($property_path, ContextInterface $context) {
|
||||
$value = NULL;
|
||||
$data_definition = NULL;
|
||||
if ($context->hasContextValue()) {
|
||||
/** @var \Drupal\Core\TypedData\ComplexDataInterface $data */
|
||||
$data = $context->getContextData();
|
||||
foreach (explode(':', $property_path) as $name) {
|
||||
|
||||
if ($data instanceof ListInterface) {
|
||||
if (!is_numeric($name)) {
|
||||
// Implicitly default to delta 0 for lists when not specified.
|
||||
$data = $data->first();
|
||||
}
|
||||
else {
|
||||
// If we have a delta, fetch it and continue with the next part.
|
||||
$data = $data->get($name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Forward to the target value if this is a data reference.
|
||||
if ($data instanceof DataReferenceInterface) {
|
||||
$data = $data->getTarget();
|
||||
}
|
||||
|
||||
if (!$data->getDataDefinition()->getPropertyDefinition($name)) {
|
||||
throw new \Exception("Unknown property $name in property path $property_path");
|
||||
}
|
||||
$data = $data->get($name);
|
||||
}
|
||||
|
||||
$value = $data->getValue();
|
||||
$data_definition = $data instanceof DataReferenceInterface ? $data->getDataDefinition()->getTargetDefinition() : $data->getDataDefinition();
|
||||
}
|
||||
else {
|
||||
/** @var \Drupal\Core\TypedData\ComplexDataDefinitionInterface $data_definition */
|
||||
$data_definition = $context->getContextDefinition()->getDataDefinition();
|
||||
foreach (explode(':', $property_path) as $name) {
|
||||
|
||||
if ($data_definition instanceof ListDataDefinitionInterface) {
|
||||
$data_definition = $data_definition->getItemDefinition();
|
||||
|
||||
// If the delta was specified explicitly, continue with the next part.
|
||||
if (is_numeric($name)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Forward to the target definition if this is a data reference
|
||||
// definition.
|
||||
if ($data_definition instanceof DataReferenceDefinitionInterface) {
|
||||
$data_definition = $data_definition->getTargetDefinition();
|
||||
}
|
||||
|
||||
if (!$data_definition->getPropertyDefinition($name)) {
|
||||
throw new \Exception("Unknown property $name in property path $property_path");
|
||||
}
|
||||
$data_definition = $data_definition->getPropertyDefinition($name);
|
||||
}
|
||||
|
||||
// Forward to the target definition if this is a data reference
|
||||
// definition.
|
||||
if ($data_definition instanceof DataReferenceDefinitionInterface) {
|
||||
$data_definition = $data_definition->getTargetDefinition();
|
||||
}
|
||||
}
|
||||
$context_definition = new ContextDefinition($data_definition->getDataType(), $data_definition->getLabel(), $data_definition->isRequired(), FALSE, $data_definition->getDescription());
|
||||
return new Context($context_definition, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a context from an array of contexts by a tokenized pattern.
|
||||
*
|
||||
* This is more than simple isset/empty checks on the contexts array. The
|
||||
* pattern could be node:uid:name which will iterate over all provided
|
||||
* contexts in the array for one named 'node', it will then load the data
|
||||
* definition of 'node' and check for a property named 'uid'. This will then
|
||||
* set a new (temporary) context on the array and recursively call itself to
|
||||
* navigate through related properties all the way down until the request
|
||||
* property is located. At that point the property is passed to a
|
||||
* TypedDataResolver which will convert it to an appropriate ContextInterface
|
||||
* object.
|
||||
*
|
||||
* @param $token
|
||||
* A ":" delimited set of tokens representing
|
||||
* @param \Drupal\Core\Plugin\Context\ContextInterface[] $contexts
|
||||
* The array of available contexts.
|
||||
*
|
||||
* @return \Drupal\Core\Plugin\Context\ContextInterface
|
||||
* The requested token as a full Context object.
|
||||
*
|
||||
* @throws \Drupal\ctools\ContextNotFoundException
|
||||
*/
|
||||
public function convertTokenToContext($token, $contexts) {
|
||||
// If the requested token is already a context, just return it.
|
||||
if (isset($contexts[$token])) {
|
||||
return $contexts[$token];
|
||||
}
|
||||
else {
|
||||
list($base, $property_path) = explode(':', $token, 2);
|
||||
// A base must always be set. This method recursively calls itself
|
||||
// setting bases for this reason.
|
||||
if (!empty($contexts[$base])) {
|
||||
return $this->getContextFromProperty($property_path, $contexts[$base]);
|
||||
}
|
||||
// @todo improve this exception message.
|
||||
throw new ContextNotFoundException("The requested context was not found in the supplied array of contexts.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides an administrative label for a tokenized relationship.
|
||||
*
|
||||
* @param string $token
|
||||
* The token related to a context in the contexts array.
|
||||
* @param \Drupal\Core\Plugin\Context\ContextInterface[] $contexts
|
||||
* An array of contexts from which to extract our token's label.
|
||||
*
|
||||
* @return \Drupal\Core\StringTranslation\TranslatableMarkup
|
||||
* The administrative label of $token.
|
||||
*/
|
||||
public function getLabelByToken($token, $contexts) {
|
||||
// @todo Optimize this by allowing to limit the desired token?
|
||||
$tokens = $this->getTokensForContexts($contexts);
|
||||
if (isset($tokens[$token])) {
|
||||
return $tokens[$token];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts an array of tokens and labels.
|
||||
*
|
||||
* @param \Drupal\Core\Plugin\Context\ContextInterface[] $contexts
|
||||
* The array of contexts with which we are currently dealing.
|
||||
*
|
||||
* @return array
|
||||
* An array of token keys and corresponding labels.
|
||||
*/
|
||||
public function getTokensForContexts($contexts) {
|
||||
$tokens = [];
|
||||
foreach ($contexts as $context_id => $context) {
|
||||
$data_definition = $context->getContextDefinition()->getDataDefinition();
|
||||
if ($data_definition instanceof ComplexDataDefinitionInterface) {
|
||||
foreach ($this->getTokensFromComplexData($data_definition) as $token => $label) {
|
||||
$tokens["$context_id:$token"] = $data_definition->getLabel() . ': ' . $label;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns tokens for a complex data definition.
|
||||
*
|
||||
* @param \Drupal\Core\TypedData\ComplexDataDefinitionInterface $complex_data_definition
|
||||
*
|
||||
* @return array
|
||||
* An array of token keys and corresponding labels.
|
||||
*/
|
||||
protected function getTokensFromComplexData(ComplexDataDefinitionInterface $complex_data_definition) {
|
||||
$tokens = [];
|
||||
// Loop over all properties.
|
||||
foreach ($complex_data_definition->getPropertyDefinitions() as $property_name => $property_definition) {
|
||||
|
||||
// Item definitions do not always have a label. Use the list definition
|
||||
// label if the item does not have one.
|
||||
$property_label = $property_definition->getLabel();
|
||||
if ($property_definition instanceof ListDataDefinitionInterface) {
|
||||
$property_definition = $property_definition->getItemDefinition();
|
||||
$property_label = $property_definition->getLabel() ?: $property_label;
|
||||
}
|
||||
|
||||
// If the property is complex too, recurse to find child properties.
|
||||
if ($property_definition instanceof ComplexDataDefinitionInterface) {
|
||||
$property_tokens = $this->getTokensFromComplexData($property_definition);
|
||||
foreach ($property_tokens as $token => $label) {
|
||||
$tokens[$property_name . ':' . $token] = count($property_tokens) > 1 ? ($property_label . ': ' . $label) : $property_label;
|
||||
}
|
||||
}
|
||||
|
||||
// Only expose references as tokens.
|
||||
// @todo Consider to expose primitive and non-reference typed data
|
||||
// definitions too, like strings, integers and dates. The current UI
|
||||
// will not scale to that.
|
||||
if ($property_definition instanceof DataReferenceDefinitionInterface) {
|
||||
$tokens[$property_name] = $property_definition->getLabel();
|
||||
}
|
||||
}
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
}
|
180
web/modules/contrib/ctools/src/Wizard/EntityFormWizardBase.php
Normal file
180
web/modules/contrib/ctools/src/Wizard/EntityFormWizardBase.php
Normal file
|
@ -0,0 +1,180 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Wizard;
|
||||
|
||||
|
||||
use Drupal\Core\DependencyInjection\ClassResolverInterface;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
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 Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
/**
|
||||
* The base class for all entity form wizards.
|
||||
*/
|
||||
abstract class EntityFormWizardBase extends FormWizardBase implements EntityFormWizardInterface {
|
||||
|
||||
/**
|
||||
* The entity manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityManagerInterface
|
||||
*/
|
||||
protected $entityManager;
|
||||
|
||||
/**
|
||||
* @param \Drupal\user\SharedTempStoreFactory $tempstore
|
||||
* Tempstore Factory for keeping track of values in each step of the
|
||||
* wizard.
|
||||
* @param \Drupal\Core\Form\FormBuilderInterface $builder
|
||||
* The Form Builder.
|
||||
* @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver
|
||||
* The class resolver.
|
||||
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
|
||||
* The event dispatcher.
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* @param $tempstore_id
|
||||
* The shared temp store factory collection name.
|
||||
* @param null $machine_name
|
||||
* The SharedTempStore key for our current wizard values.
|
||||
* @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;
|
||||
parent::__construct($tempstore, $builder, $class_resolver, $event_dispatcher, $route_match, $tempstore_id, $machine_name, $step);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getParameters() {
|
||||
return [
|
||||
'tempstore' => \Drupal::service('user.shared_tempstore'),
|
||||
'builder' => \Drupal::service('form_builder'),
|
||||
'class_resolver' => \Drupal::service('class_resolver'),
|
||||
'event_dispatcher' => \Drupal::service('event_dispatcher'),
|
||||
'entity_manager' => \Drupal::service('entity.manager'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function initValues() {
|
||||
$storage = $this->entityManager->getStorage($this->getEntityType());
|
||||
if ($this->getMachineName()) {
|
||||
$values = $this->getTempstore()->get($this->getMachineName());
|
||||
if (!$values) {
|
||||
$entity = $storage->load($this->getMachineName());
|
||||
$values[$this->getEntityType()] = $entity;
|
||||
$values['id'] = $entity->id();
|
||||
$values['label'] = $entity->label();
|
||||
}
|
||||
}
|
||||
else {
|
||||
$entity = $storage->create([]);
|
||||
$values[$this->getEntityType()] = $entity;
|
||||
}
|
||||
$event = new WizardEvent($this, $values);
|
||||
$this->dispatcher->dispatch(FormWizardInterface::LOAD_VALUES, $event);
|
||||
return $event->getValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function finish(array &$form, FormStateInterface $form_state) {
|
||||
$cached_values = $form_state->getTemporaryValue('wizard');
|
||||
/** @var $entity \Drupal\Core\Entity\EntityInterface */
|
||||
$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(),
|
||||
)));
|
||||
}
|
||||
else {
|
||||
drupal_set_message($this->t('The %label @entity_type was not saved.', array(
|
||||
'%label' => $entity->label(),
|
||||
'@entity_type' => $definition->getLabel(),
|
||||
)));
|
||||
}
|
||||
$form_state->setRedirectUrl($entity->toUrl('collection'));
|
||||
parent::finish($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for generating label and id form elements.
|
||||
*
|
||||
* @param array $form
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function customizeForm(array $form, FormStateInterface $form_state) {
|
||||
$form = parent::customizeForm($form, $form_state);
|
||||
if ($this->machine_name) {
|
||||
$entity = $this->entityManager->getStorage($this->getEntityType())
|
||||
->load($this->machine_name);
|
||||
}
|
||||
else {
|
||||
$entity = NULL;
|
||||
}
|
||||
$cached_values = $form_state->getTemporaryValue('wizard');
|
||||
// If the entity already exists, allow for non-linear step interaction.
|
||||
if ($entity) {
|
||||
// Setup the step rendering theme element.
|
||||
$prefix = [
|
||||
'#theme' => ['ctools_wizard_trail_links'],
|
||||
'#wizard' => $this,
|
||||
'#cached_values' => $cached_values,
|
||||
];
|
||||
$form['#prefix'] = \Drupal::service('renderer')->render($prefix);
|
||||
}
|
||||
// Get the current form operation.
|
||||
$operation = $this->getOperation($cached_values);
|
||||
$operations = $this->getOperations($cached_values);
|
||||
$default_operation = reset($operations);
|
||||
if ($operation['form'] == $default_operation['form']) {
|
||||
// Get the plugin definition of this entity.
|
||||
$definition = $this->entityManager->getDefinition($this->getEntityType());
|
||||
// Create id and label form elements.
|
||||
$form['name'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#attributes' => array('class' => array('fieldset-no-legend')),
|
||||
'#title' => $this->getWizardLabel(),
|
||||
);
|
||||
$form['name']['label'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->getMachineLabel(),
|
||||
'#required' => TRUE,
|
||||
'#size' => 32,
|
||||
'#default_value' => !empty($cached_values['label']) ? $cached_values['label'] : '',
|
||||
'#maxlength' => 255,
|
||||
'#disabled' => !empty($cached_values['label']),
|
||||
);
|
||||
$form['name']['id'] = array(
|
||||
'#type' => 'machine_name',
|
||||
'#maxlength' => 128,
|
||||
'#machine_name' => array(
|
||||
'source' => array('name', 'label'),
|
||||
'exists' => $this->exists(),
|
||||
),
|
||||
'#description' => $this->t('A unique machine-readable name for this @entity_type. It must only contain lowercase letters, numbers, and underscores.', ['@entity_type' => $definition->getLabel()]),
|
||||
'#default_value' => !empty($cached_values['id']) ? $cached_values['id'] : '',
|
||||
'#disabled' => !empty($cached_values['id']),
|
||||
);
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Wizard;
|
||||
|
||||
/**
|
||||
* Form wizard interface for use with entities.
|
||||
*/
|
||||
interface EntityFormWizardInterface extends FormWizardInterface {
|
||||
|
||||
/**
|
||||
* The fieldset #title for your label & machine name elements.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getWizardLabel();
|
||||
|
||||
/**
|
||||
* The form element #title for your unique identifier label.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMachineLabel();
|
||||
|
||||
/**
|
||||
* The machine name of the entity type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEntityType();
|
||||
|
||||
/**
|
||||
* A method for determining if this entity already exists.
|
||||
*
|
||||
* @return callable
|
||||
* The callable to pass the id to via typical machine_name form element.
|
||||
*/
|
||||
public function exists();
|
||||
|
||||
}
|
465
web/modules/contrib/ctools/src/Wizard/FormWizardBase.php
Normal file
465
web/modules/contrib/ctools/src/Wizard/FormWizardBase.php
Normal file
|
@ -0,0 +1,465 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Wizard;
|
||||
|
||||
use Drupal\Core\Ajax\AjaxResponse;
|
||||
use Drupal\Core\Ajax\CloseModalDialogCommand;
|
||||
use Drupal\Core\DependencyInjection\ClassResolverInterface;
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormBuilderInterface;
|
||||
use Drupal\Core\Form\FormInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\ctools\Ajax\OpenModalWizardCommand;
|
||||
use Drupal\ctools\Event\WizardEvent;
|
||||
use Drupal\user\SharedTempStoreFactory;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
/**
|
||||
* The base class for all form wizard.
|
||||
*/
|
||||
abstract class FormWizardBase extends FormBase implements FormWizardInterface {
|
||||
|
||||
/**
|
||||
* Tempstore Factory for keeping track of values in each step of the wizard.
|
||||
*
|
||||
* @var \Drupal\user\SharedTempStoreFactory
|
||||
*/
|
||||
protected $tempstore;
|
||||
|
||||
/**
|
||||
* The Form Builder.
|
||||
*
|
||||
* @var \Drupal\Core\Form\FormBuilderInterface
|
||||
*/
|
||||
protected $builder;
|
||||
|
||||
/**
|
||||
* The class resolver.
|
||||
*
|
||||
* @var \Drupal\Core\DependencyInjection\ClassResolverInterface;
|
||||
*/
|
||||
protected $classResolver;
|
||||
|
||||
/**
|
||||
* The event dispatcher.
|
||||
*
|
||||
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
|
||||
*/
|
||||
protected $dispatcher;
|
||||
|
||||
/**
|
||||
* The shared temp store factory collection name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $tempstore_id;
|
||||
|
||||
/**
|
||||
* The SharedTempStore key for our current wizard values.
|
||||
*
|
||||
* @var string|NULL
|
||||
*/
|
||||
protected $machine_name;
|
||||
|
||||
/**
|
||||
* The current active step of the wizard.
|
||||
*
|
||||
* @var string|NULL
|
||||
*/
|
||||
protected $step;
|
||||
|
||||
/**
|
||||
* @param \Drupal\user\SharedTempStoreFactory $tempstore
|
||||
* Tempstore Factory for keeping track of values in each step of the
|
||||
* wizard.
|
||||
* @param \Drupal\Core\Form\FormBuilderInterface $builder
|
||||
* The Form Builder.
|
||||
* @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver
|
||||
* The class resolver.
|
||||
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
|
||||
* The event dispatcher.
|
||||
* @param $tempstore_id
|
||||
* The shared temp store factory collection name.
|
||||
* @param null $machine_name
|
||||
* The SharedTempStore key for our current wizard values.
|
||||
* @param null $step
|
||||
* The current active step of the wizard.
|
||||
*/
|
||||
public function __construct(SharedTempStoreFactory $tempstore, FormBuilderInterface $builder, ClassResolverInterface $class_resolver, EventDispatcherInterface $event_dispatcher, RouteMatchInterface $route_match, $tempstore_id, $machine_name = NULL, $step = NULL) {
|
||||
$this->tempstore = $tempstore;
|
||||
$this->builder = $builder;
|
||||
$this->classResolver = $class_resolver;
|
||||
$this->dispatcher = $event_dispatcher;
|
||||
$this->routeMatch = $route_match;
|
||||
$this->tempstore_id = $tempstore_id;
|
||||
$this->machine_name = $machine_name;
|
||||
$this->step = $step;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getParameters() {
|
||||
return [
|
||||
'tempstore' => \Drupal::service('user.shared_tempstore'),
|
||||
'builder' => \Drupal::service('form_builder'),
|
||||
'class_resolver' => \Drupal::service('class_resolver'),
|
||||
'event_dispatcher' => \Drupal::service('event_dispatcher'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function initValues() {
|
||||
$values = [];
|
||||
$event = new WizardEvent($this, $values);
|
||||
$this->dispatcher->dispatch(FormWizardInterface::LOAD_VALUES, $event);
|
||||
return $event->getValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTempstoreId() {
|
||||
return $this->tempstore_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTempstore() {
|
||||
return $this->tempstore->get($this->getTempstoreId());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMachineName() {
|
||||
return $this->machine_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getStep($cached_values) {
|
||||
if (!$this->step) {
|
||||
$operations = $this->getOperations($cached_values);
|
||||
$steps = array_keys($operations);
|
||||
$this->step = reset($steps);
|
||||
}
|
||||
return $this->step;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getOperation($cached_values) {
|
||||
$operations = $this->getOperations($cached_values);
|
||||
$step = $this->getStep($cached_values);
|
||||
if (!empty($operations[$step])) {
|
||||
return $operations[$step];
|
||||
}
|
||||
$operation = reset($operations);
|
||||
return $operation;
|
||||
}
|
||||
|
||||
/**
|
||||
* The translated text of the "Next" button's text.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNextOp() {
|
||||
return $this->t('Next');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNextParameters($cached_values) {
|
||||
// Get the steps by key.
|
||||
$operations = $this->getOperations($cached_values);
|
||||
$steps = array_keys($operations);
|
||||
// Get the steps after the current step.
|
||||
$after = array_slice($operations, array_search($this->getStep($cached_values), $steps) + 1);
|
||||
// Get the steps after the current step by key.
|
||||
$after_keys = array_keys($after);
|
||||
$step = reset($after_keys);
|
||||
if (!$step) {
|
||||
$keys = array_keys($operations);
|
||||
$step = end($keys);
|
||||
}
|
||||
return [
|
||||
'machine_name' => $this->getMachineName(),
|
||||
'step' => $step,
|
||||
'js' => 'nojs',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPreviousParameters($cached_values) {
|
||||
$operations = $this->getOperations($cached_values);
|
||||
$step = $this->getStep($cached_values);
|
||||
|
||||
// Get the steps by key.
|
||||
$steps = array_keys($operations);
|
||||
// Get the steps before the current step.
|
||||
$before = array_slice($operations, 0, array_search($step, $steps));
|
||||
// Get the steps before the current step by key.
|
||||
$before = array_keys($before);
|
||||
// Reverse the steps for easy access to the next step.
|
||||
$before_steps = array_reverse($before);
|
||||
$step = reset($before_steps);
|
||||
return [
|
||||
'machine_name' => $this->getMachineName(),
|
||||
'step' => $step,
|
||||
'js' => 'nojs',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
if (!$this->getMachineName() || !$this->getTempstore()->get($this->getMachineName())) {
|
||||
$cached_values = $this->initValues();
|
||||
}
|
||||
else {
|
||||
$cached_values = $this->getTempstore()->get($this->getMachineName());
|
||||
}
|
||||
$operation = $this->getOperation($cached_values);
|
||||
/* @var $operation \Drupal\Core\Form\FormInterface */
|
||||
$operation = $this->classResolver->getInstanceFromDefinition($operation['form']);
|
||||
return $operation->getFormId();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$cached_values = $form_state->getTemporaryValue('wizard');
|
||||
// Get the current form operation.
|
||||
$operation = $this->getOperation($cached_values);
|
||||
$form = $this->customizeForm($form, $form_state);
|
||||
/* @var $formClass \Drupal\Core\Form\FormInterface */
|
||||
$formClass = $this->classResolver->getInstanceFromDefinition($operation['form']);
|
||||
// Pass include any custom values for this operation.
|
||||
if (!empty($operation['values'])) {
|
||||
$cached_values = array_merge($cached_values, $operation['values']);
|
||||
$form_state->setTemporaryValue('wizard', $cached_values);
|
||||
}
|
||||
// Build the form.
|
||||
$form = $formClass->buildForm($form, $form_state);
|
||||
if (isset($operation['title'])) {
|
||||
$form['#title'] = $operation['title'];
|
||||
}
|
||||
$form['actions'] = $this->actions($formClass, $form_state);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateForm(array &$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
// Only perform this logic if we're moving to the next page. This prevents
|
||||
// the loss of cached values on ajax submissions.
|
||||
if ((string)$form_state->getValue('op') == (string)$this->getNextOp()) {
|
||||
$cached_values = $form_state->getTemporaryValue('wizard');
|
||||
if ($form_state->hasValue('label')) {
|
||||
$cached_values['label'] = $form_state->getValue('label');
|
||||
}
|
||||
if ($form_state->hasValue('id')) {
|
||||
$cached_values['id'] = $form_state->getValue('id');
|
||||
}
|
||||
if (is_null($this->machine_name) && !empty($cached_values['id'])) {
|
||||
$this->machine_name = $cached_values['id'];
|
||||
}
|
||||
$this->getTempstore()->set($this->getMachineName(), $cached_values);
|
||||
if (!$form_state->get('ajax')) {
|
||||
$form_state->setRedirect($this->getRouteName(), $this->getNextParameters($cached_values));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function populateCachedValues(array &$form, FormStateInterface $form_state) {
|
||||
$cached_values = $this->getTempstore()->get($this->getMachineName());
|
||||
if (!$cached_values) {
|
||||
$cached_values = $form_state->getTemporaryValue('wizard');
|
||||
if (!$cached_values) {
|
||||
$cached_values = $this->initValues();
|
||||
$form_state->setTemporaryValue('wizard', $cached_values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function previous(array &$form, FormStateInterface $form_state) {
|
||||
$cached_values = $form_state->getTemporaryValue('wizard');
|
||||
$form_state->setRedirect($this->getRouteName(), $this->getPreviousParameters($cached_values));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function finish(array &$form, FormStateInterface $form_state) {
|
||||
$this->getTempstore()->delete($this->getMachineName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for generating default form elements.
|
||||
*
|
||||
* @param array $form
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function customizeForm(array $form, FormStateInterface $form_state) {
|
||||
// Setup the step rendering theme element.
|
||||
$prefix = [
|
||||
'#theme' => ['ctools_wizard_trail'],
|
||||
'#wizard' => $this,
|
||||
'#cached_values' => $form_state->getTemporaryValue('wizard'),
|
||||
];
|
||||
// @todo properly inject the renderer.
|
||||
$form['#prefix'] = \Drupal::service('renderer')->render($prefix);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates action elements for navigating between the operation steps.
|
||||
*
|
||||
* @param \Drupal\Core\Form\FormInterface $form_object
|
||||
* The current operation form.
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The current form state.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function actions(FormInterface $form_object, FormStateInterface $form_state) {
|
||||
$cached_values = $form_state->getTemporaryValue('wizard');
|
||||
$operations = $this->getOperations($cached_values);
|
||||
$step = $this->getStep($cached_values);
|
||||
$operation = $operations[$step];
|
||||
|
||||
$steps = array_keys($operations);
|
||||
// Slice to find the operations that occur before the current operation.
|
||||
$before = array_slice($operations, 0, array_search($step, $steps));
|
||||
// Slice to find the operations that occur after the current operation.
|
||||
$after = array_slice($operations, array_search($step, $steps) + 1);
|
||||
|
||||
$actions = [
|
||||
'submit' => [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Next'),
|
||||
'#button_type' => 'primary',
|
||||
'#validate' => [
|
||||
'::populateCachedValues',
|
||||
[$form_object, 'validateForm'],
|
||||
],
|
||||
'#submit' => [
|
||||
[$form_object, 'submitForm'],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// Add any submit or validate functions for the step and the global ones.
|
||||
if (isset($operation['validate'])) {
|
||||
$actions['submit']['#validate'] = array_merge($actions['submit']['#validate'], $operation['validate']);
|
||||
}
|
||||
$actions['submit']['#validate'][] = '::validateForm';
|
||||
if (isset($operation['submit'])) {
|
||||
$actions['submit']['#submit'] = array_merge($actions['submit']['#submit'], $operation['submit']);
|
||||
}
|
||||
$actions['submit']['#submit'][] = '::submitForm';
|
||||
|
||||
if ($form_state->get('ajax')) {
|
||||
// Ajax submissions need to submit to the current step, not "next".
|
||||
$parameters = $this->getNextParameters($cached_values);
|
||||
$parameters['step'] = $this->getStep($cached_values);
|
||||
$actions['submit']['#ajax'] = [
|
||||
'callback' => '::ajaxSubmit',
|
||||
'url' => Url::fromRoute($this->getRouteName(), $parameters),
|
||||
'options' => ['query' => \Drupal::request()->query->all() + [FormBuilderInterface::AJAX_FORM_REQUEST => TRUE]],
|
||||
];
|
||||
}
|
||||
|
||||
// If there are steps before this one, label the button "previous"
|
||||
// otherwise do not display a button.
|
||||
if ($before) {
|
||||
$actions['previous'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Previous'),
|
||||
'#validate' => array(
|
||||
array($this, 'populateCachedValues'),
|
||||
),
|
||||
'#submit' => array(
|
||||
array($this, 'previous'),
|
||||
),
|
||||
'#limit_validation_errors' => array(),
|
||||
'#weight' => -10,
|
||||
);
|
||||
if ($form_state->get('ajax')) {
|
||||
// Ajax submissions need to submit to the current step, not "previous".
|
||||
$parameters = $this->getPreviousParameters($cached_values);
|
||||
$parameters['step'] = $this->getStep($cached_values);
|
||||
$actions['previous']['#ajax'] = [
|
||||
'callback' => '::ajaxPrevious',
|
||||
'url' => Url::fromRoute($this->getRouteName(), $parameters),
|
||||
'options' => ['query' => \Drupal::request()->query->all() + [FormBuilderInterface::AJAX_FORM_REQUEST => TRUE]],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// If there are not steps after this one, label the button "Finish".
|
||||
if (!$after) {
|
||||
$actions['submit']['#value'] = $this->t('Finish');
|
||||
$actions['submit']['#submit'][] = array($this, 'finish');
|
||||
if ($form_state->get('ajax')) {
|
||||
$actions['submit']['#ajax']['callback'] = [$this, 'ajaxFinish'];
|
||||
}
|
||||
}
|
||||
|
||||
return $actions;
|
||||
}
|
||||
|
||||
public function ajaxSubmit(array $form, FormStateInterface $form_state) {
|
||||
$cached_values = $form_state->getTemporaryValue('wizard');
|
||||
$response = new AjaxResponse();
|
||||
$parameters = $this->getNextParameters($cached_values);
|
||||
$response->addCommand(new OpenModalWizardCommand($this, $this->getTempstoreId(), $parameters));
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function ajaxPrevious(array $form, FormStateInterface $form_state) {
|
||||
$cached_values = $form_state->getTemporaryValue('wizard');
|
||||
$response = new AjaxResponse();
|
||||
$parameters = $this->getPreviousParameters($cached_values);
|
||||
$response->addCommand(new OpenModalWizardCommand($this, $this->getTempstoreId(), $parameters));
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function ajaxFinish(array $form, FormStateInterface $form_state) {
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new CloseModalDialogCommand());
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function getRouteName() {
|
||||
return $this->routeMatch->getRouteName();
|
||||
}
|
||||
|
||||
}
|
182
web/modules/contrib/ctools/src/Wizard/FormWizardInterface.php
Normal file
182
web/modules/contrib/ctools/src/Wizard/FormWizardInterface.php
Normal file
|
@ -0,0 +1,182 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Wizard;
|
||||
|
||||
use Drupal\Core\Form\FormInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Form wizard interface.
|
||||
*/
|
||||
interface FormWizardInterface extends FormInterface {
|
||||
|
||||
/**
|
||||
* Constant value for wizard load event.
|
||||
*/
|
||||
const LOAD_VALUES = 'wizard.load';
|
||||
|
||||
/**
|
||||
* Return an array of parameters required to construct this wizard.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getParameters();
|
||||
|
||||
/**
|
||||
* Initialize wizard values.
|
||||
*
|
||||
* return mixed.
|
||||
*/
|
||||
public function initValues();
|
||||
|
||||
/**
|
||||
* The shared temp store factory collection name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTempstoreId();
|
||||
|
||||
/**
|
||||
* The active SharedTempStore for this wizard.
|
||||
*
|
||||
* @return \Drupal\user\SharedTempStore
|
||||
*/
|
||||
public function getTempstore();
|
||||
|
||||
/**
|
||||
* The SharedTempStore key for our current wizard values.
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function getMachineName();
|
||||
|
||||
/**
|
||||
* Retrieve the current active step of the wizard.
|
||||
*
|
||||
* This will return the first step of the wizard if no step has been set.
|
||||
*
|
||||
* @param mixed $cached_values
|
||||
* The values returned by $this->getTempstore()->get($this->getMachineName());
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getStep($cached_values);
|
||||
|
||||
/**
|
||||
* Retrieve a list of FormInterface classes by their step key in the wizard.
|
||||
*
|
||||
* @param mixed $cached_values
|
||||
* The values returned by $this->getTempstore()->get($this->getMachineName()); *
|
||||
*
|
||||
* @return array
|
||||
* An associative array keyed on the step name with an array value with the
|
||||
* following keys:
|
||||
* - title (string): Human-readable title of the step.
|
||||
* - form (string): Fully-qualified class name of the form for this step.
|
||||
* - values (array): Optional array of cached values to override when on
|
||||
* this step.
|
||||
* - validate (array): Optional array of callables to be called when this
|
||||
* step is validated.
|
||||
* - submit (array): Optional array of callables to be called when this
|
||||
* step is submitted.
|
||||
*/
|
||||
public function getOperations($cached_values);
|
||||
|
||||
/**
|
||||
* Retrieve the current Operation.
|
||||
*
|
||||
* @param mixed $cached_values
|
||||
* The values returned by $this->getTempstore()->get($this->getMachineName());
|
||||
*
|
||||
* @return string
|
||||
* The class name to instantiate.
|
||||
*/
|
||||
public function getOperation($cached_values);
|
||||
|
||||
/**
|
||||
* The name of the route to which forward or backwards steps redirect.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRouteName();
|
||||
|
||||
/**
|
||||
* The Route parameters for a 'next' step.
|
||||
*
|
||||
* If your route requires more than machine_name and step keys, override and
|
||||
* extend this method as needed.
|
||||
*
|
||||
* @param mixed $cached_values
|
||||
* The values returned by $this->getTempstore()->get($this->getMachineName());
|
||||
*
|
||||
* @return array
|
||||
* An array keyed by:
|
||||
* machine_name
|
||||
* step
|
||||
*/
|
||||
public function getNextParameters($cached_values);
|
||||
|
||||
/**
|
||||
* The Route parameters for a 'previous' step.
|
||||
*
|
||||
* If your route requires more than machine_name and step keys, override and
|
||||
* extend this method as needed.
|
||||
*
|
||||
* @param mixed $cached_values
|
||||
* The values returned by $this->getTempstore()->get($this->getMachineName());
|
||||
*
|
||||
* @return array
|
||||
* An array keyed by:
|
||||
* machine_name
|
||||
* step
|
||||
*/
|
||||
public function getPreviousParameters($cached_values);
|
||||
|
||||
/**
|
||||
* Form validation handler that populates the cached values from tempstore.
|
||||
*
|
||||
* Temporary values are only available for a single page load so form
|
||||
* submission will lose all the values. This was we reload and provide them
|
||||
* to the validate and submit process.
|
||||
*
|
||||
* @param array $form
|
||||
* Drupal form array
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The initial form state before validation or submission of the steps.
|
||||
*/
|
||||
public function populateCachedValues(array &$form, FormStateInterface $form_state);
|
||||
|
||||
/**
|
||||
* Form submit handler to step backwards in the wizard.
|
||||
*
|
||||
* "Next" steps are handled by \Drupal\Core\Form\FormInterface::submitForm().
|
||||
*
|
||||
* @param array $form
|
||||
* Drupal form array
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The current form state of the wizard. This will not contain values from
|
||||
* the current step since the previous button does not actually submit
|
||||
* those values.
|
||||
*/
|
||||
public function previous(array &$form, FormStateInterface $form_state);
|
||||
|
||||
/**
|
||||
* Form submit handler for finalizing the wizard values.
|
||||
*
|
||||
* If you need to generate an entity or save config or raw table data
|
||||
* subsequent to your form wizard, this is the responsible method.
|
||||
*
|
||||
* @param array $form
|
||||
* Drupal form array
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The final form state of the wizard.
|
||||
*/
|
||||
public function finish(array &$form, FormStateInterface $form_state);
|
||||
|
||||
public function ajaxSubmit(array $form, FormStateInterface $form_state);
|
||||
|
||||
public function ajaxPrevious(array $form, FormStateInterface $form_state);
|
||||
|
||||
public function ajaxFinish(array $form, FormStateInterface $form_state);
|
||||
|
||||
}
|
129
web/modules/contrib/ctools/src/Wizard/WizardFactory.php
Normal file
129
web/modules/contrib/ctools/src/Wizard/WizardFactory.php
Normal file
|
@ -0,0 +1,129 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ctools\Wizard;
|
||||
|
||||
use Drupal\Core\Form\FormBuilderInterface;
|
||||
use Drupal\Core\Form\FormState;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
class WizardFactory implements WizardFactoryInterface {
|
||||
|
||||
/**
|
||||
* The Form Builder.
|
||||
*
|
||||
* @var \Drupal\Core\Form\FormBuilderInterface
|
||||
*/
|
||||
protected $builder;
|
||||
|
||||
/**
|
||||
* The event dispatcher.
|
||||
*
|
||||
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
|
||||
*/
|
||||
protected $dispatcher;
|
||||
|
||||
/**
|
||||
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
|
||||
* The form builder.
|
||||
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
|
||||
* The event dispatcher.
|
||||
*/
|
||||
public function __construct(FormBuilderInterface $form_builder, EventDispatcherInterface $event_dispatcher) {
|
||||
$this->builder = $form_builder;
|
||||
$this->dispatcher = $event_dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getWizardForm(FormWizardInterface $wizard, array $parameters = [], $ajax = FALSE) {
|
||||
$form_state = $this->getFormState($wizard, $parameters, $ajax);
|
||||
$form = $this->builder->buildForm($wizard, $form_state);
|
||||
|
||||
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)) {
|
||||
if (!empty($form['#prefix'])) {
|
||||
// Form prefix is expected to be a string. Prepend the messages to
|
||||
// that string.
|
||||
$form['#prefix'] = '<div class="wizard-messages">' . $messages . '</div>' . $form['#prefix'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* A class name implementing FormWizardInterface.
|
||||
* @param array $parameters
|
||||
* The array of parameters specific to this wizard.
|
||||
*
|
||||
* @return \Drupal\ctools\Wizard\FormWizardInterface
|
||||
*/
|
||||
public function createWizard($class, array $parameters) {
|
||||
$arguments = [];
|
||||
$reflection = new \ReflectionClass($class);
|
||||
$constructor = $reflection->getMethod('__construct');
|
||||
foreach ($constructor->getParameters() as $parameter) {
|
||||
if (array_key_exists($parameter->name, $parameters)) {
|
||||
$arguments[] = $parameters[$parameter->name];
|
||||
}
|
||||
elseif ($parameter->isDefaultValueAvailable()) {
|
||||
$arguments[] = $parameter->getDefaultValue();
|
||||
}
|
||||
}
|
||||
/** @var $wizard \Drupal\ctools\Wizard\FormWizardInterface */
|
||||
$wizard = $reflection->newInstanceArgs($arguments);
|
||||
return $wizard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the wizard form state.
|
||||
*
|
||||
* @param \Drupal\ctools\Wizard\FormWizardInterface $wizard
|
||||
* The form wizard.
|
||||
* @param array $parameters
|
||||
* The array of parameters specific to this wizard.
|
||||
* @param bool $ajax
|
||||
*
|
||||
* @return \Drupal\Core\Form\FormState
|
||||
*/
|
||||
public function getFormState(FormWizardInterface $wizard, array $parameters, $ajax = FALSE) {
|
||||
$form_state = new FormState();
|
||||
// If a wizard has no values, initialize them.
|
||||
if (!$wizard->getMachineName() || !$wizard->getTempstore()->get($wizard->getMachineName())) {
|
||||
$cached_values = $wizard->initValues();
|
||||
// Save the cached values that were initialized.
|
||||
if ($wizard->getMachineName()) {
|
||||
$wizard->getTempstore()->set($wizard->getMachineName(), $cached_values);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$cached_values = $wizard->getTempstore()->get($wizard->getMachineName());
|
||||
}
|
||||
$form_state->setTemporaryValue('wizard', $cached_values);
|
||||
$form_state->set('ajax', $ajax);
|
||||
|
||||
$parameters['form'] = [];
|
||||
$parameters['form_state'] = $form_state;
|
||||
$method = new \ReflectionMethod($wizard, 'buildForm');
|
||||
$arguments = [];
|
||||
foreach ($method->getParameters() as $parameter) {
|
||||
if (array_key_exists($parameter->name, $parameters)) {
|
||||
$arguments[] = $parameters[$parameter->name];
|
||||
}
|
||||
elseif ($parameter->isDefaultValueAvailable()) {
|
||||
$arguments[] = $parameter->getDefaultValue();
|
||||
}
|
||||
}
|
||||
unset($parameters['form'], $parameters['form_state']);
|
||||
// Remove $form and $form_state from the arguments, and re-index them.
|
||||
unset($arguments[0], $arguments[1]);
|
||||
$form_state->addBuildInfo('args', array_values($arguments));
|
||||
return $form_state;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
namespace Drupal\ctools\Wizard;
|
||||
|
||||
interface WizardFactoryInterface {
|
||||
/**
|
||||
* Get the wizard form.
|
||||
*
|
||||
* @param FormWizardInterface $wizard
|
||||
* The form wizard
|
||||
* @param array $parameters
|
||||
* The array of default parameters specific to this wizard.
|
||||
* @param bool $ajax
|
||||
* Whether or not this wizard is displayed via ajax modals.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getWizardForm(FormWizardInterface $wizard, array $parameters = [], $ajax = FALSE);
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* A class name implementing FormWizardInterface.
|
||||
* @param array $parameters
|
||||
* The array of parameters specific to this wizard.
|
||||
*
|
||||
* @return \Drupal\ctools\Wizard\FormWizardInterface
|
||||
*/
|
||||
public function createWizard($class, array $parameters);
|
||||
|
||||
/**
|
||||
* Get the wizard form state.
|
||||
*
|
||||
* @param \Drupal\ctools\Wizard\FormWizardInterface $wizard
|
||||
* The form wizard.
|
||||
* @param array $parameters
|
||||
* The array of parameters specific to this wizard.
|
||||
* @param bool $ajax
|
||||
*
|
||||
* @return \Drupal\Core\Form\FormState
|
||||
*/
|
||||
public function getFormState(FormWizardInterface $wizard, array $parameters, $ajax = FALSE);
|
||||
|
||||
}
|
Reference in a new issue