Core and composer updates
This commit is contained in:
parent
a82634bb98
commit
62cac30480
1118 changed files with 21770 additions and 6306 deletions
|
@ -81,7 +81,7 @@ class Drupal {
|
|||
/**
|
||||
* The current system version.
|
||||
*/
|
||||
const VERSION = '8.3.1';
|
||||
const VERSION = '8.3.4';
|
||||
|
||||
/**
|
||||
* Core API compatibility.
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
namespace Drupal\Component\Plugin\Context;
|
||||
|
||||
/**
|
||||
* Interface for context definitions.
|
||||
* Interface used to define definition objects found in ContextInterface.
|
||||
*
|
||||
* @see \Drupal\Component\Plugin\Context\ContextInterface
|
||||
*
|
||||
* @todo WARNING: This interface is going to receive some additions as part of
|
||||
* https://www.drupal.org/node/2346999.
|
||||
|
|
|
@ -3,7 +3,14 @@
|
|||
namespace Drupal\Component\Plugin\Context;
|
||||
|
||||
/**
|
||||
* A generic context interface for wrapping data a plugin needs to operate.
|
||||
* Provides data and definitions for plugins during runtime and administration.
|
||||
*
|
||||
* Plugin contexts are satisfied by ContextInterface implementing objects.
|
||||
* These objects always contain a definition of what data they will provide
|
||||
* during runtime. During run time, ContextInterface implementing objects must
|
||||
* also provide the corresponding data value.
|
||||
*
|
||||
* @see \Drupal\Component\Plugin\Context\ContextDefinitionInterface
|
||||
*/
|
||||
interface ContextInterface {
|
||||
|
||||
|
|
|
@ -27,6 +27,12 @@ class YamlPecl implements SerializationInterface {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public static function decode($raw) {
|
||||
static $init;
|
||||
if (!isset($init)) {
|
||||
// We never want to unserialize !php/object.
|
||||
ini_set('yaml.decode_php', 0);
|
||||
$init = TRUE;
|
||||
}
|
||||
// yaml_parse() will error with an empty value.
|
||||
if (!trim($raw)) {
|
||||
return NULL;
|
||||
|
|
|
@ -61,13 +61,15 @@ class Html {
|
|||
* Do not pass one string containing multiple classes as they will be
|
||||
* incorrectly concatenated with dashes, i.e. "one two" will become "one-two".
|
||||
*
|
||||
* @param string $class
|
||||
* The class name to clean.
|
||||
* @param mixed $class
|
||||
* The class name to clean. It can be a string or anything that can be cast
|
||||
* to string.
|
||||
*
|
||||
* @return string
|
||||
* The cleaned class name.
|
||||
*/
|
||||
public static function getClass($class) {
|
||||
$class = (string) $class;
|
||||
if (!isset(static::$classes[$class])) {
|
||||
static::$classes[$class] = static::cleanCssIdentifier(Unicode::strtolower($class));
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ class UrlHelper {
|
|||
$params = [];
|
||||
|
||||
foreach ($query as $key => $value) {
|
||||
$key = ($parent ? $parent . '[' . rawurlencode($key) . ']' : rawurlencode($key));
|
||||
$key = ($parent ? $parent . rawurlencode('[' . $key . ']') : rawurlencode($key));
|
||||
|
||||
// Recurse into children.
|
||||
if (is_array($value)) {
|
||||
|
@ -142,7 +142,12 @@ class UrlHelper {
|
|||
|
||||
// External URLs: not using parse_url() here, so we do not have to rebuild
|
||||
// the scheme, host, and path without having any use for it.
|
||||
if (strpos($url, '://') !== FALSE) {
|
||||
// The URL is considered external if it contains the '://' delimiter. Since
|
||||
// a URL can also be passed as a query argument, we check if this delimiter
|
||||
// appears in front of the '?' query argument delimiter.
|
||||
$scheme_delimiter_position = strpos($url, '://');
|
||||
$query_delimiter_position = strpos($url, '?');
|
||||
if ($scheme_delimiter_position !== FALSE && ($query_delimiter_position === FALSE || $scheme_delimiter_position < $query_delimiter_position)) {
|
||||
// Split off everything before the query string into 'path'.
|
||||
$parts = explode('?', $url);
|
||||
|
||||
|
|
|
@ -18,8 +18,6 @@ use Drupal\Core\StringTranslation\TranslatableMarkup;
|
|||
* "node" = @ContextDefinition("entity:node")
|
||||
* }
|
||||
* @endcode
|
||||
* Remove spaces after @ in your actual plugin - these are put into this sample
|
||||
* code so that it is not recognized as an annotation.
|
||||
*
|
||||
* To add a label to a context definition use the "label" key:
|
||||
* @code
|
||||
|
|
|
@ -6,6 +6,8 @@ use Symfony\Component\DependencyInjection\ContainerAwareTrait;
|
|||
|
||||
/**
|
||||
* Defines the chained fast cache backend factory.
|
||||
*
|
||||
* @see \Drupal\Core\Cache\ChainedFastBackend
|
||||
*/
|
||||
class ChainedFastBackendFactory implements CacheFactoryInterface {
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ use Drupal\Component\PhpStorage\FileStorage;
|
|||
use Composer\Script\Event;
|
||||
use Composer\Installer\PackageEvent;
|
||||
use Composer\Semver\Constraint\Constraint;
|
||||
use PHP_CodeSniffer;
|
||||
|
||||
/**
|
||||
* Provides static functions for composer script events.
|
||||
|
@ -137,28 +136,6 @@ EOT;
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures phpcs if present.
|
||||
*
|
||||
* @param \Composer\Script\Event $event
|
||||
*/
|
||||
public static function configurePhpcs(Event $event) {
|
||||
// Grab the local repo which tells us what's been installed.
|
||||
$local_repository = $event->getComposer()
|
||||
->getRepositoryManager()
|
||||
->getLocalRepository();
|
||||
// Make sure both phpcs and coder are installed.
|
||||
$phpcs_package = $local_repository->findPackage('squizlabs/php_codesniffer', '*');
|
||||
$coder_package = $local_repository->findPackage('drupal/coder', '*');
|
||||
if (!empty($phpcs_package) && !empty($coder_package)) {
|
||||
$config = $event->getComposer()->getConfig();
|
||||
$vendor_dir = $config->get('vendor-dir');
|
||||
// Set phpcs' installed_paths config to point to our coder_sniffer
|
||||
// directory.
|
||||
PHP_CodeSniffer::setConfigData('installed_paths', $vendor_dir . '/drupal/coder/coder_sniffer');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove possibly problematic test files from vendored projects.
|
||||
*
|
||||
|
|
|
@ -466,7 +466,7 @@ class ConfigInstaller implements ConfigInstallerInterface {
|
|||
// Check the dependencies of configuration provided by the module.
|
||||
list($invalid_default_config, $missing_dependencies) = $this->findDefaultConfigWithUnmetDependencies($storage, $enabled_extensions, $profile_storages);
|
||||
if (!empty($invalid_default_config)) {
|
||||
throw UnmetDependenciesException::create($name, array_unique($missing_dependencies));
|
||||
throw UnmetDependenciesException::create($name, array_unique($missing_dependencies, SORT_REGULAR));
|
||||
}
|
||||
|
||||
// Install profiles can not have config clashes. Configuration that
|
||||
|
|
|
@ -19,8 +19,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
* difficult to unit test. Therefore this base class should only be used by
|
||||
* controller classes that contain only trivial glue code. Controllers that
|
||||
* contain sufficiently complex logic that it's worth testing should not use
|
||||
* this base class but use ContainerInjectionInterface instead, or even better be
|
||||
* refactored to be trivial glue code.
|
||||
* this base class but use ContainerInjectionInterface instead, or even
|
||||
* better be refactored to be trivial glue code.
|
||||
*
|
||||
* The services exposed here are those that it is reasonable for a well-behaved
|
||||
* controller to leverage. A controller that needs other services may
|
||||
|
@ -70,7 +70,7 @@ abstract class ControllerBase implements ContainerInjectionInterface {
|
|||
/**
|
||||
* The configuration factory.
|
||||
*
|
||||
* @var \Drupal\Core\Config\Config
|
||||
* @var \Drupal\Core\Config\ConfigFactoryInterface
|
||||
*/
|
||||
protected $configFactory;
|
||||
|
||||
|
|
|
@ -10,9 +10,9 @@ use Symfony\Component\DependencyInjection\Reference;
|
|||
* Provides a compiler pass for stacked HTTP kernels.
|
||||
*
|
||||
* Builds the HTTP kernel by collecting all services tagged 'http_middleware'
|
||||
* and assembling them into a StackedKernel. The middleware with the lowest
|
||||
* priority ends up as the outermost while the highest priority middleware
|
||||
* wraps the actual HTTP kernel defined by the http_kernel.basic service.
|
||||
* and assembling them into a StackedKernel. The middleware with the highest
|
||||
* priority ends up as the outermost while the lowest priority middleware wraps
|
||||
* the actual HTTP kernel defined by the http_kernel.basic service.
|
||||
*
|
||||
* The 'http_middleware' service tag additionally accepts a 'responder'
|
||||
* parameter. It should be set to TRUE if many or most requests will be handled
|
||||
|
|
|
@ -870,6 +870,16 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
|
|||
// If there is no container and no cached container definition, build a new
|
||||
// one from scratch.
|
||||
if (!isset($container) && !isset($container_definition)) {
|
||||
// Building the container creates 1000s of objects. Garbage collection of
|
||||
// these objects is expensive. This appears to be causing random
|
||||
// segmentation faults in PHP 5.6 due to
|
||||
// https://bugs.php.net/bug.php?id=72286. Once the container is rebuilt,
|
||||
// garbage collection is re-enabled.
|
||||
$disable_gc = version_compare(PHP_VERSION, '7', '<') && gc_enabled();
|
||||
if ($disable_gc) {
|
||||
gc_collect_cycles();
|
||||
gc_disable();
|
||||
}
|
||||
$container = $this->compileContainer();
|
||||
|
||||
// Only dump the container if dumping is allowed. This is useful for
|
||||
|
@ -879,6 +889,11 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
|
|||
$dumper = new $this->phpArrayDumperClass($container);
|
||||
$container_definition = $dumper->getArray();
|
||||
}
|
||||
// If garbage collection was disabled prior to rebuilding container,
|
||||
// re-enable it.
|
||||
if ($disable_gc) {
|
||||
gc_enable();
|
||||
}
|
||||
}
|
||||
|
||||
// The container was rebuilt successfully.
|
||||
|
|
|
@ -830,6 +830,7 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C
|
|||
$translation->translationInitialize = FALSE;
|
||||
$translation->typedData = NULL;
|
||||
$translation->loadedRevisionId = &$this->loadedRevisionId;
|
||||
$translation->isDefaultRevision = &$this->isDefaultRevision;
|
||||
|
||||
return $translation;
|
||||
}
|
||||
|
@ -1095,7 +1096,7 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C
|
|||
// Ensure that the following properties are actually cloned by
|
||||
// overwriting the original references with ones pointing to copies of
|
||||
// them: enforceIsNew, newRevision, loadedRevisionId, fields, entityKeys,
|
||||
// translatableEntityKeys and values.
|
||||
// translatableEntityKeys, values and isDefaultRevision.
|
||||
$enforce_is_new = $this->enforceIsNew;
|
||||
$this->enforceIsNew = &$enforce_is_new;
|
||||
|
||||
|
@ -1117,6 +1118,9 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C
|
|||
$values = $this->values;
|
||||
$this->values = &$values;
|
||||
|
||||
$default_revision = $this->isDefaultRevision;
|
||||
$this->isDefaultRevision = &$default_revision;
|
||||
|
||||
foreach ($this->fields as $name => $fields_by_langcode) {
|
||||
$this->fields[$name] = [];
|
||||
// Untranslatable fields may have multiple references for the same field
|
||||
|
|
|
@ -318,8 +318,14 @@ class EntityAutocomplete extends Textfield {
|
|||
* A string of entity labels separated by commas.
|
||||
*/
|
||||
public static function getEntityLabels(array $entities) {
|
||||
/** @var \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository */
|
||||
$entity_repository = \Drupal::service('entity.repository');
|
||||
|
||||
$entity_labels = [];
|
||||
foreach ($entities as $entity) {
|
||||
// Set the entity in the correct language for display.
|
||||
$entity = $entity_repository->getTranslationFromContext($entity);
|
||||
|
||||
// Use the special view label, since some entities allow the label to be
|
||||
// viewed, even if the entity is not allowed to be viewed.
|
||||
$label = ($entity->access('view label')) ? $entity->label() : t('- Restricted access -');
|
||||
|
|
|
@ -110,6 +110,7 @@ interface EntityInterface extends AccessibleInterface, CacheableDependencyInterf
|
|||
* @deprecated in Drupal 8.0.0, intended to be removed in Drupal 9.0.0
|
||||
* Use \Drupal\Core\Entity\EntityInterface::toUrl() instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2614344
|
||||
* @see \Drupal\Core\Entity\EntityInterface::toUrl
|
||||
*/
|
||||
public function urlInfo($rel = 'canonical', array $options = []);
|
||||
|
@ -167,6 +168,7 @@ interface EntityInterface extends AccessibleInterface, CacheableDependencyInterf
|
|||
* @deprecated in Drupal 8.0.0, intended to be removed in Drupal 9.0.0
|
||||
* Please use toUrl() instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2614344
|
||||
* @see \Drupal\Core\Entity\EntityInterface::toUrl
|
||||
*/
|
||||
public function url($rel = 'canonical', $options = []);
|
||||
|
@ -189,6 +191,7 @@ interface EntityInterface extends AccessibleInterface, CacheableDependencyInterf
|
|||
* @deprecated in Drupal 8.0.0, intended to be removed in Drupal 9.0.0
|
||||
* Please use toLink() instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2614344
|
||||
* @see \Drupal\Core\Entity\EntityInterface::toLink
|
||||
*/
|
||||
public function link($text = NULL, $rel = 'canonical', array $options = []);
|
||||
|
|
|
@ -22,7 +22,9 @@ interface EntityListBuilderInterface {
|
|||
* sorting the loaded entities.
|
||||
*
|
||||
* @return \Drupal\Core\Entity\EntityInterface[]
|
||||
* An array of entities implementing \Drupal\Core\Entity\EntityInterface.
|
||||
* An array of entities implementing \Drupal\Core\Entity\EntityInterface
|
||||
* indexed by their IDs. Returns an empty array if no matching entities are
|
||||
* found.
|
||||
*/
|
||||
public function load();
|
||||
|
||||
|
|
|
@ -603,6 +603,13 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
|
|||
$this->database->delete($this->revisionTable)
|
||||
->condition($this->revisionKey, $revision->getRevisionId())
|
||||
->execute();
|
||||
|
||||
if ($this->revisionDataTable) {
|
||||
$this->database->delete($this->revisionDataTable)
|
||||
->condition($this->revisionKey, $revision->getRevisionId())
|
||||
->execute();
|
||||
}
|
||||
|
||||
$this->deleteRevisionFromDedicatedTables($revision);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Core\Field;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Entity\EntityAccessControlHandler;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
||||
/**
|
||||
* Provides en entity access control handler for base field override entity.
|
||||
*/
|
||||
class BaseFieldOverrideAccessControlHandler extends EntityAccessControlHandler {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
|
||||
$access = parent::checkAccess($entity, $operation, $account);
|
||||
return $access->orIf(AccessResult::allowedIfHasPermission($account, 'administer ' . $entity->getTargetEntityTypeId() . ' fields'));
|
||||
}
|
||||
|
||||
}
|
|
@ -16,7 +16,8 @@ use Drupal\Core\Field\FieldException;
|
|||
* id = "base_field_override",
|
||||
* label = @Translation("Base field override"),
|
||||
* handlers = {
|
||||
* "storage" = "Drupal\Core\Field\BaseFieldOverrideStorage"
|
||||
* "storage" = "Drupal\Core\Field\BaseFieldOverrideStorage",
|
||||
* "access" = "Drupal\Core\Field\BaseFieldOverrideAccessControlHandler",
|
||||
* },
|
||||
* config_prefix = "base_field_override",
|
||||
* entity_keys = {
|
||||
|
|
|
@ -104,7 +104,8 @@ abstract class EntityReferenceFormatterBase extends FormatterBase {
|
|||
// tags on which the access results depend, to ensure users that cannot view
|
||||
// this field at the moment will gain access once any of those cache tags
|
||||
// are invalidated.
|
||||
$field_level_access_cacheability->applyTo($elements);
|
||||
$field_level_access_cacheability->merge(CacheableMetadata::createFromRenderArray($elements))
|
||||
->applyTo($elements);
|
||||
|
||||
return $elements;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Core\Field\Plugin\migrate\field;
|
||||
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase;
|
||||
|
||||
/**
|
||||
* @MigrateField(
|
||||
* id = "email",
|
||||
* core = {6,7},
|
||||
* type_map = {
|
||||
* "email" = "email"
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class Email extends FieldPluginBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFieldWidgetMap() {
|
||||
return [
|
||||
'email_textfield' => 'email_default',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFieldFormatterMap() {
|
||||
return [
|
||||
'email_formatter_default' => 'basic_string',
|
||||
'email_formatter_contact' => 'basic_string',
|
||||
'email_formatter_plain' => 'basic_string',
|
||||
'email_formatter_spamspan' => 'basic_string',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function processFieldValues(MigrationInterface $migration, $field_name, $data) {
|
||||
$process = [
|
||||
'plugin' => 'iterator',
|
||||
'source' => $field_name,
|
||||
'process' => [
|
||||
'value' => 'email',
|
||||
],
|
||||
];
|
||||
$migration->setProcessOfProperty($field_name, $process);
|
||||
}
|
||||
|
||||
}
|
|
@ -5,7 +5,7 @@ namespace Drupal\Core\Lock;
|
|||
/**
|
||||
* @defgroup lock Locking mechanisms
|
||||
* @{
|
||||
* Functions to coordinate long-running operations across requests.
|
||||
* Functions to coordinate long operations across requests.
|
||||
*
|
||||
* In most environments, multiple Drupal page requests (a.k.a. threads or
|
||||
* processes) will execute in parallel. This leads to potential conflicts or
|
||||
|
@ -15,15 +15,14 @@ namespace Drupal\Core\Lock;
|
|||
* problems with such code, the cron system uses a locking process to ensure
|
||||
* that cron is not started again if it is already running.
|
||||
*
|
||||
* This is a cooperative, advisory lock system. Any long-running operation
|
||||
* that could potentially be attempted in parallel by multiple requests should
|
||||
* try to acquire a lock before proceeding. By obtaining a lock, one request
|
||||
* notifies any other requests that a specific operation is in progress which
|
||||
* must not be executed in parallel.
|
||||
* To avoid these types of conflicts, Drupal has a cooperative, advisory lock
|
||||
* system. Any long-running operation that could potentially be attempted in
|
||||
* parallel by multiple requests should try to acquire a lock before
|
||||
* proceeding. By obtaining a lock, one request notifies any other requests that
|
||||
* a specific operation is in progress which must not be executed in parallel.
|
||||
*
|
||||
* To use this API, pick a unique name for the lock. A sensible choice is the
|
||||
* name of the function performing the operation. A very simple example use of
|
||||
* this API:
|
||||
* name of the function performing the operation. Here is a simple example:
|
||||
* @code
|
||||
* function mymodule_long_operation() {
|
||||
* $lock = \Drupal::lock();
|
||||
|
@ -53,6 +52,26 @@ namespace Drupal\Core\Lock;
|
|||
* $lock->acquire() and $lock->wait() will automatically break (delete) a lock
|
||||
* whose duration has exceeded the timeout specified when it was acquired.
|
||||
*
|
||||
* The following limitations in this implementation should be carefully noted:
|
||||
* - Time: Timestamps are derived from the local system clock of the environment
|
||||
* the code is executing in. The orderly progression of time from this
|
||||
* viewpoint can be disrupted by external events such as NTP synchronization
|
||||
* and operator intervention. Where multiple web servers are involved in
|
||||
* serving the site, they will have their own independent clocks, introducing
|
||||
* another source of error in the time keeping process. Timeout values applied
|
||||
* to locks must therefore be considered approximate, and should not be relied
|
||||
* upon.
|
||||
* - Uniqueness: Uniqueness of lock names is not enforced. The impact of the
|
||||
* use of a common lock name will depend on what processes and resources the
|
||||
* lock is being used to manage.
|
||||
* - Sharing: There is limited support for resources shared across sites.
|
||||
* The locks are stored as rows in the semaphore table and, as such, they
|
||||
* have the same visibility as the table. If resources managed by a lock are
|
||||
* shared across sites then the semaphore table must be shared across sites
|
||||
* as well. This is a binary situation: either all resources are shared and
|
||||
* the semaphore table is shared or no resources are shared and the semaphore
|
||||
* table is not shared. Mixed mode operation is not supported.
|
||||
*
|
||||
* @} End of "defgroup lock".
|
||||
*/
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ interface LocalTaskManagerInterface extends PluginManagerInterface {
|
|||
public function getTasksBuild($current_route_name, RefinableCacheableDependencyInterface &$cacheability);
|
||||
|
||||
/**
|
||||
* Collects the local tasks (tabs) for the current route.
|
||||
* Renders the local tasks (tabs) for the given route.
|
||||
*
|
||||
* @param string $route_name
|
||||
* The route for which to make renderable local tasks.
|
||||
|
|
|
@ -21,6 +21,13 @@ class MenuLinkTree implements MenuLinkTreeInterface {
|
|||
*/
|
||||
protected $treeStorage;
|
||||
|
||||
/**
|
||||
* The menu link plugin manager.
|
||||
*
|
||||
* @var \Drupal\Core\Menu\MenuLinkManagerInterface
|
||||
*/
|
||||
protected $menuLinkManager;
|
||||
|
||||
/**
|
||||
* The route provider to load routes by name.
|
||||
*
|
||||
|
|
|
@ -282,27 +282,44 @@ class MenuTreeStorage implements MenuTreeStorageInterface {
|
|||
* depth.
|
||||
*/
|
||||
protected function doSave(array $link) {
|
||||
$original = $this->loadFull($link['id']);
|
||||
// @todo Should we just return here if the link values match the original
|
||||
// values completely?
|
||||
// https://www.drupal.org/node/2302137
|
||||
$affected_menus = [];
|
||||
|
||||
// Get the existing definition if it exists. This does not use
|
||||
// self::loadFull() to avoid the unserialization of fields with 'serialize'
|
||||
// equal to TRUE as defined in self::schemaDefinition(). The makes $original
|
||||
// easier to compare with the return value of self::preSave().
|
||||
$query = $this->connection->select($this->table, $this->options);
|
||||
$query->fields($this->table);
|
||||
$query->condition('id', $link['id']);
|
||||
$original = $this->safeExecuteSelect($query)->fetchAssoc();
|
||||
|
||||
if ($original) {
|
||||
$link['mlid'] = $original['mlid'];
|
||||
$link['has_children'] = $original['has_children'];
|
||||
$affected_menus[$original['menu_name']] = $original['menu_name'];
|
||||
$fields = $this->preSave($link, $original);
|
||||
// If $link matches the $original data then exit early as there are no
|
||||
// changes to make. Use array_diff_assoc() to check if they match because:
|
||||
// - Some of the data types of the values are not the same. The values
|
||||
// in $original are all strings because they have come from database but
|
||||
// $fields contains typed values.
|
||||
// - MenuTreeStorage::preSave() removes the 'mlid' from $fields.
|
||||
// - The order of the keys in $original and $fields is different.
|
||||
if (array_diff_assoc($fields, $original) == [] && array_diff_assoc($original, $fields) == ['mlid' => $link['mlid']]) {
|
||||
return $affected_menus;
|
||||
}
|
||||
}
|
||||
|
||||
$transaction = $this->connection->startTransaction();
|
||||
try {
|
||||
if ($original) {
|
||||
$link['mlid'] = $original['mlid'];
|
||||
$link['has_children'] = $original['has_children'];
|
||||
$affected_menus[$original['menu_name']] = $original['menu_name'];
|
||||
}
|
||||
else {
|
||||
if (!$original) {
|
||||
// Generate a new mlid.
|
||||
$options = ['return' => Database::RETURN_INSERT_ID] + $this->options;
|
||||
$link['mlid'] = $this->connection->insert($this->table, $options)
|
||||
->fields(['id' => $link['id'], 'menu_name' => $link['menu_name']])
|
||||
->execute();
|
||||
$fields = $this->preSave($link, []);
|
||||
}
|
||||
$fields = $this->preSave($link, $original);
|
||||
// We may be moving the link to a new menu.
|
||||
$affected_menus[$fields['menu_name']] = $fields['menu_name'];
|
||||
$query = $this->connection->update($this->table, $this->options);
|
||||
|
|
|
@ -5,7 +5,10 @@ namespace Drupal\Core\Plugin\Context;
|
|||
use Drupal\Component\Plugin\Context\ContextDefinitionInterface as ComponentContextDefinitionInterface;
|
||||
|
||||
/**
|
||||
* Interface for context definitions.
|
||||
* Interface to define definition objects in ContextInterface via TypedData.
|
||||
*
|
||||
* @see \Drupal\Component\Plugin\Context\ContextDefinitionInterface
|
||||
* @see \Drupal\Core\Plugin\Context\ContextInterface
|
||||
*/
|
||||
interface ContextDefinitionInterface extends ComponentContextDefinitionInterface {
|
||||
|
||||
|
|
|
@ -6,7 +6,10 @@ use Drupal\Component\Plugin\Context\ContextInterface as ComponentContextInterfac
|
|||
use Drupal\Core\Cache\CacheableDependencyInterface;
|
||||
|
||||
/**
|
||||
* Interface for context.
|
||||
* Context data and definitions for plugins supporting caching and return docs.
|
||||
*
|
||||
* @see \Drupal\Component\Plugin\Context\ContextInterface
|
||||
* @see \Drupal\Core\Plugin\Context\ContextDefinitionInterface
|
||||
*/
|
||||
interface ContextInterface extends ComponentContextInterface, CacheableDependencyInterface {
|
||||
|
||||
|
|
|
@ -361,7 +361,7 @@ class DefaultPluginManager extends PluginManagerBase implements PluginManagerInt
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheMaxAge() {
|
||||
return CACHE::PERMANENT;
|
||||
return Cache::PERMANENT;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace Drupal\Core\Plugin;
|
|||
interface ObjectWithPluginCollectionInterface {
|
||||
|
||||
/**
|
||||
* Gets the plugin collections used by this entity.
|
||||
* Gets the plugin collections used by this object.
|
||||
*
|
||||
* @return \Drupal\Component\Plugin\LazyPluginCollection[]
|
||||
* An array of plugin collections, keyed by the property name they use to
|
||||
|
|
|
@ -73,22 +73,17 @@ class StatusMessages extends RenderElement {
|
|||
* @see drupal_get_messages()
|
||||
*/
|
||||
public static function renderMessages($type) {
|
||||
$render = [];
|
||||
$messages = drupal_get_messages($type);
|
||||
if ($messages) {
|
||||
// Render the messages.
|
||||
$render = [
|
||||
'#theme' => 'status_messages',
|
||||
// @todo Improve when https://www.drupal.org/node/2278383 lands.
|
||||
'#message_list' => $messages,
|
||||
'#status_headings' => [
|
||||
'status' => t('Status message'),
|
||||
'error' => t('Error message'),
|
||||
'warning' => t('Warning message'),
|
||||
],
|
||||
];
|
||||
}
|
||||
return $render;
|
||||
// Render the messages.
|
||||
return [
|
||||
'#theme' => 'status_messages',
|
||||
// @todo Improve when https://www.drupal.org/node/2278383 lands.
|
||||
'#message_list' => drupal_get_messages($type),
|
||||
'#status_headings' => [
|
||||
'status' => t('Status message'),
|
||||
'error' => t('Error message'),
|
||||
'warning' => t('Warning message'),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -225,12 +225,7 @@
|
|||
* For further information on the Theme and Render APIs, see:
|
||||
* - https://www.drupal.org/docs/8/theming
|
||||
* - https://www.drupal.org/developing/api/8/render
|
||||
* - https://www.drupal.org/node/722174
|
||||
* - https://www.drupal.org/node/933976
|
||||
* - https://www.drupal.org/node/930760
|
||||
*
|
||||
* @todo Check these links. Some are for Drupal 7, and might need updates for
|
||||
* Drupal 8.
|
||||
* - @link themeable Theme system overview @endlink.
|
||||
*
|
||||
* @section arrays Render arrays
|
||||
* The core structure of the Render API is the render array, which is a
|
||||
|
|
24
web/core/lib/Drupal/Core/Test/ObjectSerialization.php
Normal file
24
web/core/lib/Drupal/Core/Test/ObjectSerialization.php
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Core\Test;
|
||||
|
||||
/**
|
||||
* Object to test that security issues around serialization.
|
||||
*/
|
||||
class ObjectSerialization {
|
||||
|
||||
/**
|
||||
* ObjectSerialization constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
throw new \Exception('This object should never be constructed');
|
||||
}
|
||||
|
||||
/**
|
||||
* ObjectSerialization deconstructor.
|
||||
*/
|
||||
public function __destruct() {
|
||||
throw new \Exception('This object should never be destructed');
|
||||
}
|
||||
|
||||
}
|
Reference in a new issue