diff --git a/src/Entity/EntityBrowser.php b/src/Entity/EntityBrowser.php index 6011f63..c969c5e 100644 --- a/src/Entity/EntityBrowser.php +++ b/src/Entity/EntityBrowser.php @@ -303,6 +303,9 @@ class EntityBrowser extends ConfigEntityBase implements EntityBrowserInterface, */ public function getFirstWidget() { $instance_ids = $this->getWidgets()->getInstanceIds(); + $instance_ids = array_filter($instance_ids, function ($id) { + return $this->getWidget($id)->access()->isAllowed(); + }); return reset($instance_ids); } diff --git a/src/Form/EntityBrowserForm.php b/src/Form/EntityBrowserForm.php index 80ea0a9..8383862 100644 --- a/src/Form/EntityBrowserForm.php +++ b/src/Form/EntityBrowserForm.php @@ -11,6 +11,7 @@ use Drupal\entity_browser\DisplayAjaxInterface; use Drupal\entity_browser\EntityBrowserFormInterface; use Drupal\entity_browser\EntityBrowserInterface; use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\Core\Render\RendererInterface; /** * The entity browser form. @@ -39,16 +40,26 @@ class EntityBrowserForm extends FormBase implements EntityBrowserFormInterface { protected $selectionStorage; /** + * The renderer service. + * + * @var \Drupal\Core\Render\RendererInterface + */ + protected $renderer; + + /** * Constructs a EntityBrowserForm object. * * @param \Drupal\Component\Uuid\UuidInterface $uuid_generator * The UUID generator service. * @param \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface $selection_storage * Selection storage. + * @param \Drupal\Core\Render\RendererInterface $renderer + * The renderer service. */ - public function __construct(UuidInterface $uuid_generator, KeyValueStoreExpirableInterface $selection_storage) { + public function __construct(UuidInterface $uuid_generator, KeyValueStoreExpirableInterface $selection_storage, RendererInterface $renderer) { $this->uuidGenerator = $uuid_generator; $this->selectionStorage = $selection_storage; + $this->renderer = $renderer; } /** @@ -57,7 +68,8 @@ class EntityBrowserForm extends FormBase implements EntityBrowserFormInterface { public static function create(ContainerInterface $container) { return new static( $container->get('uuid'), - $container->get('entity_browser.selection_storage') + $container->get('entity_browser.selection_storage'), + $container->get('renderer') ); } @@ -137,10 +149,21 @@ class EntityBrowserForm extends FormBase implements EntityBrowserFormInterface { $form[$form['#browser_parts']['widget_selector']] = $this->entityBrowser ->getWidgetSelector() ->getForm($form, $form_state); - $form[$form['#browser_parts']['widget']] = $this->entityBrowser - ->getWidgets() - ->get($this->getCurrentWidget($form_state)) - ->getForm($form, $form_state, $this->entityBrowser->getAdditionalWidgetParameters()); + + $widget = $this->entityBrowser->getWidget($this->getCurrentWidget($form_state)); + if ($widget->access()->isAllowed()) { + $form[$form['#browser_parts']['widget']] = $widget->getForm($form, $form_state, $this->entityBrowser->getAdditionalWidgetParameters()); + } + else { + $form[$form['#browser_parts']['widget']]['#markup'] = $this->t('Access to the widget forbidden.'); + } + + // Add cache access cache metadata from the widgets to the form directly as + // it is affected. + foreach ($this->entityBrowser->getWidgets() as $widget) { + /** @var \Drupal\entity_browser\WidgetInterface $widget */ + $this->renderer->addCacheableDependency($form, $widget->access()); + } $form[$form['#browser_parts']['selection_display']] = $this->entityBrowser ->getSelectionDisplay() diff --git a/src/Plugin/EntityBrowser/Widget/View.php b/src/Plugin/EntityBrowser/Widget/View.php index ba3d714..9335dca 100644 --- a/src/Plugin/EntityBrowser/Widget/View.php +++ b/src/Plugin/EntityBrowser/Widget/View.php @@ -283,7 +283,7 @@ class View extends WidgetBase implements ContainerFactoryPluginInterface { /** * {@inheritdoc} */ - public function access($return_as_object = FALSE) { + public function access() { // Mark the widget as not visible if the user has no access to the view. /** @var \Drupal\views\ViewExecutable $view */ $view = $this->entityTypeManager @@ -293,8 +293,7 @@ class View extends WidgetBase implements ContainerFactoryPluginInterface { // Check if the current user has access to this view. - $result = AccessResult::allowedIf($view->access($this->configuration['view_display'])); - return $return_as_object ? $result : $result->isAllowed(); + return AccessResult::allowedIf($view->access($this->configuration['view_display'])); } } diff --git a/src/Plugin/EntityBrowser/WidgetSelector/DropDown.php b/src/Plugin/EntityBrowser/WidgetSelector/DropDown.php index a5dd437..db44a43 100644 --- a/src/Plugin/EntityBrowser/WidgetSelector/DropDown.php +++ b/src/Plugin/EntityBrowser/WidgetSelector/DropDown.php @@ -20,6 +20,7 @@ class DropDown extends WidgetSelectorBase { * {@inheritdoc} */ public function getForm(array &$form = array(), FormStateInterface &$form_state = NULL) { + $element = []; // Set a wrapper container for us to replace the form on ajax call. $form['#prefix'] = '
'; $form['#suffix'] = '
'; @@ -29,7 +30,7 @@ class DropDown extends WidgetSelectorBase { $widget_ids = []; foreach ($this->widget_ids as $widget_id => $widget_name) { - if ($browser->getWidget($widget_id)->access()) { + if ($browser->getWidget($widget_id)->access()->isAllowed()) { $widget_ids[$widget_id] = $widget_name; } } diff --git a/src/WidgetBase.php b/src/WidgetBase.php index be28f61..f5d2ea7 100644 --- a/src/WidgetBase.php +++ b/src/WidgetBase.php @@ -376,9 +376,8 @@ abstract class WidgetBase extends PluginBase implements WidgetInterface, Contain /** * {@inheritdoc} */ - public function access($return_as_object = FALSE) { - $result = AccessResult::allowed(); - return $return_as_object ? $result : $result->isAllowed(); + public function access() { + return AccessResult::allowed(); } } diff --git a/src/WidgetInterface.php b/src/WidgetInterface.php index 005bb58..c88f4b8 100644 --- a/src/WidgetInterface.php +++ b/src/WidgetInterface.php @@ -121,14 +121,9 @@ interface WidgetInterface extends PluginInspectionInterface, ConfigurablePluginI /** * Defines if the widget is visible / accessible in a given context. * - * @return bool|\Drupal\Core\Access\AccessResultInterface - * The access result. Returns a boolean if $return_as_object is FALSE (this - * is the default) and otherwise an AccessResultInterface object. - * When a boolean is returned, the result of AccessInterface::isAllowed() is - * returned, i.e. TRUE means access is explicitly allowed, thus the widget - * is to be considered accessible by other plugins. FALSE means - * access is either explicitly forbidden or "no opinion". + * @return \Drupal\Core\Access\AccessResultInterface + * The access result. */ - public function access($return_as_object = FALSE); + public function access(); } diff --git a/tests/modules/entity_browser_test/config/install/entity_browser.browser.test_entity_browser_file.yml b/tests/modules/entity_browser_test/config/install/entity_browser.browser.test_entity_browser_file.yml index 1956d39..d75ba00 100644 --- a/tests/modules/entity_browser_test/config/install/entity_browser.browser.test_entity_browser_file.yml +++ b/tests/modules/entity_browser_test/config/install/entity_browser.browser.test_entity_browser_file.yml @@ -40,4 +40,5 @@ widgets: label: dummy weight: -8 uuid: cbc59500-04ab-4395-b063-c561f0e3bf80 - settings: { } + settings: + text: 'This is dummy widget.' diff --git a/tests/modules/entity_browser_test/entity_browser_test.services.yml b/tests/modules/entity_browser_test/entity_browser_test.services.yml new file mode 100644 index 0000000..17e1f17 --- /dev/null +++ b/tests/modules/entity_browser_test/entity_browser_test.services.yml @@ -0,0 +1,5 @@ +services: + cache_context.eb_dummy: + class: Drupal\entity_browser_test\Cache\Context\DummyCacheContext + tags: + - { name: cache.context} diff --git a/tests/modules/entity_browser_test/src/Cache/Context/DummyCacheContext.php b/tests/modules/entity_browser_test/src/Cache/Context/DummyCacheContext.php new file mode 100644 index 0000000..ee53905 --- /dev/null +++ b/tests/modules/entity_browser_test/src/Cache/Context/DummyCacheContext.php @@ -0,0 +1,36 @@ +get('eb_test_dummy_widget_access', TRUE)) { $access = AccessResult::allowed(); + $access->addCacheContexts(['eb_dummy']); } else { $access = AccessResult::forbidden(); + $access->addCacheContexts(['eb_dummy']); } - return $return_as_object ? $access : $access->isAllowed(); + return $access; } } diff --git a/tests/src/FunctionalJavascript/EntityBrowserTest.php b/tests/src/FunctionalJavascript/EntityBrowserTest.php index d97f8f1..857d2c1 100644 --- a/tests/src/FunctionalJavascript/EntityBrowserTest.php +++ b/tests/src/FunctionalJavascript/EntityBrowserTest.php @@ -105,17 +105,24 @@ class EntityBrowserTest extends EntityBrowserJavascriptTestBase { // $this->drupalPostForm(NULL, $edit, 'Select files');. \Drupal::state()->set('eb_test_dummy_widget_access', FALSE); + $this->drupalGet('entity-browser/iframe/test_entity_browser_file'); + $this->assertSession()->linkNotExists('dummy'); + $this->assertSession()->linkExists('view'); + $this->assertSession()->linkExists('upload'); + $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Contexts', 'eb_dummy'); - $this->drupalGet('node/add/article'); - - $this->assertSession()->linkExists('Select entities'); - $this->getSession()->getPage()->clickLink('Select entities'); - - $this->getSession()->switchToIFrame('entity_browser_iframe_test_entity_browser_file'); - + // Move dummy widget to the first place and make sure it does not appear. + $browser = $this->container->get('entity_type.manager') + ->getStorage('entity_browser') + ->load('test_entity_browser_file'); + $browser->getWidget('cbc59500-04ab-4395-b063-c561f0e3bf80')->setWeight(-15); + $browser->save(); + $this->drupalGet('entity-browser/iframe/test_entity_browser_file'); $this->assertSession()->linkNotExists('dummy'); $this->assertSession()->linkExists('view'); $this->assertSession()->linkExists('upload'); + $this->assertSession()->pageTextNotContains('This is dummy widget.'); + $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Contexts', 'eb_dummy'); } /** @@ -167,17 +174,24 @@ class EntityBrowserTest extends EntityBrowserJavascriptTestBase { // $this->getSession()->getPage()->selectFieldOption('widget', '2dc1ab07-2f8f-42c9-aab7-7eef7f8b7d87');. \Drupal::state()->set('eb_test_dummy_widget_access', FALSE); + $this->drupalGet('entity-browser/iframe/test_entity_browser_file'); + $this->assertSession()->optionNotExists('widget', 'cbc59500-04ab-4395-b063-c561f0e3bf80'); // Dummy + $this->assertSession()->optionExists('widget', '2dc1ab07-2f8f-42c9-aab7-7eef7f8b7d87'); // Upload + $this->assertSession()->optionExists('widget', '774798f1-5ec5-4b63-84bd-124cd51ec07d'); // View + $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Contexts', 'eb_dummy'); - $this->drupalGet('node/add/article'); - - $this->assertSession()->linkExists('Select entities'); - $this->getSession()->getPage()->clickLink('Select entities'); - - $this->getSession()->switchToIFrame('entity_browser_iframe_test_entity_browser_file'); - + // Move dummy widget to the first place and make sure it does not appear. + $browser = $this->container->get('entity_type.manager') + ->getStorage('entity_browser') + ->load('test_entity_browser_file'); + $browser->getWidget('cbc59500-04ab-4395-b063-c561f0e3bf80')->setWeight(-15); + $browser->save(); + $this->drupalGet('entity-browser/iframe/test_entity_browser_file'); $this->assertSession()->optionNotExists('widget', 'cbc59500-04ab-4395-b063-c561f0e3bf80'); // Dummy $this->assertSession()->optionExists('widget', '2dc1ab07-2f8f-42c9-aab7-7eef7f8b7d87'); // Upload $this->assertSession()->optionExists('widget', '774798f1-5ec5-4b63-84bd-124cd51ec07d'); // View + $this->assertSession()->pageTextNotContains('This is dummy widget.'); + $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Contexts', 'eb_dummy'); } /**