updated core to 8.6.3
This commit is contained in:
@@ -200,7 +200,7 @@ class PhpArrayContainer extends Container {
|
||||
// The PhpArrayDumper just uses the hash of the private service
|
||||
// definition to generate a unique ID.
|
||||
//
|
||||
// @see \Drupal\Component\DependecyInjection\Dumper\OptimizedPhpArrayDumper::getPrivateServiceCall
|
||||
// @see \Drupal\Component\DependencyInjection\Dumper\OptimizedPhpArrayDumper::getPrivateServiceCall
|
||||
if ($type == 'private_service') {
|
||||
$id = $argument->id;
|
||||
|
||||
|
||||
@@ -394,7 +394,7 @@ class PoStreamReader implements PoStreamInterface, PoReaderInterface {
|
||||
($this->context != 'MSGCTXT') &&
|
||||
($this->context != 'MSGID_PLURAL') &&
|
||||
($this->context != 'MSGSTR_ARR')) {
|
||||
// Plural message strings must come after msgid, msgxtxt,
|
||||
// Plural message strings must come after msgid, msgctxt,
|
||||
// msgid_plural, or other msgstr[] entries.
|
||||
$this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: "msgstr[]" is unexpected on line %line.', $log_vars);
|
||||
return FALSE;
|
||||
|
||||
@@ -36,7 +36,7 @@ abstract class SecuredRedirectResponse extends RedirectResponse {
|
||||
* Copies over the values from the given response.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\RedirectResponse $response
|
||||
* The redirect reponse object.
|
||||
* The redirect response object.
|
||||
*/
|
||||
protected function fromResponse(RedirectResponse $response) {
|
||||
$this->setProtocolVersion($response->getProtocolVersion());
|
||||
|
||||
@@ -29,7 +29,7 @@ abstract class PluginManagerBase implements PluginManagerInterface {
|
||||
/**
|
||||
* The object that returns the preconfigured plugin instance appropriate for a particular runtime condition.
|
||||
*
|
||||
* @var \Drupal\Component\Plugin\Mapper\MapperInterface
|
||||
* @var \Drupal\Component\Plugin\Mapper\MapperInterface|null
|
||||
*/
|
||||
protected $mapper;
|
||||
|
||||
@@ -104,6 +104,9 @@ abstract class PluginManagerBase implements PluginManagerInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getInstance(array $options) {
|
||||
if (!$this->mapper) {
|
||||
throw new \BadMethodCallException(sprintf('%s does not support this method unless %s::$mapper is set.', static::class, static::class));
|
||||
}
|
||||
return $this->mapper->getInstance($options);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
* The following changes have been done:
|
||||
* Added namespace Drupal\Core\Archiver.
|
||||
* Removed require_once 'PEAR.php'.
|
||||
* Added defintion of OS_WINDOWS taken from PEAR.php.
|
||||
* Added definition of OS_WINDOWS taken from PEAR.php.
|
||||
* Renamed class to ArchiveTar.
|
||||
* Removed extends PEAR from class.
|
||||
* Removed call parent:: __construct().
|
||||
@@ -181,7 +181,7 @@ class ArchiveTar
|
||||
if ($data == "\37\213") {
|
||||
$this->_compress = true;
|
||||
$this->_compress_type = 'gz';
|
||||
// No sure it's enought for a magic code ....
|
||||
// Not sure it's enough for a magic code ....
|
||||
} elseif ($data == "BZ") {
|
||||
$this->_compress = true;
|
||||
$this->_compress_type = 'bz2';
|
||||
@@ -2385,7 +2385,7 @@ class ArchiveTar
|
||||
|
||||
/**
|
||||
* Compress path by changing for example "/dir/foo/../bar" to "/dir/bar",
|
||||
* rand emove double slashes.
|
||||
* and remove double slashes.
|
||||
*
|
||||
* @param string $p_dir path to reduce
|
||||
*
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Drupal\Core\Cache;
|
||||
* Drupal\Core\Cache\DatabaseBackend provides the default implementation, which
|
||||
* can be consulted as an example.
|
||||
*
|
||||
* The cache indentifiers are case sensitive.
|
||||
* The cache identifiers are case sensitive.
|
||||
*
|
||||
* @ingroup cache
|
||||
*/
|
||||
|
||||
@@ -157,9 +157,7 @@ class MemoryBackend implements CacheBackendInterface, CacheTagsInvalidatorInterf
|
||||
*/
|
||||
public function invalidateMultiple(array $cids) {
|
||||
foreach ($cids as $cid) {
|
||||
if (isset($this->cache[$cid])) {
|
||||
$this->cache[$cid]->expire = $this->getRequestTime() - 1;
|
||||
}
|
||||
$this->cache[$cid]->expire = $this->getRequestTime() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -160,7 +160,10 @@ class ConfigInstaller implements ConfigInstallerInterface {
|
||||
*/
|
||||
public function installOptionalConfig(StorageInterface $storage = NULL, $dependency = []) {
|
||||
$profile = $this->drupalGetProfile();
|
||||
$optional_profile_config = [];
|
||||
$enabled_extensions = $this->getEnabledExtensions();
|
||||
$existing_config = $this->getActiveStorages()->listAll();
|
||||
|
||||
// Create the storages to read configuration from.
|
||||
if (!$storage) {
|
||||
// Search the install profile's optional configuration too.
|
||||
$storage = new ExtensionInstallStorage($this->getActiveStorages(StorageInterface::DEFAULT_COLLECTION), InstallStorage::CONFIG_OPTIONAL_DIRECTORY, StorageInterface::DEFAULT_COLLECTION, TRUE, $this->installProfile);
|
||||
@@ -171,7 +174,6 @@ class ConfigInstaller implements ConfigInstallerInterface {
|
||||
// Creates a profile storage to search for overrides.
|
||||
$profile_install_path = $this->drupalGetPath('module', $profile) . '/' . InstallStorage::CONFIG_OPTIONAL_DIRECTORY;
|
||||
$profile_storage = new FileStorage($profile_install_path, StorageInterface::DEFAULT_COLLECTION);
|
||||
$optional_profile_config = $profile_storage->listAll();
|
||||
}
|
||||
else {
|
||||
// Profile has not been set yet. For example during the first steps of the
|
||||
@@ -179,10 +181,17 @@ class ConfigInstaller implements ConfigInstallerInterface {
|
||||
$profile_storage = NULL;
|
||||
}
|
||||
|
||||
$enabled_extensions = $this->getEnabledExtensions();
|
||||
$existing_config = $this->getActiveStorages()->listAll();
|
||||
// Build the list of possible configuration to create.
|
||||
$list = $storage->listAll();
|
||||
if ($profile_storage && !empty($dependency)) {
|
||||
// Only add the optional profile configuration into the list if we are
|
||||
// have a dependency to check. This ensures that optional profile
|
||||
// configuration is not unexpectedly re-created after being deleted.
|
||||
$list = array_unique(array_merge($list, $profile_storage->listAll()));
|
||||
}
|
||||
|
||||
$list = array_unique(array_merge($storage->listAll(), $optional_profile_config));
|
||||
// Filter the list of configuration to only include configuration that
|
||||
// should be created.
|
||||
$list = array_filter($list, function ($config_name) use ($existing_config) {
|
||||
// Only list configuration that:
|
||||
// - does not already exist
|
||||
@@ -226,6 +235,8 @@ class ConfigInstaller implements ConfigInstallerInterface {
|
||||
unset($all_config[$config_name]);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the optional configuration if there is any left after filtering.
|
||||
if (!empty($config_to_create)) {
|
||||
$this->createConfiguration(StorageInterface::DEFAULT_COLLECTION, $config_to_create, TRUE);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,8 @@ interface ConfigInstallerInterface {
|
||||
* @param \Drupal\Core\Config\StorageInterface $storage
|
||||
* (optional) The configuration storage to search for optional
|
||||
* configuration. If not provided, all enabled extension's optional
|
||||
* configuration directories will be searched.
|
||||
* configuration directories including the install profile's will be
|
||||
* searched.
|
||||
* @param array $dependency
|
||||
* (optional) If set, ensures that the configuration being installed has
|
||||
* this dependency. The format is dependency type as the key ('module',
|
||||
|
||||
@@ -189,7 +189,7 @@ interface ConfigEntityInterface extends EntityInterface, ThirdPartySettingsInter
|
||||
* For example, a default view might not be installable if the base table
|
||||
* doesn't exist.
|
||||
*
|
||||
* @retun bool
|
||||
* @return bool
|
||||
* TRUE if the entity is installable, FALSE otherwise.
|
||||
*/
|
||||
public function isInstallable();
|
||||
|
||||
@@ -46,7 +46,7 @@ class FileStorage implements StorageInterface {
|
||||
$this->collection = $collection;
|
||||
|
||||
// Use a NULL File Cache backend by default. This will ensure only the
|
||||
// internal statc caching of FileCache is used and thus avoids blowing up
|
||||
// internal static caching of FileCache is used and thus avoids blowing up
|
||||
// the APCu cache.
|
||||
$this->fileCache = FileCacheFactory::get('config', ['cache_backend_class' => NULL]);
|
||||
}
|
||||
@@ -279,6 +279,9 @@ class FileStorage implements StorageInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAllCollectionNames() {
|
||||
if (!is_dir($this->directory)) {
|
||||
return [];
|
||||
}
|
||||
$collections = $this->getAllCollectionNamesHelper($this->directory);
|
||||
sort($collections);
|
||||
return $collections;
|
||||
@@ -305,7 +308,8 @@ class FileStorage implements StorageInterface {
|
||||
* @param string $directory
|
||||
* The directory to check for sub directories. This allows this
|
||||
* function to be used recursively to discover all the collections in the
|
||||
* storage.
|
||||
* storage. It is the responsibility of the caller to ensure the directory
|
||||
* exists.
|
||||
*
|
||||
* @return array
|
||||
* A list of collection names contained within the provided directory.
|
||||
|
||||
@@ -65,7 +65,7 @@ class Tasks extends InstallTasks {
|
||||
Database::getConnection();
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
// Detect utf8mb4 incompability.
|
||||
// Detect utf8mb4 incompatibility.
|
||||
if ($e->getCode() == Connection::UNSUPPORTED_CHARSET || ($e->getCode() == Connection::SQLSTATE_SYNTAX_ERROR && $e->errorInfo[1] == Connection::UNKNOWN_CHARSET)) {
|
||||
$this->fail(t('Your MySQL server and PHP MySQL driver must support utf8mb4 character encoding. Make sure to use a database system that supports this (such as MySQL/MariaDB/Percona 5.5.3 and up), and that the utf8mb4 character set is compiled in. See the <a href=":documentation" target="_blank">MySQL documentation</a> for more information.', [':documentation' => 'https://dev.mysql.com/doc/refman/5.0/en/cannot-initialize-character-set.html']));
|
||||
$info = Database::getConnectionInfo();
|
||||
|
||||
@@ -38,7 +38,7 @@ class Connection extends DatabaseConnection {
|
||||
/**
|
||||
* A map of condition operators to PostgreSQL operators.
|
||||
*
|
||||
* In PostgreSQL, 'LIKE' is case-sensitive. ILKE should be used for
|
||||
* In PostgreSQL, 'LIKE' is case-sensitive. ILIKE should be used for
|
||||
* case-insensitive statements.
|
||||
*/
|
||||
protected static $postgresqlConditionOperatorMap = [
|
||||
|
||||
@@ -914,6 +914,8 @@ class Select extends Query implements SelectInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __clone() {
|
||||
parent::__clone();
|
||||
|
||||
// On cloning, also clone the dependent objects. However, we do not
|
||||
// want to clone the database connection object as that would duplicate the
|
||||
// connection itself.
|
||||
@@ -923,6 +925,11 @@ class Select extends Query implements SelectInterface {
|
||||
foreach ($this->union as $key => $aggregate) {
|
||||
$this->union[$key]['query'] = clone($aggregate['query']);
|
||||
}
|
||||
foreach ($this->tables as $alias => $table) {
|
||||
if ($table['table'] instanceof SelectInterface) {
|
||||
$this->tables[$alias]['table'] = clone $table['table'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ class StatementPrefetch implements \Iterator, StatementInterface {
|
||||
/**
|
||||
* Driver-specific options. Can be used by child classes.
|
||||
*
|
||||
* @var Array
|
||||
* @var array
|
||||
*/
|
||||
protected $driverOptions;
|
||||
|
||||
@@ -41,14 +41,14 @@ class StatementPrefetch implements \Iterator, StatementInterface {
|
||||
/**
|
||||
* Main data store.
|
||||
*
|
||||
* @var Array
|
||||
* @var array
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* The current row, retrieved in \PDO::FETCH_ASSOC format.
|
||||
*
|
||||
* @var Array
|
||||
* @var array
|
||||
*/
|
||||
protected $currentRow = NULL;
|
||||
|
||||
@@ -62,7 +62,7 @@ class StatementPrefetch implements \Iterator, StatementInterface {
|
||||
/**
|
||||
* The list of column names in this result set.
|
||||
*
|
||||
* @var Array
|
||||
* @var array
|
||||
*/
|
||||
protected $columnNames = NULL;
|
||||
|
||||
@@ -91,7 +91,7 @@ class StatementPrefetch implements \Iterator, StatementInterface {
|
||||
/**
|
||||
* Holds supplementary current fetch options (which will be used by the next fetch).
|
||||
*
|
||||
* @var Array
|
||||
* @var array
|
||||
*/
|
||||
protected $fetchOptions = [
|
||||
'class' => 'stdClass',
|
||||
@@ -110,7 +110,7 @@ class StatementPrefetch implements \Iterator, StatementInterface {
|
||||
/**
|
||||
* Holds supplementary default fetch options.
|
||||
*
|
||||
* @var Array
|
||||
* @var array
|
||||
*/
|
||||
protected $defaultFetchOptions = [
|
||||
'class' => 'stdClass',
|
||||
|
||||
@@ -22,7 +22,7 @@ class CorsCompilerPass implements CompilerPassInterface {
|
||||
$enabled = !empty($cors_config['enabled']);
|
||||
}
|
||||
|
||||
// Remove the CORS middleware completly in case it was not enabled.
|
||||
// Remove the CORS middleware completely in case it was not enabled.
|
||||
if (!$enabled) {
|
||||
$container->removeDefinition('http_middleware.cors');
|
||||
}
|
||||
|
||||
@@ -298,12 +298,16 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the application root directory based on assumptions.
|
||||
* Determine the application root directory based on this file's location.
|
||||
*
|
||||
* @return string
|
||||
* The application root.
|
||||
*/
|
||||
protected static function guessApplicationRoot() {
|
||||
// Determine the application root by:
|
||||
// - Removing the namespace directories from the path.
|
||||
// - Getting the path to the directory two levels up from the path
|
||||
// determined in the previous step.
|
||||
return dirname(dirname(substr(__DIR__, 0, -strlen(__NAMESPACE__))));
|
||||
}
|
||||
|
||||
@@ -1091,7 +1095,7 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
|
||||
// misses.
|
||||
$old_loader = $this->classLoader;
|
||||
$this->classLoader = $loader;
|
||||
// Our class loaders are preprended to ensure they come first like the
|
||||
// Our class loaders are prepended to ensure they come first like the
|
||||
// class loader they are replacing.
|
||||
$old_loader->register(TRUE);
|
||||
$loader->register(TRUE);
|
||||
|
||||
@@ -60,6 +60,7 @@ class ContentEntityDeleteForm extends ContentEntityConfirmFormBase {
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
|
||||
$entity = $this->getEntity();
|
||||
$message = $this->getDeletionMessage();
|
||||
|
||||
// Make sure that deleting a translation does not delete the whole entity.
|
||||
if (!$entity->isDefaultTranslation()) {
|
||||
@@ -73,7 +74,7 @@ class ContentEntityDeleteForm extends ContentEntityConfirmFormBase {
|
||||
$form_state->setRedirectUrl($this->getRedirectUrl());
|
||||
}
|
||||
|
||||
$this->messenger()->addStatus($this->getDeletionMessage());
|
||||
$this->messenger()->addStatus($message);
|
||||
$this->logDeletionMessage();
|
||||
}
|
||||
|
||||
|
||||
@@ -251,8 +251,8 @@ class EntityAutocomplete extends Textfield {
|
||||
/**
|
||||
* Finds an entity from an autocomplete input without an explicit ID.
|
||||
*
|
||||
* The method will return an entity ID if one single entity unambuguously
|
||||
* matches the incoming input, and sill assign form errors otherwise.
|
||||
* The method will return an entity ID if one single entity unambiguously
|
||||
* matches the incoming input, and assign form errors otherwise.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface $handler
|
||||
* Entity reference selection plugin.
|
||||
|
||||
@@ -68,6 +68,7 @@ class EntityBundleListener implements EntityBundleListenerInterface {
|
||||
}
|
||||
// Invoke hook_entity_bundle_create() hook.
|
||||
$this->moduleHandler->invokeAll('entity_bundle_create', [$entity_type_id, $bundle]);
|
||||
$this->entityFieldManager->clearCachedFieldDefinitions();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -497,7 +497,7 @@ class EntityFieldManager implements EntityFieldManagerInterface {
|
||||
}
|
||||
}
|
||||
|
||||
$this->cacheSet($cid, $this->fieldMap, Cache::PERMANENT, ['entity_types']);
|
||||
$this->cacheSet($cid, $this->fieldMap, Cache::PERMANENT, ['entity_types', 'entity_field_info']);
|
||||
}
|
||||
}
|
||||
return $this->fieldMap;
|
||||
|
||||
@@ -194,7 +194,7 @@ abstract class EntityStorageBase extends EntityHandlerBase implements EntityStor
|
||||
* Invokes a hook on behalf of the entity.
|
||||
*
|
||||
* @param string $hook
|
||||
* One of 'presave', 'insert', 'update', 'predelete', 'delete', or
|
||||
* One of 'create', 'presave', 'insert', 'update', 'predelete', 'delete', or
|
||||
* 'revision_delete'.
|
||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
||||
* The entity object.
|
||||
|
||||
@@ -16,7 +16,7 @@ use Drupal\Core\TypedData\DataReferenceBase;
|
||||
* or the entity ID may be passed.
|
||||
*
|
||||
* Note that the definition of the referenced entity's type is required, whereas
|
||||
* defining referencable entity bundle(s) is optional. A reference defining the
|
||||
* defining referenceable entity bundle(s) is optional. A reference defining the
|
||||
* type and bundle of the referenced entity can be created as following:
|
||||
* @code
|
||||
* $definition = \Drupal\Core\Entity\EntityDefinition::create($entity_type)
|
||||
|
||||
@@ -518,7 +518,7 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
|
||||
// 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()
|
||||
// \Drupal\Core\Entity\Sql\TableMappingInterface::getColumnNames()
|
||||
// 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.
|
||||
|
||||
@@ -1174,12 +1174,12 @@ class SqlContentEntityStorageSchema implements DynamicallyFieldableEntityStorage
|
||||
* The entity type.
|
||||
* @param array $schema
|
||||
* The table schema, passed by reference.
|
||||
*
|
||||
* @return array
|
||||
* A partial schema array for the base table.
|
||||
*/
|
||||
protected function processBaseTable(ContentEntityTypeInterface $entity_type, array &$schema) {
|
||||
$this->processIdentifierSchema($schema, $entity_type->getKey('id'));
|
||||
// Process the schema for the 'id' entity key only if it exists.
|
||||
if ($entity_type->hasKey('id')) {
|
||||
$this->processIdentifierSchema($schema, $entity_type->getKey('id'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1189,12 +1189,12 @@ class SqlContentEntityStorageSchema implements DynamicallyFieldableEntityStorage
|
||||
* The entity type.
|
||||
* @param array $schema
|
||||
* The table schema, passed by reference.
|
||||
*
|
||||
* @return array
|
||||
* A partial schema array for the base table.
|
||||
*/
|
||||
protected function processRevisionTable(ContentEntityTypeInterface $entity_type, array &$schema) {
|
||||
$this->processIdentifierSchema($schema, $entity_type->getKey('revision'));
|
||||
// Process the schema for the 'revision' entity key only if it exists.
|
||||
if ($entity_type->hasKey('revision')) {
|
||||
$this->processIdentifierSchema($schema, $entity_type->getKey('revision'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1333,11 +1333,23 @@ class SqlContentEntityStorageSchema implements DynamicallyFieldableEntityStorage
|
||||
// Create field columns.
|
||||
$schema[$table_name] = $this->getSharedTableFieldSchema($storage_definition, $table_name, $column_names);
|
||||
if (!$only_save) {
|
||||
// The entity schema needs to be checked because the field schema is
|
||||
// potentially incomplete.
|
||||
// @todo Fix this in https://www.drupal.org/node/2929120.
|
||||
$entity_schema = $this->getEntitySchema($this->entityType);
|
||||
foreach ($schema[$table_name]['fields'] as $name => $specifier) {
|
||||
// Check if the field is part of the primary keys and pass along
|
||||
// this information when adding the field.
|
||||
// @see \Drupal\Core\Database\Schema::addField()
|
||||
$new_keys = [];
|
||||
if (isset($entity_schema[$table_name]['primary key']) && array_intersect($column_names, $entity_schema[$table_name]['primary key'])) {
|
||||
$new_keys = ['primary key' => $entity_schema[$table_name]['primary key']];
|
||||
}
|
||||
|
||||
// Check if the field exists because it might already have been
|
||||
// created as part of the earlier entity type update event.
|
||||
if (!$schema_handler->fieldExists($table_name, $name)) {
|
||||
$schema_handler->addField($table_name, $name, $specifier);
|
||||
$schema_handler->addField($table_name, $name, $specifier, $new_keys);
|
||||
}
|
||||
}
|
||||
if (!empty($schema[$table_name]['indexes'])) {
|
||||
|
||||
@@ -60,10 +60,7 @@ class KernelDestructionSubscriber implements EventSubscriberInterface, Container
|
||||
* An array of event listener definitions.
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
// Run this subscriber after others as those might use services that need
|
||||
// to be terminated as well or run code that needs to run before
|
||||
// termination.
|
||||
$events[KernelEvents::TERMINATE][] = ['onKernelTerminate', -100];
|
||||
$events[KernelEvents::TERMINATE][] = ['onKernelTerminate', 100];
|
||||
return $events;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Drupal\Core\Field\Plugin\Field\FieldFormatter;
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Datetime\DateFormatterInterface;
|
||||
use Drupal\Core\Datetime\DrupalDateTime;
|
||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
use Drupal\Core\Field\FormatterBase;
|
||||
@@ -104,7 +105,7 @@ class TimestampAgoFormatter extends FormatterBase implements ContainerFactoryPlu
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsForm(array $form, FormStateInterface $form_state) {
|
||||
$elements = parent::settingsForm($form, $form_state);
|
||||
$form = parent::settingsForm($form, $form_state);
|
||||
|
||||
$form['future_format'] = [
|
||||
'#type' => 'textfield',
|
||||
@@ -120,7 +121,7 @@ class TimestampAgoFormatter extends FormatterBase implements ContainerFactoryPlu
|
||||
'#description' => $this->t('Use <em>@interval</em> where you want the formatted interval text to appear.'),
|
||||
];
|
||||
|
||||
$elements['granularity'] = [
|
||||
$form['granularity'] = [
|
||||
'#type' => 'number',
|
||||
'#title' => $this->t('Granularity'),
|
||||
'#description' => $this->t('How many time interval units should be shown in the formatted output.'),
|
||||
@@ -129,7 +130,7 @@ class TimestampAgoFormatter extends FormatterBase implements ContainerFactoryPlu
|
||||
'#max' => 6,
|
||||
];
|
||||
|
||||
return $elements;
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,10 +139,19 @@ class TimestampAgoFormatter extends FormatterBase implements ContainerFactoryPlu
|
||||
public function settingsSummary() {
|
||||
$summary = parent::settingsSummary();
|
||||
|
||||
$future_date = strtotime('1 year 1 month 1 week 1 day 1 hour 1 minute');
|
||||
$past_date = strtotime('-1 year -1 month -1 week -1 day -1 hour -1 minute');
|
||||
$summary[] = $this->t('Future date: %display', ['%display' => $this->formatTimestamp($future_date)]);
|
||||
$summary[] = $this->t('Past date: %display', ['%display' => $this->formatTimestamp($past_date)]);
|
||||
$future_date = new DrupalDateTime('1 year 1 month 1 week 1 day 1 hour 1 minute');
|
||||
$past_date = new DrupalDateTime('-1 year -1 month -1 week -1 day -1 hour -1 minute');
|
||||
$granularity = $this->getSetting('granularity');
|
||||
$options = [
|
||||
'granularity' => $granularity,
|
||||
'return_as_object' => FALSE,
|
||||
];
|
||||
|
||||
$future_date_interval = new FormattableMarkup($this->getSetting('future_format'), ['@interval' => $this->dateFormatter->formatTimeDiffUntil($future_date->getTimestamp(), $options)]);
|
||||
$past_date_interval = new FormattableMarkup($this->getSetting('past_format'), ['@interval' => $this->dateFormatter->formatTimeDiffSince($past_date->getTimestamp(), $options)]);
|
||||
|
||||
$summary[] = $this->t('Future date: %display', ['%display' => $future_date_interval]);
|
||||
$summary[] = $this->t('Past date: %display', ['%display' => $past_date_interval]);
|
||||
|
||||
return $summary;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ interface ConfirmFormInterface extends FormInterface {
|
||||
/**
|
||||
* Returns the question to ask the user.
|
||||
*
|
||||
* @return string
|
||||
* @return \Drupal\Core\StringTranslation\TranslatableMarkup
|
||||
* The form question. The page title will be set to this value.
|
||||
*/
|
||||
public function getQuestion();
|
||||
@@ -26,7 +26,7 @@ interface ConfirmFormInterface extends FormInterface {
|
||||
/**
|
||||
* Returns additional text to display as a description.
|
||||
*
|
||||
* @return string
|
||||
* @return \Drupal\Core\StringTranslation\TranslatableMarkup
|
||||
* The form description.
|
||||
*/
|
||||
public function getDescription();
|
||||
@@ -34,7 +34,7 @@ interface ConfirmFormInterface extends FormInterface {
|
||||
/**
|
||||
* Returns a caption for the button that confirms the action.
|
||||
*
|
||||
* @return string
|
||||
* @return \Drupal\Core\StringTranslation\TranslatableMarkup
|
||||
* The form confirmation text.
|
||||
*/
|
||||
public function getConfirmText();
|
||||
@@ -42,7 +42,7 @@ interface ConfirmFormInterface extends FormInterface {
|
||||
/**
|
||||
* Returns a caption for the link which cancels the action.
|
||||
*
|
||||
* @return string
|
||||
* @return \Drupal\Core\StringTranslation\TranslatableMarkup
|
||||
* The form cancellation text.
|
||||
*/
|
||||
public function getCancelText();
|
||||
|
||||
@@ -687,7 +687,7 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface, FormS
|
||||
// will be replaced at the very last moment. This ensures forms with
|
||||
// dynamically generated action URLs don't have poor cacheability.
|
||||
// Use the proper API to generate the placeholder, when we have one. See
|
||||
// https://www.drupal.org/node/2562341. The placholder uses a fixed string
|
||||
// https://www.drupal.org/node/2562341. The placeholder uses a fixed string
|
||||
// that is Crypt::hashBase64('Drupal\Core\Form\FormBuilder::prepareForm');
|
||||
$placeholder = 'form_action_p_pvdeGsVG5zNF_XLGPTvYSKCf43t8qZYSwcfZl2uzM';
|
||||
|
||||
|
||||
@@ -87,8 +87,8 @@ class FormState implements FormStateInterface {
|
||||
* copy of the form is immediately built and sent to the browser, instead of a
|
||||
* redirect. This is used for multi-step forms, such as wizards and
|
||||
* confirmation forms. Normally, self::$rebuild is set by a submit handler,
|
||||
* since its is usually logic within a submit handler that determines whether
|
||||
* a form is done or requires another step. However, a validation handler may
|
||||
* since it is usually logic within a submit handler that determines whether a
|
||||
* form is done or requires another step. However, a validation handler may
|
||||
* already set self::$rebuild to cause the form processing to bypass submit
|
||||
* handlers and rebuild the form instead, even if there are no validation
|
||||
* errors.
|
||||
|
||||
@@ -43,7 +43,7 @@ class HandlerStackConfigurator {
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Contructs a new HandlerStackConfigurator object.
|
||||
* Constructs a new HandlerStackConfigurator object.
|
||||
*
|
||||
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
|
||||
* The service container.
|
||||
|
||||
@@ -44,7 +44,7 @@ class TrustedHostsRequestFactory {
|
||||
* @param array $request
|
||||
* (optional) An array of request variables.
|
||||
* @param array $attributes
|
||||
* (optioanl) An array of attributes.
|
||||
* (optional) An array of attributes.
|
||||
* @param array $cookies
|
||||
* (optional) The request cookies ($_COOKIE).
|
||||
* @param array $files
|
||||
|
||||
@@ -19,7 +19,7 @@ class InstallProfileMismatchException extends InstallerException {
|
||||
* @param string $settings_profile
|
||||
* The profile in settings.php.
|
||||
* @param string $settings_file
|
||||
* The path to settigns.php.
|
||||
* The path to settings.php.
|
||||
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
|
||||
* The string translation manager.
|
||||
*
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
namespace Drupal\Core\Mail;
|
||||
|
||||
use Drupal\Component\Render\MarkupInterface;
|
||||
use Drupal\Component\Render\PlainTextOutput;
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
|
||||
use Drupal\Core\Messenger\MessengerTrait;
|
||||
@@ -10,6 +12,7 @@ use Drupal\Core\Plugin\DefaultPluginManager;
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\Render\Markup;
|
||||
use Drupal\Core\Render\RenderContext;
|
||||
use Drupal\Core\Render\RendererInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
@@ -277,6 +280,13 @@ class MailManager extends DefaultPluginManager implements MailManagerInterface {
|
||||
// Retrieve the responsible implementation for this message.
|
||||
$system = $this->getInstance(['module' => $module, 'key' => $key]);
|
||||
|
||||
// Attempt to convert relative URLs to absolute.
|
||||
foreach ($message['body'] as &$body_part) {
|
||||
if ($body_part instanceof MarkupInterface) {
|
||||
$body_part = Markup::create(Html::transformRootRelativeUrlsToAbsolute((string) $body_part, \Drupal::request()->getSchemeAndHttpHost()));
|
||||
}
|
||||
}
|
||||
|
||||
// Format the message body.
|
||||
$message = $system->format($message);
|
||||
|
||||
|
||||
@@ -83,33 +83,36 @@ class LocalActionDefault extends PluginBase implements LocalActionInterface, Con
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRouteParameters(RouteMatchInterface $route_match) {
|
||||
$parameters = isset($this->pluginDefinition['route_parameters']) ? $this->pluginDefinition['route_parameters'] : [];
|
||||
$route_parameters = isset($this->pluginDefinition['route_parameters']) ? $this->pluginDefinition['route_parameters'] : [];
|
||||
$route = $this->routeProvider->getRouteByName($this->getRouteName());
|
||||
$variables = $route->compile()->getVariables();
|
||||
|
||||
// Normally the \Drupal\Core\ParamConverter\ParamConverterManager has
|
||||
// processed the Request attributes, and in that case the _raw_variables
|
||||
// attribute holds the original path strings keyed to the corresponding
|
||||
// slugs in the path patterns. For example, if the route's path pattern is
|
||||
// run, and the route parameters have been upcast. The original values can
|
||||
// be retrieved from the raw parameters. For example, if the route's path is
|
||||
// /filter/tips/{filter_format} and the path is /filter/tips/plain_text then
|
||||
// $raw_variables->get('filter_format') == 'plain_text'.
|
||||
$raw_variables = $route_match->getRawParameters();
|
||||
// $raw_parameters->get('filter_format') == 'plain_text'. Parameters that
|
||||
// are not represented in the route path as slugs might be added by a route
|
||||
// enhancer and will not be present in the raw parameters.
|
||||
$raw_parameters = $route_match->getRawParameters();
|
||||
$parameters = $route_match->getParameters();
|
||||
|
||||
foreach ($variables as $name) {
|
||||
if (isset($parameters[$name])) {
|
||||
if (isset($route_parameters[$name])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($raw_variables && $raw_variables->has($name)) {
|
||||
$parameters[$name] = $raw_variables->get($name);
|
||||
if ($raw_parameters->has($name)) {
|
||||
$route_parameters[$name] = $raw_parameters->get($name);
|
||||
}
|
||||
elseif ($value = $route_match->getRawParameter($name)) {
|
||||
$parameters[$name] = $value;
|
||||
elseif ($parameters->has($name)) {
|
||||
$route_parameters[$name] = $parameters->get($name);
|
||||
}
|
||||
}
|
||||
|
||||
// The UrlGenerator will throw an exception if expected parameters are
|
||||
// missing. This method should be overridden if that is possible.
|
||||
return $parameters;
|
||||
return $route_parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -196,9 +196,10 @@ class LocalActionManager extends DefaultPluginManager implements LocalActionMana
|
||||
}
|
||||
}
|
||||
$links = [];
|
||||
$cacheability = new CacheableMetadata();
|
||||
$cacheability->addCacheContexts(['route']);
|
||||
/** @var $plugin \Drupal\Core\Menu\LocalActionInterface */
|
||||
foreach ($this->instances[$route_appears] as $plugin_id => $plugin) {
|
||||
$cacheability = new CacheableMetadata();
|
||||
$route_name = $plugin->getRouteName();
|
||||
$route_parameters = $plugin->getRouteParameters($this->routeMatch);
|
||||
$access = $this->accessManager->checkNamedRoute($route_name, $route_parameters, $this->account, TRUE);
|
||||
@@ -213,9 +214,8 @@ class LocalActionManager extends DefaultPluginManager implements LocalActionMana
|
||||
'#weight' => $plugin->getWeight(),
|
||||
];
|
||||
$cacheability->addCacheableDependency($access)->addCacheableDependency($plugin);
|
||||
$cacheability->applyTo($links[$plugin_id]);
|
||||
}
|
||||
$links['#cache']['contexts'][] = 'route';
|
||||
$cacheability->applyTo($links);
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
@@ -41,34 +41,36 @@ class LocalTaskDefault extends PluginBase implements LocalTaskInterface, Cacheab
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRouteParameters(RouteMatchInterface $route_match) {
|
||||
$parameters = isset($this->pluginDefinition['route_parameters']) ? $this->pluginDefinition['route_parameters'] : [];
|
||||
$route_parameters = isset($this->pluginDefinition['route_parameters']) ? $this->pluginDefinition['route_parameters'] : [];
|
||||
$route = $this->routeProvider()->getRouteByName($this->getRouteName());
|
||||
$variables = $route->compile()->getVariables();
|
||||
|
||||
// Normally the \Drupal\Core\ParamConverter\ParamConverterManager has
|
||||
// processed the Request attributes, and in that case the _raw_variables
|
||||
// attribute holds the original path strings keyed to the corresponding
|
||||
// slugs in the path patterns. For example, if the route's path pattern is
|
||||
// run, and the route parameters have been upcast. The original values can
|
||||
// be retrieved from the raw parameters. For example, if the route's path is
|
||||
// /filter/tips/{filter_format} and the path is /filter/tips/plain_text then
|
||||
// $raw_variables->get('filter_format') == 'plain_text'.
|
||||
|
||||
$raw_variables = $route_match->getRawParameters();
|
||||
// $raw_parameters->get('filter_format') == 'plain_text'. Parameters that
|
||||
// are not represented in the route path as slugs might be added by a route
|
||||
// enhancer and will not be present in the raw parameters.
|
||||
$raw_parameters = $route_match->getRawParameters();
|
||||
$parameters = $route_match->getParameters();
|
||||
|
||||
foreach ($variables as $name) {
|
||||
if (isset($parameters[$name])) {
|
||||
if (isset($route_parameters[$name])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($raw_variables && $raw_variables->has($name)) {
|
||||
$parameters[$name] = $raw_variables->get($name);
|
||||
if ($raw_parameters->has($name)) {
|
||||
$route_parameters[$name] = $raw_parameters->get($name);
|
||||
}
|
||||
elseif ($value = $route_match->getRawParameter($name)) {
|
||||
$parameters[$name] = $value;
|
||||
elseif ($parameters->has($name)) {
|
||||
$route_parameters[$name] = $parameters->get($name);
|
||||
}
|
||||
}
|
||||
|
||||
// The UrlGenerator will throw an exception if expected parameters are
|
||||
// missing. This method should be overridden if that is possible.
|
||||
return $parameters;
|
||||
return $route_parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -30,7 +30,7 @@ interface MenuLinkTreeInterface {
|
||||
*
|
||||
* Builds menu link tree parameters that:
|
||||
* - Expand all links in the active trail based on route being viewed.
|
||||
* - Expand the descendents of the links in the active trail whose
|
||||
* - Expand the descendants of the links in the active trail whose
|
||||
* 'expanded' flag is enabled.
|
||||
*
|
||||
* This only sets the (relatively complex) parameters to achieve the two above
|
||||
|
||||
@@ -11,7 +11,7 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
*
|
||||
* Do not serve cached pages to authenticated users, or to anonymous users when
|
||||
* $_SESSION is non-empty. $_SESSION may contain status messages from a form
|
||||
* submission, the contents of a shopping cart, or other userspecific content
|
||||
* submission, the contents of a shopping cart, or other user-specific content
|
||||
* that should not be cached and displayed to other users.
|
||||
*/
|
||||
class NoSessionOpen implements RequestPolicyInterface {
|
||||
|
||||
@@ -12,10 +12,17 @@ interface InboundPathProcessorInterface {
|
||||
/**
|
||||
* Processes the inbound path.
|
||||
*
|
||||
* Implementations may make changes to the request object passed in but should
|
||||
* avoid all other side effects. This method can be called to process requests
|
||||
* other than the current request.
|
||||
*
|
||||
* @param string $path
|
||||
* The path to process, with a leading slash.
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The HttpRequest object representing the current request.
|
||||
* The HttpRequest object representing the request to process. Note, if this
|
||||
* method is being called via the path_processor_manager service and is not
|
||||
* part of routing, the current request object must be cloned before being
|
||||
* passed in.
|
||||
*
|
||||
* @return string
|
||||
* The processed path.
|
||||
|
||||
@@ -6,6 +6,7 @@ use Drupal\Component\Plugin\Context\Context as ComponentContext;
|
||||
use Drupal\Component\Plugin\Exception\ContextException;
|
||||
use Drupal\Core\Cache\CacheableDependencyInterface;
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
|
||||
use Drupal\Core\TypedData\TypedDataInterface;
|
||||
use Drupal\Core\TypedData\TypedDataTrait;
|
||||
|
||||
@@ -15,6 +16,7 @@ use Drupal\Core\TypedData\TypedDataTrait;
|
||||
class Context extends ComponentContext implements ContextInterface {
|
||||
|
||||
use TypedDataTrait;
|
||||
use DependencySerializationTrait;
|
||||
|
||||
/**
|
||||
* The data associated with the context.
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Drupal\Core\ProxyBuilder;
|
||||
use Drupal\Component\ProxyBuilder\ProxyBuilder as BaseProxyBuilder;
|
||||
|
||||
/**
|
||||
* Extend the component proxy builder by using the DependencySerialziationTrait.
|
||||
* Extend the component proxy builder by using the DependencySerializationTrait.
|
||||
*/
|
||||
class ProxyBuilder extends BaseProxyBuilder {
|
||||
|
||||
|
||||
@@ -11,12 +11,14 @@ use Drupal\Core\Render\Element;
|
||||
* Properties:
|
||||
* - #default_value: An RFC-compliant email address.
|
||||
* - #size: The size of the input element in characters.
|
||||
* - #pattern: A string for the native HTML5 pattern attribute.
|
||||
*
|
||||
* Example usage:
|
||||
* @code
|
||||
* $form['email'] = array(
|
||||
* '#type' => 'email',
|
||||
* '#title' => $this->t('Email'),
|
||||
* '#pattern' => '*@example.com',
|
||||
* );
|
||||
* @end
|
||||
*
|
||||
|
||||
@@ -10,6 +10,7 @@ use Drupal\Core\Render\Element;
|
||||
*
|
||||
* Properties:
|
||||
* - #size: The size of the input element in characters.
|
||||
* - #pattern: A string for the native HTML5 pattern attribute.
|
||||
*
|
||||
* Usage example:
|
||||
* @code
|
||||
@@ -17,6 +18,7 @@ use Drupal\Core\Render\Element;
|
||||
* '#type' => 'password',
|
||||
* '#title' => $this->t('Password'),
|
||||
* '#size' => 25,
|
||||
* '#pattern' => '[01]+',
|
||||
* );
|
||||
* @endcode
|
||||
*
|
||||
|
||||
@@ -32,7 +32,7 @@ use Drupal\Core\Url;
|
||||
* strings, if they are literals provided by your module, should be
|
||||
* internationalized and translated; see the
|
||||
* @link i18n Internationalization topic @endlink for more information. Note
|
||||
* that although in the properies list that follows, they are designated to be
|
||||
* that although in the properties list that follows, they are designated to be
|
||||
* of type string, they would generally end up being
|
||||
* \Drupal\Core\StringTranslation\TranslatableMarkup objects instead.
|
||||
*
|
||||
|
||||
@@ -12,12 +12,14 @@ use Drupal\Core\Render\Element;
|
||||
*
|
||||
* Properties:
|
||||
* - #size: The size of the input element in characters.
|
||||
* - #pattern: A string for the native HTML5 pattern attribute.
|
||||
*
|
||||
* Usage example:
|
||||
* @code
|
||||
* $form['phone'] = array(
|
||||
* '#type' => 'tel',
|
||||
* '#title' => $this->t('Phone'),
|
||||
* '#pattern' => '[^\d]*',
|
||||
* );
|
||||
* @endcode
|
||||
*
|
||||
|
||||
@@ -15,6 +15,7 @@ use Drupal\Core\Render\Element;
|
||||
* autocomplete JavaScript library.
|
||||
* - #autocomplete_route_parameters: An array of parameters to be used in
|
||||
* conjunction with the route name.
|
||||
* - #pattern: A string for the native HTML5 pattern attribute.
|
||||
*
|
||||
* Usage example:
|
||||
* @code
|
||||
@@ -24,7 +25,8 @@ use Drupal\Core\Render\Element;
|
||||
* '#default_value' => $node->title,
|
||||
* '#size' => 60,
|
||||
* '#maxlength' => 128,
|
||||
* '#required' => TRUE,
|
||||
* '#pattern' => 'some-prefix-[a-z]+',
|
||||
* '#required' => TRUE,
|
||||
* );
|
||||
* @endcode
|
||||
*
|
||||
|
||||
@@ -12,6 +12,7 @@ use Drupal\Core\Render\Element;
|
||||
* Properties:
|
||||
* - #default_value: A valid URL string.
|
||||
* - #size: The size of the input element in characters.
|
||||
* - #pattern: A string for the native HTML5 pattern attribute.
|
||||
*
|
||||
* Usage example:
|
||||
* @code
|
||||
@@ -19,6 +20,7 @@ use Drupal\Core\Render\Element;
|
||||
* '#type' => 'url',
|
||||
* '#title' => $this->t('Home Page'),
|
||||
* '#size' => 30,
|
||||
* '#pattern' => '*.example.com',
|
||||
* ...
|
||||
* );
|
||||
* @endcode
|
||||
|
||||
@@ -106,7 +106,7 @@ class SessionConfiguration implements SessionConfigurationInterface {
|
||||
* Return the session cookie domain.
|
||||
*
|
||||
* The Set-Cookie response header and its domain attribute are defined in RFC
|
||||
* 2109, RFC 2965 and RFC 6265 each one superseeding the previous version.
|
||||
* 2109, RFC 2965 and RFC 6265 each one superseding the previous version.
|
||||
*
|
||||
* @see http://tools.ietf.org/html/rfc2109
|
||||
* @see http://tools.ietf.org/html/rfc2965
|
||||
|
||||
@@ -14,8 +14,7 @@ interface WriteSafeSessionHandlerInterface {
|
||||
* only capable of forcibly disabling that session data is written to storage.
|
||||
*
|
||||
* @param bool $flag
|
||||
* TRUE if the session the session is allowed to be written, FALSE
|
||||
* otherwise.
|
||||
* TRUE if the session is allowed to be written, FALSE otherwise.
|
||||
*/
|
||||
public function setSessionWritable($flag);
|
||||
|
||||
@@ -23,8 +22,7 @@ interface WriteSafeSessionHandlerInterface {
|
||||
* Returns whether or not a session may be written to storage.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the session the session is allowed to be written, FALSE
|
||||
* otherwise.
|
||||
* TRUE if the session is allowed to be written, FALSE otherwise.
|
||||
*/
|
||||
public function isSessionWritable();
|
||||
|
||||
|
||||
@@ -2,15 +2,12 @@
|
||||
|
||||
namespace Drupal\Core\State;
|
||||
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Cache\CacheCollector;
|
||||
use Drupal\Core\KeyValueStore\KeyValueFactoryInterface;
|
||||
use Drupal\Core\Lock\LockBackendInterface;
|
||||
|
||||
/**
|
||||
* Provides the state system using a key value store.
|
||||
*/
|
||||
class State extends CacheCollector implements StateInterface {
|
||||
class State implements StateInterface {
|
||||
|
||||
/**
|
||||
* The key value store to use.
|
||||
@@ -19,18 +16,20 @@ class State extends CacheCollector implements StateInterface {
|
||||
*/
|
||||
protected $keyValueStore;
|
||||
|
||||
/**
|
||||
* Static state cache.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $cache = [];
|
||||
|
||||
/**
|
||||
* Constructs a State object.
|
||||
*
|
||||
* @param \Drupal\Core\KeyValueStore\KeyValueFactoryInterface $key_value_factory
|
||||
* The key value store to use.
|
||||
* @param \Drupal\Core\Cache\CacheBackendInterface $cache
|
||||
* The cache backend.
|
||||
* @param \Drupal\Core\Lock\LockBackendInterface $lock
|
||||
* The lock backend.
|
||||
*/
|
||||
public function __construct(KeyValueFactoryInterface $key_value_factory, CacheBackendInterface $cache, LockBackendInterface $lock) {
|
||||
parent::__construct('state', $cache, $lock);
|
||||
public function __construct(KeyValueFactoryInterface $key_value_factory) {
|
||||
$this->keyValueStore = $key_value_factory->get('state');
|
||||
}
|
||||
|
||||
@@ -38,18 +37,8 @@ class State extends CacheCollector implements StateInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get($key, $default = NULL) {
|
||||
$value = parent::get($key);
|
||||
return $value !== NULL ? $value : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function resolveCacheMiss($key) {
|
||||
$value = $this->keyValueStore->get($key);
|
||||
$this->storage[$key] = $value;
|
||||
$this->persist($key);
|
||||
return $value;
|
||||
$values = $this->getMultiple([$key]);
|
||||
return isset($values[$key]) ? $values[$key] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,9 +46,33 @@ class State extends CacheCollector implements StateInterface {
|
||||
*/
|
||||
public function getMultiple(array $keys) {
|
||||
$values = [];
|
||||
$load = [];
|
||||
foreach ($keys as $key) {
|
||||
$values[$key] = $this->get($key);
|
||||
// Check if we have a value in the cache.
|
||||
if (isset($this->cache[$key])) {
|
||||
$values[$key] = $this->cache[$key];
|
||||
}
|
||||
// Load the value if we don't have an explicit NULL value.
|
||||
elseif (!array_key_exists($key, $this->cache)) {
|
||||
$load[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
if ($load) {
|
||||
$loaded_values = $this->keyValueStore->getMultiple($load);
|
||||
foreach ($load as $key) {
|
||||
// If we find a value, even one that is NULL, add it to the cache and
|
||||
// return it.
|
||||
if (isset($loaded_values[$key]) || array_key_exists($key, $loaded_values)) {
|
||||
$values[$key] = $loaded_values[$key];
|
||||
$this->cache[$key] = $loaded_values[$key];
|
||||
}
|
||||
else {
|
||||
$this->cache[$key] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
@@ -67,7 +80,7 @@ class State extends CacheCollector implements StateInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function set($key, $value) {
|
||||
parent::set($key, $value);
|
||||
$this->cache[$key] = $value;
|
||||
$this->keyValueStore->set($key, $value);
|
||||
}
|
||||
|
||||
@@ -76,7 +89,7 @@ class State extends CacheCollector implements StateInterface {
|
||||
*/
|
||||
public function setMultiple(array $data) {
|
||||
foreach ($data as $key => $value) {
|
||||
parent::set($key, $value);
|
||||
$this->cache[$key] = $value;
|
||||
}
|
||||
$this->keyValueStore->setMultiple($data);
|
||||
}
|
||||
@@ -85,8 +98,7 @@ class State extends CacheCollector implements StateInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function delete($key) {
|
||||
parent::delete($key);
|
||||
$this->keyValueStore->delete($key);
|
||||
$this->deleteMultiple([$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,7 +106,7 @@ class State extends CacheCollector implements StateInterface {
|
||||
*/
|
||||
public function deleteMultiple(array $keys) {
|
||||
foreach ($keys as $key) {
|
||||
parent::delete($key);
|
||||
unset($this->cache[$key]);
|
||||
}
|
||||
$this->keyValueStore->deleteMultiple($keys);
|
||||
}
|
||||
@@ -103,7 +115,7 @@ class State extends CacheCollector implements StateInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resetCache() {
|
||||
$this->clear();
|
||||
$this->cache = [];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ interface StreamWrapperInterface extends PhpStreamWrapperInterface {
|
||||
const READ_VISIBLE = 0x0014;
|
||||
|
||||
/**
|
||||
* This is the default 'type' falg. This does not include
|
||||
* This is the default 'type' flag. This does not include
|
||||
* StreamWrapperInterface::LOCAL, because PHP grants a greater trust level to
|
||||
* local files (for example, they can be used in an "include" statement,
|
||||
* regardless of the "allow_url_include" setting), so stream wrappers need to
|
||||
|
||||
@@ -123,6 +123,7 @@ class PrivateTempStore {
|
||||
if ($this->currentUser->isAnonymous()) {
|
||||
// @todo when https://www.drupal.org/node/2865991 is resolved, use force
|
||||
// start session API rather than setting an arbitrary value directly.
|
||||
$this->startSession();
|
||||
$this->requestStack
|
||||
->getCurrentRequest()
|
||||
->getSession()
|
||||
@@ -219,7 +220,34 @@ class PrivateTempStore {
|
||||
* The owner.
|
||||
*/
|
||||
protected function getOwner() {
|
||||
return $this->currentUser->id() ?: $this->requestStack->getCurrentRequest()->getSession()->getId();
|
||||
$owner = $this->currentUser->id();
|
||||
if ($this->currentUser->isAnonymous()) {
|
||||
$this->startSession();
|
||||
$owner = $this->requestStack->getCurrentRequest()->getSession()->getId();
|
||||
}
|
||||
return $owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start session because it is required for a private temp store.
|
||||
*
|
||||
* Ensures that an anonymous user has a session created for them, as
|
||||
* otherwise subsequent page loads will not be able to retrieve their
|
||||
* tempstore data.
|
||||
*
|
||||
* @todo when https://www.drupal.org/node/2865991 is resolved, use force
|
||||
* start session API.
|
||||
*/
|
||||
protected function startSession() {
|
||||
$has_session = $this->requestStack
|
||||
->getCurrentRequest()
|
||||
->hasSession();
|
||||
if (!$has_session) {
|
||||
/** @var \Symfony\Component\HttpFoundation\Session\SessionInterface $session */
|
||||
$session = \Drupal::service('session');
|
||||
$this->requestStack->getCurrentRequest()->setSession($session);
|
||||
$session->start();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ class TypedDataManager extends DefaultPluginManager implements TypedDataManagerI
|
||||
throw new \InvalidArgumentException("Property $property_name is unknown.");
|
||||
}
|
||||
// Create the prototype without any value, but with initial parenting
|
||||
// so that constructors can set up the objects correclty.
|
||||
// so that constructors can set up the objects correctly.
|
||||
$this->prototypes[$key] = $this->create($definition, NULL, $property_name, $object);
|
||||
}
|
||||
|
||||
|
||||
@@ -197,7 +197,7 @@ class UpdateRegistry {
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers that update fucntions got executed.
|
||||
* Registers that update functions were executed.
|
||||
*
|
||||
* @param string[] $function_names
|
||||
* The executed update functions.
|
||||
|
||||
@@ -105,7 +105,7 @@ class Module extends Updater implements UpdaterInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function postInstallTasks() {
|
||||
// Since this is being called outsite of the primary front controller,
|
||||
// Since this is being called outside of the primary front controller,
|
||||
// the base_url needs to be set explicitly to ensure that links are
|
||||
// relative to the site root.
|
||||
// @todo Simplify with https://www.drupal.org/node/2548095
|
||||
|
||||
@@ -87,7 +87,7 @@ class Theme extends Updater implements UpdaterInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function postInstallTasks() {
|
||||
// Since this is being called outsite of the primary front controller,
|
||||
// Since this is being called outside of the primary front controller,
|
||||
// the base_url needs to be set explicitly to ensure that links are
|
||||
// relative to the site root.
|
||||
// @todo Simplify with https://www.drupal.org/node/2548095
|
||||
|
||||
@@ -78,7 +78,6 @@ class UnroutedUrlAssembler implements UnroutedUrlAssemblerInterface {
|
||||
$options += ['query' => []];
|
||||
|
||||
$options['query'] = NestedArray::mergeDeep($parsed['query'], $options['query']);
|
||||
ksort($options['query']);
|
||||
|
||||
if ($parsed['fragment'] && !$options['fragment']) {
|
||||
$options['fragment'] = '#' . $parsed['fragment'];
|
||||
|
||||
Reference in New Issue
Block a user