Move into nested docroot

This commit is contained in:
Rob Davies 2017-02-13 15:31:17 +00:00
parent 83a0d3a149
commit c8b70abde9
13405 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,57 @@
<?php
namespace Drupal\outside_in\Ajax;
use Drupal\Core\Ajax\OpenDialogCommand;
/**
* Defines an AJAX command to open content in a dialog in a off-canvas tray.
*
* @ingroup ajax
*/
class OpenOffCanvasDialogCommand extends OpenDialogCommand {
/**
* Constructs an OpenOffCanvasDialogCommand object.
*
* The off-canvas dialog differs from the normal modal provided by
* OpenDialogCommand in that a off-canvas has built in positioning and
* behaviours. Drupal provides a built-in off-canvas tray for this purpose,
* so the selector is hard-coded in the call to the parent constructor.
*
* @param string $title
* The title of the dialog.
* @param string|array $content
* The content that will be placed in the dialog, either a render array
* or an HTML string.
* @param array $dialog_options
* (optional) Settings to be passed to the dialog implementation. Any
* jQuery UI option can be used. See http://api.jqueryui.com/dialog.
* @param array|null $settings
* (optional) Custom settings that will be passed to the Drupal behaviors
* on the content of the dialog. If left empty, the settings will be
* populated automatically from the current request.
*/
public function __construct($title, $content, array $dialog_options = [], $settings = NULL) {
parent::__construct('#drupal-offcanvas', $title, $content, $dialog_options, $settings);
$this->dialogOptions['modal'] = FALSE;
$this->dialogOptions['autoResize'] = FALSE;
$this->dialogOptions['resizable'] = 'w';
$this->dialogOptions['draggable'] = FALSE;
$this->dialogOptions['drupalAutoButtons'] = FALSE;
// @todo drupal.ajax.js does not respect drupalAutoButtons properly, pass an
// empty set of buttons until https://www.drupal.org/node/2793343 is in.
$this->dialogOptions['buttons'] = [];
}
/**
* {@inheritdoc}
*/
public function render() {
$build = parent::render();
$build['effect'] = 'fade';
$build['speed'] = 1000;
return $build;
}
}

View file

@ -0,0 +1,100 @@
<?php
namespace Drupal\outside_in\Block;
use Drupal\block\BlockForm;
use Drupal\block\BlockInterface;
use Drupal\Core\Block\BlockPluginInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\PluginWithFormsInterface;
/**
* Provides form for block instance forms when used in the off-canvas tray.
*
* This form removes advanced sections of regular block form such as the
* visibility settings, machine ID and region.
*/
class BlockEntityOffCanvasForm extends BlockForm {
/**
* Provides a title callback to get the block's admin label.
*
* @param \Drupal\block\BlockInterface $block
* The block entity.
*
* @return \Drupal\Core\StringTranslation\TranslatableMarkup
* The title.
*/
public function title(BlockInterface $block) {
// @todo Wrap "Configure " in <span class="visually-hidden"></span> once
// https://www.drupal.org/node/2359901 is fixed.
return $this->t('Configure @block', ['@block' => $block->getPlugin()->getPluginDefinition()['admin_label']]);
}
/**
* {@inheritdoc}
*/
public function form(array $form, FormStateInterface $form_state) {
$form = parent::form($form, $form_state);
// Create link to full block form.
$query = [];
if ($destination = $this->getRequest()->query->get('destination')) {
$query['destination'] = $destination;
}
$form['advanced_link'] = [
'#type' => 'link',
'#title' => $this->t('Advanced options'),
'#url' => $this->entity->toUrl('edit-form', ['query' => $query]),
'#weight' => 1000,
];
// Remove the ID and region elements.
unset($form['id'], $form['region'], $form['settings']['admin_label']);
return $form;
}
/**
* {@inheritdoc}
*/
protected function actions(array $form, FormStateInterface $form_state) {
$actions = parent::actions($form, $form_state);
$actions['submit']['#value'] = $this->t('Save @block', ['@block' => $this->entity->getPlugin()->getPluginDefinition()['admin_label']]);
$actions['delete']['#access'] = FALSE;
return $actions;
}
/**
* {@inheritdoc}
*/
protected function buildVisibilityInterface(array $form, FormStateInterface $form_state) {
// Do not display the visibility.
return [];
}
/**
* {@inheritdoc}
*/
protected function validateVisibility(array $form, FormStateInterface $form_state) {
// Intentionally empty.
}
/**
* {@inheritdoc}
*/
protected function submitVisibility(array $form, FormStateInterface $form_state) {
// Intentionally empty.
}
/**
* {@inheritdoc}
*/
protected function getPluginForm(BlockPluginInterface $block) {
if ($block instanceof PluginWithFormsInterface) {
return $this->pluginFormFactory->createInstance($block, 'offcanvas', 'configure');
}
return $block;
}
}

