Skip to content
Commits on Source (19)
...@@ -196,17 +196,12 @@ services: ...@@ -196,17 +196,12 @@ services:
plugin.manager.menu.local_task: plugin.manager.menu.local_task:
class: Drupal\Core\Menu\LocalTaskManager class: Drupal\Core\Menu\LocalTaskManager
arguments: ['@controller_resolver', '@request', '@router.route_provider', '@module_handler', '@cache.cache', '@language_manager', '@access_manager', '@current_user'] arguments: ['@controller_resolver', '@request', '@router.route_provider', '@module_handler', '@cache.cache', '@language_manager', '@access_manager', '@current_user']
scope: request
plugin.manager.menu.contextual_link: plugin.manager.menu.contextual_link:
class: Drupal\Core\Menu\ContextualLinkManager class: Drupal\Core\Menu\ContextualLinkManager
arguments: ['@controller_resolver', '@module_handler', '@cache.cache', '@language_manager', '@access_manager', '@current_user'] arguments: ['@controller_resolver', '@module_handler', '@cache.cache', '@language_manager', '@access_manager', '@current_user']
request: request:
class: Symfony\Component\HttpFoundation\Request class: Symfony\Component\HttpFoundation\Request
# @TODO the synthetic setting must be uncommented whenever drupal_session_initialize() synthetic: true
# is run after there is a request and the following two lines should be removed.
factory_class: Symfony\Component\HttpFoundation\Request
factory_method: createFromGlobals
#synthetic: true
event_dispatcher: event_dispatcher:
class: Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher class: Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher
arguments: ['@service_container'] arguments: ['@service_container']
...@@ -350,6 +345,10 @@ services: ...@@ -350,6 +345,10 @@ services:
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
arguments: ['@settings'] arguments: ['@settings']
ajax_response_subscriber:
class: Drupal\Core\EventSubscriber\AjaxResponseSubscriber
tags:
- { name: event_subscriber }
route_enhancer.authentication: route_enhancer.authentication:
class: Drupal\Core\Routing\Enhancer\AuthenticationEnhancer class: Drupal\Core\Routing\Enhancer\AuthenticationEnhancer
calls: calls:
...@@ -421,7 +420,6 @@ services: ...@@ -421,7 +420,6 @@ services:
- [setCurrentUser, ['@?current_user']] - [setCurrentUser, ['@?current_user']]
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
scope: request
access_route_subscriber: access_route_subscriber:
class: Drupal\Core\EventSubscriber\AccessRouteSubscriber class: Drupal\Core\EventSubscriber\AccessRouteSubscriber
tags: tags:
......
...@@ -1552,7 +1552,7 @@ function watchdog($type, $message, array $variables = NULL, $severity = WATCHDOG ...@@ -1552,7 +1552,7 @@ function watchdog($type, $message, array $variables = NULL, $severity = WATCHDOG
$log_entry['referer'] = $request->headers->get('Referer', ''); $log_entry['referer'] = $request->headers->get('Referer', '');
$log_entry['ip'] = $request->getClientIP(); $log_entry['ip'] = $request->getClientIP();
} }
catch (\InvalidArgumentException $e) { catch (DependencyInjectionRuntimeException $e) {
// We are not in a request context. // We are not in a request context.
} }
...@@ -1718,9 +1718,18 @@ function drupal_set_title($title = NULL, $output = Title::CHECK_PLAIN) { ...@@ -1718,9 +1718,18 @@ function drupal_set_title($title = NULL, $output = Title::CHECK_PLAIN) {
* The user session object. * The user session object.
*/ */
function drupal_anonymous_user() { function drupal_anonymous_user() {
try {
$request = \Drupal::request();
$hostname = $request->getClientIP();
}
catch (DependencyInjectionRuntimeException $e) {
// We are not in a request context.
$hostname = '';
}
$values = array( $values = array(
'uid' => 0, 'uid' => 0,
'hostname' => \Drupal::request()->getClientIP(), 'hostname' => $hostname,
'roles' => array(DRUPAL_ANONYMOUS_RID), 'roles' => array(DRUPAL_ANONYMOUS_RID),
); );
return new UserSession($values); return new UserSession($values);
...@@ -1861,10 +1870,13 @@ function drupal_handle_request($test_only = FALSE) { ...@@ -1861,10 +1870,13 @@ function drupal_handle_request($test_only = FALSE) {
// @todo Remove this once everything in the bootstrap has been // @todo Remove this once everything in the bootstrap has been
// converted to services in the DIC. // converted to services in the DIC.
$kernel->boot(); $kernel->boot();
drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE);
// Create a request object from the HttpFoundation. // Create a request object from the HttpFoundation.
$request = Request::createFromGlobals(); $request = Request::createFromGlobals();
\Drupal::getContainer()->set('request', $request);
drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE);
$response = $kernel->handle($request)->prepare($request)->send(); $response = $kernel->handle($request)->prepare($request)->send();
$kernel->terminate($request, $response); $kernel->terminate($request, $response);
...@@ -1994,6 +2006,8 @@ function _drupal_bootstrap_kernel() { ...@@ -1994,6 +2006,8 @@ function _drupal_bootstrap_kernel() {
if (!\Drupal::getContainer()) { if (!\Drupal::getContainer()) {
$kernel = new DrupalKernel('prod', drupal_classloader()); $kernel = new DrupalKernel('prod', drupal_classloader());
$kernel->boot(); $kernel->boot();
$request = Request::createFromGlobals();
\Drupal::getContainer()->set('request', $request);
} }
} }
......
...@@ -399,14 +399,15 @@ function drupal_add_feed($url = NULL, $title = '') { ...@@ -399,14 +399,15 @@ function drupal_add_feed($url = NULL, $title = '') {
if (isset($url)) { if (isset($url)) {
$stored_feed_links[$url] = theme('feed_icon', array('url' => $url, 'title' => $title)); $stored_feed_links[$url] = theme('feed_icon', array('url' => $url, 'title' => $title));
drupal_add_html_head_link(array( $build['#attached']['drupal_add_html_head_link'][][] = array(
'rel' => 'alternate', 'rel' => 'alternate',
'type' => 'application/rss+xml', 'type' => 'application/rss+xml',
'title' => $title, 'title' => $title,
// Force the URL to be absolute, for consistency with other <link> tags // Force the URL to be absolute, for consistency with other <link> tags
// output by Drupal. // output by Drupal.
'href' => url($url, array('absolute' => TRUE)), 'href' => url($url, array('absolute' => TRUE)),
)); );
drupal_render($build);
} }
return $stored_feed_links; return $stored_feed_links;
} }
......
...@@ -625,10 +625,19 @@ function drupal_install_system() { ...@@ -625,10 +625,19 @@ function drupal_install_system() {
// Create tables. // Create tables.
drupal_install_schema('system'); drupal_install_schema('system');
if (!drupal_container()->has('kernel')) { if (!\Drupal::getContainer()->has('kernel')) {
// Immediately boot a kernel to have real services ready. // Immediately boot a kernel to have real services ready. If there's already
// an initialized request object in the pre-kernel container, persist it in
// the post-kernel container.
if (\Drupal::getContainer()->initialized('request')) {
$request = \Drupal::request();
}
$kernel = new DrupalKernel('install', drupal_classloader(), FALSE); $kernel = new DrupalKernel('install', drupal_classloader(), FALSE);
$kernel->boot(); $kernel->boot();
if (isset($request)) {
\Drupal::getContainer()->set('request', $request);
}
} }
$system_path = drupal_get_path('module', 'system'); $system_path = drupal_get_path('module', 'system');
......
...@@ -368,17 +368,11 @@ function list_themes($refresh = FALSE) { ...@@ -368,17 +368,11 @@ function list_themes($refresh = FALSE) {
$list = array(); $list = array();
// Extract from the database only when it is available. // Extract from the database only when it is available.
// Also check that the site is not in the middle of an install or update. // Also check that the site is not in the middle of an install or update.
if (!defined('MAINTENANCE_MODE')) { try {
try { $themes = system_list('theme');
$themes = system_list('theme');
}
catch (Exception $e) {
// If the database is not available, rebuild the theme data.
$themes = _system_rebuild_theme_data();
}
} }
else { catch (Exception $e) {
// Scan the installation when the database should not be read. // If the database is not available, rebuild the theme data.
$themes = _system_rebuild_theme_data(); $themes = _system_rebuild_theme_data();
} }
...@@ -1279,8 +1273,14 @@ function template_preprocess_status_messages(&$variables) { ...@@ -1279,8 +1273,14 @@ function template_preprocess_status_messages(&$variables) {
* is used as its CSS class. Each link should be itself an array, with the * is used as its CSS class. Each link should be itself an array, with the
* following elements: * following elements:
* - title: The link text. * - title: The link text.
* - href: The link URL. If omitted, the 'title' is shown as a plain text * - route_name: (optional) The name of the route to link to. If omitted
* item in the links list. * (and if 'href' is omitted as well), the 'title' is shown as
* a plain text item in the links list.
* - route_parameters: (optional) An array of route parameters for the link.
* - href: (optional) The link URL. It is preferred to use 'route_name' and
* 'route parameters' for internal links. Use 'href' for links to external
* URLs. If omitted (and if 'route_name' is omitted as well), the 'title'
* is shown as a plain text item in the links list.
* - html: (optional) Whether or not 'title' is HTML. If set, the title * - html: (optional) Whether or not 'title' is HTML. If set, the title
* will not be passed through * will not be passed through
* \Drupal\Component\Utility\String::checkPlain(). * \Drupal\Component\Utility\String::checkPlain().
...@@ -2226,7 +2226,12 @@ function template_preprocess_html(&$variables) { ...@@ -2226,7 +2226,12 @@ function template_preprocess_html(&$variables) {
if (theme_get_setting('features.favicon')) { if (theme_get_setting('features.favicon')) {
$favicon = theme_get_setting('favicon.url'); $favicon = theme_get_setting('favicon.url');
$type = theme_get_setting('favicon.mimetype'); $type = theme_get_setting('favicon.mimetype');
drupal_add_html_head_link(array('rel' => 'shortcut icon', 'href' => Url::stripDangerousProtocols($favicon), 'type' => $type)); $build['#attached']['drupal_add_html_head_link'][][] = array(
'rel' => 'shortcut icon',
'href' => Url::stripDangerousProtocols($favicon),
'type' => $type,
);
drupal_render($build);
} }
$site_config = \Drupal::config('system.site'); $site_config = \Drupal::config('system.site');
...@@ -2509,7 +2514,12 @@ function template_preprocess_maintenance_page(&$variables) { ...@@ -2509,7 +2514,12 @@ function template_preprocess_maintenance_page(&$variables) {
if (theme_get_setting('features.favicon')) { if (theme_get_setting('features.favicon')) {
$favicon = theme_get_setting('favicon.url'); $favicon = theme_get_setting('favicon.url');
$type = theme_get_setting('favicon.mimetype'); $type = theme_get_setting('favicon.mimetype');
drupal_add_html_head_link(array('rel' => 'shortcut icon', 'href' => Url::stripDangerousProtocols($favicon), 'type' => $type)); $build['#attached']['drupal_add_html_head_link'][][] = array(
'rel' => 'shortcut icon',
'href' => Url::stripDangerousProtocols($favicon),
'type' => $type,
);
drupal_render($build);
} }
// Get all region content set with drupal_add_region_content(). // Get all region content set with drupal_add_region_content().
......
...@@ -9,9 +9,6 @@ ...@@ -9,9 +9,6 @@
/** /**
* Defines an object which stores multiple plugin instances to lazy load them. * Defines an object which stores multiple plugin instances to lazy load them.
*
* The \ArrayAccess implementation is only for backwards compatibility, it is
* deprecated and should not be used by new code.
*/ */
abstract class PluginBag implements \Iterator, \Countable { abstract class PluginBag implements \Iterator, \Countable {
...@@ -30,7 +27,7 @@ abstract class PluginBag implements \Iterator, \Countable { ...@@ -30,7 +27,7 @@ abstract class PluginBag implements \Iterator, \Countable {
protected $instanceIDs = array(); protected $instanceIDs = array();
/** /**
* Initializes a plugin and stores the result in $this->pluginInstances. * Initializes and stores a plugin.
* *
* @param string $instance_id * @param string $instance_id
* The ID of the plugin instance to initialize. * The ID of the plugin instance to initialize.
...@@ -85,7 +82,7 @@ public function set($instance_id, $value) { ...@@ -85,7 +82,7 @@ public function set($instance_id, $value) {
/** /**
* Removes an initialized plugin. * Removes an initialized plugin.
* *
* The plugin can still be used, it will be reinitialized. * The plugin can still be used; it will be reinitialized.
* *
* @param string $instance_id * @param string $instance_id
* The ID of the plugin instance to remove. * The ID of the plugin instance to remove.
...@@ -95,7 +92,7 @@ public function remove($instance_id) { ...@@ -95,7 +92,7 @@ public function remove($instance_id) {
} }
/** /**
* Adds an instance ID to the array of available instance IDs. * Adds an instance ID to the available instance IDs.
* *
* @param string $id * @param string $id
* The ID of the plugin instance to add. * The ID of the plugin instance to add.
...@@ -117,7 +114,7 @@ public function getInstanceIds() { ...@@ -117,7 +114,7 @@ public function getInstanceIds() {
} }
/** /**
* Sets the instance IDs property. * Sets all instance IDs.
* *
* @param array $instance_ids * @param array $instance_ids
* An associative array of instance IDs. * An associative array of instance IDs.
...@@ -138,28 +135,28 @@ public function removeInstanceId($instance_id) { ...@@ -138,28 +135,28 @@ public function removeInstanceId($instance_id) {
} }
/** /**
* Implements \Iterator::current(). * {@inheritdoc}
*/ */
public function current() { public function current() {
return $this->get($this->key()); return $this->get($this->key());
} }
/** /**
* Implements \Iterator::next(). * {@inheritdoc}
*/ */
public function next() { public function next() {
next($this->instanceIDs); next($this->instanceIDs);
} }
/** /**
* Implements \Iterator::key(). * {@inheritdoc}
*/ */
public function key() { public function key() {
return key($this->instanceIDs); return key($this->instanceIDs);
} }
/** /**
* Implements \Iterator::valid(). * {@inheritdoc}
*/ */
public function valid() { public function valid() {
$key = key($this->instanceIDs); $key = key($this->instanceIDs);
...@@ -167,14 +164,14 @@ public function valid() { ...@@ -167,14 +164,14 @@ public function valid() {
} }
/** /**
* Implements \Iterator::rewind(). * {@inheritdoc}
*/ */
public function rewind() { public function rewind() {
reset($this->instanceIDs); reset($this->instanceIDs);
} }
/** /**
* Implements \Countable::count(). * {@inheritdoc}
*/ */
public function count() { public function count() {
return count($this->instanceIDs); return count($this->instanceIDs);
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/** /**
* JSON response object for AJAX requests. * JSON response object for AJAX requests.
...@@ -46,17 +47,25 @@ public function addCommand($command, $prepend = FALSE) { ...@@ -46,17 +47,25 @@ public function addCommand($command, $prepend = FALSE) {
} }
/** /**
* Sets the response's data to be the array of AJAX commands. * {@inheritdoc}
*
* @param Request $request
* A request object.
* *
* @return Response * Sets the response's data to be the array of AJAX commands.
* The current response.
*/ */
public function prepare(Request $request) { public function prepare(Request $request) {
$this->setData($this->ajaxRender($request)); $this->prepareResponse($request);
return parent::prepare($request); return $this;
}
/**
* Sets the rendered AJAX right before the response is prepared.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The request object.
*/
public function prepareResponse(Request $request) {
if ($this->data == '{}') {
$this->setData($this->ajaxRender($request));
}
} }
/** /**
......
...@@ -369,10 +369,17 @@ protected function getKernelParameters() { ...@@ -369,10 +369,17 @@ protected function getKernelParameters() {
protected function initializeContainer() { protected function initializeContainer() {
$this->containerNeedsDumping = FALSE; $this->containerNeedsDumping = FALSE;
$persist = $this->getServicesToPersist(); $persist = $this->getServicesToPersist();
// If we are rebuilding the kernel and we are in a request scope, store // The request service requires custom persisting logic, since it is also
// request info so we can add them back after the rebuild. // potentially scoped. During Drupal installation, there is a request
if (isset($this->container) && $this->container->hasScope('request')) { // service without a request scope.
$request = $this->container->get('request'); $request_scope = FALSE;
if (isset($this->container)) {
if ($this->container->isScopeActive('request')) {
$request_scope = TRUE;
}
if ($this->container->initialized('request')) {
$request = $this->container->get('request');
}
} }
$this->container = NULL; $this->container = NULL;
$class = $this->getClassName(); $class = $this->getClassName();
...@@ -445,8 +452,10 @@ protected function initializeContainer() { ...@@ -445,8 +452,10 @@ protected function initializeContainer() {
// Set the class loader which was registered as a synthetic service. // Set the class loader which was registered as a synthetic service.
$this->container->set('class_loader', $this->classLoader); $this->container->set('class_loader', $this->classLoader);
// If we have a request set it back to the new container. // If we have a request set it back to the new container.
if (isset($request)) { if ($request_scope) {
$this->container->enterScope('request'); $this->container->enterScope('request');
}
if (isset($request)) {
$this->container->set('request', $request); $this->container->set('request', $request);
} }
\Drupal::setContainer($this->container); \Drupal::setContainer($this->container);
......
...@@ -225,16 +225,11 @@ class EntityType extends Plugin { ...@@ -225,16 +225,11 @@ class EntityType extends Plugin {
public $bundle_keys; public $bundle_keys;
/** /**
* The base router path for the entity type's field administration page. * The name of the entity type which provides bundles.
*
* If the entity type has a bundle, include {bundle} in the path.
*
* For example, the node entity type specifies
* "admin/structure/types/manage/{bundle}" as its base field admin path.
* *
* @var string (optional) * @var string (optional)
*/ */
public $route_base_path; public $bundle_entity_type = 'bundle';
/** /**
* Link templates using the URI template syntax. * Link templates using the URI template syntax.
......
...@@ -904,9 +904,18 @@ public function __clone() { ...@@ -904,9 +904,18 @@ public function __clone() {
// Avoid deep-cloning when we are initializing a translation object, since // Avoid deep-cloning when we are initializing a translation object, since
// it will represent the same entity, only with a different active language. // it will represent the same entity, only with a different active language.
if (!$this->translationInitialize) { if (!$this->translationInitialize) {
foreach ($this->fields as $name => $properties) { $definitions = $this->getPropertyDefinitions();
foreach ($properties as $langcode => $property) { foreach ($this->fields as $name => $values) {
$this->fields[$name][$langcode] = clone $property; $this->fields[$name] = array();
// Untranslatable fields may have multiple references for the same field
// object keyed by language. To avoid creating different field objects
// we retain just the original value, as references will be recreated
// later as needed.
if (empty($definitions[$name]['translatable']) && count($values) > 1) {
$values = array_intersect_key($values, array(Language::LANGCODE_DEFAULT => TRUE));
}
foreach ($values as $langcode => $items) {
$this->fields[$name][$langcode] = clone $items;
$this->fields[$name][$langcode]->setContext($name, $this); $this->fields[$name][$langcode]->setContext($name, $this);
} }
} }
......
...@@ -176,6 +176,10 @@ public function form(array $form, array &$form_state) { ...@@ -176,6 +176,10 @@ public function form(array $form, array &$form_state) {
* @see \Drupal\Core\Entity\EntityFormController::form() * @see \Drupal\Core\Entity\EntityFormController::form()
*/ */
public function processForm($element, $form_state, $form) { public function processForm($element, $form_state, $form) {
// If the form is cached, process callbacks may not have a valid reference
// to the entity object, hence we must restore it.
$this->entity = $form_state['controller']->getEntity();
// Assign the weights configured in the form display. // Assign the weights configured in the form display.
foreach ($this->getFormDisplay($form_state)->getComponents() as $name => $options) { foreach ($this->getFormDisplay($form_state)->getComponents() as $name => $options) {
if (isset($element[$name])) { if (isset($element[$name])) {
......
...@@ -301,9 +301,9 @@ public function getAdminPath($entity_type, $bundle) { ...@@ -301,9 +301,9 @@ public function getAdminPath($entity_type, $bundle) {
$admin_path = ''; $admin_path = '';
$entity_info = $this->getDefinition($entity_type); $entity_info = $this->getDefinition($entity_type);
// Check for an entity type's admin base path. // Check for an entity type's admin base path.
if (isset($entity_info['route_base_path'])) { if (isset($entity_info['links']['admin-form'])) {
// Replace any dynamic 'bundle' portion of the path with the actual bundle. $route_parameters[$entity_info['bundle_entity_type']] = $bundle;
$admin_path = str_replace('{bundle}', $bundle, $entity_info['route_base_path']); $admin_path = \Drupal::urlGenerator()->getPathFromRoute($entity_info['links']['admin-form'], $route_parameters);
} }
return $admin_path; return $admin_path;
...@@ -313,10 +313,11 @@ public function getAdminPath($entity_type, $bundle) { ...@@ -313,10 +313,11 @@ public function getAdminPath($entity_type, $bundle) {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getAdminRouteInfo($entity_type, $bundle) { public function getAdminRouteInfo($entity_type, $bundle) {
$entity_info = $this->getDefinition($entity_type);
return array( return array(
'route_name' => "field_ui.overview_$entity_type", 'route_name' => "field_ui.overview_$entity_type",
'route_parameters' => array( 'route_parameters' => array(
'bundle' => $bundle, $entity_info['bundle_entity_type'] => $bundle,
) )
); );
} }
......
...@@ -164,6 +164,11 @@ public function getViewBuilder($entity_type); ...@@ -164,6 +164,11 @@ public function getViewBuilder($entity_type);
* *
* @return string * @return string
* The administration path for an entity type bundle, if it exists. * The administration path for an entity type bundle, if it exists.
*
* @deprecated since version 8.0
* System paths should not be used - use route names and parameters.
*
* @see self::getAdminRouteInfo()
*/ */
public function getAdminPath($entity_type, $bundle); public function getAdminPath($entity_type, $bundle);
......
<?php
/**
* @file
* Contains \Drupal\Core\EventSubscriber\AjaxResponseSubscriber.
*/
namespace Drupal\Core\EventSubscriber;
use Drupal\Core\Ajax\AjaxResponse;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
class AjaxResponseSubscriber implements EventSubscriberInterface {
/**
* Renders the ajax commands right before preparing the result.
*
* @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
* The response event, which contains the possible AjaxResponse object.
*/
public function onResponse(FilterResponseEvent $event) {
$response = $event->getResponse();
if ($response instanceof AjaxResponse) {
$response->prepareResponse($event->getRequest());
}
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events[KernelEvents::RESPONSE][] = array('onResponse', -100);
return $events;
}
}
...@@ -2,9 +2,7 @@ ...@@ -2,9 +2,7 @@
/** /**
* @file * @file
* Provides views data and handlers for action.module. * Provides views data for action.module.
*
* @ingroup views_module_handlers
*/ */
/** /**
......
...@@ -3,8 +3,6 @@ ...@@ -3,8 +3,6 @@
/** /**
* @file * @file
* Provides views data for aggregator.module. * Provides views data for aggregator.module.
*
* @ingroup views_module_handlers
*/ */
/** /**
......
...@@ -36,10 +36,10 @@ ...@@ -36,10 +36,10 @@
* admin_permission = "administer blocks", * admin_permission = "administer blocks",
* base_table = "custom_block", * base_table = "custom_block",
* revision_table = "custom_block_revision", * revision_table = "custom_block_revision",
* route_base_path = "admin/structure/block/custom-blocks/manage/{bundle}",
* links = { * links = {
* "canonical" = "custom_block.edit", * "canonical" = "custom_block.edit",
* "edit-form" = "custom_block.edit" * "edit-form" = "custom_block.edit",
* "admin-form" = "custom_block.type_edit"
* }, * },
* fieldable = TRUE, * fieldable = TRUE,
* translatable = TRUE, * translatable = TRUE,
...@@ -52,7 +52,8 @@ ...@@ -52,7 +52,8 @@
* }, * },
* bundle_keys = { * bundle_keys = {
* "bundle" = "type" * "bundle" = "type"
* } * },
* bundle_entity_type = "custom_block_type"
* ) * )
*/ */
class CustomBlock extends ContentEntityBase implements CustomBlockInterface { class CustomBlock extends ContentEntityBase implements CustomBlockInterface {
......
...@@ -696,28 +696,43 @@ function template_preprocess_book_navigation(&$variables) { ...@@ -696,28 +696,43 @@ function template_preprocess_book_navigation(&$variables) {
if ($book_link['mlid']) { if ($book_link['mlid']) {
$variables['tree'] = book_children($book_link); $variables['tree'] = book_children($book_link);
$build = array();
if ($prev = book_prev($book_link)) { if ($prev = book_prev($book_link)) {
$prev_href = url($prev['href']); $prev_href = url($prev['href']);
drupal_add_html_head_link(array('rel' => 'prev', 'href' => $prev_href)); $build['#attached']['drupal_add_html_head_link'][][] = array(
'rel' => 'prev',
'href' => $prev_href,
);
$variables['prev_url'] = $prev_href; $variables['prev_url'] = $prev_href;
$variables['prev_title'] = check_plain($prev['title']); $variables['prev_title'] = check_plain($prev['title']);
} }
if ($book_link['plid'] && $parent = book_link_load($book_link['plid'])) { if ($book_link['plid'] && $parent = book_link_load($book_link['plid'])) {
$parent_href = url($parent['link_path']); $parent_href = url($parent['link_path']);
drupal_add_html_head_link(array('rel' => 'up', 'href' => $parent_href)); $build['#attached']['drupal_add_html_head_link'][][] = array(
'rel' => 'up',
'href' => $parent_href,
);
$variables['parent_url'] = $parent_href; $variables['parent_url'] = $parent_href;
$variables['parent_title'] = check_plain($parent['title']); $variables['parent_title'] = check_plain($parent['title']);
} }
if ($next = book_next($book_link)) { if ($next = book_next($book_link)) {
$next_href = url($next['href']); $next_href = url($next['href']);
drupal_add_html_head_link(array('rel' => 'next', 'href' => $next_href)); $build['#attached']['drupal_add_html_head_link'][][] = array(
'rel' => 'next',
'href' => $next_href,
);
$variables['next_url'] = $next_href; $variables['next_url'] = $next_href;
$variables['next_title'] = check_plain($next['title']); $variables['next_title'] = check_plain($next['title']);
} }
} }
if (!empty($build)) {
drupal_render($build);
}
$variables['has_links'] = FALSE; $variables['has_links'] = FALSE;
// Link variables to filter for values and set state of the flag variable. // Link variables to filter for values and set state of the flag variable.
$links = array('prev_url', 'prev_title', 'parent_url', 'parent_title', 'next_url', 'next_title'); $links = array('prev_url', 'prev_title', 'parent_url', 'parent_title', 'next_url', 'next_title');
......
<?php
/**
* @file
* Enable, install, update and uninstall functions for the breakpoint module.
*/
/**
* Implements hook_install().
*
* Import breakpoints from all enabled themes.
*/
function breakpoint_install() {
// Import breakpoints from enabled themes.
$themes = array_filter(list_themes(), function ($theme) {return $theme->status;});
_breakpoint_theme_enabled(array_keys($themes));
// Import breakpoints from modules.
_breakpoint_modules_installed(array_keys(\Drupal::moduleHandler()->getModuleList()));
}
...@@ -33,20 +33,6 @@ function breakpoint_help($path, $arg) { ...@@ -33,20 +33,6 @@ function breakpoint_help($path, $arg) {
} }
} }
/**
* Implements hook_themes_enabled().
*
* @param array $theme_list
* An array of theme names.
*
* @see _breakpoint_theme_enabled()
*
* @todo: This should be removed if https://drupal.org/node/1813110 is resolved.
*/
function breakpoint_themes_enabled($theme_list) {
_breakpoint_theme_enabled($theme_list);
}
/** /**
* Implements hook_themes_disabled(). * Implements hook_themes_disabled().
* *
...@@ -61,20 +47,6 @@ function breakpoint_themes_disabled($theme_list) { ...@@ -61,20 +47,6 @@ function breakpoint_themes_disabled($theme_list) {
_breakpoint_delete_breakpoints($theme_list, Breakpoint::SOURCE_TYPE_THEME); _breakpoint_delete_breakpoints($theme_list, Breakpoint::SOURCE_TYPE_THEME);
} }
/**
* Implements hook_modules_installed().
*
* @param array $modules
* An array of the modules that were enabled.
*
* @see _breakpoint_modules_enabled()
*
* @todo: This should be removed if https://drupal.org/node/1813110 is resolved.
*/
function breakpoint_modules_installed($modules) {
_breakpoint_modules_installed($modules);
}
/** /**
* Implements hook_modules_uninstalled(). * Implements hook_modules_uninstalled().
* *
...@@ -89,91 +61,6 @@ function breakpoint_modules_uninstalled($modules) { ...@@ -89,91 +61,6 @@ function breakpoint_modules_uninstalled($modules) {
_breakpoint_delete_breakpoints($modules, Breakpoint::SOURCE_TYPE_MODULE); _breakpoint_delete_breakpoints($modules, Breakpoint::SOURCE_TYPE_MODULE);
} }
/**
* Import breakpoints from all new enabled themes.
*
* @param array $theme_list
* An array of theme names.
*/
function _breakpoint_theme_enabled($theme_list) {
$themes = list_themes();
foreach ($theme_list as $theme_key) {
$media_queries = breakpoint_get_theme_media_queries($theme_key);
_breakpoint_import_media_queries($theme_key, $themes[$theme_key]->info['name'], Breakpoint::SOURCE_TYPE_THEME, $media_queries);
// Import custom groups.
_breakpoint_import_breakpoint_groups($theme_key, Breakpoint::SOURCE_TYPE_THEME);
}
}
/**
* Import breakpoints from all new installed modules.
*
* @param array $modules
* An array of the modules that were installed.
*/
function _breakpoint_modules_installed($modules) {
foreach ($modules as $module) {
$media_queries = breakpoint_get_module_media_queries($module);
_breakpoint_import_media_queries($module, $module, Breakpoint::SOURCE_TYPE_MODULE, $media_queries);
// Import custom groups.
_breakpoint_import_breakpoint_groups($module, Breakpoint::SOURCE_TYPE_MODULE);
}
}
/**
* Import media queries from a theme or module and create a default group.
*
* @param string $group_name
* Machine readable name of the breakpoint group.
* @param string $label
* Human readable name of the breakpoint group.
* @param string $source_type
* Either Breakpoint::SOURCE_TYPE_THEME or Breakpoint::SOURCE_TYPE_MODULE.
* @param array $media_queries
* An array of breakpoints in the form $breakpoint['name'] = 'media query'.
*/
function _breakpoint_import_media_queries($group_name, $label, $source_type, $media_queries) {
if (!empty($media_queries)) {
// Create a new breakpoint group if it doesn't exist.
$breakpoint_group = _breakpoint_group_create_or_load($group_name, $label, $group_name, $source_type);
// Load all media queries, create a breakpoint for each one and add them
// to this breakpoint group.
foreach ($media_queries as $name => $media_query) {
$breakpoint_group->addBreakpointFromMediaQuery($name, $media_query);
}
$breakpoint_group->save();
}
}
/**
* Import breakpoint groups from theme or module.
*
* @param string $source
* The theme or module name
* @param string $source_type
* Either Breakpoint::SOURCE_TYPE_THEME or Breakpoint::SOURCE_TYPE_MODULE.
*/
function _breakpoint_import_breakpoint_groups($source, $source_type) {
$breakpoint_groups = \Drupal::config($source . '.breakpoint_groups');
if ($breakpoint_groups) {
foreach ($breakpoint_groups->get() as $group_name => $data) {
// Breakpoints is mandatory, extra check since this is coming from config.
if (isset($data['breakpoints']) && !empty($data['breakpoints'])) {
// Create a new breakpoint group if it doesn't exist.
$breakpoint_group = _breakpoint_group_create_or_load($group_name, isset($data['label']) ? $data['label'] : $group_name, $source, $source_type);
// Add the breakpoints.
$breakpoint_group->addBreakpoints($data['breakpoints']);
$breakpoint_group->save();
}
else {
throw new \Exception('Illegal config file detected.');
}
}
}
}
/** /**
* Remove breakpoints from all disabled themes or uninstalled modules. * Remove breakpoints from all disabled themes or uninstalled modules.
* *
...@@ -245,65 +132,6 @@ function _breakpoint_delete_breakpoint_groups($group_id, $source_type) { ...@@ -245,65 +132,6 @@ function _breakpoint_delete_breakpoint_groups($group_id, $source_type) {
} }
} }
/**
* Get a list of available breakpoints from a specified theme.
*
* @param string $theme_key
* The name of the theme.
*
* @return array
* An array of breakpoints in the form $breakpoint['name'] = 'media query'.
*/
function breakpoint_get_theme_media_queries($theme_key) {
$themes = list_themes();
if (!isset($themes[$theme_key])) {
throw new \Exception('Illegal theme_key passed.');
}
$config = \Drupal::config($theme_key . '.breakpoints');
if ($config) {
return $config->get();
}
return array();
}
/**
* Get a list of available breakpoints from a specified module.
*
* @param string $module
* The name of the module.
*
* @return array
* An array of breakpoints in the form $breakpoint['name'] = 'media query'.
*/
function breakpoint_get_module_media_queries($module) {
if (!\Drupal::moduleHandler()->moduleExists($module)) {
throw new \Exception('Illegal module name passed.');
}
$config = \Drupal::config($module . '.breakpoints');
if ($config) {
return $config->get();
}
return array();
}
/**
* Load one breakpoint group by its identifier.
*
* @param string $id
* The id of the breakpoint group to load.
*
* @return \Drupal\breakpoint\Entity\BreakpointGroup|null
* The breakpoint group, or NULL if there is no entity with the given id.
*
* @todo Remove this in a follow-up issue.
* @see http://drupal.org/node/1798214
*/
function breakpoint_group_load($id) {
return entity_load('breakpoint_group', $id);
}
/** /**
* Load one breakpoint by its identifier. * Load one breakpoint by its identifier.
* *
...@@ -351,36 +179,3 @@ function breakpoint_select_options() { ...@@ -351,36 +179,3 @@ function breakpoint_select_options() {
asort($options); asort($options);
return $options; return $options;
} }
/**
* Helper function to easily create/load a breakpoint group.
*
* @param string $name
* Machine readable name of the breakpoint group.
* @param string $label
* Human readable name of the breakpoint group.
* @param string $source
* Machine readable name of the defining theme or module.
* @param string $source_type
* Either Breakpoint::SOURCE_TYPE_THEME or Breakpoint::SOURCE_TYPE_MODULE.
*
* @return \Drupal\breakpoint\Entity\BreakpointGroup
*
* @see _breakpoint_import_media_queries()
* @see _breakpoint_import_breakpoint_groups()
*/
function _breakpoint_group_create_or_load($name, $label, $source, $source_type) {
// Try loading the breakpoint group.
$breakpoint_group = entity_load('breakpoint_group', $source_type . '.' . $source . '.' . $name);
// Create a new breakpoint group if it doesn't exist.
if (!$breakpoint_group) {
// Build a new breakpoint group.
$breakpoint_group = entity_create('breakpoint_group', array(
'name' => $name,
'label' => $label,
'source' => $source,
'sourceType' => $source_type,
));
}
return $breakpoint_group;
}