diff --git a/panelizer.module b/panelizer.module index 2672b1b..00f1e62 100644 --- a/panelizer.module +++ b/panelizer.module @@ -45,7 +45,7 @@ function panelizer_panels_build_alter(&$build, PanelsDisplayVariant $panels_disp $storage_type = $panels_display->getStorageType(); // Add our Javascript customizations for the IPE. - if ($builder->getPluginId() == 'ipe' && in_array($storage_type, ['panelizer_default', 'panelizer_field'])) { + if ($builder->getPluginId() == 'ipe' && in_array($storage_type, ['panelizer_default', 'panelizer_field']) && in_array('panels_ipe/panels_ipe', $build['#attached']['library'])) { $build['#attached']['library'][] = 'panelizer/panels_ipe'; /** @var \Drupal\Core\Entity\EntityInterface $entity */ diff --git a/src/Exception/PanelizerException.php b/src/Exception/PanelizerException.php new file mode 100644 index 0000000..27821a3 --- /dev/null +++ b/src/Exception/PanelizerException.php @@ -0,0 +1,15 @@ +save(); } + else { + throw new PanelizerException("Custom overrides not enabled on this entity, bundle and view mode"); + } } /** @@ -276,7 +280,9 @@ class Panelizer implements PanelizerInterface { // Get each one individually. $panels_displays = []; foreach ($display_names as $name) { - $panels_displays[$name] = $this->getDefaultPanelsDisplay($name, $entity_type_id, $bundle, $view_mode, $display); + if ($panels_display = $this->getDefaultPanelsDisplay($name, $entity_type_id, $bundle, $view_mode, $display)) { + $panels_displays[$name] = $panels_display; + } } return $panels_displays; @@ -288,6 +294,11 @@ class Panelizer implements PanelizerInterface { public function getDefaultPanelsDisplay($name, $entity_type_id, $bundle, $view_mode, EntityViewDisplayInterface $display = NULL) { if (!$display) { $display = $this->getEntityViewDisplay($entity_type_id, $bundle, $view_mode); + // If we still don't find a display, then we won't find a Panelizer + // default for sure. + if (!$display) { + return NULL; + } } $config = $display->getThirdPartySetting('panelizer', 'displays', []); @@ -296,8 +307,7 @@ class Panelizer implements PanelizerInterface { $panels_display = $this->panelsManager->importDisplay($config[$name], FALSE); } else { - $panels_display = $this->getEntityPlugin($entity_type_id)->getDefaultDisplay($display, $bundle, $view_mode); - // @todo: This is actually an appropriate place to set the storage info. + return NULL; } // @todo: Should be set when written, not here! @@ -317,6 +327,9 @@ class Panelizer implements PanelizerInterface { */ public function setDefaultPanelsDisplay($name, $entity_type_id, $bundle, $view_mode, PanelsDisplayVariant $panels_display) { $display = $this->getEntityViewDisplay($entity_type_id, $bundle, $view_mode); + if (!$display) { + throw new PanelizerException("Unable to find display for given entity type, bundle and view mode"); + } // Set this individual Panels display. $panels_displays = $display->getThirdPartySetting('panelizer', 'displays', []); diff --git a/src/PanelizerInterface.php b/src/PanelizerInterface.php index 7b64a9c..0372277 100644 --- a/src/PanelizerInterface.php +++ b/src/PanelizerInterface.php @@ -47,6 +47,10 @@ interface PanelizerInterface { * The name of the default if setting to a default; otherwise NULL. * @param \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant|NULL $panels_display * The Panels display if this is an override; otherwise NULL. + * + * @throws \Drupal\panelizer\Exception\PanelizerException + * When custom overrides aren't enabled on this entity, bundle and view + * mode. */ public function setPanelsDisplay(FieldableEntityInterface $entity, $view_mode, $default, PanelsDisplayVariant $panels_display = NULL); @@ -64,7 +68,7 @@ interface PanelizerInterface { * passed in here so the Panelizer service doesn't have to look it up; * otherwise, this argument can bo omitted. * - * @return \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant[]|NULL + * @return \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant[] * An associative array of Panels displays, keyed by the machine name of * the default if panelized; NULL otherwise. All panelized view modes will * have at least one named 'default'. @@ -75,7 +79,7 @@ interface PanelizerInterface { * Gets one default Panels display for an entity type, bundle and view mode. * * @param string $name - * The entity type id. + * The name of the default. * @param string $entity_type_id * The entity type id. * @param string $bundle @@ -87,18 +91,27 @@ interface PanelizerInterface { * passed in here so the Panelizer service doesn't have to look it up; * otherwise, this argument can bo omitted. * - * @return \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant - * The default Panels display named 'default'. + * @return \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant|NULL + * The default Panels display with the given name if it exists; otherwise + * NULL. */ public function getDefaultPanelsDisplay($name, $entity_type_id, $bundle, $view_mode, EntityViewDisplayInterface $display = NULL); /** * @param $name + * The name of the default. * @param $entity_type_id + * The entity type id. * @param $bundle + * The bundle. * @param $view_mode + * The view mode. * @param \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant $panels_display - * @return mixed + * The Panels display to use as the default. + * + * @throws \Drupal\panelizer\Exception\PanelizerException + * When a display can't be found for the given entity type, bundle and view + * mode. */ public function setDefaultPanelsDisplay($name, $entity_type_id, $bundle, $view_mode, PanelsDisplayVariant $panels_display); diff --git a/src/Plugin/PanelizerEntity/PanelizerNode.php b/src/Plugin/PanelizerEntity/PanelizerNode.php index 11ec21d..f5e387c 100644 --- a/src/Plugin/PanelizerEntity/PanelizerNode.php +++ b/src/Plugin/PanelizerEntity/PanelizerNode.php @@ -23,12 +23,8 @@ class PanelizerNode extends PanelizerEntityBase { * {@inheritdoc} */ public function getDefaultDisplay(EntityViewDisplayInterface $display, $bundle, $view_mode) { - $panels_display = parent::getDefaultDisplay($display, $bundle, $view_mode); - - // @todo: Add an accessor in Panels for this! - $configuration = $panels_display->getConfiguration(); - $configuration['page_title'] = '[node:title]'; - $panels_display->setConfiguration($configuration); + $panels_display = parent::getDefaultDisplay($display, $bundle, $view_mode) + ->setPageTitle('[node:title]'); // Remove the 'title' block because it's covered already. foreach ($panels_display->getRegionAssignments() as $region => $blocks) { diff --git a/src/Plugin/PanelsStorage/PanelizerDefaultPanelsStorage.php b/src/Plugin/PanelsStorage/PanelizerDefaultPanelsStorage.php index 201c35c..72009c9 100644 --- a/src/Plugin/PanelsStorage/PanelizerDefaultPanelsStorage.php +++ b/src/Plugin/PanelsStorage/PanelizerDefaultPanelsStorage.php @@ -8,11 +8,13 @@ namespace Drupal\panelizer\Plugin\PanelsStorage; use Drupal\Core\Access\AccessResult; +use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Plugin\Context\Context; use Drupal\Core\Plugin\Context\ContextDefinition; use Drupal\Core\Session\AccountInterface; +use Drupal\panelizer\Exception\PanelizerException; use Drupal\panelizer\PanelizerInterface; use Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant; use Drupal\panels\Storage\PanelsStorageBase; @@ -86,6 +88,8 @@ class PanelizerDefaultPanelsStorage extends PanelsStorageBase implements Contain * - View mode: string * - Default name: string * - Entity: \Drupal\Core\Entity\EntityInterface|NULL + * + * @throws \Drupal\panelizer\Exception\PanelizerException */ protected function parseId($id) { list ($entity_type_id, $part_two, $view_mode, $name) = explode(':', $id); @@ -93,8 +97,12 @@ class PanelizerDefaultPanelsStorage extends PanelsStorageBase implements Contain if (strpos($entity_type_id, '*') === 0) { $entity_type_id = substr($entity_type_id, 1); $storage = $this->entityTypeManager->getStorage($entity_type_id); - $entity = $storage->load($part_two); - $bundle = $entity->bundle(); + if ($entity = $storage->load($part_two)) { + $bundle = $entity->bundle(); + } + else { + throw new PanelizerException("Unable to load $entity_type_id with id $part_two"); + } } else { $entity = NULL; @@ -105,19 +113,42 @@ class PanelizerDefaultPanelsStorage extends PanelsStorageBase implements Contain } /** + * Returns the entity context. + * + * Wraps creating new Context objects to avoid typed data in tests. + * + * @param string $entity_type_id + * The entity type id. + * @param \Drupal\Core\Entity\EntityInterface|NULL $entity + * The entity. + * + * @return \Drupal\Core\Plugin\Context\Context + * The context. + */ + protected function getEntityContext($entity_type_id, EntityInterface $entity = NULL) { + return new Context(new ContextDefinition('entity:' . $entity_type_id, NULL, TRUE), $entity); + } + + /** * {@inheritdoc} */ public function load($id) { - list ($entity_type_id, $bundle, $view_mode, $name, $entity) = $this->parseId($id); - $panels_display = $this->panelizer->getDefaultPanelsDisplay($name, $entity_type_id, $bundle, $view_mode); - // Set a placeholder context so that the calling code knows that we need - // an entity context. If we have the value available, then we actually set - // the context value. - $contexts = [ - '@panelizer.entity_context:entity' => new Context(new ContextDefinition('entity:' . $entity_type_id, NULL, TRUE), $entity), - ]; - $panels_display->setContexts($contexts); - return $panels_display; + try { + list ($entity_type_id, $bundle, $view_mode, $name, $entity) = $this->parseId($id); + if ($panels_display = $this->panelizer->getDefaultPanelsDisplay($name, $entity_type_id, $bundle, $view_mode)) { + // Set a placeholder context so that the calling code knows that we need + // an entity context. If we have the value available, then we actually set + // the context value. + $contexts = [ + '@panelizer.entity_context:entity' => $this->getEntityContext($entity_type_id, $entity), + ]; + $panels_display->setContexts($contexts); + return $panels_display; + } + } + catch (PanelizerException $e) { + // Do nothing to fallback on returning NULL. + } } /** @@ -125,15 +156,26 @@ class PanelizerDefaultPanelsStorage extends PanelsStorageBase implements Contain */ public function save(PanelsDisplayVariant $panels_display) { $id = $panels_display->getStorageId(); - list ($entity_type_id, $bundle, $view_mode, $name) = $this->parseId($id); - return $this->panelizer->setDefaultPanelsDisplay($name, $entity_type_id, $bundle, $view_mode, $panels_display); + try { + list ($entity_type_id, $bundle, $view_mode, $name) = $this->parseId($id); + $this->panelizer->setDefaultPanelsDisplay($name, $entity_type_id, $bundle, $view_mode, $panels_display); + } + catch (PanelizerException $e) { + throw new \Exception("Couldn't find Panelizer default to store Panels display"); + } } /** * {@inheritdoc} */ public function access($id, $op, AccountInterface $account) { - list ($entity_type_id, $bundle, $view_mode, $name) = $this->parseId($id); + try { + list ($entity_type_id, $bundle, $view_mode, $name) = $this->parseId($id); + } + catch (PanelizerException $e) { + return AccessResult::forbidden(); + } + if ($panels_display = $this->panelizer->getDefaultPanelsDisplay($name, $entity_type_id, $bundle, $view_mode)) { if ($op == 'change layout') { if ($this->panelizer->hasDefaultPermission('change layout', $entity_type_id, $bundle, $view_mode, $name, $account)) { diff --git a/src/Plugin/PanelsStorage/PanelizerFieldPanelsStorage.php b/src/Plugin/PanelsStorage/PanelizerFieldPanelsStorage.php index 9fbfb7f..7ea92c8 100644 --- a/src/Plugin/PanelsStorage/PanelizerFieldPanelsStorage.php +++ b/src/Plugin/PanelsStorage/PanelizerFieldPanelsStorage.php @@ -8,12 +8,14 @@ namespace Drupal\panelizer\Plugin\PanelsStorage; use Drupal\Core\Access\AccessResult; +use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Plugin\Context\Context; use Drupal\Core\Plugin\Context\ContextDefinition; use Drupal\Core\Session\AccountInterface; +use Drupal\panelizer\Exception\PanelizerException; use Drupal\panelizer\PanelizerInterface; use Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant; use Drupal\panels\Storage\PanelsStorageBase; @@ -78,7 +80,7 @@ class PanelizerFieldPanelsStorage extends PanelsStorageBase implements Container * @return \Drupal\Core\Entity\EntityInterface|NULL */ protected function loadEntity($id) { - list ($entity_type, $id, , $revision_id) = explode(':', $id); + list ($entity_type, $id, , $revision_id) = array_pad(explode(':', $id), 4, NULL); $storage = $this->entityTypeManager->getStorage($entity_type); if ($revision_id) { @@ -92,18 +94,36 @@ class PanelizerFieldPanelsStorage extends PanelsStorageBase implements Container } /** + * Returns the entity context. + * + * Wraps creating new Context objects to avoid typed data in tests. + * + * @param string $entity_type_id + * The entity type id. + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity. + * + * @return \Drupal\Core\Plugin\Context\Context + * The context. + */ + protected function getEntityContext($entity_type_id, EntityInterface $entity) { + return new Context(new ContextDefinition('entity:' . $entity_type_id, NULL, TRUE), $entity); + } + + /** * {@inheritdoc} */ public function load($id) { if ($entity = $this->loadEntity($id)) { list ($entity_type_id, , $view_mode) = explode(':', $id); - $panels_display = $this->panelizer->getPanelsDisplay($entity, $view_mode); - // Set the entity as a context on the Panels display. - $contexts = [ - '@panelizer.entity_context:entity' => new Context(new ContextDefinition('entity:' . $entity_type_id, NULL, TRUE), $entity), - ]; - $panels_display->setContexts($contexts); - return $panels_display; + if ($panels_display = $this->panelizer->getPanelsDisplay($entity, $view_mode)) { + // Set the entity as a context on the Panels display. + $contexts = [ + '@panelizer.entity_context:entity' => $this->getEntityContext($entity_type_id, $entity), + ]; + $panels_display->setContexts($contexts); + return $panels_display; + } } } @@ -115,7 +135,13 @@ class PanelizerFieldPanelsStorage extends PanelsStorageBase implements Container if ($entity = $this->loadEntity($id)) { list (,, $view_mode) = explode(':', $id); if ($entity instanceof FieldableEntityInterface) { - $this->panelizer->setPanelsDisplay($entity, $view_mode, NULL, $panels_display); + try { + $this->panelizer->setPanelsDisplay($entity, $view_mode, NULL, $panels_display); + } + catch (PanelizerException $e) { + // Translate to expected exception type. + throw new \Exception($e->getMessage()); + } } } else { diff --git a/tests/src/Unit/PanelizerDefaultPanelsStorageTest.php b/tests/src/Unit/PanelizerDefaultPanelsStorageTest.php new file mode 100644 index 0000000..51f0a55 --- /dev/null +++ b/tests/src/Unit/PanelizerDefaultPanelsStorageTest.php @@ -0,0 +1,266 @@ +storage = $this->prophesize(EntityStorageInterface::class); + + $this->entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class); + $this->entityTypeManager->getStorage('entity_type_id')->willReturn($this->storage->reveal()); + + $this->panelizer = $this->prophesize(Panelizer::class); + + $this->panelsStorage = $this->getMockBuilder(PanelizerDefaultPanelsStorage::class) + ->setConstructorArgs([ + [], + '', + [], + $this->entityTypeManager->reveal(), + $this->panelizer->reveal(), + ]) + ->setMethods(['getEntityContext']) + ->getMock(); + } + + /** + * @covers ::load + */ + public function testLoadEmptyContext() { + $entity_context = $this->prophesize(Context::class); + + $panels_display = $this->prophesize(PanelsDisplayVariant::class); + $panels_display->setContexts([ + '@panelizer.entity_context:entity' => $entity_context->reveal(), + ])->shouldBeCalled(); + + $this->panelizer->getDefaultPanelsDisplay('default', 'entity_type_id', 'bundle', 'view_mode', NULL) + ->willReturn($panels_display->reveal()); + + $this->panelsStorage->method('getEntityContext') + ->with($this->equalTo('entity_type_id'), $this->isNull()) + ->willReturn($entity_context->reveal()); + + $this->assertSame($panels_display->reveal(), $this->panelsStorage->load('entity_type_id:bundle:view_mode:default')); + } + + /** + * @covers ::load + */ + public function testLoadWithContextValue() { + $entity_context = $this->prophesize(Context::class); + + $panels_display = $this->prophesize(PanelsDisplayVariant::class); + $panels_display->setContexts([ + '@panelizer.entity_context:entity' => $entity_context->reveal(), + ])->shouldBeCalled(); + + $this->panelizer->getDefaultPanelsDisplay('default', 'entity_type_id', 'bundle', 'view_mode', NULL) + ->willReturn($panels_display->reveal()); + + $entity = $this->prophesize(EntityInterface::class); + $entity->bundle()->willReturn("bundle"); + $this->storage->load('123')->willReturn($entity->reveal())->shouldBeCalled(); + + $this->panelsStorage->method('getEntityContext') + ->with($this->equalTo('entity_type_id'), $entity->reveal()) + ->willReturn($entity_context->reveal()); + + $this->assertSame($panels_display->reveal(), $this->panelsStorage->load('*entity_type_id:123:view_mode:default')); + } + + /** + * @covers ::load + */ + public function testLoadDoesntExist() { + $this->panelizer->getDefaultPanelsDisplay('default', 'entity_type_id', 'bundle', 'view_mode', NULL) + ->willReturn(NULL); + + $this->assertSame(NULL, $this->panelsStorage->load('entity_type_id:bundle:view_mode:default')); + } + + /** + * @covers ::load + */ + public function testLoadNoEntity() { + $this->storage->load('123')->willReturn(NULL)->shouldBeCalled(); + + $this->panelizer->getDefaultPanelsDisplay('default', 'entity_type_id', 'bundle', 'view_mode', NULL) + ->shouldNotBeCalled(); + + $this->assertSame(NULL, $this->panelsStorage->load('*entity_type_id:123:view_mode:default')); + } + + /** + * @covers ::save + */ + public function testSaveSuccessful() { + $panels_display = $this->prophesize(PanelsDisplayVariant::class); + $panels_display->getStorageId()->willReturn('entity_type_id:bundle:view_mode:default'); + + $this->panelizer->setDefaultPanelsDisplay('default', 'entity_type_id', 'bundle', 'view_mode', $panels_display->reveal()) + ->shouldBeCalled(); + + $this->panelsStorage->save($panels_display->reveal()); + } + + /** + * @covers ::save + * + * @expectedException \Exception + * @expectedExceptionMessage Couldn't find Panelizer default to store Panels display + */ + public function testSaveDoesntExist() { + $panels_display = $this->prophesize(PanelsDisplayVariant::class); + $panels_display->getStorageId()->willReturn('entity_type_id:bundle:view_mode:default'); + + $this->panelizer->setDefaultPanelsDisplay('default', 'entity_type_id', 'bundle', 'view_mode', $panels_display->reveal()) + ->willThrow(new PanelizerException()); + + $this->panelsStorage->save($panels_display->reveal()); + } + + /** + * @covers ::save + * + * @expectedException \Exception + * @expectedExceptionMessage Couldn't find Panelizer default to store Panels display + */ + public function testSaveNoEntity() { + $panels_display = $this->prophesize(PanelsDisplayVariant::class); + $panels_display->getStorageId()->willReturn('*entity_type_id:123:view_mode:default'); + + $this->storage->load('123')->willReturn(NULL)->shouldBeCalled(); + + $this->panelizer->setDefaultPanelsDisplay('default', 'entity_type_id', 'bundle', 'view_mode', $panels_display->reveal()) + ->shouldNotBeCalled(); + + $this->panelsStorage->save($panels_display->reveal()); + } + + /** + * @covers ::access + */ + public function testAccessRead() { + $panels_display = $this->prophesize(PanelsDisplayVariant::class); + $account = $this->prophesize(AccountInterface::class); + + $this->panelizer->getDefaultPanelsDisplay('default', 'entity_type_id', 'bundle', 'view_mode') + ->willReturn($panels_display->reveal()); + $this->panelizer->hasDefaultPermission()->shouldNotBeCalled(); + + $this->assertEquals(AccessResult::allowed(), $this->panelsStorage->access('entity_type_id:bundle:view_mode:default', 'read', $account->reveal())); + } + + /** + * @covers ::access + */ + public function testAccessNotFound() { + $account = $this->prophesize(AccountInterface::class); + + $this->panelizer->getDefaultPanelsDisplay('default', 'entity_type_id', 'bundle', 'view_mode') + ->willReturn(NULL); + $this->panelizer->hasDefaultPermission()->shouldNotBeCalled(); + + $this->assertEquals(AccessResult::forbidden(), $this->panelsStorage->access('entity_type_id:bundle:view_mode:default', 'read', $account->reveal())); + } + + /** + * @covers ::access + */ + public function testAccessNoEntity() { + $account = $this->prophesize(AccountInterface::class); + + $this->storage->load('123')->willReturn(NULL)->shouldBeCalled(); + + $this->panelizer->getDefaultPanelsDisplay('default', 'entity_type_id', 'bundle', 'view_mode') + ->shouldNotBeCalled(); + + $this->assertEquals(AccessResult::forbidden(), $this->panelsStorage->access('*entity_type_id:123:view_mode:default', 'read', $account->reveal())); + } + + /** + * @covers ::access + */ + public function testAccessChangeContent() { + $panels_display = $this->prophesize(PanelsDisplayVariant::class); + $account = $this->prophesize(AccountInterface::class); + + $this->panelizer->getDefaultPanelsDisplay('default', 'entity_type_id', 'bundle', 'view_mode') + ->willReturn($panels_display->reveal()); + $this->panelizer->hasDefaultPermission('change content', 'entity_type_id', 'bundle', 'view_mode', 'default', $account->reveal()) + ->willReturn(TRUE); + + $this->assertEquals(AccessResult::allowed(), $this->panelsStorage->access('entity_type_id:bundle:view_mode:default', 'update', $account->reveal())); + $this->assertEquals(AccessResult::allowed(), $this->panelsStorage->access('entity_type_id:bundle:view_mode:default', 'delete', $account->reveal())); + $this->assertEquals(AccessResult::allowed(), $this->panelsStorage->access('entity_type_id:bundle:view_mode:default', 'create', $account->reveal())); + } + + /** + * @covers ::access + */ + public function testAccessChangeLayout() { + $panels_display = $this->prophesize(PanelsDisplayVariant::class); + $account = $this->prophesize(AccountInterface::class); + + $this->panelizer->getDefaultPanelsDisplay('default', 'entity_type_id', 'bundle', 'view_mode') + ->willReturn($panels_display->reveal()); + $this->panelizer->hasDefaultPermission('change layout', 'entity_type_id', 'bundle', 'view_mode', 'default', $account->reveal()) + ->willReturn(TRUE); + + $this->assertEquals(AccessResult::allowed(), $this->panelsStorage->access('entity_type_id:bundle:view_mode:default', 'change layout', $account->reveal())); + } + +} diff --git a/tests/src/Unit/PanelizerFieldPanelsStorageTest.php b/tests/src/Unit/PanelizerFieldPanelsStorageTest.php new file mode 100644 index 0000000..367a82a --- /dev/null +++ b/tests/src/Unit/PanelizerFieldPanelsStorageTest.php @@ -0,0 +1,282 @@ +storage = $this->prophesize(EntityStorageInterface::class); + + $this->entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class); + $this->entityTypeManager->getStorage('entity_type_id')->willReturn($this->storage->reveal()); + + $this->panelizer = $this->prophesize(Panelizer::class); + + $this->panelsStorage = $this->getMockBuilder(PanelizerFieldPanelsStorage::class) + ->setConstructorArgs([ + [], + '', + [], + $this->entityTypeManager->reveal(), + $this->panelizer->reveal(), + ]) + ->setMethods(['getEntityContext']) + ->getMock(); + } + + /** + * @covers ::load + */ + public function testLoad() { + $entity_context = $this->prophesize(Context::class); + + $panels_display = $this->prophesize(PanelsDisplayVariant::class); + $panels_display->setContexts([ + '@panelizer.entity_context:entity' => $entity_context->reveal(), + ])->shouldBeCalled(); + + $entity = $this->prophesize(FieldableEntityInterface::class); + + $this->panelizer->getPanelsDisplay($entity->reveal(), 'view_mode') + ->willReturn($panels_display->reveal()); + + $this->storage->load('123')->willReturn($entity->reveal())->shouldBeCalled(); + + $this->panelsStorage->method('getEntityContext') + ->with($this->equalTo('entity_type_id'), $entity->reveal()) + ->willReturn($entity_context->reveal()); + + $this->assertSame($panels_display->reveal(), $this->panelsStorage->load('entity_type_id:123:view_mode')); + } + + /** + * @covers ::load + */ + public function testLoadRevision() { + $entity_context = $this->prophesize(Context::class); + + $panels_display = $this->prophesize(PanelsDisplayVariant::class); + $panels_display->setContexts([ + '@panelizer.entity_context:entity' => $entity_context->reveal(), + ])->shouldBeCalled(); + + $entity = $this->prophesize(FieldableEntityInterface::class); + + $this->panelizer->getPanelsDisplay($entity->reveal(), 'view_mode') + ->willReturn($panels_display->reveal()); + + $this->storage->loadRevision('456')->willReturn($entity->reveal())->shouldBeCalled(); + + $this->panelsStorage->method('getEntityContext') + ->with($this->equalTo('entity_type_id'), $entity->reveal()) + ->willReturn($entity_context->reveal()); + + $this->assertSame($panels_display->reveal(), $this->panelsStorage->load('entity_type_id:123:view_mode:456')); + } + + /** + * @covers ::load + */ + public function testLoadNoEntity() { + $this->storage->load('123')->willReturn(NULL)->shouldBeCalled(); + + $this->panelizer->getPanelsDisplay()->shouldNotBeCalled(); + + $this->assertSame(NULL, $this->panelsStorage->load('entity_type_id:123:view_mode')); + } + + /** + * @covers ::load + */ + public function testLoadNotFound() { + $entity = $this->prophesize(FieldableEntityInterface::class); + + $this->storage->load('123')->willReturn($entity->reveal()); + + $this->panelizer->getPanelsDisplay($entity->reveal(), 'view_mode') + ->willReturn(NULL); + + $this->assertSame(NULL, $this->panelsStorage->load('entity_type_id:123:view_mode')); + } + + /** + * @covers ::save + */ + public function testSaveSuccessful() { + $panels_display = $this->prophesize(PanelsDisplayVariant::class); + $panels_display->getStorageId()->willReturn('entity_type_id:123:view_mode'); + + $entity = $this->prophesize(FieldableEntityInterface::class); + + $this->panelizer->setPanelsDisplay($entity->reveal(), 'view_mode', NULL, $panels_display) + ->shouldBeCalled(); + + $this->storage->load('123')->willReturn($entity->reveal())->shouldBeCalled(); + + $this->panelsStorage->save($panels_display->reveal()); + } + + /** + * @covers ::save + * + * @expectedException \Exception + * @expectedExceptionMessage Couldn't find entity to store Panels display on + */ + public function testSaveNoEntity() { + $panels_display = $this->prophesize(PanelsDisplayVariant::class); + $panels_display->getStorageId()->willReturn('entity_type_id:123:view_mode'); + + $this->panelizer->setPanelsDisplay()->shouldNotBeCalled(); + + $this->storage->load('123')->willReturn(NULL)->shouldBeCalled(); + + $this->panelsStorage->save($panels_display->reveal()); + } + + /** + * @covers ::save + * + * @expectedException \Exception + * @expectedExceptionMessage Save failed + */ + public function testSaveFailed() { + $panels_display = $this->prophesize(PanelsDisplayVariant::class); + $panels_display->getStorageId()->willReturn('entity_type_id:123:view_mode'); + + $entity = $this->prophesize(FieldableEntityInterface::class); + + $this->panelizer->setPanelsDisplay($entity->reveal(), 'view_mode', NULL, $panels_display) + ->willThrow(new PanelizerException("Save failed")); + + $this->storage->load('123')->willReturn($entity->reveal())->shouldBeCalled(); + + $this->panelsStorage->save($panels_display->reveal()); + } + + /** + * @covers ::access + */ + public function testAccessRead() { + $panels_display = $this->prophesize(PanelsDisplayVariant::class); + $account = $this->prophesize(AccountInterface::class); + + $entity = $this->prophesize(FieldableEntityInterface::class); + $entity->access('read', $account->reveal()) + ->willReturn(TRUE); + + $this->storage->load('123')->willReturn($entity->reveal()); + + $this->panelizer->getPanelsDisplay($entity->reveal(), 'view_mode') + ->willReturn($panels_display->reveal()); + $this->panelizer->hasEntityPermission()->shouldNotBeCalled(); + + $this->assertEquals(AccessResult::allowed(), $this->panelsStorage->access('entity_type_id:123:view_mode', 'read', $account->reveal())); + } + + /** + * @covers ::access + */ + public function testAccessNoEntity() { + $account = $this->prophesize(AccountInterface::class); + + $this->storage->load('123')->willReturn(NULL)->shouldBeCalled(); + + $this->panelizer->getPanelsDisplay()->shouldNotBeCalled(); + + $this->assertEquals(AccessResult::forbidden(), $this->panelsStorage->access('entity_type_id:123:view_mode', 'read', $account->reveal())); + } + + + /** + * @covers ::access + */ + public function testAccessChangeContent() { + $panels_display = $this->prophesize(PanelsDisplayVariant::class); + $account = $this->prophesize(AccountInterface::class); + + $entity = $this->prophesize(FieldableEntityInterface::class); + $entity->access('update', $account->reveal()) + ->willReturn(TRUE); + + $this->storage->load('123')->willReturn($entity->reveal()); + + $this->panelizer->getPanelsDisplay($entity->reveal(), 'view_mode') + ->willReturn($panels_display->reveal()); + $this->panelizer->hasEntityPermission('change content', $entity->reveal(), 'view_mode', $account->reveal()) + ->willReturn(TRUE); + + $this->assertEquals(AccessResult::allowed(), $this->panelsStorage->access('entity_type_id:123:view_mode', 'update', $account->reveal())); + } + + /** + * @covers ::access + */ + public function testAccessChangeLayout() { + $panels_display = $this->prophesize(PanelsDisplayVariant::class); + $account = $this->prophesize(AccountInterface::class); + + $entity = $this->prophesize(FieldableEntityInterface::class); + $entity->access('update', $account->reveal()) + ->willReturn(TRUE); + + $this->storage->load('123')->willReturn($entity->reveal()); + + $this->panelizer->getPanelsDisplay($entity->reveal(), 'view_mode') + ->willReturn($panels_display->reveal()); + $this->panelizer->hasEntityPermission('change layout', $entity->reveal(), 'view_mode', $account->reveal()) + ->willReturn(TRUE); + + $this->assertEquals(AccessResult::allowed(), $this->panelsStorage->access('entity_type_id:123:view_mode', 'change layout', $account->reveal())); + } + +}