View file

@ -0,0 +1,54 @@
<?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();
}
}

View file

@ -0,0 +1,104 @@
<?php
namespace Drupal\outside_in\Form;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\PluginFormBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* The off-canvas form handler for the SystemBrandingBlock.
*
* @see outside_in_block_alter()
*/
class SystemBrandingOffCanvasForm extends PluginFormBase implements ContainerInjectionInterface {
/**
* The block plugin.
*
* @var \Drupal\Core\Block\BlockPluginInterface
*/
protected $plugin;
/**
* The config factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* SystemBrandingOffCanvasForm constructor.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The config factory.
*/
public function __construct(ConfigFactoryInterface $config_factory) {
$this->configFactory = $config_factory;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('config.factory')
);
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form = $this->plugin->buildConfigurationForm($form, $form_state);
$form['block_branding']['#type'] = 'details';
$form['block_branding']['#weight'] = 10;
// Unset links to Site Information form, we can make these changes here.
unset($form['block_branding']['use_site_name']['#description'], $form['block_branding']['use_site_slogan']['#description']);
$site_config = $this->configFactory->getEditable('system.site');
$form['site_information'] = [
'#type' => 'details',
'#title' => t('Site details'),
'#open' => TRUE,
];
$form['site_information']['site_name'] = [
'#type' => 'textfield',
'#title' => t('Site name'),
'#default_value' => $site_config->get('name'),
'#required' => TRUE,
];
$form['site_information']['site_slogan'] = [
'#type' => 'textfield',
'#title' => t('Slogan'),
'#default_value' => $site_config->get('slogan'),
'#description' => t("How this is used depends on your site's theme."),
];
return $form;
}
/**
* {@inheritdoc}
*/
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
$this->plugin->validateConfigurationForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
$site_info = $form_state->getValue('site_information');
$this->configFactory->getEditable('system.site')
->set('name', $site_info['site_name'])
->set('slogan', $site_info['site_slogan'])
->save();
$this->plugin->submitConfigurationForm($form, $form_state);
}
}

View file

@ -0,0 +1,149 @@
<?php
namespace Drupal\outside_in\Form;
use Drupal\Component\Plugin\PluginInspectionInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\PluginFormBase;
use Drupal\Core\Render\Element;
use Drupal\Core\Routing\RedirectDestinationTrait;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\system\MenuInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* The off-canvas form handler for the SystemMenuBlock.
*
* @see outside_in_block_alter()
*/
class SystemMenuOffCanvasForm extends PluginFormBase implements ContainerInjectionInterface {
use StringTranslationTrait;
use RedirectDestinationTrait;
/**
* The plugin.
*
* @var \Drupal\Core\Block\BlockPluginInterface
*/
protected $plugin;
/**
* @var \Drupal\system\MenuInterface
*/
protected $entity;
/**
* @var \Drupal\Core\Entity\EntityStorageInterface
*/
protected $menuStorage;
/**
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* SystemMenuOffCanvasForm constructor.
*
* @param \Drupal\Core\Entity\EntityStorageInterface $menu_storage
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
*/
public function __construct(EntityStorageInterface $menu_storage, EntityTypeManagerInterface $entity_type_manager, TranslationInterface $string_translation) {
$this->menuStorage = $menu_storage;
$this->entityTypeManager = $entity_type_manager;
$this->stringTranslation = $string_translation;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity_type.manager')->getStorage('menu'),
$container->get('entity_type.manager'),
$container->get('string_translation')
);
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form = $this->plugin->buildConfigurationForm([], $form_state);
// Move the menu levels section to the bottom.
$form['menu_levels']['#weight'] = 100;
$form['entity_form'] = [
'#type' => 'details',
'#title' => $this->t('Edit menu %label', array('%label' => $this->entity->label())),
'#open' => TRUE,
];
$form['entity_form'] += $this->getEntityForm($this->entity)->buildForm([], $form_state);
// Print the menu link titles as text instead of a link.
if (!empty($form['entity_form']['links']['links'])) {
foreach (Element::children($form['entity_form']['links']['links']) as $child) {
$title = $form['entity_form']['links']['links'][$child]['title'][1]['#title'];
$form['entity_form']['links']['links'][$child]['title'][1] = ['#markup' => $title];
}
}
// Change the header text.
$form['entity_form']['links']['links']['#header'][0] = $this->t('Link');
$form['entity_form']['links']['links']['#header'][1]['data'] = $this->t('On');
// Remove the label, ID, description, and buttons from the entity form.
unset($form['entity_form']['label'], $form['entity_form']['id'], $form['entity_form']['description'], $form['entity_form']['actions']);
// Since the overview form is further nested than expected, update the
// #parents. See \Drupal\menu_ui\MenuForm::form().
$form_state->set('menu_overview_form_parents', ['settings', 'entity_form', 'links']);
return $form;
}
/**
* {@inheritdoc}
*/
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
$this->plugin->validateConfigurationForm($form, $form_state);
$this->getEntityForm($this->entity)->validateForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
$this->plugin->submitConfigurationForm($form, $form_state);
$this->getEntityForm($this->entity)->submitForm($form, $form_state);
$this->entity->save();
}
/**
* Gets the entity form for this menu.
*
* @param \Drupal\system\MenuInterface $entity
* The menu entity.
*
* @return \Drupal\Core\Entity\EntityFormInterface
* The entity form.
*/
protected function getEntityForm(MenuInterface $entity) {
$entity_form = $this->entityTypeManager->getFormObject('menu', 'edit');
$entity_form->setEntity($entity);
return $entity_form;
}
/**
* {@inheritdoc}
*/
public function setPlugin(PluginInspectionInterface $plugin) {
$this->plugin = $plugin;
$this->entity = $this->menuStorage->load($this->plugin->getDerivativeId());
}
}

