Update to Drupal 8.1.8. For more information, see https://www.drupal.org/project/drupal/releases/8.1.8

This commit is contained in:
Pantheon Automation 2016-08-03 13:22:33 -07:00 committed by Greg Anderson
parent e9f047ccf8
commit f9f23cdf38
312 changed files with 6751 additions and 1546 deletions

View file

@ -12,8 +12,10 @@
},
"require": {
"php": ">=5.5.9",
"symfony/dependency-injection": "~2.8",
"symfony/expression-language": "~2.7"
"symfony/dependency-injection": "~2.8"
},
"suggest": {
"symfony/expression-language": "For using expressions in service container configuration"
},
"autoload": {
"psr-4": {

View file

@ -1,5 +1,5 @@
{
"name": "drupal/core-fileCache",
"name": "drupal/core-file-cache",
"description": "FileCache.",
"keywords": ["drupal"],
"homepage": "https://www.drupal.org/project/drupal",

View file

@ -1,5 +1,5 @@
{
"name": "drupal/core-httpFoundation",
"name": "drupal/core-http-foundation",
"description": "HttpFoundation.",
"keywords": ["drupal"],
"homepage": "https://www.drupal.org/project/drupal",

View file

@ -1,5 +1,5 @@
{
"name": "drupal/core-phpStorage",
"name": "drupal/core-php-storage",
"description": "PhpStorage.",
"keywords": ["drupal"],
"homepage": "https://www.drupal.org/project/drupal",

View file

@ -123,7 +123,7 @@ class Crypt {
* The number of random bytes to fetch and base64 encode.
*
* @return string
* The base64 encoded result will have a length of up to 4 * $byte_count.
* The base64 encoded result will have a length of up to 4 * $count.
*
* @see \Drupal\Component\Utility\Crypt::randomBytes()
*/

View file

@ -36,6 +36,25 @@ class Html {
*/
protected static $isAjax = FALSE;
/**
* All attributes that may contain URIs.
*
* - The attributes 'code' and 'codebase' are omitted, because they only exist
* for the <applet> tag. The time of Java applets has passed.
* - The attribute 'icon' is omitted, because no browser implements the
* <command> tag anymore.
* See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/command.
* - The 'manifest' attribute is omitted because it only exists for the <html>
* tag. That tag only makes sense in a HTML-served-as-HTML context, in which
* case relative URLs are guaranteed to work.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes
* @see https://stackoverflow.com/questions/2725156/complete-list-of-html-tag-attributes-which-have-a-url-value
*
* @var string[]
*/
protected static $uriAttributes = ['href', 'poster', 'src', 'cite', 'data', 'action', 'formaction', 'srcset', 'about'];
/**
* Prepares a string for use as a valid class name.
*
@ -402,4 +421,61 @@ EOD;
return htmlspecialchars($text, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
/**
* Converts all root-relative URLs to absolute URLs.
*
* Does not change any existing protocol-relative or absolute URLs. Does not
* change other relative URLs because they would result in different absolute
* URLs depending on the current path. For example: when the same content
* containing such a relative URL (for example 'image.png'), is served from
* its canonical URL (for example 'http://example.com/some-article') or from
* a listing or feed (for example 'http://example.com/all-articles') their
* "current path" differs, resulting in different absolute URLs:
* 'http://example.com/some-article/image.png' versus
* 'http://example.com/all-articles/image.png'. Only one can be correct.
* Therefore relative URLs that are not root-relative cannot be safely
* transformed and should generally be avoided.
*
* Necessary for HTML that is served outside of a website, for example, RSS
* and e-mail.
*
* @param string $html
* The partial (X)HTML snippet to load. Invalid markup will be corrected on
* import.
* @param string $scheme_and_host
* The root URL, which has a URI scheme, host and optional port.
*
* @return string
* The updated (X)HTML snippet.
*/
public static function transformRootRelativeUrlsToAbsolute($html, $scheme_and_host) {
assert('empty(array_diff(array_keys(parse_url($scheme_and_host)), ["scheme", "host", "port"]))', '$scheme_and_host contains scheme, host and port at most.');
assert('isset(parse_url($scheme_and_host)["scheme"])', '$scheme_and_host is absolute and hence has a scheme.');
assert('isset(parse_url($scheme_and_host)["host"])', '$base_url is absolute and hence has a host.');
$html_dom = Html::load($html);
$xpath = new \DOMXpath($html_dom);
// Update all root-relative URLs to absolute URLs in the given HTML.
foreach (static::$uriAttributes as $attr) {
foreach ($xpath->query("//*[starts-with(@$attr, '/') and not(starts-with(@$attr, '//'))]") as $node) {
$node->setAttribute($attr, $scheme_and_host . $node->getAttribute($attr));
}
foreach ($xpath->query("//*[@srcset]") as $node) {
// @see https://html.spec.whatwg.org/multipage/embedded-content.html#attr-img-srcset
// @see https://html.spec.whatwg.org/multipage/embedded-content.html#image-candidate-string
$image_candidate_strings = explode(',', $node->getAttribute('srcset'));
$image_candidate_strings = array_map('trim', $image_candidate_strings);
for ($i = 0; $i < count($image_candidate_strings); $i++) {
$image_candidate_string = $image_candidate_strings[$i];
if ($image_candidate_string[0] === '/' && $image_candidate_string[1] !== '/') {
$image_candidate_strings[$i] = $scheme_and_host . $image_candidate_string;
}
}
$node->setAttribute('srcset', implode(', ', $image_candidate_strings));
}
}
return Html::serialize($html_dom);
}
}

View file

@ -3,7 +3,7 @@
namespace Drupal\Component\Uuid;
/**
* UUID implementation using the Windows internal GUID extension.
* Generates a UUID using the Windows internal GUID extension.
*
* @see http://php.net/com_create_guid
*/

View file

@ -3,7 +3,7 @@
namespace Drupal\Component\Uuid;
/**
* UUID implementation using the PECL extension.
* Generates a UUID using the PECL extension.
*/
class Pecl implements UuidInterface {

View file

@ -13,7 +13,7 @@ class Uuid {
const VALID_PATTERN = '[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}';
/**
* Checks that a string appears to be in the format of a UUID.
* Checks whether a string appears to be in the format of a UUID.
*
* Implementations should not implement validation, since UUIDs should be in
* a consistent format across all implementations.

View file

@ -95,7 +95,10 @@ abstract class ConfigFactoryOverrideBase implements EventSubscriberInterface {
elseif (is_array($override_data[$key])) {
if (is_array($original_data[$key])) {
// Do the filtering one level deeper.
$changed = $this->filterNestedArray($original_data[$key], $override_data[$key]);
// Ensure that we track $changed along the way.
if ($this->filterNestedArray($original_data[$key], $override_data[$key])) {
$changed = TRUE;
}
// If no overrides are left under this level, remove the level.
if (empty($override_data[$key])) {
unset($override_data[$key]);

View file

@ -159,7 +159,8 @@ class Cron implements CronInterface {
$queue_worker = $this->queueManager->createInstance($queue_name);
$end = time() + (isset($info['cron']['time']) ? $info['cron']['time'] : 15);
$queue = $this->queueFactory->get($queue_name);
while (time() < $end && ($item = $queue->claimItem())) {
$lease_time = isset($info['cron']['time']) ?: NULL;
while (time() < $end && ($item = $queue->claimItem($lease_time))) {
try {
$queue_worker->processItem($item->data);
$queue->deleteItem($item);

View file

@ -660,7 +660,7 @@ class Select extends Query implements SelectInterface {
* {@inheritdoc}
*/
public function range($start = NULL, $length = NULL) {
$this->range = func_num_args() ? array('start' => $start, 'length' => $length) : array();
$this->range = $start !== NULL ? array('start' => $start, 'length' => $length) : array();
return $this;
}
@ -860,6 +860,14 @@ class Select extends Query implements SelectInterface {
$query .= "\nHAVING " . $this->having;
}
// UNION is a little odd, as the select queries to combine are passed into
// this query, but syntactically they all end up on the same level.
if ($this->union) {
foreach ($this->union as $union) {
$query .= ' ' . $union['type'] . ' ' . (string) $union['query'];
}
}
// ORDER BY
if ($this->order) {
$query .= "\nORDER BY ";
@ -879,14 +887,6 @@ class Select extends Query implements SelectInterface {
$query .= "\nLIMIT " . (int) $this->range['length'] . " OFFSET " . (int) $this->range['start'];
}
// UNION is a little odd, as the select queries to combine are passed into
// this query, but syntactically they all end up on the same level.
if ($this->union) {
foreach ($this->union as $union) {
$query .= ' ' . $union['type'] . ' ' . (string) $union['query'];
}
}
if ($this->forUpdate) {
$query .= ' FOR UPDATE';
}

View file

@ -1032,6 +1032,11 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C
$this->clearTranslationCache();
$translations = $this->translations;
$this->translations = &$translations;
// Ensure the enforceIsNew property is actually cloned by overwriting the
// original reference with one pointing to a copy of it.
$enforce_is_new = $this->enforceIsNew;
$this->enforceIsNew = &$enforce_is_new;
}
}

View file

@ -222,7 +222,9 @@ abstract class Entity implements EntityInterface {
->setOption('entity', $this);
// Display links by default based on the current language.
if ($rel !== 'collection') {
// Link relations that do not require an existing entity should not be
// affected by this entity's language, however.
if (!in_array($rel, ['collection', 'add-page', 'add-form'], TRUE)) {
$options += ['language' => $this->language()];
}
@ -302,10 +304,14 @@ abstract class Entity implements EntityInterface {
protected function urlRouteParameters($rel) {
$uri_route_parameters = [];
if ($rel != 'collection') {
if (!in_array($rel, ['collection', 'add-page', 'add-form'], TRUE)) {
// The entity ID is needed as a route parameter.
$uri_route_parameters[$this->getEntityTypeId()] = $this->id();
}
if ($rel === 'add-form' && ($this->getEntityType()->hasKey('bundle'))) {
$parameter_name = $this->getEntityType()->getBundleEntityType() ?: $this->getEntityType()->getKey('bundle');
$uri_route_parameters[$parameter_name] = $this->bundle();
}
if ($rel === 'revision' && $this instanceof RevisionableInterface) {
$uri_route_parameters[$this->getEntityTypeId() . '_revision'] = $this->getRevisionId();
}

View file

@ -277,7 +277,7 @@ class EntityViewDisplay extends EntityDisplayBase implements EntityViewDisplayIn
'view_mode' => $this->originalMode,
'display' => $this,
);
\Drupal::moduleHandler()->alter('entity_display_build', $build_list[$key], $context);
\Drupal::moduleHandler()->alter('entity_display_build', $build_list[$id], $context);
}
return $build_list;

View file

@ -172,7 +172,7 @@ class EntityResolverManager {
// First try to figure out whether there is already a parameter upcasting
// the same entity type already.
foreach ($parameter_definitions as $info) {
if (isset($info['type'])) {
if (isset($info['type']) && (strpos($info['type'], 'entity:') === 0)) {
// The parameter types are in the form 'entity:$entity_type'.
list(, $parameter_entity_type) = explode(':', $info['type'], 2);
if ($parameter_entity_type == $entity_type) {

View file

@ -515,15 +515,29 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
// Find revisioned fields that are not entity keys. Exclude the langcode
// key as the base table holds only the default language.
$base_fields = array_diff($table_mapping->getFieldNames($this->baseTable), array($this->langcodeKey));
$fields = array_diff($table_mapping->getFieldNames($this->revisionDataTable), $base_fields);
$revisioned_fields = array_diff($table_mapping->getFieldNames($this->revisionDataTable), $base_fields);
// Find fields that are not revisioned or entity keys. Data fields have
// the same value regardless of entity revision.
$data_fields = array_diff($table_mapping->getFieldNames($this->dataTable), $fields, $base_fields);
$data_fields = array_diff($table_mapping->getFieldNames($this->dataTable), $revisioned_fields, $base_fields);
// If there are no data fields then only revisioned fields are needed
// else both data fields and revisioned fields are needed to map the
// entity values.
$all_fields = $revisioned_fields;
if ($data_fields) {
$fields = array_merge($fields, $data_fields);
$all_fields = array_merge($revisioned_fields, $data_fields);
$query->leftJoin($this->dataTable, 'data', "(revision.$this->idKey = data.$this->idKey)");
$query->fields('data', $data_fields);
$column_names = [];
// Some fields can have more then one columns in the data table so
// column names are needed.
foreach ($data_fields as $data_field) {
// \Drupal\Core\Entity\Sql\TableMappingInterface:: getColumNames()
// returns an array keyed by property names so remove the keys
// before array_merge() to avoid losing data with fields having the
// same columns i.e. value.
$column_names = array_merge($column_names, array_values($table_mapping->getColumnNames($data_field)));
}
$query->fields('data', $column_names);
}
// Get the revision IDs.
@ -534,7 +548,7 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
$query->condition('revision.' . $this->revisionKey, $revision_ids, 'IN');
}
else {
$fields = $table_mapping->getFieldNames($this->dataTable);
$all_fields = $table_mapping->getFieldNames($this->dataTable);
}
$result = $query->execute();
@ -547,7 +561,7 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
$translations[$id][$langcode] = TRUE;
foreach ($fields as $field_name) {
foreach ($all_fields as $field_name) {
$columns = $table_mapping->getColumnNames($field_name);
// Do not key single-column fields by property name.
if (count($columns) == 1) {

View file

@ -45,7 +45,11 @@ interface TableMappingInterface {
public function getAllColumns($table_name);
/**
* Gets a list of names of fields stored in the specified table.
* Gets a list of names for entity fields stored in the specified table.
*
* The return list is contains the entity field names, not database field
* (i.e. column) names. To get the mapping of specific entity field to
* database columns use ::getColumnNames().
*
* @param string $table_name
* The name of the table to return the field names for.

View file

@ -717,7 +717,7 @@ function hook_entity_view_mode_info_alter(&$view_modes) {
* - translatable: (optional) A boolean value specifying whether this bundle
* has translation support enabled. Defaults to FALSE.
*
* @see entity_get_bundles()
* @see \Drupal\Core\Entity\EntityTypeBundleInfo::getBundleInfo()
* @see hook_entity_bundle_info_alter()
*/
function hook_entity_bundle_info() {
@ -731,7 +731,7 @@ function hook_entity_bundle_info() {
* @param array $bundles
* An array of bundles, keyed first by entity type, then by bundle name.
*
* @see entity_get_bundles()
* @see Drupal\Core\Entity\EntityTypeBundleInfo::getBundleInfo()
* @see hook_entity_bundle_info()
*/
function hook_entity_bundle_info_alter(&$bundles) {

View file

@ -0,0 +1,72 @@
<?php
namespace Drupal\Core\EventSubscriber;
use Drupal\Component\Utility\Html;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* Subscribes to filter RSS responses, to make relative URIs absolute.
*/
class RssResponseRelativeUrlFilter implements EventSubscriberInterface {
/**
* Converts relative URLs to absolute URLs.
*
* @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
* The response event.
*/
public function onResponse(FilterResponseEvent $event) {
// Only care about RSS responses.
if (stripos($event->getResponse()->headers->get('Content-Type'), 'application/rss+xml') === FALSE) {
return;
}
$response = $event->getResponse();
$response->setContent($this->transformRootRelativeUrlsToAbsolute($response->getContent(), $event->getRequest()));
}
/**
* Converts all root-relative URLs to absolute URLs in RSS markup.
*
* Does not change any existing protocol-relative or absolute URLs.
*
* @param string $rss_markup
* The RSS markup to update.
* @param \Symfony\Component\HttpFoundation\Request $request
* The current request.
*
* @return string
* The updated RSS markup.
*/
protected function transformRootRelativeUrlsToAbsolute($rss_markup, Request $request) {
$rss_dom = new \DOMDocument();
$rss_dom->loadXML($rss_markup);
// Invoke Html::transformRootRelativeUrlsToAbsolute() on all HTML content
// embedded in this RSS feed.
foreach ($rss_dom->getElementsByTagName('description') as $node) {
$html_markup = $node->nodeValue;
if (!empty($html_markup)) {
$node->nodeValue = Html::transformRootRelativeUrlsToAbsolute($html_markup, $request->getSchemeAndHttpHost());
}
}
return $rss_dom->saveXML();
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
// Should run after any other response subscriber that modifies the markup.
// @see \Drupal\Core\EventSubscriber\ActiveLinkResponseFilter
$events[KernelEvents::RESPONSE][] = ['onResponse', -512];
return $events;
}
}

View file

@ -175,7 +175,7 @@ function hook_module_preinstall($module) {
* This function differs from hook_install() in that it gives all other modules
* a chance to perform actions when a module is installed, whereas
* hook_install() is only called on the module actually being installed. See
* \Drupal\Core\Extension\ModuleHandler::install() for a detailed description of
* \Drupal\Core\Extension\ModuleInstaller::install() for a detailed description of
* the order in which install hooks are invoked.
*
* This hook should be implemented in a .module file, not in an .install file.
@ -183,7 +183,7 @@ function hook_module_preinstall($module) {
* @param $modules
* An array of the modules that were installed.
*
* @see \Drupal\Core\Extension\ModuleHandler::install()
* @see \Drupal\Core\Extension\ModuleInstaller::install()
* @see hook_install()
*/
function hook_modules_installed($modules) {
@ -223,7 +223,7 @@ function hook_modules_installed($modules) {
* be removed during uninstall should be removed with hook_uninstall().
*
* @see hook_schema()
* @see \Drupal\Core\Extension\ModuleHandler::install()
* @see \Drupal\Core\Extension\ModuleInstaller::install()
* @see hook_uninstall()
* @see hook_modules_installed()
*/

View file

@ -236,13 +236,15 @@ interface FieldStorageDefinitionInterface extends CacheableDependencyInterface {
*
* @return array[]
* The field schema, as an array of key/value pairs in the format returned
* by hook_field_schema():
* by \Drupal\Core\Field\FieldItemInterface::schema():
* - columns: An array of Schema API column specifications, keyed by column
* name. This specifies what comprises a single value for a given field.
* No assumptions should be made on how storage backends internally use
* the original column name to structure their storage.
* - indexes: An array of Schema API index definitions. Some storage
* backends might not support indexes.
* - unique keys: An array of Schema API unique key definitions. Some
* storage backends might not support unique keys.
* - foreign keys: An array of Schema API foreign key definitions. Note,
* however, that depending on the storage backend specified for the field,
* the field data is not necessarily stored in SQL.

View file

@ -160,48 +160,42 @@ class EntityReferenceEntityFormatter extends EntityReferenceFormatterBase implem
$elements = array();
foreach ($this->getEntitiesToView($items, $langcode) as $delta => $entity) {
if ($entity->id()) {
// Due to render caching and delayed calls, the viewElements() method
// will be called later in the rendering process through a '#pre_render'
// callback, so we need to generate a counter that takes into account
// all the relevant information about this field and the referenced
// entity that is being rendered.
$recursive_render_id = $items->getFieldDefinition()->getTargetEntityTypeId()
. $items->getFieldDefinition()->getTargetBundle()
. $items->getName()
. $entity->id();
// Due to render caching and delayed calls, the viewElements() method
// will be called later in the rendering process through a '#pre_render'
// callback, so we need to generate a counter that takes into account
// all the relevant information about this field and the referenced
// entity that is being rendered.
$recursive_render_id = $items->getFieldDefinition()->getTargetEntityTypeId()
. $items->getFieldDefinition()->getTargetBundle()
. $items->getName()
. $entity->id();
if (isset(static::$recursiveRenderDepth[$recursive_render_id])) {
static::$recursiveRenderDepth[$recursive_render_id]++;
}
else {
static::$recursiveRenderDepth[$recursive_render_id] = 1;
}
// Protect ourselves from recursive rendering.
if (static::$recursiveRenderDepth[$recursive_render_id] > static::RECURSIVE_RENDER_LIMIT) {
$this->loggerFactory->get('entity')->error('Recursive rendering detected when rendering entity %entity_type: %entity_id, using the %field_name field on the %bundle_name bundle. Aborting rendering.', [
'%entity_type' => $entity->getEntityTypeId(),
'%entity_id' => $entity->id(),
'%field_name' => $items->getName(),
'%bundle_name' => $items->getFieldDefinition()->getTargetBundle(),
]);
return $elements;
}
$view_builder = $this->entityTypeManager->getViewBuilder($entity->getEntityTypeId());
$elements[$delta] = $view_builder->view($entity, $view_mode, $entity->language()->getId());
// Add a resource attribute to set the mapping property's value to the
// entity's url. Since we don't know what the markup of the entity will
// be, we shouldn't rely on it for structured data such as RDFa.
if (!empty($items[$delta]->_attributes)) {
$items[$delta]->_attributes += array('resource' => $entity->url());
}
if (isset(static::$recursiveRenderDepth[$recursive_render_id])) {
static::$recursiveRenderDepth[$recursive_render_id]++;
}
else {
// This is an "auto_create" item.
$elements[$delta] = array('#markup' => $entity->label());
static::$recursiveRenderDepth[$recursive_render_id] = 1;
}
// Protect ourselves from recursive rendering.
if (static::$recursiveRenderDepth[$recursive_render_id] > static::RECURSIVE_RENDER_LIMIT) {
$this->loggerFactory->get('entity')->error('Recursive rendering detected when rendering entity %entity_type: %entity_id, using the %field_name field on the %bundle_name bundle. Aborting rendering.', [
'%entity_type' => $entity->getEntityTypeId(),
'%entity_id' => $entity->id(),
'%field_name' => $items->getName(),
'%bundle_name' => $items->getFieldDefinition()->getTargetBundle(),
]);
return $elements;
}
$view_builder = $this->entityTypeManager->getViewBuilder($entity->getEntityTypeId());
$elements[$delta] = $view_builder->view($entity, $view_mode, $entity->language()->getId());
// Add a resource attribute to set the mapping property's value to the
// entity's url. Since we don't know what the markup of the entity will
// be, we shouldn't rely on it for structured data such as RDFa.
if (!empty($items[$delta]->_attributes) && !$entity->isNew() && $entity->hasLinkTemplate('canonical')) {
$items[$delta]->_attributes += array('resource' => $entity->toUrl()->toString());
}
}

View file

@ -53,8 +53,12 @@ class MimeTypeGuesser implements MimeTypeGuesserInterface {
*/
public function guess($path) {
if ($wrapper = $this->streamWrapperManager->getViaUri($path)) {
// Get the real path from the stream wrapper.
$path = $wrapper->realpath();
// Get the real path from the stream wrapper, if available. Files stored
// in remote file systems will not have one.
$real_path = $wrapper->realpath();
if ($real_path !== FALSE) {
$path = $real_path;
}
}
if ($this->sortedGuessers === NULL) {

View file

@ -73,7 +73,7 @@ class InstallerServiceProvider implements ServiceProviderInterface, ServiceModif
// No service may persist when the early installer kernel is rebooted into
// the production environment.
// @todo The DrupalKernel reboot performed by drupal_install_system() is
// actually not a "regular" reboot (like ModuleHandler::install()), so
// actually not a "regular" reboot (like ModuleInstaller::install()), so
// services are not actually persisted.
foreach ($container->findTaggedServiceIds('persist') as $id => $tags) {
$definition = $container->getDefinition($id);

View file

@ -2,6 +2,7 @@
namespace Drupal\Core\ParamConverter;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Symfony\Component\Routing\Route;
@ -31,14 +32,24 @@ class EntityRevisionParamConverter implements ParamConverterInterface {
*/
protected $entityTypeManager;
/**
* The entity repository.
*
* @var \Drupal\Core\Entity\EntityRepositoryInterface
*/
protected $entityRepository;
/**
* Creates a new EntityRevisionParamConverter instance.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
* The entity repository.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
public function __construct(EntityTypeManagerInterface $entity_type_manager, EntityRepositoryInterface $entity_repository) {
$this->entityTypeManager = $entity_type_manager;
$this->entityRepository = $entity_repository;
}
/**
@ -46,8 +57,8 @@ class EntityRevisionParamConverter implements ParamConverterInterface {
*/
public function convert($value, $definition, $name, array $defaults) {
list (, $entity_type_id) = explode(':', $definition['type'], 2);
$entity_storage = $this->entityTypeManager->getStorage($entity_type_id);
return $entity_storage->loadRevision($value);
$entity = $this->entityTypeManager->getStorage($entity_type_id)->loadRevision($value);
return $this->entityRepository->getTranslationFromContext($entity);
}
/**

View file

@ -25,7 +25,7 @@ interface AttachmentsResponseProcessorInterface {
* $build['#attached']['library'][] = [
* 'library' => ['core/jquery']
* ];
* $build['#attached']['http_header'][] = [
* $build['#attached']['http_header'] = [
* ['Content-Type', 'application/rss+xml; charset=utf-8'],
* ];
* @endcode

View file

@ -636,8 +636,33 @@ class Renderer implements RendererInterface {
return FALSE;
}
foreach (array_keys($elements['#attached']['placeholders']) as $placeholder) {
$elements = $this->renderPlaceholder($placeholder, $elements);
// The 'status messages' placeholder needs to be special cased, because it
// depends on global state that can be modified when other placeholders are
// being rendered: any code can add messages to render.
// This violates the principle that each lazy builder must be able to render
// itself in isolation, and therefore in any order. However, we cannot
// change the way drupal_set_message() works in the Drupal 8 cycle. So we
// have to accommodate its special needs.
// Allowing placeholders to be rendered in a particular order (in this case:
// last) would violate this isolation principle. Thus a monopoly is granted
// to this one special case, with this hard-coded solution.
// @see \Drupal\Core\Render\Element\StatusMessages
// @see https://www.drupal.org/node/2712935#comment-11368923
// First render all placeholders except 'status messages' placeholders.
$message_placeholders = [];
foreach ($elements['#attached']['placeholders'] as $placeholder => $placeholder_element) {
if (isset($placeholder_element['#lazy_builder']) && $placeholder_element['#lazy_builder'][0] === 'Drupal\Core\Render\Element\StatusMessages::renderMessages') {
$message_placeholders[] = $placeholder;
}
else {
$elements = $this->renderPlaceholder($placeholder, $elements);
}
}
// Then render 'status messages' placeholders.
foreach ($message_placeholders as $message_placeholder) {
$elements = $this->renderPlaceholder($message_placeholder, $elements);
}
return TRUE;

View file

@ -788,17 +788,17 @@ function hook_render_template($template_file, $variables) {
* A module may implement this hook in order to alter the element type defaults
* defined by a module.
*
* @param array $types
* @param array $info
* An associative array with structure identical to that of the return value
* of \Drupal\Core\Render\ElementInfoManagerInterface::getInfo().
*
* @see \Drupal\Core\Render\ElementInfoManager
* @see \Drupal\Core\Render\Element\ElementInterface
*/
function hook_element_info_alter(array &$types) {
function hook_element_info_alter(array &$info) {
// Decrease the default size of textfields.
if (isset($types['textfield']['#size'])) {
$types['textfield']['#size'] = 40;
if (isset($info['textfield']['#size'])) {
$info['textfield']['#size'] = 40;
}
}

View file

@ -15,6 +15,13 @@ namespace Drupal\Core\StreamWrapper;
*/
abstract class LocalReadOnlyStream extends LocalStream {
/**
* {@inheritdoc}
*/
public static function getType() {
return StreamWrapperInterface::READ_VISIBLE | StreamWrapperInterface::LOCAL;
}
/**
* Support for fopen(), file_get_contents(), etc.
*