updated core to 8.6.3

This commit is contained in:
2018-11-21 12:49:46 +01:00
parent 8ca34853a3
commit c92c348eee
521 changed files with 12199 additions and 4578 deletions
@@ -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);
}
+3 -3
View File
@@ -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
*/
+1 -3
View File
@@ -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();
+6 -2
View File
@@ -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');
}
+6 -2
View File
@@ -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();
+1 -1
View File
@@ -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';
+2 -2
View File
@@ -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.
*
+10
View File
@@ -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;
}
+15 -13
View File
@@ -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();
+41 -29
View File
@@ -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.
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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'];