View file

@ -0,0 +1,66 @@
<?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;
}
}

View file

@ -0,0 +1,18 @@
<?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();
}

View file

@ -0,0 +1,63 @@
<?php
namespace Drupal\outside_in\Render\MainContent;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Controller\TitleResolverInterface;
use Drupal\Core\Render\MainContent\DialogRenderer;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\outside_in\Ajax\OpenOffCanvasDialogCommand;
use Symfony\Component\HttpFoundation\Request;
/**
* Default main content renderer for offcanvas dialog requests.
*/
class OffCanvasRender extends DialogRenderer {
/**
* The renderer.
*
* @var \Drupal\Core\Render\RendererInterface
*/
protected $renderer;
/**
* Constructs a new OffCanvasRender.
*
* @param \Drupal\Core\Controller\TitleResolverInterface $title_resolver
* The title resolver.
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer.
*/
public function __construct(TitleResolverInterface $title_resolver, RendererInterface $renderer) {
parent::__construct($title_resolver);
$this->renderer = $renderer;
}
/**
* {@inheritdoc}
*/
public function renderResponse(array $main_content, Request $request, RouteMatchInterface $route_match) {
$response = new AjaxResponse();
// First render the main content, because it might provide a title.
$content = $this->renderer->renderRoot($main_content);
// Attach the library necessary for using the OpenOffCanvasDialogCommand and
// set the attachments for this Ajax response.
$main_content['#attached']['library'][] = 'outside_in/drupal.off_canvas';
$response->setAttachments($main_content['#attached']);
// If the main content doesn't provide a title, use the title resolver.
$title = isset($main_content['#title']) ? $main_content['#title'] : $this->titleResolver->getTitle($request, $route_match->getRouteObject());
// Determine the title: use the title provided by the main content if any,
// otherwise get it from the routing information.
$options = $request->request->get('dialogOptions', []);
$response->addCommand(new OpenOffCanvasDialogCommand($title, $content, $options));
return $response;
}
}

View file

@ -0,0 +1,59 @@
<?php
namespace Drupal\outside_in\Tests\Ajax;
use Drupal\ajax_test\Controller\AjaxTestController;
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
use Drupal\system\Tests\Ajax\AjaxTestBase;
/**
* Performs tests on opening and manipulating dialogs via AJAX commands.
*
* @group outside_in
*/
class OffCanvasDialogTest extends AjaxTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['outside_in'];
/**
* Test sending AJAX requests to open and manipulate offcanvas dialog.
*/
public function testDialog() {
$this->drupalLogin($this->drupalCreateUser(['administer contact forms']));
// Ensure the elements render without notices or exceptions.
$this->drupalGet('ajax-test/dialog');
// Set up variables for this test.
$dialog_renderable = AjaxTestController::dialogContents();
$dialog_contents = \Drupal::service('renderer')->renderRoot($dialog_renderable);
$offcanvas_expected_response = [
'command' => 'openDialog',
'selector' => '#drupal-offcanvas',
'settings' => NULL,
'data' => $dialog_contents,
'dialogOptions' =>
[
'title' => 'AJAX Dialog & contents',
'modal' => FALSE,
'autoResize' => FALSE,
'resizable' => 'w',
'draggable' => FALSE,
'drupalAutoButtons' => FALSE,
'buttons' => [],
],
'effect' => 'fade',
'speed' => 1000,
];
// Emulate going to the JS version of the page and check the JSON response.
$ajax_result = $this->drupalGetAjax('ajax-test/dialog-contents', ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_dialog_offcanvas']]);
$this->assertEqual($offcanvas_expected_response, $ajax_result[3], 'Off-canvas dialog JSON response matches.');
}
}