diff --git a/config/schema/page_manager.schema.yml b/config/schema/page_manager.schema.yml index 0cc98c5..8c772bf 100644 --- a/config/schema/page_manager.schema.yml +++ b/config/schema/page_manager.schema.yml @@ -46,6 +46,42 @@ page_manager.page.*: type: string label: 'Context value' +page_manager.page_variant.*.*: + type: config_entity + label: 'Page variant configuration' + mapping: + id: + type: string + label: 'ID' + label: + type: label + label: 'Label' + weight: + type: integer + label: 'Weight' + uuid: + type: string + label: 'UUID' + variant: + type: string + label: 'Display variant' + variant_settings: + type: display_variant.plugin.[%parent.variant] + page: + type: string + label: 'Parent page' + selection_criteria: + type: sequence + label: 'Selection criteria' + sequence: + - type: condition.plugin.[id] + label: 'Selection condition' + selection_logic: + type: string + label: 'Selection logic' + contexts: + type: mapping + page_manager.block_plugin.*: type: block.settings.[id] mapping: @@ -68,15 +104,6 @@ display_variant.plugin.block_display: type: display_variant.plugin label: 'Block display variant' mapping: - selection_logic: - type: string - label: 'Selection logic' - selection_conditions: - type: sequence - label: 'Selection Conditions' - sequence: - - type: condition.plugin.[id] - label: 'Selection Condition' blocks: type: sequence label: 'Blocks' diff --git a/page_manager.links.action.yml b/page_manager.links.action.yml index 713470d..8e9eec5 100644 --- a/page_manager.links.action.yml +++ b/page_manager.links.action.yml @@ -2,4 +2,4 @@ entity.page.add_form: route_name: entity.page.add_form title: 'Add page' appears_on: - - 'page_manager.page_list' + - 'entity.page.collection' diff --git a/page_manager.links.menu.yml b/page_manager.links.menu.yml index f7d73d2..3870671 100644 --- a/page_manager.links.menu.yml +++ b/page_manager.links.menu.yml @@ -1,5 +1,5 @@ -page_manager.page_list: +entity.page.collection: title: 'Pages' parent: system.admin_structure description: 'Manage pages.' - route_name: page_manager.page_list + route_name: entity.page.collection diff --git a/page_manager.routing.yml b/page_manager.routing.yml index 96b0b61..6f5b1e3 100644 --- a/page_manager.routing.yml +++ b/page_manager.routing.yml @@ -1,6 +1,6 @@ #### Pages -page_manager.page_list: +entity.page.collection: path: '/admin/structure/page_manager' defaults: _entity_list: 'page' @@ -118,92 +118,92 @@ page_manager.display_variant_select: requirements: _entity_access: page.update -page_manager.display_variant_add: +entity.page_variant.add_form: path: '/admin/structure/page_manager/manage/{page}/add/{display_variant_id}' defaults: - _form: '\Drupal\page_manager\Form\DisplayVariantAddForm' - _title: 'Add new display variant' + _entity_form: 'page_variant.add' + _title: 'Add page variant' requirements: - _entity_access: page.update + _entity_create_access: page_variant -page_manager.display_variant_edit: - path: '/admin/structure/page_manager/manage/{page}/manage/{display_variant_id}' +entity.page_variant.edit_form: + path: '/admin/structure/page_manager/variant/{page_variant}' defaults: - _form: '\Drupal\page_manager\Form\DisplayVariantEditForm' - _title_callback: '\Drupal\page_manager\Controller\PageManagerController::editDisplayVariantTitle' + _entity_form: 'page_variant.edit' + _title: 'Edit page variant' requirements: - _entity_access: page.update + _entity_access: page_variant.update -page_manager.display_variant_delete: - path: '/admin/structure/page_manager/manage/{page}/manage/{display_variant_id}/delete' +entity.page_variant.delete_form: + path: '/admin/structure/page_variant/variant/{page_variant}/delete' defaults: - _form: '\Drupal\page_manager\Form\DisplayVariantDeleteForm' - _title: 'Delete display variant' + _entity_form: 'page_variant.delete' + _title: 'Delete page variant' requirements: - _entity_access: page.update + _entity_access: page_variant.delete page_manager.display_variant_select_block: - path: '/admin/structure/page_manager/manage/{page}/manage/{display_variant_id}/block/select' + path: '/admin/structure/page_manager/variant/{page_variant}/block/select' defaults: _controller: '\Drupal\page_manager\Controller\PageManagerController::selectBlock' _title: 'Select block' requirements: - _entity_access: page.update + _entity_access: page_variant.update page_manager.display_variant_add_block: - path: '/admin/structure/page_manager/manage/{page}/manage/{display_variant_id}/block/add/{block_id}' + path: '/admin/structure/page_manager/variant/{page_variant}/block/add/{block_id}' defaults: _form: '\Drupal\page_manager\Form\DisplayVariantAddBlockForm' - _title: 'Add block to display variant' + _title: 'Add block to variant' requirements: - _entity_access: page.update + _entity_access: page_variant.update page_manager.display_variant_edit_block: - path: '/admin/structure/page_manager/manage/{page}/manage/{display_variant_id}/block/edit/{block_id}' + path: '/admin/structure/page_manager/variant/{page_variant}/block/edit/{block_id}' defaults: _form: '\Drupal\page_manager\Form\DisplayVariantEditBlockForm' _title: 'Edit block in display variant' requirements: - _entity_access: page.update + _entity_access: page_variant.update page_manager.display_variant_delete_block: - path: '/admin/structure/page_manager/manage/{page}/manage/{display_variant_id}/block/delete/{block_id}' + path: '/admin/structure/page_manager/variant/{page_variant}/block/delete/{block_id}' defaults: _form: '\Drupal\page_manager\Form\DisplayVariantDeleteBlockForm' _title: 'Delete block in display variant' requirements: - _entity_access: page.update + _entity_access: page_variant.update #### Selection Conditions page_manager.selection_condition_select: - path: '/admin/structure/page_manager/manage/{page}/manage/{display_variant_id}/selection/select' + path: '/admin/structure/page_manager/variant/{page_variant}/selection/select' defaults: _controller: '\Drupal\page_manager\Controller\PageManagerController::selectSelectionCondition' _title: 'Select selection condition' requirements: - _entity_access: page.update + _entity_access: page_variant.update page_manager.selection_condition_add: - path: '/admin/structure/page_manager/manage/{page}/manage/{display_variant_id}/selection/add/{condition_id}' + path: '/admin/structure/page_manager/variant/{page_variant}/selection/add/{condition_id}' defaults: _form: '\Drupal\page_manager\Form\SelectionConditionAddForm' _title: 'Add new selection condition' requirements: - _entity_access: page.update + _entity_access: page_variant.update page_manager.selection_condition_edit: - path: '/admin/structure/page_manager/manage/{page}/manage/{display_variant_id}/selection/edit/{condition_id}' + path: '/admin/structure/page_manager/variant/{page_variant}/selection/edit/{condition_id}' defaults: _form: '\Drupal\page_manager\Form\SelectionConditionEditForm' _title_callback: '\Drupal\page_manager\Controller\PageManagerController::editSelectionConditionTitle' requirements: - _entity_access: page.update + _entity_access: page_variant.update page_manager.selection_condition_delete: - path: '/admin/structure/page_manager/manage/{page}/manage/{display_variant_id}/selection/delete/{condition_id}' + path: '/admin/structure/page_manager/variant/{page_variant}/selection/delete/{condition_id}' defaults: _form: '\Drupal\page_manager\Form\SelectionConditionDeleteForm' _title: 'Delete selection condition' requirements: - _entity_access: page.update + _entity_access: page_variant.update diff --git a/src/Controller/PageManagerController.php b/src/Controller/PageManagerController.php index a07f18a..525627e 100644 --- a/src/Controller/PageManagerController.php +++ b/src/Controller/PageManagerController.php @@ -14,6 +14,7 @@ use Drupal\Core\Plugin\Context\ContextHandlerInterface; use Drupal\Core\Url; use Drupal\page_manager\Form\AjaxFormTrait; use Drupal\page_manager\PageInterface; +use Drupal\page_manager\PageVariantEntityInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; @@ -131,20 +132,16 @@ class PageManagerController extends ControllerBase { /** * Route title callback. * - * @param \Drupal\page_manager\PageInterface $page + * @param \Drupal\page_manager\PageVariantEntityInterface $page * The page entity. - * @param string $display_variant_id - * The display variant ID. * @param string $condition_id * The selection condition ID. * * @return string * The title for the selection condition edit form. */ - public function editSelectionConditionTitle(PageInterface $page, $display_variant_id, $condition_id) { - /** @var \Drupal\page_manager\Plugin\ConditionVariantInterface $display_variant */ - $display_variant = $page->getVariant($display_variant_id); - $selection_condition = $display_variant->getSelectionCondition($condition_id); + public function editSelectionConditionTitle(PageVariantEntityInterface $page_variant, $condition_id) { + $selection_condition = $page_variant->getSelectionCondition($condition_id); return $this->t('Edit %label selection condition', ['%label' => $selection_condition->getPluginDefinition()['label']]); } @@ -185,7 +182,7 @@ class PageManagerController extends ControllerBase { drupal_set_message($this->t('The %label page has been disabled.', ['%label' => $page->label()])); } - return $this->redirect('page_manager.page_list'); + return $this->redirect('entity.page.collection'); } /** @@ -205,7 +202,7 @@ class PageManagerController extends ControllerBase { foreach ($this->variantManager->getDefinitions() as $display_variant_id => $display_variant) { $build['#links'][$display_variant_id] = [ 'title' => $display_variant['admin_label'], - 'url' => Url::fromRoute('page_manager.display_variant_add', [ + 'url' => Url::fromRoute('entity.page_variant.add_form', [ 'page' => $page->id(), 'display_variant_id' => $display_variant_id, ]), @@ -246,26 +243,23 @@ class PageManagerController extends ControllerBase { /** * Presents a list of selection conditions to add to the page entity. * - * @param \Drupal\page_manager\PageInterface $page - * The page entity. - * @param string $display_variant_id - * The display variant ID. + * @param \Drupal\page_manager\PageVariantEntityInterface $page_variant + * The page variant entity. * * @return array * The selection condition selection page. */ - public function selectSelectionCondition(PageInterface $page, $display_variant_id) { + public function selectSelectionCondition(PageVariantEntityInterface $page_variant) { $build = [ '#theme' => 'links', '#links' => [], ]; - $available_plugins = $this->conditionManager->getDefinitionsForContexts($page->getContexts()); + $available_plugins = $this->conditionManager->getDefinitionsForContexts($page_variant->getContexts()); foreach ($available_plugins as $selection_id => $selection_condition) { $build['#links'][$selection_id] = [ 'title' => $selection_condition['label'], 'url' => Url::fromRoute('page_manager.selection_condition_add', [ - 'page' => $page->id(), - 'display_variant_id' => $display_variant_id, + 'page_variant' => $page_variant->id(), 'condition_id' => $selection_id, ]), 'attributes' => $this->getAjaxAttributes(), @@ -279,15 +273,13 @@ class PageManagerController extends ControllerBase { * * @param \Symfony\Component\HttpFoundation\Request $request * The current request. - * @param \Drupal\page_manager\PageInterface $page + * @param \Drupal\page_manager\PageVariantEntityInterface $page_variant * The page entity. - * @param string $display_variant_id - * The display variant ID. * * @return array * The block selection page. */ - public function selectBlock(Request $request, PageInterface $page, $display_variant_id) { + public function selectBlock(Request $request, PageVariantEntityInterface $page_variant) { // Add a section containing the available blocks to be added to the variant. $build = [ '#type' => 'container', @@ -297,7 +289,7 @@ class PageManagerController extends ControllerBase { ], ], ]; - $available_plugins = $this->blockManager->getDefinitionsForContexts($page->getContexts()); + $available_plugins = $this->blockManager->getDefinitionsForContexts($page_variant->getPage()->getContexts()); foreach ($available_plugins as $plugin_id => $plugin_definition) { // Make a section for each region. $category = $plugin_definition['category']; @@ -315,8 +307,7 @@ class PageManagerController extends ControllerBase { $build[$category_key]['content']['#links'][$plugin_id] = [ 'title' => $plugin_definition['admin_label'], 'url' => Url::fromRoute('page_manager.display_variant_add_block', [ - 'page' => $page->id(), - 'display_variant_id' => $display_variant_id, + 'page_variant' => $page_variant->id(), 'block_id' => $plugin_id, 'region' => $request->query->get('region'), ]), diff --git a/src/Entity/Page.php b/src/Entity/Page.php index b73ebc5..19e485b 100644 --- a/src/Entity/Page.php +++ b/src/Entity/Page.php @@ -11,7 +11,7 @@ use Drupal\page_manager\PageInterface; use Drupal\Core\Condition\ConditionPluginCollection; use Drupal\Core\Config\Entity\ConfigEntityBase; use Drupal\Core\Entity\EntityStorageInterface; -use Drupal\page_manager\Plugin\VariantAwareTrait; +use Drupal\page_manager\PageVariantEntityInterface; /** * Defines a Page entity class. @@ -40,11 +40,11 @@ use Drupal\page_manager\Plugin\VariantAwareTrait; * "label", * "use_admin_theme", * "path", - * "display_variants", * "access_logic", * "access_conditions", * }, * links = { + * "collection" = "/admin/structure/page_manager", * "add-form" = "/admin/structure/page_manager/add", * "edit-form" = "/admin/structure/page_manager/manage/{page}", * "delete-form" = "/admin/structure/page_manager/manage/{page}/delete", @@ -55,8 +55,6 @@ use Drupal\page_manager\Plugin\VariantAwareTrait; */ class Page extends ConfigEntityBase implements PageInterface { - use VariantAwareTrait; - /** * The ID of the page entity. * @@ -79,11 +77,11 @@ class Page extends ConfigEntityBase implements PageInterface { protected $path; /** - * The configuration of the display variants. + * The page variant entities. * - * @var array + * @var \Drupal\page_manager\Entity\PageVariantEntity[]. */ - protected $display_variants = []; + protected $displayVariants; /** * The configuration of access conditions. @@ -159,7 +157,6 @@ class Page extends ConfigEntityBase implements PageInterface { 'id', 'label', 'path', - 'display_variants', 'access_conditions', 'access_logic', 'use_admin_theme', @@ -190,14 +187,6 @@ class Page extends ConfigEntityBase implements PageInterface { */ public function postCreate(EntityStorageInterface $storage) { parent::postCreate($storage); - // Ensure there is at least one display variant. - if (!count($this->getVariants())) { - $this->addVariant([ - 'id' => 'http_status_code', - 'label' => 'Default', - 'weight' => 10, - ]); - } } /** @@ -240,7 +229,7 @@ class Page extends ConfigEntityBase implements PageInterface { * {@inheritdoc} */ protected function getVariantConfig() { - return $this->get('display_variants'); + return $this->displayVariants; } /** @@ -248,7 +237,6 @@ class Page extends ConfigEntityBase implements PageInterface { */ public function getPluginCollections() { return [ - 'display_variants' => $this->getVariants(), 'access_conditions' => $this->getAccessConditions(), ]; } @@ -345,13 +333,81 @@ class Page extends ConfigEntityBase implements PageInterface { /** * {@inheritdoc} */ + public function addVariant(array $configuration) { + if (empty($configuration['id'])) { + throw new \Exception("Must pass an 'id' for the new page variant."); + } + if (strpos($configuration['id'], '.') === FALSE) { + $configuration['id'] = $this->id() . '.' . $configuration['id']; + } + $configuration['page'] = $this->id(); + /** @var $variant \Drupal\page_manager\PageVariantEntityInterface */ + $variant = \Drupal::entityManager()->getStorage('page_variant')->create($configuration); + return $this->addVariantEntity($variant); + } + + public function addVariantEntity(PageVariantEntityInterface $variant) { + $this->displayVariants[$variant->id()] = $variant; + return $variant->id(); + } + + /** + * {@inheritdoc} + */ + public function getVariant($variant_id) { + $variants = $this->getVariants(); + if (!isset($variants[$variant_id])) { + throw new \Exception('The requested display variant does not exist or is not associated with this page.'); + } + return $variants[$variant_id]; + } + + /** + * {@inheritdoc} + */ + public function removeVariant($variant_id) { + $this->getVariant($variant_id)->delete(); + return $this; + } + + /** + * {@inheritdoc} + */ + public function getVariants() { + if (!isset($this->displayVariants)) { + $this->displayVariants = []; + /** @var $variant \Drupal\page_manager\PageVariantEntityInterface */ + foreach (\Drupal::entityManager()->getStorage('page_variant')->loadByProperties(['page' => $this->id()]) as $variant) { + $this->displayVariants[$variant->uuid()] = $variant; + } + uasort($this->displayVariants, [$this, 'variantSortHelper']); + } + return $this->displayVariants; + } + + /** + * {@inheritdoc} + */ + public function variantSortHelper($a, $b) { + $a_weight = $a->getWeight(); + $b_weight = $b->getWeight(); + if ($a_weight == $b_weight) { + return 0; + } + + return ($a_weight < $b_weight) ? -1 : 1; + } + + /** + * {@inheritdoc} + */ public function __sleep() { $vars = parent::__sleep(); // Avoid serializing plugin collections and the page executable as they // might contain references to a lot of objects including the container. $unset_vars = [ - 'variantCollection' => 'display_variants', + 'displayVariants' => NULL, 'accessConditionCollection' => 'access_variants', 'executable' => NULL, ]; diff --git a/src/Entity/PageVariantEntity.php b/src/Entity/PageVariantEntity.php new file mode 100644 index 0000000..ceaa58f --- /dev/null +++ b/src/Entity/PageVariantEntity.php @@ -0,0 +1,259 @@ +variant_settings = $this->getVariantPlugin()->getConfiguration(); + } + + /** + * {@inheritdoc} + */ + public function calculateDependencies() { + parent::calculateDependencies(); + + $this->addDependency('config', $this->getPage()->getConfigDependencyName()); + + foreach ($this->getSelectionConditions() as $instance) { + $this->calculatePluginDependencies($instance); + } + + return $this->getDependencies(); + } + + /** + * {@inheritdoc} + */ + public function getPluginCollections() { + return [ + 'selection_criteria' => $this->getSelectionConditions(), + ]; + } + + /** + * {@inheritdoc} + */ + public function getVariantPlugin() { + if (!$this->variantPlugin) { + // @todo Inject this service! + $this->variantPlugin = \Drupal::service('plugin.manager.display_variant')->createInstance($this->variant, $this->variant_settings); + } + return $this->variantPlugin; + } + + /** + * {@inheritdoc} + */ + public function getVariantPluginId() { + return $this->variant; + } + + /** + * {@inheritdoc} + */ + public function getPage() { + return Page::load($this->page); + } + + /** + * {@inheritdoc} + */ + public function getContexts() { + return array_merge($this->getPage()->getContexts(), $this->contexts); + } + + /** + * {@inheritdoc} + */ + public function getWeight() { + return $this->weight; + } + + /** + * {@inheritdoc} + */ + public function setWeight($weight) { + $this->weight = $weight; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getSelectionConditions() { + if (!$this->selectionConditionCollection) { + $this->selectionConditionCollection = new ConditionPluginCollection(\Drupal::service('plugin.manager.condition'), $this->get('selection_criteria')); + } + return $this->selectionConditionCollection; + } + + /** + * {@inheritdoc} + */ + public function addSelectionCondition(array $configuration) { + $configuration['uuid'] = $this->uuidGenerator()->generate(); + $this->getSelectionConditions()->addInstanceId($configuration['uuid'], $configuration); + return $configuration['uuid']; + } + + /** + * {@inheritdoc} + */ + public function getSelectionCondition($condition_id) { + return $this->getSelectionConditions()->get($condition_id); + } + + /** + * {@inheritdoc} + */ + public function removeSelectionCondition($condition_id) { + $this->getSelectionConditions()->removeInstanceId($condition_id); + return $this; + } + + /** + * {@inheritdoc} + */ + public function getSelectionLogic() { + return $this->selection_logic; + } + +} diff --git a/src/Entity/PageViewBuilder.php b/src/Entity/PageViewBuilder.php index d1dd584..0c652a2 100644 --- a/src/Entity/PageViewBuilder.php +++ b/src/Entity/PageViewBuilder.php @@ -10,6 +10,7 @@ namespace Drupal\page_manager\Entity; use Drupal\Core\Cache\RefinableCacheableDependencyInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityViewBuilder; +use Symfony\Component\HttpKernel\Exception\HttpException; /** * Provides a view builder for page entities. @@ -20,15 +21,18 @@ class PageViewBuilder extends EntityViewBuilder { * {@inheritdoc} */ public function view(EntityInterface $entity, $view_mode = 'full', $langcode = NULL) { - $build = []; /** @var $entity \Drupal\page_manager\PageInterface */ - if ($display_variant = $entity->getExecutable()->selectDisplayVariant()) { + if ($page_variant = $entity->getExecutable()->selectVariant()) { + $display_variant = $page_variant->getVariantPlugin(); if ($display_variant instanceof RefinableCacheableDependencyInterface) { $display_variant->addCacheableDependency($entity); + $display_variant->addCacheableDependency($page_variant); } - $build = $display_variant->build(); + return $display_variant->build(); + } + else { + throw new HttpException(404); } - return $build; } /** diff --git a/src/Form/AccessConditionFormBase.php b/src/Form/AccessConditionFormBase.php index a0dc108..f50ac9f 100644 --- a/src/Form/AccessConditionFormBase.php +++ b/src/Form/AccessConditionFormBase.php @@ -8,6 +8,7 @@ namespace Drupal\page_manager\Form; use Drupal\Core\Form\FormStateInterface; +use Drupal\page_manager\PageInterface; /** * Provides a base form for editing and adding an access condition. @@ -15,6 +16,21 @@ use Drupal\Core\Form\FormStateInterface; abstract class AccessConditionFormBase extends ConditionFormBase { /** + * The page entity this condition belongs to. + * + * @var \Drupal\page_manager\PageInterface + */ + protected $page; + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state, PageInterface $page = NULL, $condition_id = NULL) { + $this->page = $page; + return parent::buildForm($form, $form_state, $condition_id, $page->getContexts()); + } + + /** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { diff --git a/src/Form/ConditionFormBase.php b/src/Form/ConditionFormBase.php index 7ba10f7..4d0528e 100644 --- a/src/Form/ConditionFormBase.php +++ b/src/Form/ConditionFormBase.php @@ -12,7 +12,6 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormBase; use Drupal\Core\Plugin\ContextAwarePluginInterface; use Drupal\Core\Plugin\ContextAwarePluginAssignmentTrait; -use Drupal\page_manager\PageInterface; /** * Provides a base form for editing and adding a condition. @@ -22,13 +21,6 @@ abstract class ConditionFormBase extends FormBase { use ContextAwarePluginAssignmentTrait; /** - * The page entity this condition belongs to. - * - * @var \Drupal\page_manager\PageInterface - */ - protected $page; - - /** * The condition used by this form. * * @var \Drupal\Core\Condition\ConditionInterface @@ -66,11 +58,10 @@ abstract class ConditionFormBase extends FormBase { /** * {@inheritdoc} */ - public function buildForm(array $form, FormStateInterface $form_state, PageInterface $page = NULL, $condition_id = NULL) { - $this->page = $page; + public function buildForm(array $form, FormStateInterface $form_state, $condition_id = NULL, $contexts = []) { $this->condition = $this->prepareCondition($condition_id); $temporary = $form_state->getTemporary(); - $temporary['gathered_contexts'] = $this->page->getContexts(); + $temporary['gathered_contexts'] = $contexts; $form_state->setTemporary($temporary); // Allow the condition to add to the form. diff --git a/src/Form/DisplayVariantAddBlockForm.php b/src/Form/DisplayVariantAddBlockForm.php index 56f7687..0bb67a1 100644 --- a/src/Form/DisplayVariantAddBlockForm.php +++ b/src/Form/DisplayVariantAddBlockForm.php @@ -9,7 +9,7 @@ namespace Drupal\page_manager\Form; use Drupal\Component\Plugin\PluginManagerInterface; use Drupal\Core\Form\FormStateInterface; -use Drupal\page_manager\PageInterface; +use Drupal\page_manager\PageVariantEntityInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; @@ -53,15 +53,15 @@ class DisplayVariantAddBlockForm extends DisplayVariantConfigureBlockFormBase { */ protected function prepareBlock($plugin_id) { $block = $this->blockManager->createInstance($plugin_id); - $block_id = $this->displayVariant->addBlock($block->getConfiguration()); - return $this->displayVariant->getBlock($block_id); + $block_id = $this->pageVariant->getVariantPlugin()->addBlock($block->getConfiguration()); + return $this->pageVariant->getVariantPlugin()->getBlock($block_id); } /** * {@inheritdoc} */ - public function buildForm(array $form, FormStateInterface $form_state, Request $request = NULL, PageInterface $page = NULL, $display_variant_id = NULL, $block_id = NULL) { - $form = parent::buildForm($form, $form_state, $page, $display_variant_id, $block_id); + public function buildForm(array $form, FormStateInterface $form_state, Request $request = NULL, PageVariantEntityInterface $page_variant = NULL, $block_id = NULL) { + $form = parent::buildForm($form, $form_state, $page_variant, $block_id); $form['region']['#default_value'] = $request->query->get('region'); return $form; } diff --git a/src/Form/DisplayVariantAddForm.php b/src/Form/DisplayVariantAddForm.php deleted file mode 100644 index 334c48b..0000000 --- a/src/Form/DisplayVariantAddForm.php +++ /dev/null @@ -1,85 +0,0 @@ -variantManager = $variant_manager; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('plugin.manager.display_variant') - ); - } - - /** - * {@inheritdoc} - */ - public function getFormId() { - return 'page_manager_display_variant_add_form'; - } - - /** - * {@inheritdoc} - */ - protected function submitText() { - return $this->t('Add display variant'); - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - parent::submitForm($form, $form_state); - - // If this display variant is new, add it to the page. - $display_variant_id = $this->page->addVariant($this->displayVariant->getConfiguration()); - - // Save the page entity. - $this->page->save(); - drupal_set_message($this->t('The %label display variant has been added.', ['%label' => $this->displayVariant->label()])); - $form_state->setRedirect('page_manager.display_variant_edit', [ - 'page' => $this->page->id(), - 'display_variant_id' => $display_variant_id, - ]); - } - - /** - * {@inheritdoc} - */ - protected function prepareDisplayVariant($display_variant_id) { - // Create a new display variant instance. - return $this->variantManager->createInstance($display_variant_id); - } - -} diff --git a/src/Form/DisplayVariantConfigureBlockFormBase.php b/src/Form/DisplayVariantConfigureBlockFormBase.php index 4154681..b8eac83 100644 --- a/src/Form/DisplayVariantConfigureBlockFormBase.php +++ b/src/Form/DisplayVariantConfigureBlockFormBase.php @@ -12,7 +12,7 @@ use Drupal\Core\Form\FormState; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContextAwarePluginAssignmentTrait; use Drupal\Core\Plugin\ContextAwarePluginInterface; -use Drupal\page_manager\PageInterface; +use Drupal\page_manager\PageVariantEntityInterface; /** * Provides a base form for configuring a block as part of a display variant. @@ -24,16 +24,9 @@ abstract class DisplayVariantConfigureBlockFormBase extends FormBase { /** * The page entity. * - * @var \Drupal\page_manager\PageInterface + * @var \Drupal\page_manager\PageVariantEntityInterface */ - protected $page; - - /** - * The display variant. - * - * @var \Drupal\page_manager\Plugin\BlockVariantInterface - */ - protected $displayVariant; + protected $pageVariant; /** * The plugin being configured. @@ -64,11 +57,10 @@ abstract class DisplayVariantConfigureBlockFormBase extends FormBase { /** * {@inheritdoc} */ - public function buildForm(array $form, FormStateInterface $form_state, PageInterface $page = NULL, $display_variant_id = NULL, $block_id = NULL) { - $this->page = $page; - $this->displayVariant = $page->getVariant($display_variant_id); + public function buildForm(array $form, FormStateInterface $form_state, PageVariantEntityInterface $page_variant = NULL, $block_id = NULL) { + $this->pageVariant = $page_variant; $this->block = $this->prepareBlock($block_id); - $form_state->set('display_variant_id', $display_variant_id); + $form_state->set('page_variant_id', $page_variant->id()); $form_state->set('block_id', $this->block->getConfiguration()['uuid']); $form['#tree'] = TRUE; @@ -80,13 +72,13 @@ abstract class DisplayVariantConfigureBlockFormBase extends FormBase { $form['region'] = [ '#title' => $this->t('Region'), '#type' => 'select', - '#options' => $this->displayVariant->getRegionNames(), - '#default_value' => $this->displayVariant->getRegionAssignment($this->block->getConfiguration()['uuid']), + '#options' => $this->pageVariant->getVariantPlugin()->getRegionNames(), + '#default_value' => $this->pageVariant->getVariantPlugin()->getRegionAssignment($this->block->getConfiguration()['uuid']), '#required' => TRUE, ]; if ($this->block instanceof ContextAwarePluginInterface) { - $form['context_mapping'] = $this->addContextAssignmentElement($this->block, $this->page->getContexts()); + $form['context_mapping'] = $this->addContextAssignmentElement($this->block, $this->pageVariant->getPage()->getContexts()); } $form['actions']['submit'] = [ @@ -102,9 +94,8 @@ abstract class DisplayVariantConfigureBlockFormBase extends FormBase { */ public function validateForm(array &$form, FormStateInterface $form_state) { // The page might have been serialized, resulting in a new display variant - // collection. Refresh the display variant and block objects. - $this->displayVariant = $this->page->getVariant($form_state->get('display_variant_id')); - $this->block = $this->displayVariant->getBlock($form_state->get('block_id')); + // collection. Refresh the block object. + $this->block = $this->pageVariant->getVariantPlugin()->getBlock($form_state->get('block_id')); $settings = (new FormState())->setValues($form_state->getValue('settings')); // Call the plugin validate handler. @@ -128,12 +119,11 @@ abstract class DisplayVariantConfigureBlockFormBase extends FormBase { $this->block->setContextMapping($form_state->getValue('context_mapping', [])); } - $this->displayVariant->updateBlock($this->block->getConfiguration()['uuid'], ['region' => $form_state->getValue('region')]); - $this->page->save(); + $this->pageVariant->getVariantPlugin()->updateBlock($this->block->getConfiguration()['uuid'], ['region' => $form_state->getValue('region')]); + $this->pageVariant->save(); - $form_state->setRedirect('page_manager.display_variant_edit', [ - 'page' => $this->page->id(), - 'display_variant_id' => $this->displayVariant->id(), + $form_state->setRedirect('entity.page_variant.edit_form', [ + 'page_variant' => $this->pageVariant->id(), ]); } diff --git a/src/Form/DisplayVariantDeleteBlockForm.php b/src/Form/DisplayVariantDeleteBlockForm.php index 65db0f1..5ff51b1 100644 --- a/src/Form/DisplayVariantDeleteBlockForm.php +++ b/src/Form/DisplayVariantDeleteBlockForm.php @@ -10,7 +10,7 @@ namespace Drupal\page_manager\Form; use Drupal\Core\Form\ConfirmFormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; -use Drupal\page_manager\PageInterface; +use Drupal\page_manager\PageVariantEntityInterface; /** * Provides a form for deleting an access condition. @@ -18,18 +18,11 @@ use Drupal\page_manager\PageInterface; class DisplayVariantDeleteBlockForm extends ConfirmFormBase { /** - * The page entity. + * The page variant. * - * @var \Drupal\page_manager\PageInterface + * @var \Drupal\page_manager\PageVariantEntityInterface */ - protected $page; - - /** - * The display variant. - * - * @var \Drupal\page_manager\Plugin\BlockVariantInterface - */ - protected $displayVariant; + protected $pageVariant; /** * The plugin being configured. @@ -56,9 +49,8 @@ class DisplayVariantDeleteBlockForm extends ConfirmFormBase { * {@inheritdoc} */ public function getCancelUrl() { - return new Url('page_manager.display_variant_edit', [ - 'page' => $this->page->id(), - 'display_variant_id' => $this->displayVariant->id() + return new Url('entity.page_variant.edit_form', [ + 'page_variant' => $this->pageVariant->id(), ]); } @@ -72,10 +64,9 @@ class DisplayVariantDeleteBlockForm extends ConfirmFormBase { /** * {@inheritdoc} */ - public function buildForm(array $form, FormStateInterface $form_state, PageInterface $page = NULL, $display_variant_id = NULL, $block_id = NULL) { - $this->page = $page; - $this->displayVariant = $this->page->getVariant($display_variant_id); - $this->block = $this->displayVariant->getBlock($block_id); + public function buildForm(array $form, FormStateInterface $form_state, PageVariantEntityInterface $page_variant = NULL, $block_id = NULL) { + $this->pageVariant = $page_variant; + $this->block = $this->pageVariant->getVariantPlugin()->getBlock($block_id); return parent::buildForm($form, $form_state); } @@ -83,8 +74,8 @@ class DisplayVariantDeleteBlockForm extends ConfirmFormBase { * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { - $this->displayVariant->removeBlock($this->block->getConfiguration()['uuid']); - $this->page->save(); + $this->pageVariant->getVariantPlugin()->removeBlock($this->block->getConfiguration()['uuid']); + $this->pageVariant->save(); drupal_set_message($this->t('The block %label has been removed.', ['%label' => $this->block->label()])); $form_state->setRedirectUrl($this->getCancelUrl()); diff --git a/src/Form/DisplayVariantEditBlockForm.php b/src/Form/DisplayVariantEditBlockForm.php index 1bb4532..ba101e4 100644 --- a/src/Form/DisplayVariantEditBlockForm.php +++ b/src/Form/DisplayVariantEditBlockForm.php @@ -23,7 +23,7 @@ class DisplayVariantEditBlockForm extends DisplayVariantConfigureBlockFormBase { * {@inheritdoc} */ protected function prepareBlock($block_id) { - return $this->displayVariant->getBlock($block_id); + return $this->pageVariant->getVariantPlugin()->getBlock($block_id); } /** diff --git a/src/Form/DisplayVariantEditForm.php b/src/Form/DisplayVariantEditForm.php deleted file mode 100644 index 990f462..0000000 --- a/src/Form/DisplayVariantEditForm.php +++ /dev/null @@ -1,333 +0,0 @@ -t('Update display variant'); - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state, PageInterface $page = NULL, $display_variant_id = NULL) { - $form = parent::buildForm($form, $form_state, $page, $display_variant_id); - - if ($this->displayVariant instanceof BlockVariantInterface) { - $form['block_section'] = $this->buildBlockForm(); - } - if ($this->displayVariant instanceof ConditionVariantInterface) { - $form['selection_section'] = $this->buildSelectionForm(); - } - - return $form; - } - - /** - * Builds the block form for a variant. - * - * @return array - */ - protected function buildBlockForm() { - if (!$this->displayVariant instanceof BlockVariantInterface) { - return []; - } - - // Determine the page ID, used for links below. - $page_id = $this->getPage()->id(); - - // Set up the attributes used by a modal to prevent duplication later. - $attributes = $this->getAjaxAttributes(); - $add_button_attributes = $this->getAjaxButtonAttributes(); - - $form = []; - if ($block_assignments = $this->displayVariant->getRegionAssignments()) { - // Build a table of all blocks used by this display variant. - $form = [ - '#type' => 'details', - '#title' => $this->t('Blocks'), - '#open' => TRUE, - ]; - $form['add'] = [ - '#type' => 'link', - '#title' => $this->t('Add new block'), - '#url' => Url::fromRoute('page_manager.display_variant_select_block', [ - 'page' => $page_id, - 'display_variant_id' => $this->displayVariant->id(), - ]), - '#attributes' => $add_button_attributes, - '#attached' => [ - 'library' => [ - 'core/drupal.ajax', - ], - ], - ]; - $form['blocks'] = [ - '#type' => 'table', - '#header' => [ - $this->t('Label'), - $this->t('Plugin ID'), - $this->t('Region'), - $this->t('Weight'), - $this->t('Operations'), - ], - '#empty' => $this->t('There are no regions for blocks.'), - // @todo This should utilize https://drupal.org/node/2065485. - '#parents' => ['display_variant', 'blocks'], - ]; - // Loop through the blocks per region. - foreach ($block_assignments as $region => $blocks) { - // Add a section for each region and allow blocks to be dragged between - // them. - $form['blocks']['#tabledrag'][] = [ - 'action' => 'match', - 'relationship' => 'sibling', - 'group' => 'block-region-select', - 'subgroup' => 'block-region-' . $region, - 'hidden' => FALSE, - ]; - $form['blocks']['#tabledrag'][] = [ - 'action' => 'order', - 'relationship' => 'sibling', - 'group' => 'block-weight', - 'subgroup' => 'block-weight-' . $region, - ]; - $form['blocks'][$region] = [ - '#attributes' => [ - 'class' => ['region-title', 'region-title-' . $region], - 'no_striping' => TRUE, - ], - ]; - $form['blocks'][$region]['title'] = [ - '#markup' => $this->displayVariant->getRegionName($region), - '#wrapper_attributes' => [ - 'colspan' => 5, - ], - ]; - $form['blocks'][$region . '-message'] = [ - '#attributes' => [ - 'class' => [ - 'region-message', - 'region-' . $region . '-message', - empty($blocks) ? 'region-empty' : 'region-populated', - ], - ], - ]; - $form['blocks'][$region . '-message']['message'] = [ - '#markup' => '' . $this->t('No blocks in this region') . '', - '#wrapper_attributes' => [ - 'colspan' => 5, - ], - ]; - - /** @var $blocks \Drupal\Core\Block\BlockPluginInterface[] */ - foreach ($blocks as $block_id => $block) { - $row = [ - '#attributes' => [ - 'class' => ['draggable'], - ], - ]; - $row['label']['#markup'] = $block->label(); - $row['id']['#markup'] = $block->getPluginId(); - // Allow the region to be changed for each block. - $row['region'] = [ - '#title' => $this->t('Region'), - '#title_display' => 'invisible', - '#type' => 'select', - '#options' => $this->displayVariant->getRegionNames(), - '#default_value' => $this->displayVariant->getRegionAssignment($block_id), - '#attributes' => [ - 'class' => ['block-region-select', 'block-region-' . $region], - ], - ]; - // Allow the weight to be changed for each block. - $configuration = $block->getConfiguration(); - $row['weight'] = [ - '#type' => 'weight', - '#default_value' => isset($configuration['weight']) ? $configuration['weight'] : 0, - '#title' => $this->t('Weight for @block block', ['@block' => $block->label()]), - '#title_display' => 'invisible', - '#attributes' => [ - 'class' => ['block-weight', 'block-weight-' . $region], - ], - ]; - // Add the operation links. - $operations = []; - $operations['edit'] = [ - 'title' => $this->t('Edit'), - 'url' => Url::fromRoute('page_manager.display_variant_edit_block', [ - 'page' => $page_id, - 'display_variant_id' => $this->displayVariant->id(), - 'block_id' => $block_id, - ]), - 'attributes' => $attributes, - ]; - $operations['delete'] = [ - 'title' => $this->t('Delete'), - 'url' => Url::fromRoute('page_manager.display_variant_delete_block', [ - 'page' => $page_id, - 'display_variant_id' => $this->displayVariant->id(), - 'block_id' => $block_id, - ]), - 'attributes' => $attributes, - ]; - - $row['operations'] = [ - '#type' => 'operations', - '#links' => $operations, - ]; - $form['blocks'][$block_id] = $row; - } - } - } - return $form; - } - - /** - * Builds the selection form for a variant. - * - * @return array - */ - protected function buildSelectionForm() { - // Set up the attributes used by a modal to prevent duplication later. - $attributes = $this->getAjaxAttributes(); - $add_button_attributes = $this->getAjaxButtonAttributes(); - - $form = []; - if ($this->displayVariant instanceof ConditionVariantInterface) { - if ($selection_conditions = $this->displayVariant->getSelectionConditions()) { - // Selection conditions. - $form = [ - '#type' => 'details', - '#title' => $this->t('Selection Conditions'), - '#open' => TRUE, - ]; - $form['add'] = [ - '#type' => 'link', - '#title' => $this->t('Add new selection condition'), - '#url' => Url::fromRoute('page_manager.selection_condition_select', [ - 'page' => $this->page->id(), - 'display_variant_id' => $this->displayVariant->id(), - ]), - '#attributes' => $add_button_attributes, - '#attached' => [ - 'library' => [ - 'core/drupal.ajax', - ], - ], - ]; - $form['table'] = [ - '#type' => 'table', - '#header' => [ - $this->t('Label'), - $this->t('Description'), - $this->t('Operations'), - ], - '#empty' => $this->t('There are no selection conditions.'), - ]; - - $form['selection_logic'] = [ - '#type' => 'radios', - '#options' => [ - 'and' => $this->t('All conditions must pass'), - 'or' => $this->t('Only one condition must pass'), - ], - '#default_value' => $this->displayVariant->getSelectionLogic(), - ]; - - $form['selection'] = [ - '#tree' => TRUE, - ]; - foreach ($selection_conditions as $selection_id => $selection_condition) { - $row = []; - $row['label']['#markup'] = $selection_condition->getPluginDefinition()['label']; - $row['description']['#markup'] = $selection_condition->summary(); - $operations = []; - $operations['edit'] = [ - 'title' => $this->t('Edit'), - 'url' => Url::fromRoute('page_manager.selection_condition_edit', [ - 'page' => $this->page->id(), - 'display_variant_id' => $this->displayVariant->id(), - 'condition_id' => $selection_id, - ]), - 'attributes' => $attributes, - ]; - $operations['delete'] = [ - 'title' => $this->t('Delete'), - 'url' => Url::fromRoute('page_manager.selection_condition_delete', [ - 'page' => $this->page->id(), - 'display_variant_id' => $this->displayVariant->id(), - 'condition_id' => $selection_id, - ]), - 'attributes' => $attributes, - ]; - $row['operations'] = [ - '#type' => 'operations', - '#links' => $operations, - ]; - $form['table'][$selection_id] = $row; - } - } - } - - return $form; - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - // @todo This feels very wrong. - if ($this->displayVariant instanceof BlockVariantInterface) { - // If the blocks were rearranged, update their values. - if (!$form_state->isValueEmpty(['display_variant', 'blocks'])) { - foreach ($form_state->getValue(['display_variant', 'blocks']) as $block_id => $block_values) { - $this->displayVariant->updateBlock($block_id, $block_values); - } - } - } - - parent::submitForm($form, $form_state); - - // Save the page entity. - $this->page->save(); - drupal_set_message($this->t('The %label display variant has been updated.', ['%label' => $this->displayVariant->label()])); - $form_state->setRedirectUrl($this->page->urlInfo('edit-form')); - } - - /** - * {@inheritdoc} - */ - protected function prepareDisplayVariant($display_variant_id) { - // Load the display variant directly from the page entity. - return $this->page->getVariant($display_variant_id); - } - -} diff --git a/src/Form/DisplayVariantFormBase.php b/src/Form/DisplayVariantFormBase.php deleted file mode 100644 index be22098..0000000 --- a/src/Form/DisplayVariantFormBase.php +++ /dev/null @@ -1,122 +0,0 @@ -page; - } - - /** - * {@inheritdoc} - */ - public function getDisplayVariant() { - return $this->displayVariant; - } - - /** - * Returns the text to use for the submit button. - * - * @return string - * The submit button text. - */ - abstract protected function submitText(); - - /** - * {@inheritdoc} - */ - public function getBaseFormId() { - return 'page_manager_display_variant_form'; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state, PageInterface $page = NULL, $display_variant_id = NULL) { - $this->page = $page; - $this->displayVariant = $this->prepareDisplayVariant($display_variant_id); - if ($this->displayVariant instanceof ContextAwareVariantInterface) { - $this->displayVariant->setContexts($this->page->getExecutable()->getContexts()); - } - - // Allow the display variant to add to the form. - $form['display_variant'] = $this->displayVariant->buildConfigurationForm([], $form_state); - $form['display_variant']['#tree'] = TRUE; - - $form['actions'] = ['#type' => 'actions']; - $form['actions']['submit'] = [ - '#type' => 'submit', - '#value' => $this->submitText(), - '#button_type' => 'primary', - ]; - - return $form; - } - - /** - * {@inheritdoc} - */ - public function validateForm(array &$form, FormStateInterface $form_state) { - // Allow the display variant to validate the form. - $display_variant_values = (new FormState())->setValues($form_state->getValue('display_variant')); - $this->displayVariant->validateConfigurationForm($form, $display_variant_values); - // Update the original form values. - $form_state->setValue('display_variant', $display_variant_values->getValues()); - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - // Allow the display variant to submit the form. - $display_variant_values = (new FormState())->setValues($form_state->getValue('display_variant')); - $this->displayVariant->submitConfigurationForm($form, $display_variant_values); - // Update the original form values. - $form_state->setValue('display_variant', $display_variant_values->getValues()); - } - -} diff --git a/src/Form/DisplayVariantFormInterface.php b/src/Form/DisplayVariantFormInterface.php deleted file mode 100644 index e615c3f..0000000 --- a/src/Form/DisplayVariantFormInterface.php +++ /dev/null @@ -1,31 +0,0 @@ - 'display-variant-weight', ]], ]; - foreach ($this->entity->getVariants() as $display_variant_id => $display_variant) { + /** @var \Drupal\page_manager\PageVariantEntityInterface $page_variant */ + foreach ($this->entity->getVariants() as $page_variant) { $row = [ '#attributes' => [ 'class' => ['draggable'], ], ]; - $row['label']['#markup'] = $display_variant->label(); - $row['id']['#markup'] = $display_variant->adminLabel(); + $row['label']['#markup'] = $page_variant->label(); + $row['id']['#markup'] = $page_variant->getVariantPlugin()->adminLabel(); $row['weight'] = [ '#type' => 'weight', - '#default_value' => $display_variant->getWeight(), - '#title' => $this->t('Weight for @display_variant display variant', ['@display_variant' => $display_variant->label()]), + '#default_value' => $page_variant->getWeight(), + '#title' => $this->t('Weight for @page_variant variant', ['@page_variant' => $page_variant->label()]), '#title_display' => 'invisible', '#attributes' => [ 'class' => ['display-variant-weight'], @@ -155,23 +156,21 @@ class PageEditForm extends PageFormBase { $operations = []; $operations['edit'] = [ 'title' => $this->t('Edit'), - 'url' => Url::fromRoute('page_manager.display_variant_edit', [ - 'page' => $this->entity->id(), - 'display_variant_id' => $display_variant_id, + 'url' => Url::fromRoute('entity.page_variant.edit_form', [ + 'page_variant' => $page_variant->id(), ]), ]; $operations['delete'] = [ 'title' => $this->t('Delete'), - 'url' => Url::fromRoute('page_manager.display_variant_delete', [ - 'page' => $this->entity->id(), - 'display_variant_id' => $display_variant_id, + 'url' => Url::fromRoute('entity.page_variant.delete_form', [ + 'page_variant' => $page_variant->id(), ]), ]; $row['operations'] = [ '#type' => 'operations', '#links' => $operations, ]; - $form['display_variant_section']['display_variants'][$display_variant_id] = $row; + $form['display_variant_section']['display_variants'][$page_variant->uuid()] = $row; } if ($access_conditions = $this->entity->getAccessConditions()) { @@ -254,12 +253,13 @@ class PageEditForm extends PageFormBase { foreach ($form_state->getValue('display_variants') as $display_variant_id => $data) { if ($display_variant = $this->entity->getVariant($display_variant_id)) { $display_variant->setWeight($data['weight']); + $display_variant->save(); } } } parent::save($form, $form_state); drupal_set_message($this->t('The %label page has been updated.', ['%label' => $this->entity->label()])); - $form_state->setRedirect('page_manager.page_list'); + $form_state->setRedirect('entity.page.collection'); } } diff --git a/src/Form/PageVariantAddForm.php b/src/Form/PageVariantAddForm.php new file mode 100644 index 0000000..48b142a --- /dev/null +++ b/src/Form/PageVariantAddForm.php @@ -0,0 +1,50 @@ +t('Add display variant'); + } + + /** + * @inheritDoc + */ + protected function prepareEntity() { + parent::prepareEntity(); + + /** @var PageVariantEntityInterface $page_variant */ + $page_variant = $this->getEntity(); + + // Set some default values. + $page_variant->set('page', $this->getRouteMatch()->getParameter('page')); + $page_variant->set('variant', $this->getRouteMatch()->getParameter('display_variant_id')); + } + + /** + * {@inheritdoc} + */ + public function save(array $form, FormStateInterface $form_state) { + parent::save($form, $form_state); + $form_state->setRedirectUrl($this->getEntity()->urlInfo('edit-form')); + } + +} diff --git a/src/Form/PageVariantConfigureForm.php b/src/Form/PageVariantConfigureForm.php new file mode 100644 index 0000000..fe3c543 --- /dev/null +++ b/src/Form/PageVariantConfigureForm.php @@ -0,0 +1,66 @@ +getTemporaryValue('wizard'); + /** @var $page_variant \Drupal\page_manager\Entity\PageVariantEntity */ + $page_variant = $cached_values['variant']; + $variant = $page_variant->getVariantPlugin(); + return $variant->buildConfigurationForm($form, $form_state); + } + + /** + * Form submission handler. + * + * @param array $form + * An associative array containing the structure of the form. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The current state of the form. + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $cached_values = $form_state->getTemporaryValue('wizard'); + /** @var $page \Drupal\page_manager\Entity\Page */ + $page = $cached_values['page']; + /** @var $page_variant \Drupal\page_manager\Entity\PageVariantEntity */ + $page_variant = $cached_values['variant']; + $variant = $page_variant->getVariantPlugin(); + $variant->submitConfigurationForm($form, $form_state); + $configuration = $variant->getConfiguration(); + $page_variant->set('variant_settings', $configuration); + $page_variant->set('label', $configuration['label']); + $page->addVariantEntity($page_variant); + } + +} diff --git a/src/Form/PageVariantDeleteForm.php b/src/Form/PageVariantDeleteForm.php new file mode 100644 index 0000000..7789b75 --- /dev/null +++ b/src/Form/PageVariantDeleteForm.php @@ -0,0 +1,58 @@ +t('Are you sure you want to delete %name?', array('%name' => $this->entity->label())); + } + + /** + * {@inheritdoc} + */ + public function getCancelUrl() { + return new Url('entity.page.edit_form', [ + 'page' => $this->entity->getPage()->id(), + ]); + } + + /** + * {@inheritdoc} + */ + public function getConfirmText() { + return $this->t('Delete'); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $this->entity->delete(); + + drupal_set_message( + $this->t('The display variant %label has been removed.', + [ + '@label' => $this->entity->label() + ] + ) + ); + + $form_state->setRedirectUrl($this->getCancelUrl()); + } + +} diff --git a/src/Form/PageVariantEditForm.php b/src/Form/PageVariantEditForm.php new file mode 100644 index 0000000..bbafb07 --- /dev/null +++ b/src/Form/PageVariantEditForm.php @@ -0,0 +1,306 @@ +t('Update display variant'); + } + + /** + * @{inheritdoc} + */ + public function form(array $form, FormStateInterface $form_state) { + $form = parent::form($form, $form_state); + + if ($this->getVariantPlugin() instanceof BlockVariantInterface) { + $form['variant_settings']['block_section'] = $this->buildBlockForm(); + } + + $form['selection_section'] = $this->buildSelectionForm(); + + return $form; + } + + /** + * Builds the block form for a variant. + * + * @return array + */ + protected function buildBlockForm() { + if (!$this->getVariantPlugin() instanceof BlockVariantInterface) { + return []; + } + + /** @var \Drupal\page_manager\PageVariantInterface $page_variant */ + $page_variant = $this->getEntity(); + + // Set up the attributes used by a modal to prevent duplication later. + $attributes = $this->getAjaxAttributes(); + $add_button_attributes = $this->getAjaxButtonAttributes(); + + $form = []; + if ($block_assignments = $this->getVariantPlugin()->getRegionAssignments()) { + // Build a table of all blocks used by this display variant. + $form = [ + '#type' => 'details', + '#title' => $this->t('Blocks'), + '#open' => TRUE, + ]; + $form['add'] = [ + '#type' => 'link', + '#title' => $this->t('Add new block'), + '#url' => Url::fromRoute('page_manager.display_variant_select_block', [ + 'page_variant' => $page_variant->id(), + ]), + '#attributes' => $add_button_attributes, + '#attached' => [ + 'library' => [ + 'core/drupal.ajax', + ], + ], + ]; + $form['blocks'] = [ + '#type' => 'table', + '#header' => [ + $this->t('Label'), + $this->t('Plugin ID'), + $this->t('Region'), + $this->t('Weight'), + $this->t('Operations'), + ], + '#empty' => $this->t('There are no regions for blocks.'), + // @todo This should utilize https://drupal.org/node/2065485. + '#parents' => ['display_variant', 'blocks'], + ]; + // Loop through the blocks per region. + foreach ($block_assignments as $region => $blocks) { + // Add a section for each region and allow blocks to be dragged between + // them. + $form['blocks']['#tabledrag'][] = [ + 'action' => 'match', + 'relationship' => 'sibling', + 'group' => 'block-region-select', + 'subgroup' => 'block-region-' . $region, + 'hidden' => FALSE, + ]; + $form['blocks']['#tabledrag'][] = [ + 'action' => 'order', + 'relationship' => 'sibling', + 'group' => 'block-weight', + 'subgroup' => 'block-weight-' . $region, + ]; + $form['blocks'][$region] = [ + '#attributes' => [ + 'class' => ['region-title', 'region-title-' . $region], + 'no_striping' => TRUE, + ], + ]; + $form['blocks'][$region]['title'] = [ + '#markup' => $this->getVariantPlugin()->getRegionName($region), + '#wrapper_attributes' => [ + 'colspan' => 5, + ], + ]; + $form['blocks'][$region . '-message'] = [ + '#attributes' => [ + 'class' => [ + 'region-message', + 'region-' . $region . '-message', + empty($blocks) ? 'region-empty' : 'region-populated', + ], + ], + ]; + $form['blocks'][$region . '-message']['message'] = [ + '#markup' => '' . $this->t('No blocks in this region') . '', + '#wrapper_attributes' => [ + 'colspan' => 5, + ], + ]; + + /** @var $blocks \Drupal\Core\Block\BlockPluginInterface[] */ + foreach ($blocks as $block_id => $block) { + $row = [ + '#attributes' => [ + 'class' => ['draggable'], + ], + ]; + $row['label']['#markup'] = $block->label(); + $row['id']['#markup'] = $block->getPluginId(); + // Allow the region to be changed for each block. + $row['region'] = [ + '#title' => $this->t('Region'), + '#title_display' => 'invisible', + '#type' => 'select', + '#options' => $this->getVariantPlugin()->getRegionNames(), + '#default_value' => $this->getVariantPlugin()->getRegionAssignment($block_id), + '#attributes' => [ + 'class' => ['block-region-select', 'block-region-' . $region], + ], + ]; + // Allow the weight to be changed for each block. + $configuration = $block->getConfiguration(); + $row['weight'] = [ + '#type' => 'weight', + '#default_value' => isset($configuration['weight']) ? $configuration['weight'] : 0, + '#title' => $this->t('Weight for @block block', ['@block' => $block->label()]), + '#title_display' => 'invisible', + '#attributes' => [ + 'class' => ['block-weight', 'block-weight-' . $region], + ], + ]; + // Add the operation links. + $operations = []; + $operations['edit'] = [ + 'title' => $this->t('Edit'), + 'url' => Url::fromRoute('page_manager.display_variant_edit_block', [ + 'page_variant' => $page_variant->id(), + 'block_id' => $block_id, + ]), + 'attributes' => $attributes, + ]; + $operations['delete'] = [ + 'title' => $this->t('Delete'), + 'url' => Url::fromRoute('page_manager.display_variant_delete_block', [ + 'page_variant' => $page_variant->id(), + 'block_id' => $block_id, + ]), + 'attributes' => $attributes, + ]; + + $row['operations'] = [ + '#type' => 'operations', + '#links' => $operations, + ]; + $form['blocks'][$block_id] = $row; + } + } + } + return $form; + } + + /** + * Builds the selection form for a variant. + * + * @return array + */ + protected function buildSelectionForm() { + // Set up the attributes used by a modal to prevent duplication later. + $attributes = $this->getAjaxAttributes(); + $add_button_attributes = $this->getAjaxButtonAttributes(); + + /** @var \Drupal\page_manager\PageVariantEntityInterface $page_variant */ + $page_variant = $this->getEntity(); + + // Selection conditions. + $form = [ + '#type' => 'details', + '#title' => $this->t('Selection Conditions'), + '#open' => TRUE, + ]; + $form['add'] = [ + '#type' => 'link', + '#title' => $this->t('Add new selection condition'), + '#url' => Url::fromRoute('page_manager.selection_condition_select', [ + 'page_variant' => $page_variant->id(), + ]), + '#attributes' => $add_button_attributes, + '#attached' => [ + 'library' => [ + 'core/drupal.ajax', + ], + ], + ]; + $form['table'] = [ + '#type' => 'table', + '#header' => [ + $this->t('Label'), + $this->t('Description'), + $this->t('Operations'), + ], + '#empty' => $this->t('There are no selection conditions.'), + ]; + + $form['selection_logic'] = [ + '#type' => 'radios', + '#options' => [ + 'and' => $this->t('All conditions must pass'), + 'or' => $this->t('Only one condition must pass'), + ], + '#default_value' => $page_variant->getSelectionLogic(), + ]; + + $form['selection'] = [ + '#tree' => TRUE, + ]; + foreach ($page_variant->getSelectionConditions() as $selection_id => $selection_condition) { + $row = []; + $row['label']['#markup'] = $selection_condition->getPluginDefinition()['label']; + $row['description']['#markup'] = $selection_condition->summary(); + $operations = []; + $operations['edit'] = [ + 'title' => $this->t('Edit'), + 'url' => Url::fromRoute('page_manager.selection_condition_edit', [ + 'page_variant' => $page_variant->id(), + 'condition_id' => $selection_id, + ]), + 'attributes' => $attributes, + ]; + $operations['delete'] = [ + 'title' => $this->t('Delete'), + 'url' => Url::fromRoute('page_manager.selection_condition_delete', [ + 'page_variant' => $page_variant->id(), + 'condition_id' => $selection_id, + ]), + 'attributes' => $attributes, + ]; + $row['operations'] = [ + '#type' => 'operations', + '#links' => $operations, + ]; + $form['table'][$selection_id] = $row; + } + + return $form; + } + + public function save(array $form, FormStateInterface $form_state) { + parent::save($form, $form_state); + + // @todo This feels very wrong. + if ($this->getVariantPlugin() instanceof BlockVariantInterface) { + // If the blocks were rearranged, update their values. + if (!$form_state->isValueEmpty(['display_variant', 'blocks'])) { + foreach ($form_state->getValue(['display_variant', 'blocks']) as $block_id => $block_values) { + $this->getVariantPlugin()->updateBlock($block_id, $block_values); + } + } + } + + $form_state->setRedirectUrl($this->getEntity()->getPage()->urlInfo('edit-form')); + } + +} diff --git a/src/Form/PageVariantFormBase.php b/src/Form/PageVariantFormBase.php new file mode 100644 index 0000000..5913f1e --- /dev/null +++ b/src/Form/PageVariantFormBase.php @@ -0,0 +1,187 @@ +variantPlugin) { + /** @var PageVariantEntityInterface $page_variant */ + $page_variant = $this->getEntity(); + $this->variantPlugin = $page_variant->getVariantPlugin(); + } + + return $this->variantPlugin; + } + + /** + * Construct a new PageFormBase. + * + * @param \Drupal\Core\Entity\Query\QueryFactory $entity_query + * The entity query factory. + */ + public function __construct(QueryFactory $entity_query) { + $this->entityQuery = $entity_query; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity.query') + ); + } + + /** + * Returns the text to use for the submit button. + * + * @return string + * The submit button text. + */ + abstract protected function submitText(); + + /** + * {@inheritdoc} + */ + public function form(array $form, FormStateInterface $form_state) { + $form = parent::form($form, $form_state); + + /** @var PageVariantEntityInterface $page_variant */ + $page_variant = $this->getEntity(); + + $form['label'] = [ + '#type' => 'textfield', + '#title' => $this->t('Label'), + '#description' => $this->t('The label for this variant.'), + '#default_value' => $page_variant->label() ?: (string) $this->getVariantPlugin() + ->adminLabel(), + '#maxlength' => '255', + ]; + + $form['id'] = [ + '#type' => 'machine_name', + '#disabled' => !$page_variant->isNew(), + '#default_value' => !$page_variant->isNew() ? explode('.', $page_variant->id())[1] : '', + '#machine_name' => [ + 'exists' => [$this, 'exists'], + ], + ]; + + // Allow the display variant to add to the form. + $form['variant_settings'] = $this->getVariantPlugin()->buildConfigurationForm([], $form_state); + $form['variant_settings']['#tree'] = TRUE; + + $form['actions'] = ['#type' => 'actions']; + $form['actions']['submit'] = [ + '#type' => 'submit', + '#value' => 'Add/Edit', + '#button_type' => 'primary', + ]; + + return $form; + } + + /** + * Determines if the page variant entity already exists. + * + * @param string $id + * The page variant entity ID. + * + * @return bool + * TRUE if the entity exists, FALSE otherwise. + */ + public function exists($id) { + $this->prepareEntity(); + + /** @var PageVariantEntityInterface $page_variant */ + $page_variant = $this->getEntity(); + return (bool) $this->entityQuery->get('page_variant') + ->condition('id', $page_variant->get('page') . '.' . $id) + ->execute(); + } + + /** + * {@inheritdoc} + */ + public function save(array $form, FormStateInterface $form_state) { + /** @var PageVariantEntityInterface $page_variant */ + $page_variant = $this->getEntity(); + $page_variant->set('id', $page_variant->get('page') . '.' . $page_variant->id()); + $status = $page_variant->save(); + + if ($status) { + drupal_set_message($this->t('Saved the %label variant.', [ + '%label' => $page_variant->label(), + ])); + } + else { + drupal_set_message($this->t('The %label variant was not saved.', [ + '%label' => $page_variant->label(), + ])); + } + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, FormStateInterface $form_state) { + parent::validateForm($form, $form_state); + + // Allow the display variant to validate the form. + $display_variant_values = (new FormState())->setValues($form_state->getValue('variant_settings')); + $this->getVariantPlugin()->validateConfigurationForm($form, $display_variant_values); + // Update the original form values. + $form_state->setValue('variant_settings', $display_variant_values->getValues()); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + // Allow the display variant to submit the form. + $display_variant_values = (new FormState())->setValues($form_state->getValue('variant_settings')); + $this->getVariantPlugin()->submitConfigurationForm($form, $display_variant_values); + // Update the original form values. + $form_state->setValue('variant_settings', $display_variant_values->getValues()); + + parent::submitForm($form, $form_state); + } + +} diff --git a/src/Form/SelectionConditionDeleteForm.php b/src/Form/SelectionConditionDeleteForm.php index 0b2f406..cef609f 100644 --- a/src/Form/SelectionConditionDeleteForm.php +++ b/src/Form/SelectionConditionDeleteForm.php @@ -8,9 +8,9 @@ namespace Drupal\page_manager\Form; use Drupal\Core\Form\FormStateInterface; -use Drupal\page_manager\PageInterface; use Drupal\Core\Form\ConfirmFormBase; use Drupal\Core\Url; +use Drupal\page_manager\PageVariantEntityInterface; /** * @todo. @@ -20,16 +20,9 @@ class SelectionConditionDeleteForm extends ConfirmFormBase { /** * The page entity this selection condition belongs to. * - * @var \Drupal\page_manager\PageInterface + * @var \Drupal\page_manager\PageVariantEntityInterface */ - protected $page; - - /** - * The display variant. - * - * @var \Drupal\page_manager\Plugin\ConditionVariantInterface - */ - protected $displayVariant; + protected $pageVariant; /** * The selection condition used by this form. @@ -56,9 +49,8 @@ class SelectionConditionDeleteForm extends ConfirmFormBase { * {@inheritdoc} */ public function getCancelUrl() { - return new Url('page_manager.display_variant_edit', [ - 'page' => $this->page->id(), - 'display_variant_id' => $this->displayVariant->id(), + return new Url('entity.page_variant.edit_form', [ + 'page_variant' => $this->pageVariant->id(), ]); } @@ -72,10 +64,9 @@ class SelectionConditionDeleteForm extends ConfirmFormBase { /** * {@inheritdoc} */ - public function buildForm(array $form, FormStateInterface $form_state, PageInterface $page = NULL, $display_variant_id = NULL, $condition_id = NULL) { - $this->page = $page; - $this->displayVariant = $this->page->getVariant($display_variant_id); - $this->selectionCondition = $this->displayVariant->getSelectionCondition($condition_id); + public function buildForm(array $form, FormStateInterface $form_state, PageVariantEntityInterface $page_variant = NULL, $condition_id = NULL) { + $this->pageVariant = $page_variant; + $this->selectionCondition = $page_variant->getSelectionCondition($condition_id); return parent::buildForm($form, $form_state); } @@ -83,8 +74,8 @@ class SelectionConditionDeleteForm extends ConfirmFormBase { * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { - $this->displayVariant->removeSelectionCondition($this->selectionCondition->getConfiguration()['uuid']); - $this->page->save(); + $this->pageVariant->removeSelectionCondition($this->selectionCondition->getConfiguration()['uuid']); + $this->pageVariant->save(); drupal_set_message($this->t('The selection condition %name has been removed.', ['%name' => $this->selectionCondition->getPluginDefinition()['label']])); $form_state->setRedirectUrl($this->getCancelUrl()); } diff --git a/src/Form/SelectionConditionEditForm.php b/src/Form/SelectionConditionEditForm.php index 59b6011..881e952 100644 --- a/src/Form/SelectionConditionEditForm.php +++ b/src/Form/SelectionConditionEditForm.php @@ -24,7 +24,7 @@ class SelectionConditionEditForm extends SelectionConditionFormBase { */ protected function prepareCondition($condition_id) { // Load the selection condition directly from the display variant. - return $this->displayVariant->getSelectionCondition($condition_id); + return $this->pageVariant->getSelectionCondition($condition_id); } /** diff --git a/src/Form/SelectionConditionFormBase.php b/src/Form/SelectionConditionFormBase.php index 1244558..801672b 100644 --- a/src/Form/SelectionConditionFormBase.php +++ b/src/Form/SelectionConditionFormBase.php @@ -8,7 +8,7 @@ namespace Drupal\page_manager\Form; use Drupal\Core\Form\FormStateInterface; -use Drupal\page_manager\PageInterface; +use Drupal\page_manager\PageVariantEntityInterface; /** * Provides a base form for editing and adding a selection condition. @@ -16,18 +16,18 @@ use Drupal\page_manager\PageInterface; abstract class SelectionConditionFormBase extends ConditionFormBase { /** - * The display variant. + * The page variant entity. * - * @var \Drupal\page_manager\Plugin\ConditionVariantInterface + * @var \Drupal\page_manager\PageVariantEntityInterface */ - protected $displayVariant; + protected $pageVariant; /** * {@inheritdoc} */ - public function buildForm(array $form, FormStateInterface $form_state, PageInterface $page = NULL, $display_variant_id = NULL, $condition_id = NULL) { - $this->displayVariant = $page->getVariant($display_variant_id); - return parent::buildForm($form, $form_state, $page, $condition_id); + public function buildForm(array $form, FormStateInterface $form_state, PageVariantEntityInterface $page_variant = NULL, $condition_id = NULL) { + $this->pageVariant = $page_variant; + return parent::buildForm($form, $form_state, $condition_id, $page_variant->getContexts()); } /** @@ -39,15 +39,14 @@ abstract class SelectionConditionFormBase extends ConditionFormBase { $configuration = $this->condition->getConfiguration(); // If this selection condition is new, add it to the page. if (!isset($configuration['uuid'])) { - $this->displayVariant->addSelectionCondition($configuration); + $this->pageVariant->addSelectionCondition($configuration); } // Save the page entity. - $this->page->save(); + $this->pageVariant->save(); - $form_state->setRedirect('page_manager.display_variant_edit', [ - 'page' => $this->page->id(), - 'display_variant_id' => $this->displayVariant->id(), + $form_state->setRedirect('entity.page_variant.edit_form', [ + 'page_variant' => $this->pageVariant->id(), ]); } diff --git a/src/PageExecutable.php b/src/PageExecutable.php index 298ad87..c2e1fcd 100644 --- a/src/PageExecutable.php +++ b/src/PageExecutable.php @@ -8,6 +8,8 @@ namespace Drupal\page_manager; use Drupal\Component\Plugin\Context\ContextInterface; +use Drupal\Core\Condition\ConditionAccessResolverTrait; +use Drupal\Core\Plugin\ContextAwarePluginInterface; use Drupal\page_manager\Event\PageManagerContextEvent; use Drupal\page_manager\Event\PageManagerEvents; use Drupal\page_manager\Plugin\ContextAwareVariantInterface; @@ -17,6 +19,8 @@ use Drupal\page_manager\Plugin\ContextAwareVariantInterface; */ class PageExecutable implements PageExecutableInterface { + use ConditionAccessResolverTrait; + /** * The page entity. * @@ -27,9 +31,9 @@ class PageExecutable implements PageExecutableInterface { /** * The selected display variant. * - * @var \Drupal\Core\Display\VariantInterface|null + * @var \Drupal\page_manager\PageVariantEntityInterface */ - protected $selectedDisplayVariant; + protected $selectedVariant; /** * An array of collected contexts. @@ -58,19 +62,49 @@ class PageExecutable implements PageExecutableInterface { /** * {@inheritdoc} */ - public function selectDisplayVariant() { - if (!$this->selectedDisplayVariant) { - foreach ($this->page->getVariants() as $display_variant) { - if ($display_variant instanceof ContextAwareVariantInterface) { - $display_variant->setContexts($this->getContexts()); - } - if ($display_variant->access()) { - $this->selectedDisplayVariant = $display_variant; + public function selectVariant() { + if (!$this->selectedVariant) { + foreach ($this->page->getVariants() as $page_variant) { + if ($this->canSelectPageVariant($page_variant)) { + $this->selectedVariant = $page_variant; break; } } } - return $this->selectedDisplayVariant; + return $this->selectedVariant; + } + + /** + * Checks if this page variant entity is selectable. + * + * @param \Drupal\page_manager\PageVariantEntityInterface $page_variant + * The page variant entity. + * + * @return boolean + * TRUE if the variant is selectable; otherwise FALSE. + */ + public function canSelectPageVariant(PageVariantEntityInterface $page_variant) { + $conditions = $page_variant->getSelectionConditions(); + $contexts = $page_variant->getContexts(); + + foreach ($conditions as $condition) { + if ($condition instanceof ContextAwarePluginInterface) { + // @todo: inject this! + /** @var \Drupal\Core\Plugin\Context\ContextHandlerInterface $context_handler */ + $context_handler = \Drupal::service('context.handler'); + $context_handler->applyContextMapping($condition, $contexts); + } + } + + if ($this->resolveConditions($conditions, $page_variant->getSelectionLogic())) { + $variant_plugin = $page_variant->getVariantPlugin(); + if ($variant_plugin instanceof ContextAwareVariantInterface) { + $variant_plugin->setContexts($page_variant->getContexts()); + } + return $variant_plugin->access(); + } + + return FALSE; } /** diff --git a/src/PageExecutableInterface.php b/src/PageExecutableInterface.php index aeff68e..0357670 100644 --- a/src/PageExecutableInterface.php +++ b/src/PageExecutableInterface.php @@ -32,11 +32,11 @@ interface PageExecutableInterface { * This loops through the available display variants and checks each for * access, returning the first one that is accessible. * - * @return \Drupal\Core\Display\VariantInterface|null + * @return \Drupal\page_manager\PageVariantEntityInterface * Either the first accessible display variant, or NULL if none are * accessible. */ - public function selectDisplayVariant(); + public function selectVariant(); /** * Gets the values for all defined contexts. diff --git a/src/PageInterface.php b/src/PageInterface.php index 59bc383..fadec22 100644 --- a/src/PageInterface.php +++ b/src/PageInterface.php @@ -14,7 +14,7 @@ use Drupal\page_manager\Plugin\VariantAwareInterface; /** * Provides an interface for page entities. */ -interface PageInterface extends ConfigEntityInterface, EntityWithPluginCollectionInterface, VariantAwareInterface { +interface PageInterface extends ConfigEntityInterface, EntityWithPluginCollectionInterface { /** * Returns whether the page entity is enabled. @@ -48,6 +48,46 @@ interface PageInterface extends ConfigEntityInterface, EntityWithPluginCollectio public function usesAdminTheme(); /** + * 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\page_manager\PageVariantEntityInterface + * 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\page_manager\PageVariantEntityInterface[] + * An array of the variants. + */ + public function getVariants(); + + /** * Returns the conditions used for determining access for this page entity. * * @return \Drupal\Core\Condition\ConditionInterface[]|\Drupal\Core\Condition\ConditionPluginCollection diff --git a/src/PageVariantEntityInterface.php b/src/PageVariantEntityInterface.php new file mode 100644 index 0000000..294f7c0 --- /dev/null +++ b/src/PageVariantEntityInterface.php @@ -0,0 +1,110 @@ +selectionConditionCollection) { - $this->selectionConditionCollection = new ConditionPluginCollection(\Drupal::service('plugin.manager.condition'), $this->getSelectionConfiguration()); - } - return $this->selectionConditionCollection; - } - - /** - * @see \Drupal\page_manager\Plugin\ConditionVariantInterface::addSelectionCondition() - */ - public function addSelectionCondition(array $configuration) { - $configuration['uuid'] = $this->uuidGenerator()->generate(); - $this->getSelectionConditions()->addInstanceId($configuration['uuid'], $configuration); - return $configuration['uuid']; - } - - /** - * @see \Drupal\page_manager\Plugin\ConditionVariantInterface::getSelectionCondition() - */ - public function getSelectionCondition($condition_id) { - return $this->getSelectionConditions()->get($condition_id); - } - - /** - * @see \Drupal\page_manager\Plugin\ConditionVariantInterface::removeSelectionCondition() - */ - public function removeSelectionCondition($condition_id) { - $this->getSelectionConditions()->removeInstanceId($condition_id); - return $this; - } - - /** - * Determines if the selection conditions will pass given a set of contexts. - * - * @param \Drupal\Component\Plugin\Context\ContextInterface[] $contexts - * An array of set contexts, keyed by context name. - * - * @return bool - * TRUE if access is granted, FALSE otherwise. - */ - protected function determineSelectionAccess(array $contexts) { - $conditions = $this->getSelectionConditions(); - foreach ($conditions as $condition) { - if ($condition instanceof ContextAwarePluginInterface) { - $this->contextHandler()->applyContextMapping($condition, $contexts); - } - } - return $this->resolveConditions($conditions, $this->getSelectionLogic()); - } - - /** - * @see \Drupal\page_manager\Plugin\ConditionVariantInterface::getSelectionLogic() - */ - abstract public function getSelectionLogic(); - - /** - * Returns the configuration for stored selection conditions. - * - * @return array - * An array of condition configuration, keyed by the unique condition ID. - */ - abstract protected function getSelectionConfiguration(); - - /** - * Returns the UUID generator. - * - * @return \Drupal\Component\Uuid\UuidInterface - */ - abstract protected function uuidGenerator(); - - /** - * Returns the context handler. - * - * @return \Drupal\Core\Plugin\Context\ContextHandlerInterface - */ - abstract protected function contextHandler(); - -} diff --git a/src/Plugin/DisplayVariant/BlockDisplayVariant.php b/src/Plugin/DisplayVariant/BlockDisplayVariant.php index 151fa38..be09a7e 100644 --- a/src/Plugin/DisplayVariant/BlockDisplayVariant.php +++ b/src/Plugin/DisplayVariant/BlockDisplayVariant.php @@ -24,8 +24,6 @@ use Drupal\Core\Utility\Token; use Drupal\page_manager\Form\AjaxFormTrait; use Drupal\page_manager\Plugin\BlockVariantInterface; use Drupal\page_manager\Plugin\BlockVariantTrait; -use Drupal\page_manager\Plugin\ConditionVariantInterface; -use Drupal\page_manager\Plugin\ConditionVariantTrait; use Drupal\page_manager\Plugin\ContextAwareVariantInterface; use Drupal\page_manager\Plugin\ContextAwareVariantTrait; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -38,12 +36,11 @@ use Symfony\Component\DependencyInjection\ContainerInterface; * admin_label = @Translation("Block page") * ) */ -class BlockDisplayVariant extends VariantBase implements ContextAwareVariantInterface, ConditionVariantInterface, ContainerFactoryPluginInterface, BlockVariantInterface, RefinableCacheableDependencyInterface { +class BlockDisplayVariant extends VariantBase implements ContextAwareVariantInterface, ContainerFactoryPluginInterface, BlockVariantInterface, RefinableCacheableDependencyInterface { use AjaxFormTrait; use BlockVariantTrait; use ContextAwareVariantTrait; - use ConditionVariantTrait; use RefinableCacheableDependencyTrait; /** @@ -236,7 +233,10 @@ class BlockDisplayVariant extends VariantBase implements ContextAwareVariantInte * {@inheritdoc} */ public function buildConfigurationForm(array $form, FormStateInterface $form_state) { - $form = parent::buildConfigurationForm($form, $form_state); + // Don't call VariantBase::buildConfigurationForm() on purpose, because it + // adds a 'Label' field that we don't actually want to use - we store the + // label on the page variant entity. + //$form = parent::buildConfigurationForm($form, $form_state); // Allow to configure the page title, even when adding a new display. // Default to the page label in that case. @@ -264,19 +264,9 @@ class BlockDisplayVariant extends VariantBase implements ContextAwareVariantInte /** * {@inheritdoc} */ - public function access(AccountInterface $account = NULL) { - // Delegate to the conditions. - return $this->determineSelectionAccess($this->getContexts()); - } - - /** - * {@inheritdoc} - */ public function defaultConfiguration() { return parent::defaultConfiguration() + [ 'blocks' => [], - 'selection_conditions' => [], - 'selection_logic' => 'and', 'page_title' => '', ]; } @@ -288,9 +278,6 @@ class BlockDisplayVariant extends VariantBase implements ContextAwareVariantInte foreach ($this->getBlockCollection() as $instance) { $this->calculatePluginDependencies($instance); } - foreach ($this->getSelectionConditions() as $instance) { - $this->calculatePluginDependencies($instance); - } return $this->dependencies; } @@ -299,19 +286,11 @@ class BlockDisplayVariant extends VariantBase implements ContextAwareVariantInte */ public function getConfiguration() { return [ - 'selection_conditions' => $this->getSelectionConditions()->getConfiguration(), 'blocks' => $this->getBlockCollection()->getConfiguration(), ] + parent::getConfiguration(); } /** - * {@inheritdoc} - */ - public function getSelectionLogic() { - return $this->configuration['selection_logic']; - } - - /** * Renders the page title and replaces tokens. * * @param string $page_title @@ -357,13 +336,6 @@ class BlockDisplayVariant extends VariantBase implements ContextAwareVariantInte /** * {@inheritdoc} */ - protected function getSelectionConfiguration() { - return $this->configuration['selection_conditions']; - } - - /** - * {@inheritdoc} - */ protected function getBlockConfig() { return $this->configuration['blocks']; } diff --git a/src/Plugin/DisplayVariant/HttpStatusCodeDisplayVariant.php b/src/Plugin/DisplayVariant/HttpStatusCodeDisplayVariant.php index cd9246c..1a3e258 100644 --- a/src/Plugin/DisplayVariant/HttpStatusCodeDisplayVariant.php +++ b/src/Plugin/DisplayVariant/HttpStatusCodeDisplayVariant.php @@ -26,7 +26,10 @@ class HttpStatusCodeDisplayVariant extends VariantBase { * {@inheritdoc} */ public function buildConfigurationForm(array $form, FormStateInterface $form_state) { - $form = parent::buildConfigurationForm($form, $form_state); + // Don't call VariantBase::buildConfigurationForm() on purpose, because it + // adds a 'Label' field that we don't actually want to use - we store the + // label on the page variant entity. + //$form = parent::buildConfigurationForm($form, $form_state); // Get all possible status codes defined by Symfony. $options = Response::$statusTexts; diff --git a/src/Plugin/VariantAwareInterface.php b/src/Plugin/VariantAwareInterface.php deleted file mode 100644 index 0226fb7..0000000 --- a/src/Plugin/VariantAwareInterface.php +++ /dev/null @@ -1,54 +0,0 @@ -uuidGenerator()->generate(); - $this->getVariants()->addInstanceId($configuration['uuid'], $configuration); - return $configuration['uuid']; - } - - /** - * @see \Drupal\page_manager\Plugin\VariantAwareInterface::getVariant() - */ - public function getVariant($variant_id) { - return $this->getVariants()->get($variant_id); - } - - /** - * @see \Drupal\page_manager\Plugin\VariantAwareInterface::removeVariant() - */ - public function removeVariant($variant_id) { - $this->getVariants()->removeInstanceId($variant_id); - return $this; - } - - /** - * @see \Drupal\page_manager\Plugin\VariantAwareInterface::getVariants() - */ - public function getVariants() { - if (!$this->variantCollection) { - $this->variantCollection = new VariantCollection(\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(); - -} diff --git a/src/Plugin/VariantCollection.php b/src/Plugin/VariantCollection.php deleted file mode 100644 index 55819e0..0000000 --- a/src/Plugin/VariantCollection.php +++ /dev/null @@ -1,48 +0,0 @@ -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 0; - } - - return ($a_weight < $b_weight) ? -1 : 1; - } - -} diff --git a/src/Tests/PageConfigSchemaTest.php b/src/Tests/PageConfigSchemaTest.php index c0e768b..2193c53 100644 --- a/src/Tests/PageConfigSchemaTest.php +++ b/src/Tests/PageConfigSchemaTest.php @@ -48,17 +48,20 @@ class PageConfigSchemaTest extends KernelTestBase { 'node' => 'node', ], ]); + $page->save(); // Add a block display variant. $display_variant_id = $page->addVariant([ - 'id' => 'block_display', + 'variant' => 'block_display', + 'id' => 'block_page', 'label' => 'Block page', ]); + $page_variant = $page->getVariant($display_variant_id); /** @var $display_variant \Drupal\page_manager\Plugin\DisplayVariant\BlockDisplayVariant */ - $display_variant = $page->getVariant($display_variant_id); + $variant_plugin = $page_variant->getVariantPlugin(); // Add a selection condition. - $display_variant->addSelectionCondition([ + $page_variant->addSelectionCondition([ 'id' => 'node_type', 'bundles' => [ 'page' => 'page', @@ -69,18 +72,22 @@ class PageConfigSchemaTest extends KernelTestBase { ]); // Add a block. - $display_variant->addBlock([ + $variant_plugin->addBlock([ 'id' => 'entity_view:node', 'label' => 'View the node', 'provider' => 'page_manager', 'label_display' => 'visible', 'view_mode' => 'default', ]); - $page->save(); + $page_variant->save(); + + $page_config = \Drupal::config("page_manager.page.$id"); + $this->assertEqual($page_config->get('id'), $id); + $variant_config = \Drupal::config("page_manager.page_variant.$display_variant_id"); + $this->assertEqual($variant_config->get('id'), $display_variant_id); - $config = \Drupal::config("page_manager.page.$id"); - $this->assertEqual($config->get('id'), $id); - $this->assertConfigSchema(\Drupal::service('config.typed'), $config->getName(), $config->get()); + $this->assertConfigSchema(\Drupal::service('config.typed'), $page_config->getName(), $page_config->get()); + $this->assertConfigSchema(\Drupal::service('config.typed'), $variant_config->getName(), $variant_config->get()); } } diff --git a/src/Tests/PageManagerAdminTest.php b/src/Tests/PageManagerAdminTest.php index e26db02..5982528 100644 --- a/src/Tests/PageManagerAdminTest.php +++ b/src/Tests/PageManagerAdminTest.php @@ -91,14 +91,27 @@ class PageManagerAdminTest extends WebTestBase { $this->drupalGet('admin/foo'); $this->assertResponse(404); $this->drupalGet('admin/structure/page_manager/manage/foo'); - $this->clickLink('Edit'); - $this->drupalPostForm(NULL, ['display_variant[status_code]' => 200], 'Update display variant'); + $this->clickLink('Add new display variant'); + $this->clickLink('HTTP status code'); + $edit = [ + 'id' => 'http_status_code', + 'label' => 'Default', + 'variant_settings[status_code]' => 200, + ]; + $this->drupalPostForm(NULL, $edit, 'Save'); $this->drupalGet('admin/foo'); $this->assertResponse(200); $this->assertTitle('Foo | Drupal'); $this->drupalGet('admin/structure/page_manager/manage/foo'); $this->clickLink('Edit'); - $this->drupalPostForm(NULL, ['display_variant[status_code]' => 403], 'Update display variant'); + $this->drupalPostForm(NULL, ['variant_settings[status_code]' => 403], 'Save'); + + // Set the weight of the 'Default' variant to 10. + $default_variant = $this->findDisplayVariantByLabel('foo', 'Default'); + $edit = [ + 'display_variants[' . $default_variant->uuid() . '][weight]' => 10, + ]; + $this->drupalPostForm(NULL, $edit, 'Save'); // Assert that a display variant was added by default. $this->drupalGet('admin/structure/page_manager/manage/foo'); @@ -135,11 +148,12 @@ class PageManagerAdminTest extends WebTestBase { $this->clickLink('Add new display variant'); $this->clickLink('Block page'); $edit = [ - 'display_variant[label]' => 'First', - 'display_variant[page_title]' => 'Example title', + 'label' => 'First', + 'id' => 'block_page', + 'variant_settings[page_title]' => 'Example title', ]; - $this->drupalPostForm(NULL, $edit, 'Add display variant'); - $this->assertRaw(SafeMarkup::format('The %label display variant has been added.', ['%label' => 'First'])); + $this->drupalPostForm(NULL, $edit, 'Save'); + $this->assertRaw(SafeMarkup::format('Saved the %label variant.', ['%label' => 'First'])); // Test that the variant is still used but empty. $this->drupalGet('admin/foo'); @@ -224,8 +238,8 @@ class PageManagerAdminTest extends WebTestBase { $form_name . '[region]' => 'bottom', $form_name . '[weight]' => -10, ]; - $this->drupalPostForm(NULL, $edit, 'Update display variant'); - $this->assertRaw(SafeMarkup::format('The %label display variant has been updated.', ['%label' => 'First'])); + $this->drupalPostForm(NULL, $edit, 'Save'); + $this->assertRaw(SafeMarkup::format('Saved the %label variant.', ['%label' => 'First'])); $this->clickLink('Edit'); $this->assertOptionSelected('edit-display-variant-blocks-' . $block_config['uuid'] . '-region', 'bottom'); $this->assertOptionSelected('edit-display-variant-blocks-' . $block_config['uuid'] . '-weight', -10); @@ -247,7 +261,7 @@ class PageManagerAdminTest extends WebTestBase { $display_variant = $this->findDisplayVariantByLabel('foo', 'Default'); $edit = [ - 'display_variants[' . $display_variant->id() . '][weight]' => -10, + 'display_variants[' . $display_variant->uuid() . '][weight]' => -10, ]; $this->drupalPostForm('admin/structure/page_manager/manage/foo', $edit, 'Save'); $this->drupalGet('admin/foo'); @@ -295,7 +309,7 @@ class PageManagerAdminTest extends WebTestBase { protected function doTestRemoveDisplayVariant() { $this->drupalGet('admin/structure/page_manager/manage/foo'); $this->clickLink('Delete'); - $this->assertRaw(SafeMarkup::format('Are you sure you want to delete the display variant %label?', ['%label' => 'Default'])); + $this->assertRaw(SafeMarkup::format('Are you sure you want to delete %label?', ['%label' => 'Default'])); $this->drupalPostForm(NULL, [], 'Delete'); $this->assertRaw(SafeMarkup::format('The display variant %label has been removed.', ['%label' => 'Default'])); } @@ -427,8 +441,9 @@ class PageManagerAdminTest extends WebTestBase { * Either a block plugin, or NULL. */ protected function findBlockByLabel($page_id, $display_variant_label, $block_label) { - if ($display_variant = $this->findDisplayVariantByLabel($page_id, $display_variant_label)) { + if ($page_variant = $this->findDisplayVariantByLabel($page_id, $display_variant_label)) { /** @var $display_variant \Drupal\page_manager\Plugin\BlockVariantInterface */ + $display_variant = $page_variant->getVariantPlugin(); foreach ($display_variant->getRegionAssignments() as $blocks) { /** @var $blocks \Drupal\Core\Block\BlockPluginInterface[] */ foreach ($blocks as $block) { @@ -449,15 +464,15 @@ class PageManagerAdminTest extends WebTestBase { * @param string $display_variant_label * The label of the display variant. * - * @return \Drupal\Core\Display\VariantInterface|null + * @return \Drupal\page_manager\PageVariantEntityInterface|NULL * Either a display variant, or NULL. */ protected function findDisplayVariantByLabel($page_id, $display_variant_label) { if ($page = Page::load($page_id)) { /** @var $page \Drupal\page_manager\PageInterface */ - foreach ($page->getVariants() as $display_variant) { - if ($display_variant->label() == $display_variant_label) { - return $display_variant; + foreach ($page->getVariants() as $page_variant) { + if ($page_variant->label() == $display_variant_label) { + return $page_variant; } } } diff --git a/src/Tests/PageManagerTranslationIntegrationTest.php b/src/Tests/PageManagerTranslationIntegrationTest.php index fd609f1..9346a4d 100644 --- a/src/Tests/PageManagerTranslationIntegrationTest.php +++ b/src/Tests/PageManagerTranslationIntegrationTest.php @@ -65,8 +65,13 @@ class PageManagerTranslationIntegrationTest extends ContentTranslationTestBase { 'path' => 'node/%', ]; $this->drupalPostForm('admin/structure/page_manager/add', $edit, 'Save'); - $this->clickLink('Edit'); - $this->drupalPostForm(NULL, ['display_variant[status_code]' => 200], 'Update display variant'); + + // Create a new variant. + $edit = [ + 'id' => 'http_status_code', + 'variant_settings[status_code]' => 200, + ]; + $this->drupalPostForm('admin/structure/page_manager/manage/node_view/add/http_status_code', $edit, 'Save'); $this->drupalGet('node/' . $node->id()); $this->assertResponse(200); diff --git a/src/Tests/PageNodeSelectionTest.php b/src/Tests/PageNodeSelectionTest.php index aae529f..e72a219 100644 --- a/src/Tests/PageNodeSelectionTest.php +++ b/src/Tests/PageNodeSelectionTest.php @@ -8,6 +8,7 @@ namespace Drupal\page_manager\Tests; use Drupal\Core\Cache\Cache; +use Drupal\page_manager\Entity\Page; use Drupal\simpletest\WebTestBase; /** @@ -58,7 +59,14 @@ class PageNodeSelectionTest extends WebTestBase { 'path' => 'node/%', ]; $this->drupalPostForm('admin/structure/page_manager/add', $edit, 'Save'); - // Their pages should now use the default 404 display variant. + + // Create a new variant to always return 404. + $edit = [ + 'id' => 'http_status_code', + 'variant_settings[status_code]' => 404, + ]; + $this->drupalPostForm('admin/structure/page_manager/manage/node_view/add/http_status_code', $edit, 'Save'); + $this->drupalGet('node/' . $node1->id()); $this->assertResponse(404); $this->assertCacheTag('page_manager_route_name:entity.node.canonical'); @@ -72,9 +80,10 @@ class PageNodeSelectionTest extends WebTestBase { $this->clickLink('Add new display variant'); $this->clickLink('Block page'); $edit = [ - 'display_variant[label]' => 'First', + 'id' => 'block_page_first', + 'label' => 'First', ]; - $this->drupalPostForm(NULL, $edit, 'Add display variant'); + $this->drupalPostForm(NULL, $edit, 'Save'); // Add the entity view block. $this->clickLink('Add new block'); @@ -95,9 +104,22 @@ class PageNodeSelectionTest extends WebTestBase { // Set the page title to the node title. $edit = [ - 'display_variant[page_title]' => '[node:title]', + 'variant_settings[page_title]' => '[node:title]', + ]; + $this->drupalPostForm(NULL, $edit, 'Save'); + + /** @var \Drupal\page_manager\PageInterface $page */ + $page = Page::load('node_view'); + foreach ($page->getVariants() as $block_variant_uuid => $block_variant) { + if ($block_variant->label() == 'First') { + break; + } + } + // Set the weight of the block_page variant to -10. + $edit = [ + 'display_variants[' . $block_variant_uuid . '][weight]' => -10, ]; - $this->drupalPostForm(NULL, $edit, 'Update display variant'); + $this->drupalPostForm(NULL, $edit, 'Save'); // The page node will 404, but the article node will display the variant. $this->drupalGet('node/' . $node1->id()); diff --git a/src/Tests/PagePlaceholderTest.php b/src/Tests/PagePlaceholderTest.php index 6f5c937..a94d361 100644 --- a/src/Tests/PagePlaceholderTest.php +++ b/src/Tests/PagePlaceholderTest.php @@ -47,8 +47,13 @@ class PagePlaceholderTest extends WebTestBase { 'path' => '/page-manager-test/%', ]; $this->drupalPostForm('admin/structure/page_manager/add', $edit, 'Save'); - $this->clickLink('Edit'); - $this->drupalPostForm(NULL, ['display_variant[status_code]' => 200], 'Update display variant'); + + // Create a new variant. + $edit = [ + 'id' => 'http_status_code', + 'variant_settings[status_code]' => 200, + ]; + $this->drupalPostForm('admin/structure/page_manager/manage/placeholder/add/http_status_code', $edit, 'Save'); // Access the page callback again and check that now the text is not there. $this->drupalGet('page-manager-test/' . $page_string); diff --git a/src/Tests/StaticContextTest.php b/src/Tests/StaticContextTest.php index 4065502..7b35d5d 100644 --- a/src/Tests/StaticContextTest.php +++ b/src/Tests/StaticContextTest.php @@ -81,10 +81,11 @@ class StaticContextTest extends WebTestBase { $this->clickLink('Add new display variant'); $this->clickLink('Block page'); $variant_edit = [ - 'display_variant[label]' => 'Static context blocks', - 'display_variant[page_title]' => 'Static context test page', + 'label' => 'Static context blocks', + 'id' => 'block_page', + 'variant_settings[page_title]' => 'Static context test page', ]; - $this->drupalPostForm(NULL, $variant_edit, 'Add display variant'); + $this->drupalPostForm(NULL, $variant_edit, 'Save'); // Add a block that renders the node from the first static context. $this->clickLink('Add new block'); diff --git a/tests/src/Unit/BlockDisplayVariantTest.php b/tests/src/Unit/BlockDisplayVariantTest.php index 45cda87..556a4ee 100644 --- a/tests/src/Unit/BlockDisplayVariantTest.php +++ b/tests/src/Unit/BlockDisplayVariantTest.php @@ -32,31 +32,6 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; class BlockDisplayVariantTest extends UnitTestCase { /** - * Tests the access() method. - * - * @covers ::access - */ - public function testAccess() { - $display_variant = $this->getMockBuilder(BlockDisplayVariant::class) - ->disableOriginalConstructor() - ->setMethods(['determineSelectionAccess']) - ->getMock(); - $display_variant->expects($this->once()) - ->method('determineSelectionAccess') - ->willReturn(FALSE); - $this->assertSame(FALSE, $display_variant->access()); - - $display_variant = $this->getMockBuilder(BlockDisplayVariant::class) - ->disableOriginalConstructor() - ->setMethods(['determineSelectionAccess']) - ->getMock(); - $display_variant->expects($this->once()) - ->method('determineSelectionAccess') - ->willReturn(TRUE); - $this->assertSame(TRUE, $display_variant->access()); - } - - /** * Tests the build() method when a block is empty. * * @covers ::build diff --git a/tests/src/Unit/PageExecutableTest.php b/tests/src/Unit/PageExecutableTest.php index e8c967e..5901c3b 100644 --- a/tests/src/Unit/PageExecutableTest.php +++ b/tests/src/Unit/PageExecutableTest.php @@ -15,6 +15,7 @@ use Drupal\page_manager\Event\PageManagerContextEvent; use Drupal\page_manager\Event\PageManagerEvents; use Drupal\page_manager\PageExecutable; use Drupal\page_manager\PageInterface; +use Drupal\page_manager\PageVariantEntityInterface; use Drupal\Tests\UnitTestCase; use Prophecy\Argument; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -60,18 +61,20 @@ class PageExecutableTest extends UnitTestCase { * @covers ::selectDisplayVariant */ public function testSelectDisplayVariant() { - $display_variant1 = $this->prophesize(VariantInterface::class); - $display_variant1->access()->willReturn(FALSE); + $page_variant1 = $this->prophesize(PageVariantEntityInterface::class); + $page_variant1->canSelect()->willReturn(FALSE); $display_variant2 = $this->prophesize(VariantInterface::class); - $display_variant2->access()->willReturn(TRUE); + $page_variant2 = $this->prophesize(PageVariantEntityInterface::class); + $page_variant2->canSelect()->willReturn(TRUE); + $page_variant2->getVariantPlugin()->willReturn($display_variant2); $this->page->getVariants()->willReturn([ - 'variant1' => $display_variant1->reveal(), - 'variant2' => $display_variant2->reveal(), + 'variant1' => $page_variant1->reveal(), + 'variant2' => $page_variant2->reveal(), ]); - $this->assertSame($display_variant2->reveal(), $this->exectuable->selectDisplayVariant()); + $this->assertSame($display_variant2->reveal(), $this->exectuable->selectVariant()); } /** diff --git a/tests/src/Unit/VariantAwareTraitTest.php b/tests/src/Unit/VariantAwareTraitTest.php deleted file mode 100644 index bacdd59..0000000 --- a/tests/src/Unit/VariantAwareTraitTest.php +++ /dev/null @@ -1,214 +0,0 @@ -manager = $this->prophesize(PluginManagerInterface::class); - $container->set('plugin.manager.display_variant', $this->manager->reveal()); - \Drupal::setContainer($container); - } - - /** - * @covers ::getVariants - */ - public function testGetVariantsEmpty() { - $trait_object = new TestVariantAwareTrait(); - $this->manager->createInstance()->shouldNotBeCalled(); - - $variants = $trait_object->getVariants(); - $this->assertInstanceOf(VariantCollection::class, $variants); - $this->assertSame(0, count($variants)); - } - - /** - * @covers ::getVariants - */ - public function testGetVariants() { - $trait_object = new TestVariantAwareTrait(); - $config = [ - 'foo' => ['id' => 'foo_plugin'], - 'bar' => ['id' => 'bar_plugin'], - ]; - foreach ($config as $value) { - $plugin = $this->prophesize(VariantInterface::class); - $this->manager->createInstance($value['id'], $value)->willReturn($plugin->reveal()); - } - $trait_object->setVariantConfig($config); - - $variants = $trait_object->getVariants(); - $this->assertInstanceOf(VariantCollection::class, $variants); - $this->assertSame(2, count($variants)); - return $variants; - } - - /** - * @covers ::getVariants - * - * @depends testGetVariants - */ - public function testGetVariantsSort(VariantCollection $variants) { - $this->assertSame(['bar' => 'bar', 'foo' => 'foo'], $variants->getInstanceIds()); - } - - /** - * @covers ::addVariant - */ - public function testAddVariant() { - $config = ['id' => 'foo']; - $uuid = 'test-uuid'; - $expected_config = $config + ['uuid' => $uuid]; - - $uuid_generator = $this->prophesize(UuidInterface::class); - $uuid_generator->generate() - ->willReturn($uuid) - ->shouldBeCalledTimes(1); - $trait_object = new TestVariantAwareTrait(); - $trait_object->setUuidGenerator($uuid_generator->reveal()); - - $plugin_prophecy = $this->prophesize(VariantInterface::class); - $plugin_prophecy->getConfiguration() - ->willReturn($expected_config) - ->shouldBeCalled(); - $plugin_prophecy->setConfiguration($expected_config) - ->willReturn($expected_config) - ->shouldBeCalled(); - - $this->manager->createInstance('foo', $expected_config) - ->willReturn($plugin_prophecy->reveal()); - - $resulting_uuid = $trait_object->addVariant($config); - $this->assertSame($uuid, $resulting_uuid); - - $variants = $trait_object->getVariants(); - $this->assertSame([$uuid => $uuid], $variants->getInstanceIds()); - $this->assertSame([$uuid => $expected_config], $variants->getConfiguration()); - $this->assertSame($plugin_prophecy->reveal(), $variants->get($uuid)); - return [$trait_object, $uuid, $plugin_prophecy->reveal()]; - } - - /** - * @covers ::getVariant - * - * @depends testAddVariant - */ - public function testGetVariant($data) { - list($trait_object, $uuid, $plugin) = $data; - $this->manager->createInstance()->shouldNotBeCalled(); - - $this->assertSame($plugin, $trait_object->getVariant($uuid)); - return [$trait_object, $uuid]; - } - - /** - * @covers ::removeVariant - * - * @depends testGetVariant - */ - public function testRemoveVariant($data) { - list($trait_object, $uuid) = $data; - - $this->assertSame($trait_object, $trait_object->removeVariant($uuid)); - $this->assertFalse($trait_object->getVariants()->has($uuid)); - return [$trait_object, $uuid]; - } - - /** - * @covers ::getVariant - * - * @depends testRemoveVariant - * - * @expectedException \Drupal\Component\Plugin\Exception\PluginNotFoundException - * @expectedExceptionMessage Plugin ID 'test-uuid' was not found. - */ - public function testGetVariantException($data) { - list($trait_object, $uuid) = $data; - // Attempt to retrieve a variant that has been removed. - $this->assertNull($trait_object->getVariant($uuid)); - } - -} - -class TestVariantAwareTrait { - use VariantAwareTrait; - - /** - * @var array - */ - protected $variantConfig = []; - - /** - * @var \Drupal\Component\Uuid\UuidInterface - */ - protected $uuidGenerator; - - /** - * @param \Drupal\Component\Uuid\UuidInterface $uuid_generator - * - * @return $this - */ - public function setUuidGenerator(UuidInterface $uuid_generator) { - $this->uuidGenerator = $uuid_generator; - return $this; - } - - /** - * {@inheritdoc} - */ - protected function uuidGenerator() { - return $this->uuidGenerator; - } - - /** - * Sets the variant configuration. - * - * @param array $config - * The variant configuration. - * - * @return $this - */ - public function setVariantConfig(array $config) { - $this->variantConfig = $config; - return $this; - } - - /** - * {@inheritdoc} - */ - protected function getVariantConfig() { - return $this->variantConfig; - } - -}