Commit 6c3dae99 authored by Dries's avatar Dries

Merge branch '8.x' of git.drupal.org:project/drupal into 8.x

parents abd15444 a0030289
......@@ -73,8 +73,8 @@ function aggregator_form_category_validate($form, &$form_state) {
function aggregator_form_category_submit($form, &$form_state) {
// @todo Replicate this cache invalidation when these ops are separated.
// Invalidate the block cache to update aggregator category-based derivatives.
if (module_exists('block')) {
drupal_container()->get('plugin.manager.block')->clearCachedDefinitions();
if (Drupal::moduleHandler()->moduleExists('block')) {
Drupal::service('plugin.manager.block')->clearCachedDefinitions();
}
if ($form_state['values']['op'] == t('Delete')) {
$title = $form_state['values']['title'];
......
......@@ -345,7 +345,7 @@ function aggregator_save_category($edit) {
->condition('cid', $edit['cid'])
->execute();
// Make sure there is no active block for this category.
if (module_exists('block')) {
if (Drupal::moduleHandler()->moduleExists('block')) {
foreach (entity_load_multiple_by_properties('block', array('plugin' => 'aggregator_category_block:' . $edit['cid'])) as $block) {
$block->delete();
}
......@@ -365,7 +365,7 @@ function aggregator_save_category($edit) {
->execute();
$op = 'insert';
}
if (isset($op) && module_exists('menu_link')) {
if (isset($op) && Drupal::moduleHandler()->moduleExists('menu_link')) {
menu_link_maintain('aggregator', $op, $link_path, $edit['title']);
}
}
......
......@@ -209,7 +209,7 @@ public static function preCreate(EntityStorageControllerInterface $storage_contr
*/
public static function preDelete(EntityStorageControllerInterface $storage_controller, array $entities) {
// Invalidate the block cache to update aggregator feed-based derivatives.
if (module_exists('block')) {
if (\Drupal::moduleHandler()->moduleExists('block')) {
\Drupal::service('plugin.manager.block')->clearCachedDefinitions();
}
$storage_controller->deleteCategories($entities);
......
......@@ -21,23 +21,6 @@ function block_admin_demo($theme = NULL) {
);
}
/**
* Page callback: Shows the block administration page.
*
* @param string $theme
* The theme to display the administration page for.
*
* @return array
* A render array for a page containing a list of blocks.
*
* @see block_menu()
*/
function block_admin_display($theme) {
return Drupal::entityManager()
->getListController('block')
->render($theme);
}
/**
* Page callback: Build the block instance add form.
*
......
......@@ -117,10 +117,7 @@ function block_menu() {
$items['admin/structure/block'] = array(
'title' => 'Blocks',
'description' => 'Configure what block content appears in your site\'s sidebars and other regions.',
'page callback' => 'block_admin_display',
'page arguments' => array($default_theme),
'access arguments' => array('administer blocks'),
'file' => 'block.admin.inc',
'route_name' => 'block_admin_display',
);
$items['admin/structure/block/add/%/%'] = array(
'title' => 'Configure block',
......@@ -160,11 +157,8 @@ function block_menu() {
$theme = $themes[$key];
$items['admin/structure/block/list/' . $plugin_id] = array(
'title' => check_plain($theme->info['name']),
'page arguments' => array($key),
'type' => $key == $default_theme ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK,
'access callback' => '_block_themes_access',
'access arguments' => array($key),
'file' => 'block.admin.inc',
'route_name' => 'block_admin_display.' . $plugin_id
);
$items['admin/structure/block/demo/' . $key] = array(
'title' => check_plain($theme->info['name']),
......
......@@ -4,3 +4,11 @@ block_admin_block_delete:
_entity_form: 'block.delete'
requirements:
_permission: 'administer blocks'
block_admin_display:
pattern: '/admin/structure/block'
defaults:
_content: '\Drupal\block\Controller\BlockListController::listing'
entity_type: 'block'
requirements:
_permission: 'administer blocks'
......@@ -9,3 +9,12 @@ services:
factory_method: get
factory_service: cache_factory
arguments: [block]
block.route_subscriber:
class: Drupal\block\Routing\RouteSubscriber
tags:
- { name: event_subscriber}
arguments: ['@plugin.manager.system.plugin_ui']
block.theme_access_check:
class: Drupal\block\Access\BlockThemeAccessCheck
tags:
- { name: access_check}
<?php
/**
* @file
* Contains \Drupal\block\Access\BlockThemeAccessCheck.
*/
namespace Drupal\block\Access;
use Drupal\Core\Access\AccessCheckInterface;
use Symfony\Component\Routing\Route;
use Symfony\Component\HttpFoundation\Request;
/**
* Checks access for displaying block page.
*/
class BlockThemeAccessCheck implements AccessCheckInterface {
/**
* {@inheritdoc}
*/
public function applies(Route $route) {
return array_key_exists('_block_themes_access', $route->getRequirements());
}
/**
* {@inheritdoc}
*/
public function access(Route $route, Request $request) {
$theme = $request->attributes->get('theme');
return user_access('administer blocks') && drupal_theme_access($theme);
}
}
<?php
/**
* @file
* Contains \Drupal\block\Controller\BlockListController.
*/
namespace Drupal\block\Controller;
use Drupal\Core\Entity\Controller\EntityListController;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Config\ConfigFactory;
use Drupal\Core\Entity\EntityManager;
/**
* Defines a controller to list blocks.
*/
class BlockListController extends EntityListController {
/**
* The configuration factory object.
*
* @var \Drupal\Core\Config\ConfigFactory
*/
protected $configFactory;
/**
* Creates an BlockListController object.
*
* @param \Drupal\Core\Entity\EntityManager $entity_manager
* The entity manager.
* @param \Drupal\Core\Config\ConfigFactory $config_factory
* Configuration factory object.
*/
public function __construct(EntityManager $entity_manager, ConfigFactory $config_factory) {
$this->entityManager = $entity_manager;
$this->configFactory = $config_factory;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('plugin.manager.entity'),
$container->get('config.factory')
);
}
/**
* Shows the block administration page.
*
* @param string $entity_type
* Entity type of list page.
* @param string|null $theme
* Theme key of block list.
*
* @return array
* A render array as expected by drupal_render().
*/
public function listing($entity_type, $theme = NULL) {
$default_theme = $theme ?: $this->configFactory->get('system.theme')->get('default');
return $this->entityManager->getListController($entity_type)->render($default_theme);
}
}
<?php
/**
* @file
* Contains \Drupal\block\Routing\RouteSubscriber.
*/
namespace Drupal\block\Routing;
use Drupal\Core\Routing\RouteBuildEvent;
use Drupal\Core\Routing\RoutingEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Routing\Route;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Component\Plugin\PluginManagerInterface;
/**
* Listens to the dynamic route events.
*/
class RouteSubscriber implements EventSubscriberInterface {
/**
* The injection plugin manager that should be passed into the route.
*
* @var \Drupal\Component\Plugin\PluginManagerInterface
*/
protected $pluginManager;
/**
* Constructs a RouteSubscriber object.
*
* @param \Drupal\Component\Plugin\PluginManagerInterface $plugin_manager
* The service container this object should use.
*/
public function __construct(PluginManagerInterface $plugin_manager) {
$this->pluginManager = $plugin_manager;
}
/**
* Implements EventSubscriberInterface::getSubscribedEvents().
*/
public static function getSubscribedEvents() {
$events[RoutingEvents::DYNAMIC] = 'routes';
return $events;
}
/**
* Generate dynamic routes for various block pages.
*
* @param \Drupal\Core\Routing\RouteBuildEvent $event
* The route building event.
*
* @return \Symfony\Component\Routing\RouteCollection
* The route collection that contains the new dynamic route.
*/
public function routes(RouteBuildEvent $event) {
$collection = $event->getRouteCollection();
foreach ($this->pluginManager->getDefinitions() as $plugin_id => $plugin) {
list($plugin_base, $key) = explode(':', $plugin_id);
if ($plugin_base == 'block_plugin_ui') {
$route = new Route('admin/structure/block/list/' . $plugin_id, array(
'_controller' => '\Drupal\block\Controller\BlockListController::listing',
'entity_type' => 'block',
'theme' => $key,
), array(
'_block_themes_access' => 'TRUE',
));
$collection->add('block_admin_display.' . $plugin_id, $route);
}
}
}
}
......@@ -27,7 +27,7 @@ class BlockStorageUnitTest extends DrupalUnitTestBase {
*
* @var array
*/
public static $modules = array('block', 'block_test');
public static $modules = array('block', 'block_test', 'system');
/**
* The block storage controller.
......
......@@ -149,6 +149,75 @@ function testConfigLocaleUserOverride() {
$this->assertIdentical($config->get('foo'), 'en bar');
}
/**
* Tests locale override based on language.
*/
function testConfigLocaleLanguageOverride() {
$this->installSchema('system', 'variable');
$this->installSchema('language', 'language');
language_save(new Language(array(
'name' => 'French',
'langcode' => 'fr',
)));
language_save(new Language(array(
'name' => 'English',
'langcode' => 'en',
)));
language_save(new Language(array(
'name' => 'German',
'langcode' => 'de',
)));
$language = language_load('fr');
$language_config_context = config_context_enter('Drupal\language\LanguageConfigContext');
$language_config_context->setLanguage($language);
$config = config('config_test.system');
$this->assertIdentical($config->get('foo'), 'fr bar');
// Ensure the non-overridden value is still the same.
$this->assertIdentical($config->get('404'), 'herp');
// Ensure that we get the expected value when we leave the language context. The
// locale overrides contain an English override too, so although we are not
// in a language override context, the English language override
// applies due to the negotiated language for the page.
config_context_leave();
$config = config('config_test.system');
$this->assertIdentical($config->get('foo'), 'en bar');
$config_factory = \Drupal::service('config.factory');
$language = language_load('de');
$config_factory->enterContext($language_config_context->setLanguage($language));
// Should not have to re-initialize the configuration object to get new
// overrides as the new context will have a different uuid.
$config = config('config_test.system');
$this->assertIdentical($config->get('foo'), 'de bar');
// Enter an english context on top of the german context.
$language = language_load('en');
// Create a new language config context to stack on top of the existing one.
$en_language_config_context = config_context_enter('Drupal\language\LanguageConfigContext');
$en_language_config_context->setLanguage($language);
$config = config('config_test.system');
$this->assertIdentical($config->get('foo'), 'en bar');
// Ensure that we get the expected value when we leave the english
// language context.
config_context_leave();
$config = config('config_test.system');
$this->assertIdentical($config->get('foo'), 'de bar');
// Ensure that we get the expected value when we leave the german
// language context.
config_context_leave();
$config = config('config_test.system');
$this->assertIdentical($config->get('foo'), 'en bar');
// Ensure that we cannot leave the default context.
config_context_leave();
$config = config('config_test.system');
$this->assertIdentical($config->get('foo'), 'en bar');
}
/**
* Tests locale override in combination with global overrides.
*/
......
<?php
/**
* @file
* Contains \Drupal\language\LanguageConfigContext.
*/
namespace Drupal\language;
use Drupal\Core\Config\Context\ConfigContext;
use Drupal\Core\Language\Language;
/**
* Defines a configuration context object for a language.
*
* This should be used when configuration objects need a context for a language
* other than the current language.
*
*/
class LanguageConfigContext extends ConfigContext {
/**
* Predefined key for language object.
*/
const LANGUAGE_KEY = 'language';
/**
* Creates the configuration context for language.
*
* @param \Drupal\Core\Language\Language $language
* The language to add to the config context.
*
* @return \Drupal\Core\Language\Language
* The language config context object.
*/
public function setLanguage(Language $language) {
$this->set(self::LANGUAGE_KEY, $language);
// Re-initialize since the language change changes the context fundamentally.
$this->init();
return $this;
}
}
......@@ -62,10 +62,14 @@ public function __construct(LanguageManager $language_manager, ContextInterface
public function configContext(ConfigEvent $event) {
$context = $event->getContext();
// If there is a user set in the current context, set the language based on
// the preferred language of the user. Otherwise set it based on the
// negotiated interface language.
if ($account = $context->get('user.account')) {
// If there is a language set explicitly in current context, use it.
// otherwise check if there is a user set in the current context,
// to set the language based on the preferred language of the user.
// Otherwise set it based on the negotiated interface language.
if ($language = $context->get('language')) {
$context->set('locale.language', $language);
}
elseif ($account = $context->get('user.account')) {
$context->set('locale.language', language_load(user_preferred_langcode($account)));
}
elseif ($language = $this->languageManager->getLanguage(Language::TYPE_INTERFACE)) {
......
......@@ -30,7 +30,6 @@
* }
* },
* list_path = "admin/config/media/picturemapping",
* uri_callback = "picture_mapping_uri",
* config_prefix = "picture.mappings",
* entity_keys = {
* "id" = "id",
......@@ -163,4 +162,16 @@ public function hasMappings() {
return $mapping_found;
}
/**
* {@inheritdoc}
*/
public function uri() {
return array(
'path' => 'admin/config/media/picturemapping/' . $this->id(),
'options' => array(
'entity_type' => $this->entityType,
'entity' => $this,
),
);
}
}
......@@ -116,24 +116,6 @@ function picture_mapping_load($id) {
return entity_load('picture_mapping', $id);
}
/**
* Gets Picture uri callback.
*/
function picture_mapping_uri(PictureMapping $picture_mapping) {
return array(
'path' => 'admin/config/media/picturemapping/' . $picture_mapping->id(),
);
}
/**
* Sets Picture uri callback.
*/
function picture_mapping_set_uri(PictureMapping $picture_mapping) {
return array(
'path' => 'admin/config/media/picturemapping/' . $picture_mapping->id(),
);
}
/**
* Implements hook_theme().
*/
......
......@@ -289,10 +289,12 @@ function theme_shortcut_set_customize($variables) {
'#theme' => 'table',
'#header' => $header,
'#rows' => $rows,
'#empty' => t('No shortcuts available. <a href="@link">Add a shortcut</a>.', array(
'@link' => url('admin/config/user-interface/shortcut/manage/' . $form['#shortcut_set_name'] . '/add-link'),
)),
'#attributes' => array(
'id' => 'shortcuts',
'empty' => t('No shortcuts available. <a href="@link">Add a shortcut</a>.', array('@link' => url('admin/config/user-interface/shortcut/manage/' . $form['#shortcut_set_name'] . '/add-link')))
)
),
);
$output = drupal_render($table);
......
......@@ -7,15 +7,18 @@
namespace Drupal\tour\Plugin\tour\tip;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Utility\Token;
use Drupal\tour\Annotation\Tip;
use Drupal\tour\TipPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Displays some text as a tip.
*
* @Tip("text")
*/
class TipPluginText extends TipPluginBase {
class TipPluginText extends TipPluginBase implements ContainerFactoryPluginInterface {
/**
* The body text which is used for render of this Text Tip.
......@@ -24,6 +27,13 @@ class TipPluginText extends TipPluginBase {
*/
protected $body;
/**
* Token service.
*
* @var \Drupal\Core\Utility\Token
*/
protected $token;
/**
* The forced position of where the tip will be located.
*
......@@ -31,6 +41,30 @@ class TipPluginText extends TipPluginBase {
*/
protected $location;
/**
* Constructs a \Drupal\tour\Plugin\tour\tip\TipPluginText object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param array $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Utility\Token $token
* The token service.
*/
public function __construct(array $configuration, $plugin_id, array $plugin_definition, Token $token) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->token = $token;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container->get('token'));
}
/**
* Returns a ID that is guaranteed uniqueness.
*
......@@ -83,7 +117,7 @@ public function getAttributes() {
*/
public function getOutput() {
$output = '<h2 class="tour-tip-label" id="tour-tip-' . $this->getAriaId() . '-label">' . check_plain($this->getLabel()) . '</h2>';
$output .= '<p class="tour-tip-body" id="tour-tip-' . $this->getAriaId() . '-contents">' . \Drupal::token()->replace(filter_xss_admin($this->getBody())) . '</p>';
$output .= '<p class="tour-tip-body" id="tour-tip-' . $this->getAriaId() . '-contents">' . filter_xss_admin($this->token->replace($this->getBody())) . '</p>';
return array('#markup' => $output);
}
}
......@@ -49,10 +49,11 @@ public function testTourFunctionality() {
));
$this->assertEqual(count($elements), 1, 'Found English variant of tip 1.');
$elements = $this->xpath('//li[@data-id=:data_id and @class=:classes and ./p[contains(., :text)]]', array(
$elements = $this->xpath('//li[@data-id=:data_id and @class=:classes and ./p//a[@href=:href and contains(., :text)]]', array(
':classes' => 'tip-module-tour-test tip-type-text tip-tour-test-1 even last',
':data_id' => 'tour-test-1',
':text' => 'Is Drupal always the best dressed?',
':href' => url('<front>', array('absolute' => TRUE)),
':text' => 'Drupal',
));
$this->assertEqual(count($elements), 1, 'Found Token replacement.');
......
......@@ -7,12 +7,12 @@
namespace Drupal\tour;
use Drupal\Component\Plugin\Discovery\ProcessDecorator;
use Drupal\Component\Plugin\PluginManagerBase;
use Drupal\Component\Plugin\Factory\DefaultFactory;
use Drupal\Core\Plugin\Discovery\AlterDecorator;
use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
use Drupal\Core\Plugin\Discovery\CacheDecorator;
use Drupal\Component\Plugin\Discovery\ProcessDecorator;
use Drupal\Core\Plugin\Factory\ContainerFactory;
/**
* Configurable tour manager.
......@@ -32,7 +32,7 @@ public function __construct(\Traversable $namespaces) {
$this->discovery = new AlterDecorator($this->discovery, 'tour_tips_info');
$this->discovery = new CacheDecorator($this->discovery, 'tour');
$this->factory = new DefaultFactory($this->discovery);
$this->factory = new ContainerFactory($this->discovery);
}
}
......@@ -9,7 +9,7 @@ tips:
id: tour-test-1
plugin: text
label: The first tip
body: Is [site:name] always the best dressed?
body: Is <a href="[site:url]">[site:name]</a> always the best dressed?
weight: "1"
attributes:
data-id: tour-test-1
......
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