Commit ee9dacfb authored by webchick's avatar webchick

Issue #2784853 by Wim Leers, tedbow: Determine when Outside In library should...

Issue #2784853 by Wim Leers, tedbow: Determine when Outside In library should be loaded: piggyback on contextual_toolbar()
parent 4b95aa76
......@@ -101,8 +101,7 @@ function outside_in_entity_type_build(array &$entity_types) {
*/
function outside_in_preprocess_block(&$variables) {
// The main system block does not contain the block contextual links.
$variables['#cache']['contexts'][] = 'outside_in_is_applied';
if ($variables['plugin_id'] !== 'system_main_block' && \Drupal::service('outside_in.manager')->isApplicable()) {
if ($variables['plugin_id'] !== 'system_main_block') {
// Add class and attributes to all blocks to allow Javascript to target.
$variables['attributes']['class'][] = 'outside-in-editable';
$variables['attributes']['data-drupal-outsidein'] = 'editable';
......@@ -112,11 +111,15 @@ function outside_in_preprocess_block(&$variables) {
/**
* Implements hook_toolbar_alter().
*
* Includes outside_library if Edit link is in toolbar.
* Alters the 'contextual' toolbar tab if it exists (meaning the user is allowed
* to use contextual links) and if they can administer blocks.
*
* @todo Remove the "administer blocks" requirement in https://www.drupal.org/node/2822965
* @see contextual_toolbar()
*/
function outside_in_toolbar_alter(&$items) {
$items['contextual']['#cache']['contexts'][] = 'outside_in_is_applied';
if (isset($items['contextual']['tab']) && \Drupal::service('outside_in.manager')->isApplicable()) {
$items['contextual']['#cache']['contexts'][] = 'user.permissions';
if (isset($items['contextual']['tab']) && \Drupal::currentUser()->hasPermission('administer blocks')) {
$items['contextual']['#weight'] = -1000;
$items['contextual']['#attached']['library'][] = 'outside_in/drupal.outside_in';
$items['contextual']['tab']['#attributes']['data-drupal-outsidein'] = 'toggle';
......
......@@ -4,13 +4,3 @@ services:
arguments: ['@title_resolver', '@renderer']
tags:
- { name: render.main_content_renderer, format: drupal_dialog.off_canvas }
outside_in.manager:
class: Drupal\outside_in\OutsideInManager
arguments: ['@router.admin_context', '@current_route_match', '@current_user']
cache_context.outside_in_is_applied:
class: Drupal\outside_in\Cache\Context\OutsideInCacheContext
arguments: ['@outside_in.manager']
tags:
- { name: cache.context}
<?php
namespace Drupal\outside_in\Cache\Context;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\Context\CacheContextInterface;
use Drupal\outside_in\OutsideInManagerInterface;
/**
* Defines the OutsideInCacheContext service, for "Outside-In or not" caching.
*
* Cache context ID: 'outside_in_is_applied'.
*/
class OutsideInCacheContext implements CacheContextInterface {
/**
* The Outside-In manager.
*
* @var \Drupal\outside_in\OutsideInManagerInterface
*/
protected $outsideInManager;
/**
* OutsideInCacheContext constructor.
*
* @param \Drupal\outside_in\OutsideInManagerInterface $outside_in_manager
* The Outside-In manager.
*/
public function __construct(OutsideInManagerInterface $outside_in_manager) {
$this->outsideInManager = $outside_in_manager;
}
/**
* {@inheritdoc}
*/
public static function getLabel() {
return t('Settings Tray');
}
/**
* {@inheritdoc}
*/
public function getContext() {
return $this->outsideInManager->isApplicable() ? '1' : '0';
}
/**
* {@inheritdoc}
*/
public function getCacheableMetadata() {
return new CacheableMetadata();
}
}
<?php
namespace Drupal\outside_in;
use Drupal\Core\Routing\AdminContext;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
/**
* Manages information related to Settings Tray.
*/
class OutsideInManager implements OutsideInManagerInterface {
/**
* The admin context service.
*
* @var \Drupal\Core\Routing\AdminContext
*/
protected $adminContext;
/**
* The current route match.
*
* @var \Drupal\Core\Routing\RouteMatchInterface
*/
protected $routeMatch;
/**
* The current account.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $account;
/**
* OutsideInManager constructor.
*
* @param \Drupal\Core\Routing\AdminContext $admin_context
* The admin context service.
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The current route match.
* @param \Drupal\Core\Session\AccountInterface $account
* The current account.
*/
public function __construct(AdminContext $admin_context, RouteMatchInterface $route_match, AccountInterface $account) {
$this->adminContext = $admin_context;
$this->routeMatch = $route_match;
$this->account = $account;
}
/**
* {@inheritdoc}
*/
public function isApplicable() {
// Remove on Admin routes.
$is_admin_route = $this->adminContext->isAdminRoute();
// Remove on Block Demo page.
$is_admin_demo_route = $this->routeMatch->getRouteName() === 'block.admin_demo';
// @todo Check if there is actually a different admin theme.
// https://www.drupal.org/node/2784853
return $this->account->hasPermission('administer blocks') && !$is_admin_route && !$is_admin_demo_route;
}
}
<?php
namespace Drupal\outside_in;
/**
* Provides an interface for managing information related to Outside-In.
*/
interface OutsideInManagerInterface {
/**
* Determines if the Settings Tray logic should be run on the current page.
*
* @return bool
* TRUE if the Settings Tray logic should be run.
*/
public function isApplicable();
}
<?php
namespace Drupal\Tests\outside_in\Unit;
use Drupal\Core\Routing\AdminContext;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\outside_in\OutsideInManager;
use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\outside_in\OutsideInManager
* @group outside_in
*/
class OutsideInManagerTest extends UnitTestCase {
/**
* @covers ::isApplicable
* @dataProvider providerTestIsApplicable
*/
public function testIsApplicable($is_admin_route, $route_name, $has_permission, $expected) {
$admin_context = $this->prophesize(AdminContext::class);
$admin_context->isAdminRoute()->willReturn($is_admin_route);
$route_match = $this->prophesize(RouteMatchInterface::class);
$route_match->getRouteName()->willReturn($route_name);
$account = $this->prophesize(AccountInterface::class);
$account->hasPermission('administer blocks')->willReturn($has_permission);
$outside_in_manager = new OutsideInManager($admin_context->reveal(), $route_match->reveal(), $account->reveal());
$this->assertSame($expected, $outside_in_manager->isApplicable());
}
/**
* Data provider for ::testIsApplicable().
*/
public function providerTestIsApplicable() {
$data = [];
// Passing combination.
$data[] = [FALSE, 'the_route_name', TRUE, TRUE];
// Failing combinations.
$data[] = [TRUE, 'the_route_name', TRUE, FALSE];
$data[] = [TRUE, 'the_route_name', FALSE, FALSE];
$data[] = [TRUE, 'block.admin_demo', TRUE, FALSE];
$data[] = [TRUE, 'block.admin_demo', FALSE, FALSE];
$data[] = [FALSE, 'the_route_name', FALSE, FALSE];
$data[] = [FALSE, 'block.admin_demo', TRUE, FALSE];
$data[] = [FALSE, 'block.admin_demo', FALSE, FALSE];
return $data;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment