Update to Drupal 8.1.5. For more information, see https://www.drupal.org/project/drupal/releases/8.1.5
This commit is contained in:
parent
13b6ca7cc2
commit
38ba7c357d
342 changed files with 7814 additions and 1534 deletions
|
@ -49,7 +49,7 @@ class Plugin implements AnnotationInterface {
|
|||
* The annotation array.
|
||||
*
|
||||
* @return array
|
||||
* The parsed annotation as a definition.
|
||||
* The parsed annotation as a definition.
|
||||
*/
|
||||
protected function parse(array $values) {
|
||||
$definitions = array();
|
||||
|
|
|
@ -455,7 +455,7 @@ class DateTimePlus {
|
|||
/**
|
||||
* Detects if there were errors in the processing of this date.
|
||||
*
|
||||
* @return boolean
|
||||
* @return bool
|
||||
* TRUE if there were errors in the processing of this date, FALSE
|
||||
* otherwise.
|
||||
*/
|
||||
|
|
|
@ -373,7 +373,7 @@ class Container implements IntrospectableContainerInterface, ResettableContainer
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function has($id) {
|
||||
return isset($this->services[$id]) || isset($this->serviceDefinitions[$id]);
|
||||
return isset($this->aliases[$id]) || isset($this->services[$id]) || isset($this->serviceDefinitions[$id]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -60,6 +60,7 @@ class OptimizedPhpArrayDumper extends Dumper {
|
|||
*/
|
||||
public function getArray() {
|
||||
$definition = array();
|
||||
$this->aliases = $this->getAliases();
|
||||
$definition['aliases'] = $this->getAliases();
|
||||
$definition['parameters'] = $this->getParameters();
|
||||
$definition['services'] = $this->getServiceDefinitions();
|
||||
|
@ -454,6 +455,9 @@ class OptimizedPhpArrayDumper extends Dumper {
|
|||
}
|
||||
|
||||
// Private shared service.
|
||||
if (isset($this->aliases[$id])) {
|
||||
$id = $this->aliases[$id];
|
||||
}
|
||||
$definition = $this->container->getDefinition($id);
|
||||
if (!$definition->isPublic()) {
|
||||
// The ContainerBuilder does not share a private service, but this means a
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
},
|
||||
"require": {
|
||||
"php": ">=5.5.9",
|
||||
"symfony/dependency-injection": "2.7.*",
|
||||
"symfony/expression-language": "2.7.*"
|
||||
"symfony/dependency-injection": "~2.8",
|
||||
"symfony/expression-language": "~2.7"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
"license": "GPL-2.0+",
|
||||
"require": {
|
||||
"php": ">=5.5.9",
|
||||
"symfony/dependency-injection": "2.7.*",
|
||||
"symfony/event-dispatcher": "2.7.*"
|
||||
"symfony/dependency-injection": "~2.8",
|
||||
"symfony/event-dispatcher": "~2.7"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"license": "GPL-2.0+",
|
||||
"require": {
|
||||
"php": ">=5.5.9",
|
||||
"symfony/http-foundation": "2.7.*"
|
||||
"symfony/http-foundation": "~2.7"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
|
@ -30,8 +30,8 @@ trait DiscoveryTrait {
|
|||
* @param string $plugin_id
|
||||
* A plugin id.
|
||||
* @param bool $exception_on_invalid
|
||||
* (optional) If TRUE, an invalid plugin ID will throw an exception.
|
||||
* Defaults to FALSE.
|
||||
* If TRUE, an invalid plugin ID will cause an exception to be thrown; if
|
||||
* FALSE, NULL will be returned.
|
||||
*
|
||||
* @return array|null
|
||||
* A plugin definition, or NULL if the plugin ID is invalid and
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"license": "GPL-2.0+",
|
||||
"require": {
|
||||
"php": ">=5.5.9",
|
||||
"symfony/validator": "2.7.*"
|
||||
"symfony/validator": "~2.7"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace Drupal\Component\Render;
|
|||
*
|
||||
* Output strategies assist in transforming HTML strings into strings that are
|
||||
* appropriate for a given context (e.g. plain-text), through performing the
|
||||
* relevant formatting. No santization is applied.
|
||||
* relevant formatting. No sanitization is applied.
|
||||
*/
|
||||
interface OutputStrategyInterface {
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"license": "GPL-2.0+",
|
||||
"require": {
|
||||
"php": ">=5.5.9",
|
||||
"symfony/yaml": "2.7.*"
|
||||
"symfony/yaml": "~2.7"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
|
@ -149,7 +149,7 @@ class Cache {
|
|||
* Gets all cache bin services.
|
||||
*
|
||||
* @return array
|
||||
* An array of cache backend objects keyed by cache bins.
|
||||
* An array of cache backend objects keyed by cache bins.
|
||||
*/
|
||||
public static function getBins() {
|
||||
$bins = array();
|
||||
|
|
|
@ -37,7 +37,7 @@ interface CacheableDependencyInterface {
|
|||
* When this object is modified, these cache tags will be invalidated.
|
||||
*
|
||||
* @return string[]
|
||||
* A set of cache tags.
|
||||
* A set of cache tags.
|
||||
*/
|
||||
public function getCacheTags();
|
||||
|
||||
|
|
|
@ -87,8 +87,16 @@ class ChainedFastBackend implements CacheBackendInterface, CacheTagsInvalidatorI
|
|||
* The fast cache backend.
|
||||
* @param string $bin
|
||||
* The cache bin for which the object is created.
|
||||
*
|
||||
* @throws \Exception
|
||||
* When the consistent cache backend and the fast cache backend are the same
|
||||
* service.
|
||||
*/
|
||||
public function __construct(CacheBackendInterface $consistent_backend, CacheBackendInterface $fast_backend, $bin) {
|
||||
if ($consistent_backend == $fast_backend) {
|
||||
// @todo: should throw a proper exception. See https://www.drupal.org/node/2751847.
|
||||
trigger_error('Consistent cache backend and fast cache backend cannot use the same service.', E_USER_ERROR);
|
||||
}
|
||||
$this->consistentBackend = $consistent_backend;
|
||||
$this->fastBackend = $fast_backend;
|
||||
$this->bin = 'cache_' . $bin;
|
||||
|
|
|
@ -25,20 +25,22 @@ class QueryArgsCacheContext extends RequestStackCacheContextBase implements Calc
|
|||
*/
|
||||
public function getContext($query_arg = NULL) {
|
||||
if ($query_arg === NULL) {
|
||||
return $this->requestStack->getCurrentRequest()->getQueryString();
|
||||
// All arguments requested. Use normalized query string to minimize
|
||||
// variations.
|
||||
$value = $this->requestStack->getCurrentRequest()->getQueryString();
|
||||
return ($value !== NULL) ? $value : '';
|
||||
}
|
||||
elseif ($this->requestStack->getCurrentRequest()->query->has($query_arg)) {
|
||||
$value = $this->requestStack->getCurrentRequest()->query->get($query_arg);
|
||||
if ($value !== '') {
|
||||
if (is_array($value)) {
|
||||
return http_build_query($value);
|
||||
}
|
||||
elseif ($value !== '') {
|
||||
return $value;
|
||||
}
|
||||
else {
|
||||
return '?valueless?';
|
||||
}
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
return '?valueless?';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -307,8 +307,9 @@ class ConfigManager implements ConfigManagerInterface {
|
|||
|
||||
// Try to fix any dependencies and find out what will happen to the
|
||||
// dependency graph. Entities are processed in the order of most dependent
|
||||
// first. For example, this ensures that fields are removed before
|
||||
// field storages.
|
||||
// first. For example, this ensures that Menu UI third party dependencies on
|
||||
// node types are fixed before processing the node type's other
|
||||
// dependencies.
|
||||
while ($dependent = array_pop($dependents)) {
|
||||
/** @var \Drupal\Core\Config\Entity\ConfigEntityInterface $dependent */
|
||||
if ($dry_run) {
|
||||
|
@ -346,7 +347,9 @@ class ConfigManager implements ConfigManagerInterface {
|
|||
// If the entity cannot be fixed then it has to be deleted.
|
||||
if (!$fixed) {
|
||||
$delete_uuids[] = $dependent->uuid();
|
||||
$return['delete'][] = $dependent;
|
||||
// Deletes should occur in the order of the least dependent first. For
|
||||
// example, this ensures that fields are removed before field storages.
|
||||
array_unshift($return['delete'], $dependent);
|
||||
}
|
||||
}
|
||||
// Use the lists of UUIDs to filter the original list to work out which
|
||||
|
|
|
@ -173,7 +173,9 @@ class ConfigDependencyManager {
|
|||
// dependent is at the top. For example, this ensures that fields are
|
||||
// always after field storages. This is because field storages need to be
|
||||
// created before a field.
|
||||
return array_reverse(array_intersect_key($this->graph, $dependencies));
|
||||
$graph = $this->getGraph();
|
||||
uasort($graph, array($this, 'sortGraph'));
|
||||
return array_replace(array_intersect_key($graph, $dependencies), $dependencies);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -185,10 +187,32 @@ class ConfigDependencyManager {
|
|||
*/
|
||||
public function sortAll() {
|
||||
$graph = $this->getGraph();
|
||||
// Sort by reverse weight and alphabetically. The most dependent entities
|
||||
// Sort by weight and alphabetically. The most dependent entities
|
||||
// are last and entities with the same weight are alphabetically ordered.
|
||||
uasort($graph, array($this, 'sortGraph'));
|
||||
return array_keys($graph);
|
||||
uasort($graph, array($this, 'sortGraphByWeight'));
|
||||
// Use array_intersect_key() to exclude modules and themes from the list.
|
||||
return array_keys(array_intersect_key($graph, $this->data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the dependency graph by weight and alphabetically.
|
||||
*
|
||||
* @param array $a
|
||||
* First item for comparison. The compared items should be associative
|
||||
* arrays that include a 'weight' and a 'name' key.
|
||||
* @param array $b
|
||||
* Second item for comparison.
|
||||
*
|
||||
* @return int
|
||||
* The comparison result for uasort().
|
||||
*/
|
||||
protected function sortGraphByWeight(array $a, array $b) {
|
||||
$weight_cmp = SortArray::sortByKeyInt($a, $b, 'weight');
|
||||
|
||||
if ($weight_cmp === 0) {
|
||||
return SortArray::sortByKeyString($a, $b, 'name');
|
||||
}
|
||||
return $weight_cmp;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -196,7 +220,7 @@ class ConfigDependencyManager {
|
|||
*
|
||||
* @param array $a
|
||||
* First item for comparison. The compared items should be associative
|
||||
* arrays that include a 'weight' and a 'component' key.
|
||||
* arrays that include a 'weight' and a 'name' key.
|
||||
* @param array $b
|
||||
* Second item for comparison.
|
||||
*
|
||||
|
@ -207,7 +231,7 @@ class ConfigDependencyManager {
|
|||
$weight_cmp = SortArray::sortByKeyInt($a, $b, 'weight') * -1;
|
||||
|
||||
if ($weight_cmp === 0) {
|
||||
return SortArray::sortByKeyString($a, $b, 'component');
|
||||
return SortArray::sortByKeyString($a, $b, 'name');
|
||||
}
|
||||
return $weight_cmp;
|
||||
}
|
||||
|
@ -228,9 +252,11 @@ class ConfigDependencyManager {
|
|||
$graph = $this->getGraph();
|
||||
|
||||
foreach ($entities_to_check as $entity) {
|
||||
if (isset($graph[$entity]) && !empty($graph[$entity]['reverse_paths'])) {
|
||||
foreach ($graph[$entity]['reverse_paths'] as $dependency => $value) {
|
||||
$dependent_entities[$dependency] = $this->data[$dependency];
|
||||
if (isset($graph[$entity]) && !empty($graph[$entity]['paths'])) {
|
||||
foreach ($graph[$entity]['paths'] as $dependency => $value) {
|
||||
if (isset($this->data[$dependency])) {
|
||||
$dependent_entities[$dependency] = $this->data[$dependency];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -248,14 +274,21 @@ class ConfigDependencyManager {
|
|||
$graph = array();
|
||||
foreach ($this->data as $entity) {
|
||||
$graph_key = $entity->getConfigDependencyName();
|
||||
$graph[$graph_key]['edges'] = array();
|
||||
$dependencies = $entity->getDependencies('config');
|
||||
if (!empty($dependencies)) {
|
||||
foreach ($dependencies as $dependency) {
|
||||
$graph[$graph_key]['edges'][$dependency] = TRUE;
|
||||
}
|
||||
if (!isset($graph[$graph_key])) {
|
||||
$graph[$graph_key] = [
|
||||
'edges' => [],
|
||||
'name' => $graph_key,
|
||||
];
|
||||
}
|
||||
// Include all dependencies in the graph so that topographical sorting
|
||||
// works.
|
||||
foreach (array_merge($entity->getDependencies('config'), $entity->getDependencies('module'), $entity->getDependencies('theme')) as $dependency) {
|
||||
$graph[$dependency]['edges'][$graph_key] = TRUE;
|
||||
$graph[$dependency]['name'] = $dependency;
|
||||
}
|
||||
}
|
||||
// Ensure that order of the graph is consistent.
|
||||
krsort($graph);
|
||||
$graph_object = new Graph($graph);
|
||||
$this->graph = $graph_object->searchAndSort();
|
||||
}
|
||||
|
|
|
@ -93,28 +93,28 @@ interface StorageInterface {
|
|||
/**
|
||||
* Encodes configuration data into the storage-specific format.
|
||||
*
|
||||
* This is a publicly accessible static method to allow for alternative
|
||||
* usages in data conversion scripts and also tests.
|
||||
*
|
||||
* @param array $data
|
||||
* The configuration data to encode.
|
||||
*
|
||||
* @return string
|
||||
* The encoded configuration data.
|
||||
*
|
||||
* This is a publicly accessible static method to allow for alternative
|
||||
* usages in data conversion scripts and also tests.
|
||||
*/
|
||||
public function encode($data);
|
||||
|
||||
/**
|
||||
* Decodes configuration data from the storage-specific format.
|
||||
*
|
||||
* This is a publicly accessible static method to allow for alternative
|
||||
* usages in data conversion scripts and also tests.
|
||||
*
|
||||
* @param string $raw
|
||||
* The raw configuration data string to decode.
|
||||
*
|
||||
* @return array
|
||||
* The decoded configuration data as an associative array.
|
||||
*
|
||||
* This is a publicly accessible static method to allow for alternative
|
||||
* usages in data conversion scripts and also tests.
|
||||
*/
|
||||
public function decode($raw);
|
||||
|
||||
|
|
|
@ -753,14 +753,11 @@ abstract class Connection {
|
|||
*/
|
||||
public function getDriverClass($class) {
|
||||
if (empty($this->driverClasses[$class])) {
|
||||
$driver = $this->driver();
|
||||
if (!empty($this->connectionOptions['namespace'])) {
|
||||
$driver_class = $this->connectionOptions['namespace'] . '\\' . $class;
|
||||
}
|
||||
else {
|
||||
// Fallback for Drupal 7 settings.php.
|
||||
$driver_class = "Drupal\\Core\\Database\\Driver\\{$driver}\\{$class}";
|
||||
if (empty($this->connectionOptions['namespace'])) {
|
||||
// Fallback for Drupal 7 settings.php and the test runner script.
|
||||
$this->connectionOptions['namespace'] = (new \ReflectionObject($this))->getNamespaceName();
|
||||
}
|
||||
$driver_class = $this->connectionOptions['namespace'] . '\\' . $class;
|
||||
$this->driverClasses[$class] = class_exists($driver_class) ? $driver_class : $class;
|
||||
}
|
||||
return $this->driverClasses[$class];
|
||||
|
|
|
@ -246,6 +246,9 @@ class Tasks extends InstallTasks {
|
|||
// concurrency issues, when both try to update at the same time.
|
||||
try {
|
||||
$connection = Database::getConnection();
|
||||
// When testing, two installs might try to run the CREATE FUNCTION queries
|
||||
// at the same time. Do not let that happen.
|
||||
$connection->query('SELECT pg_advisory_lock(1)');
|
||||
// Don't use {} around pg_proc table.
|
||||
if (!$connection->query("SELECT COUNT(*) FROM pg_proc WHERE proname = 'rand'")->fetchField()) {
|
||||
$connection->query('CREATE OR REPLACE FUNCTION "rand"() RETURNS float AS
|
||||
|
@ -264,6 +267,7 @@ class Tasks extends InstallTasks {
|
|||
[ 'allow_delimiter_in_query' => TRUE ]
|
||||
);
|
||||
}
|
||||
$connection->query('SELECT pg_advisory_unlock(1)');
|
||||
|
||||
$this->pass(t('PostgreSQL has initialized itself.'));
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ class Tasks extends InstallTasks {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function minimumVersion() {
|
||||
return '3.6.8';
|
||||
return '3.7.11';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -420,8 +420,12 @@ class Schema extends DatabaseSchema {
|
|||
*
|
||||
* @param $table
|
||||
* Name of the table.
|
||||
*
|
||||
* @return
|
||||
* An array representing the schema, from drupal_get_schema().
|
||||
*
|
||||
* @throws \Exception
|
||||
* If a column of the table could not be parsed.
|
||||
*/
|
||||
protected function introspectSchema($table) {
|
||||
$mapped_fields = array_flip($this->getFieldTypeMap());
|
||||
|
@ -459,7 +463,7 @@ class Schema extends DatabaseSchema {
|
|||
}
|
||||
}
|
||||
else {
|
||||
new \Exception("Unable to parse the column type " . $row->type);
|
||||
throw new \Exception("Unable to parse the column type " . $row->type);
|
||||
}
|
||||
}
|
||||
$indexes = array();
|
||||
|
@ -710,7 +714,7 @@ class Schema extends DatabaseSchema {
|
|||
// Can't use query placeholders for the schema because the query would
|
||||
// have to be :prefixsqlite_master, which does not work. We also need to
|
||||
// ignore the internal SQLite tables.
|
||||
$result = db_query("SELECT name FROM " . $schema . ".sqlite_master WHERE type = :type AND name LIKE :table_name AND name NOT LIKE :pattern", array(
|
||||
$result = $this->connection->query("SELECT name FROM " . $schema . ".sqlite_master WHERE type = :type AND name LIKE :table_name AND name NOT LIKE :pattern", array(
|
||||
':type' => 'table',
|
||||
':table_name' => $table_expression,
|
||||
':pattern' => 'sqlite_%',
|
||||
|
|
|
@ -6,11 +6,11 @@ namespace Drupal\Core\Database\Query;
|
|||
* Interface for extendable query objects.
|
||||
*
|
||||
* "Extenders" follow the "Decorator" OOP design pattern. That is, they wrap
|
||||
* and "decorate" another object. In our case, they implement the same interface
|
||||
* as select queries and wrap a select query, to which they delegate almost all
|
||||
* operations. Subclasses of this class may implement additional methods or
|
||||
* override existing methods as appropriate. Extenders may also wrap other
|
||||
* extender objects, allowing for arbitrarily complex "enhanced" queries.
|
||||
* and "decorate" another object. In our case, they implement the same
|
||||
* interface as select queries and wrap a select query, to which they delegate
|
||||
* almost all operations. Subclasses of this class may implement additional
|
||||
* methods or override existing methods as appropriate. Extenders may also wrap
|
||||
* other extender objects, allowing for arbitrarily complex "enhanced" queries.
|
||||
*/
|
||||
interface ExtendableInterface {
|
||||
|
||||
|
@ -18,9 +18,12 @@ interface ExtendableInterface {
|
|||
* Enhance this object by wrapping it in an extender object.
|
||||
*
|
||||
* @param $extender_name
|
||||
* The base name of the extending class. The base name will be checked
|
||||
* against the current database connection to allow driver-specific subclasses
|
||||
* as well, using the same logic as the query objects themselves.
|
||||
* The fully-qualified name of the extender class, without the leading '\'
|
||||
* (for example, Drupal\my_module\myExtenderClass). The extender name will
|
||||
* be checked against the current database connection to allow
|
||||
* driver-specific subclasses as well, using the same logic as the query
|
||||
* objects themselves.
|
||||
*
|
||||
* @return \Drupal\Core\Database\Query\ExtendableInterface
|
||||
* The extender object, which now contains a reference to this object.
|
||||
*/
|
||||
|
|
|
@ -39,7 +39,7 @@ class Select extends Query implements SelectInterface {
|
|||
* 'type' => $join_type (one of INNER, LEFT OUTER, RIGHT OUTER),
|
||||
* 'table' => $table,
|
||||
* 'alias' => $alias_of_the_table,
|
||||
* 'condition' => $condition_clause_on_which_to_join,
|
||||
* 'condition' => $join_condition (string or Condition object),
|
||||
* 'arguments' => $array_of_arguments_for_placeholders_in_the condition.
|
||||
* 'all_fields' => TRUE to SELECT $alias.*, FALSE or NULL otherwise.
|
||||
* )
|
||||
|
@ -47,6 +47,10 @@ class Select extends Query implements SelectInterface {
|
|||
* If $table is a string, it is taken as the name of a table. If it is
|
||||
* a Select query object, it is taken as a subquery.
|
||||
*
|
||||
* If $join_condition is a Condition object, any arguments should be
|
||||
* incorporated into the object; a separate array of arguments does not
|
||||
* need to be provided.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $tables = array();
|
||||
|
@ -196,6 +200,10 @@ class Select extends Query implements SelectInterface {
|
|||
if ($table['table'] instanceof SelectInterface) {
|
||||
$args += $table['table']->arguments();
|
||||
}
|
||||
// If the join condition is an object, grab its arguments recursively.
|
||||
if (!empty($table['condition']) && $table['condition'] instanceof ConditionInterface) {
|
||||
$args += $table['condition']->arguments();
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->expressions as $expression) {
|
||||
|
@ -225,6 +233,10 @@ class Select extends Query implements SelectInterface {
|
|||
if ($table['table'] instanceof SelectInterface) {
|
||||
$table['table']->compile($connection, $queryPlaceholder);
|
||||
}
|
||||
// Make sure join conditions are also compiled.
|
||||
if (!empty($table['condition']) && $table['condition'] instanceof ConditionInterface) {
|
||||
$table['condition']->compile($connection, $queryPlaceholder);
|
||||
}
|
||||
}
|
||||
|
||||
// If there are any dependent queries to UNION, compile it recursively.
|
||||
|
@ -248,6 +260,11 @@ class Select extends Query implements SelectInterface {
|
|||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (!empty($table['condition']) && $table['condition'] instanceof ConditionInterface) {
|
||||
if (!$table['condition']->compiled()) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->union as $union) {
|
||||
|
@ -822,7 +839,7 @@ class Select extends Query implements SelectInterface {
|
|||
$query .= $table_string . ' ' . $this->connection->escapeTable($table['alias']);
|
||||
|
||||
if (!empty($table['condition'])) {
|
||||
$query .= ' ON ' . $table['condition'];
|
||||
$query .= ' ON ' . (string) $table['condition'];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -268,6 +268,7 @@ class Datelist extends DateElementBase {
|
|||
'#options' => $options,
|
||||
'#required' => $element['#required'],
|
||||
'#error_no_message' => FALSE,
|
||||
'#empty_option' => $title,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -58,8 +58,6 @@ class YamlFileLoader
|
|||
public function load($file)
|
||||
{
|
||||
// Load from the file cache, fall back to loading the file.
|
||||
// @todo Refactor this to cache parsed definition objects in
|
||||
// https://www.drupal.org/node/2464053
|
||||
$content = $this->fileCache->get($file);
|
||||
if (!$content) {
|
||||
$content = $this->loadFile($file);
|
||||
|
|
|
@ -306,7 +306,7 @@ abstract class Entity implements EntityInterface {
|
|||
// The entity ID is needed as a route parameter.
|
||||
$uri_route_parameters[$this->getEntityTypeId()] = $this->id();
|
||||
}
|
||||
if ($rel === 'revision') {
|
||||
if ($rel === 'revision' && $this instanceof RevisionableInterface) {
|
||||
$uri_route_parameters[$this->getEntityTypeId() . '_revision'] = $this->getRevisionId();
|
||||
}
|
||||
|
||||
|
|
|
@ -339,10 +339,17 @@ interface EntityInterface extends AccessibleInterface, CacheableDependencyInterf
|
|||
public static function preCreate(EntityStorageInterface $storage, array &$values);
|
||||
|
||||
/**
|
||||
* Acts on an entity after it is created but before hooks are invoked.
|
||||
* Acts on a created entity before hooks are invoked.
|
||||
*
|
||||
* Used after the entity is created, but before saving the entity and before
|
||||
* any of the presave hooks are invoked.
|
||||
*
|
||||
* See the @link entity_crud Entity CRUD topic @endlink for more information.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityStorageInterface $storage
|
||||
* The entity storage object.
|
||||
*
|
||||
* @see \Drupal\Core\Entity\EntityInterface::create()
|
||||
*/
|
||||
public function postCreate(EntityStorageInterface $storage);
|
||||
|
||||
|
|
|
@ -11,7 +11,10 @@ interface EntityTypeBundleInfoInterface {
|
|||
* Get the bundle info of all entity types.
|
||||
*
|
||||
* @return array
|
||||
* An array of all bundle information.
|
||||
* An array of bundle information where the outer array is keyed by entity
|
||||
* type. The next level is keyed by the bundle name. The inner arrays are
|
||||
* associative arrays of bundle information, such as the label for the
|
||||
* bundle.
|
||||
*/
|
||||
public function getAllBundleInfo();
|
||||
|
||||
|
@ -22,7 +25,10 @@ interface EntityTypeBundleInfoInterface {
|
|||
* The entity type.
|
||||
*
|
||||
* @return array
|
||||
* Returns the bundle information for the specified entity type.
|
||||
* An array of bundle information where the outer array is keyed by the
|
||||
* bundle name, or the entity type name if the entity does not have bundles.
|
||||
* The inner arrays are associative arrays of bundle information, such as
|
||||
* the label for the bundle.
|
||||
*/
|
||||
public function getBundleInfo($entity_type);
|
||||
|
||||
|
|
|
@ -28,24 +28,47 @@ interface QueryInterface extends AlterableInterface {
|
|||
* and the Polish 'siema' within a 'greetings' text field:
|
||||
* @code
|
||||
* $entity_ids = \Drupal::entityQuery($entity_type)
|
||||
* ->condition('greetings', 'merhaba', '=', 'tr');
|
||||
* ->condition('greetings.value', 'siema', '=', 'pl');
|
||||
* ->condition('greetings', 'merhaba', '=', 'tr')
|
||||
* ->condition('greetings.value', 'siema', '=', 'pl')
|
||||
* ->execute();
|
||||
* $entity_ids = $query->execute();
|
||||
* @endcode
|
||||
*
|
||||
* @param $field
|
||||
* Name of the field being queried. It must contain a field name,
|
||||
* optionally followed by a column name. The column can be "entity" for
|
||||
* reference fields and that can be followed similarly by a field name
|
||||
* and so on. Some examples:
|
||||
* Name of the field being queried. It must contain a field name, optionally
|
||||
* followed by a column name. The column can be "entity" for reference
|
||||
* fields and that can be followed similarly by a field name and so on. Some
|
||||
* examples:
|
||||
* - nid
|
||||
* - tags.value
|
||||
* - tags
|
||||
* - uid.entity.name
|
||||
* "tags" "is the same as "tags.value" as value is the default column.
|
||||
* If two or more conditions have the same field names they apply to the
|
||||
* same delta within that field.
|
||||
* same delta within that field. In order to limit the condition to a
|
||||
* specific item a numeric delta should be added between the field name and
|
||||
* the column name.
|
||||
* @code
|
||||
* ->condition('tags.5.value', 'news')
|
||||
* @endcode
|
||||
* This will require condition to be satisfied on a specific delta of the
|
||||
* field. The condition above will require the 6th value of the field to
|
||||
* match the provided value. Further, it's possible to create a condition on
|
||||
* the delta itself by using '%delta'. For example,
|
||||
* @code
|
||||
* ->condition('tags.%delta', 5)
|
||||
* @endcode
|
||||
* will find only entities which have at least six tags. Finally, the
|
||||
* condition on the delta itself accompanied with a condition on the value
|
||||
* will require the value to appear in the specific delta range. For
|
||||
* example,
|
||||
* @code
|
||||
* ->condition('tags.%delta', 0, '>'))
|
||||
* ->condition('tags.%delta.value', 'news'))
|
||||
* @endcode
|
||||
* will only find the "news" tag if it is not the first value. It should be
|
||||
* noted that conditions on specific deltas and delta ranges are only
|
||||
* supported when querying content entities.
|
||||
* @param $value
|
||||
* The value for $field. In most cases, this is a scalar and it's treated as
|
||||
* case-insensitive. For more complex operators, it is an array. The meaning
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace Drupal\Core\Entity\Query\Sql;
|
|||
use Drupal\Core\Database\Query\SelectInterface;
|
||||
use Drupal\Core\Entity\Query\QueryException;
|
||||
use Drupal\Core\Entity\Sql\SqlEntityStorageInterface;
|
||||
use Drupal\Core\Entity\Sql\TableMappingInterface;
|
||||
|
||||
/**
|
||||
* Adds tables and fields to the SQL entity query.
|
||||
|
@ -112,11 +113,37 @@ class Tables implements TablesInterface {
|
|||
|
||||
// Check whether this field is stored in a dedicated table.
|
||||
if ($field_storage && $table_mapping->requiresDedicatedTableStorage($field_storage)) {
|
||||
$delta = NULL;
|
||||
// Find the field column.
|
||||
$column = $field_storage->getMainPropertyName();
|
||||
|
||||
if ($key < $count) {
|
||||
$next = $specifiers[$key + 1];
|
||||
// If this is a numeric specifier we're adding a condition on the
|
||||
// specific delta.
|
||||
if (is_numeric($next)) {
|
||||
$delta = $next;
|
||||
$index_prefix .= ".$delta";
|
||||
// Do not process it again.
|
||||
$key++;
|
||||
$next = $specifiers[$key + 1];
|
||||
}
|
||||
// If this specifier is the reserved keyword "%delta" we're adding a
|
||||
// condition on a delta range.
|
||||
elseif ($next == TableMappingInterface::DELTA) {
|
||||
$index_prefix .= TableMappingInterface::DELTA;
|
||||
// Do not process it again.
|
||||
$key++;
|
||||
// If there are more specifiers to work with then continue
|
||||
// processing. If this is the last specifier then use the reserved
|
||||
// keyword as a column name.
|
||||
if ($key < $count) {
|
||||
$next = $specifiers[$key + 1];
|
||||
}
|
||||
else {
|
||||
$column = TableMappingInterface::DELTA;
|
||||
}
|
||||
}
|
||||
// Is this a field column?
|
||||
$columns = $field_storage->getColumns();
|
||||
if (isset($columns[$next]) || in_array($next, $table_mapping->getReservedColumns())) {
|
||||
|
@ -140,7 +167,7 @@ class Tables implements TablesInterface {
|
|||
$next_index_prefix = "$relationship_specifier.$column";
|
||||
}
|
||||
}
|
||||
$table = $this->ensureFieldTable($index_prefix, $field_storage, $type, $langcode, $base_table, $entity_id_field, $field_id_field);
|
||||
$table = $this->ensureFieldTable($index_prefix, $field_storage, $type, $langcode, $base_table, $entity_id_field, $field_id_field, $delta);
|
||||
$sql_column = $table_mapping->getFieldColumnName($field_storage, $column);
|
||||
$property_definitions = $field_storage->getPropertyDefinitions();
|
||||
if (isset($property_definitions[$column])) {
|
||||
|
@ -173,6 +200,27 @@ class Tables implements TablesInterface {
|
|||
// next one is a column of this field.
|
||||
if ($key < $count) {
|
||||
$next = $specifiers[$key + 1];
|
||||
// If this specifier is the reserved keyword "%delta" we're adding a
|
||||
// condition on a delta range.
|
||||
if ($next == TableMappingInterface::DELTA) {
|
||||
$key++;
|
||||
if ($key < $count) {
|
||||
$next = $specifiers[$key + 1];
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// If this is a numeric specifier we're adding a condition on the
|
||||
// specific delta. Since we know that this is a single value base
|
||||
// field no other value than 0 makes sense.
|
||||
if (is_numeric($next)) {
|
||||
if ($next > 0) {
|
||||
$this->sqlQuery->condition('1 <> 1');
|
||||
}
|
||||
$key++;
|
||||
$next = $specifiers[$key + 1];
|
||||
}
|
||||
// Is this a field column?
|
||||
$columns = $field_storage->getColumns();
|
||||
if (isset($columns[$next]) || in_array($next, $table_mapping->getReservedColumns())) {
|
||||
|
@ -264,7 +312,7 @@ class Tables implements TablesInterface {
|
|||
* @return string
|
||||
* @throws \Drupal\Core\Entity\Query\QueryException
|
||||
*/
|
||||
protected function ensureFieldTable($index_prefix, &$field, $type, $langcode, $base_table, $entity_id_field, $field_id_field) {
|
||||
protected function ensureFieldTable($index_prefix, &$field, $type, $langcode, $base_table, $entity_id_field, $field_id_field, $delta) {
|
||||
$field_name = $field->getName();
|
||||
if (!isset($this->fieldTables[$index_prefix . $field_name])) {
|
||||
$entity_type_id = $this->sqlQuery->getMetaData('entity_type');
|
||||
|
@ -274,12 +322,12 @@ class Tables implements TablesInterface {
|
|||
if ($field->getCardinality() != 1) {
|
||||
$this->sqlQuery->addMetaData('simple_query', FALSE);
|
||||
}
|
||||
$this->fieldTables[$index_prefix . $field_name] = $this->addJoin($type, $table, "%alias.$field_id_field = $base_table.$entity_id_field", $langcode);
|
||||
$this->fieldTables[$index_prefix . $field_name] = $this->addJoin($type, $table, "%alias.$field_id_field = $base_table.$entity_id_field", $langcode, $delta);
|
||||
}
|
||||
return $this->fieldTables[$index_prefix . $field_name];
|
||||
}
|
||||
|
||||
protected function addJoin($type, $table, $join_condition, $langcode) {
|
||||
protected function addJoin($type, $table, $join_condition, $langcode, $delta = NULL) {
|
||||
$arguments = array();
|
||||
if ($langcode) {
|
||||
$entity_type_id = $this->sqlQuery->getMetaData('entity_type');
|
||||
|
@ -291,6 +339,11 @@ class Tables implements TablesInterface {
|
|||
$join_condition .= ' AND %alias.' . $langcode_key . ' = ' . $placeholder;
|
||||
$arguments[$placeholder] = $langcode;
|
||||
}
|
||||
if (isset($delta)) {
|
||||
$placeholder = ':delta' . $this->sqlQuery->nextPlaceholder();
|
||||
$join_condition .= ' AND %alias.delta = ' . $placeholder;
|
||||
$arguments[$placeholder] = $delta;
|
||||
}
|
||||
return $this->sqlQuery->addJoin($type, $table, NULL, $join_condition, $arguments);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,8 +11,10 @@ interface TablesInterface {
|
|||
* Adds a field to a database query.
|
||||
*
|
||||
* @param string $field
|
||||
* If it contains a dot, then field name dot field column. If it doesn't
|
||||
* then entity property name.
|
||||
* If it doesn't contain a dot, then an entity base field name. If it
|
||||
* contains a dot, then either field name dot field column or field name dot
|
||||
* delta dot field column. Delta can be a numeric value or a "%delta" for
|
||||
* any value.
|
||||
* @param string $type
|
||||
* Join type, can either be INNER or LEFT.
|
||||
* @param string $langcode
|
||||
|
|
|
@ -204,7 +204,12 @@ class DefaultTableMapping implements TableMappingInterface {
|
|||
$column_name = count($storage_definition->getColumns()) == 1 ? $field_name : $field_name . '__' . $property_name;
|
||||
}
|
||||
elseif ($this->requiresDedicatedTableStorage($storage_definition)) {
|
||||
$column_name = !in_array($property_name, $this->getReservedColumns()) ? $field_name . '_' . $property_name : $property_name;
|
||||
if ($property_name == TableMappingInterface::DELTA) {
|
||||
$column_name = 'delta';
|
||||
}
|
||||
else {
|
||||
$column_name = !in_array($property_name, $this->getReservedColumns()) ? $field_name . '_' . $property_name : $property_name;
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new SqlContentEntityStorageException("Column information not available for the '$field_name' field.");
|
||||
|
|
|
@ -150,7 +150,7 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
|
|||
* The database connection to be used.
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
|
||||
* @param \Drupal\Core\Cache\CacheBackendInterface $cache
|
||||
* The cache backend to be used.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager.
|
||||
|
|
|
@ -1837,6 +1837,24 @@ class SqlContentEntityStorageSchema implements DynamicallyFieldableEntityStorage
|
|||
}
|
||||
}
|
||||
|
||||
// Add unique keys.
|
||||
foreach ($schema['unique keys'] as $index_name => $columns) {
|
||||
$real_name = $this->getFieldIndexName($storage_definition, $index_name);
|
||||
foreach ($columns as $column_name) {
|
||||
// Unique keys can be specified as either a column name or an array with
|
||||
// column name and length. Allow for either case.
|
||||
if (is_array($column_name)) {
|
||||
$data_schema['unique keys'][$real_name][] = array(
|
||||
$table_mapping->getFieldColumnName($storage_definition, $column_name[0]),
|
||||
$column_name[1],
|
||||
);
|
||||
}
|
||||
else {
|
||||
$data_schema['unique keys'][$real_name][] = $table_mapping->getFieldColumnName($storage_definition, $column_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add foreign keys.
|
||||
foreach ($schema['foreign keys'] as $specifier => $specification) {
|
||||
$real_name = $this->getFieldIndexName($storage_definition, $specifier);
|
||||
|
|
|
@ -19,6 +19,11 @@ use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
|||
*/
|
||||
interface TableMappingInterface {
|
||||
|
||||
/**
|
||||
* A property that represents delta used in entity query conditions.
|
||||
*/
|
||||
const DELTA = '%delta';
|
||||
|
||||
/**
|
||||
* Gets a list of table names for this mapping.
|
||||
*
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
namespace Drupal\Core\EventSubscriber;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Utility\Xss;
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\Render\BareHtmlPageRendererInterface;
|
||||
use Drupal\Core\Routing\RouteMatch;
|
||||
|
@ -13,6 +12,7 @@ use Drupal\Core\Site\MaintenanceModeInterface;
|
|||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\Core\StringTranslation\TranslationInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
|
@ -90,18 +90,25 @@ class MaintenanceModeSubscriber implements EventSubscriberInterface {
|
|||
* The event to process.
|
||||
*/
|
||||
public function onKernelRequestMaintenance(GetResponseEvent $event) {
|
||||
$route_match = RouteMatch::createFromRequest($event->getRequest());
|
||||
$request = $event->getRequest();
|
||||
$route_match = RouteMatch::createFromRequest($request);
|
||||
if ($this->maintenanceMode->applies($route_match)) {
|
||||
// Don't cache maintenance mode pages.
|
||||
\Drupal::service('page_cache_kill_switch')->trigger();
|
||||
|
||||
if (!$this->maintenanceMode->exempt($this->account)) {
|
||||
// Deliver the 503 page if the site is in maintenance mode and the
|
||||
// logged in user is not allowed to bypass it.
|
||||
|
||||
// If the request format is not 'html' then show default maintenance
|
||||
// mode page else show a text/plain page with maintenance message.
|
||||
if ($request->getRequestFormat() !== 'html') {
|
||||
$response = new Response($this->getSiteMaintenanceMessage(), 503, array('Content-Type' => 'text/plain'));
|
||||
$event->setResponse($response);
|
||||
return;
|
||||
}
|
||||
drupal_maintenance_theme();
|
||||
$content = Xss::filterAdmin(SafeMarkup::format($this->config->get('system.maintenance')->get('message'), array(
|
||||
'@site' => $this->config->get('system.site')->get('name'),
|
||||
)));
|
||||
$response = $this->bareHtmlPageRenderer->renderBarePage(['#markup' => $content], $this->t('Site under maintenance'), 'maintenance_page');
|
||||
$response = $this->bareHtmlPageRenderer->renderBarePage(['#markup' => $this->getSiteMaintenanceMessage()], $this->t('Site under maintenance'), 'maintenance_page');
|
||||
$response->setStatusCode(503);
|
||||
$event->setResponse($response);
|
||||
}
|
||||
|
@ -121,6 +128,18 @@ class MaintenanceModeSubscriber implements EventSubscriberInterface {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the site maintenance message.
|
||||
*
|
||||
* @return \Drupal\Component\Render\MarkupInterface
|
||||
* The formatted site maintenance message.
|
||||
*/
|
||||
protected function getSiteMaintenanceMessage() {
|
||||
return SafeMarkup::format($this->config->get('system.maintenance')->get('message'), array(
|
||||
'@site' => $this->config->get('system.site')->get('name'),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the drupal_set_message function.
|
||||
*/
|
||||
|
|
|
@ -214,7 +214,7 @@ interface ModuleHandlerInterface {
|
|||
* The name of the module (without the .module extension).
|
||||
* @param string $hook
|
||||
* The name of the hook to invoke.
|
||||
* @param ...
|
||||
* @param array $args
|
||||
* Arguments to pass to the hook implementation.
|
||||
*
|
||||
* @return mixed
|
||||
|
|
|
@ -72,6 +72,8 @@ use Drupal\Core\Utility\UpdateException;
|
|||
* frequently called should be left in the main module file so that they are
|
||||
* always available.
|
||||
*
|
||||
* See system_hook_info() for all hook groups defined by Drupal core.
|
||||
*
|
||||
* @return
|
||||
* An associative array whose keys are hook names and whose values are an
|
||||
* associative array containing:
|
||||
|
@ -79,8 +81,6 @@ use Drupal\Core\Utility\UpdateException;
|
|||
* system will determine whether a file with the name $module.$group.inc
|
||||
* exists, and automatically load it when required.
|
||||
*
|
||||
* See system_hook_info() for all hook groups defined by Drupal core.
|
||||
*
|
||||
* @see hook_hook_info_alter()
|
||||
*/
|
||||
function hook_hook_info() {
|
||||
|
|
|
@ -28,6 +28,8 @@ class PasswordItem extends StringItem {
|
|||
->setSetting('case_sensitive', TRUE);
|
||||
$properties['existing'] = DataDefinition::create('string')
|
||||
->setLabel(new TranslatableMarkup('Existing password'));
|
||||
$properties['pre_hashed'] = DataDefinition::create('boolean')
|
||||
->setLabel(new TranslatableMarkup('Determines if a password needs hashing'));
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
@ -40,8 +42,11 @@ class PasswordItem extends StringItem {
|
|||
|
||||
$entity = $this->getEntity();
|
||||
|
||||
// Update the user password if it has changed.
|
||||
if ($entity->isNew() || (strlen(trim($this->value)) > 0 && $this->value != $entity->original->{$this->getFieldDefinition()->getName()}->value)) {
|
||||
if ($this->pre_hashed) {
|
||||
// Reset the pre_hashed value since it has now been used.
|
||||
$this->pre_hashed = FALSE;
|
||||
}
|
||||
elseif ($entity->isNew() || (strlen(trim($this->value)) > 0 && $this->value != $entity->original->{$this->getFieldDefinition()->getName()}->value)) {
|
||||
// Allow alternate password hashing schemes.
|
||||
$this->value = \Drupal::service('password')->hash(trim($this->value));
|
||||
// Abort if the hashing failed and returned FALSE.
|
||||
|
|
|
@ -15,7 +15,29 @@ use Symfony\Component\HttpFoundation\RequestStack;
|
|||
/**
|
||||
* Provides a base class for forms.
|
||||
*
|
||||
* This class exists as a mid-point between dependency injection through
|
||||
* ContainerInjectionInterface, and a less-structured use of traits which
|
||||
* default to using the \Drupal accessor for service discovery.
|
||||
*
|
||||
* To properly inject services, override create() and use the setters provided
|
||||
* by the traits to inject the needed services.
|
||||
*
|
||||
* @code
|
||||
* public static function create($container) {
|
||||
* $form = new static();
|
||||
* // In this example we only need string translation so we use the
|
||||
* // setStringTranslation() method provided by StringTranslationTrait.
|
||||
* $form->setStringTranslation($container->get('string_translation'));
|
||||
* return $form;
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* Alternately, do not use FormBase. A class can implement FormInterface, use
|
||||
* the traits it needs, and inject services from the container as required.
|
||||
*
|
||||
* @ingroup form_api
|
||||
*
|
||||
* @see \Drupal\Core\DependencyInjection\ContainerInjectionInterface
|
||||
*/
|
||||
abstract class FormBase implements FormInterface, ContainerInjectionInterface {
|
||||
|
||||
|
|
|
@ -137,9 +137,9 @@ interface FormBuilderInterface {
|
|||
* by calling $form_state->getErrors().
|
||||
*
|
||||
* @param \Drupal\Core\Form\FormInterface|string $form_arg
|
||||
* A form object to use to build the form, or the unique string identifying
|
||||
* the desired form. If $form_arg is a string and a function with that
|
||||
* name exists, it is called to build the form array.
|
||||
* The value must be one of the following:
|
||||
* - The name of a class that implements \Drupal\Core\Form\FormInterface.
|
||||
* - An instance of a class that implements \Drupal\Core\Form\FormInterface.
|
||||
* @param $form_state
|
||||
* The current state of the form. Most important is the
|
||||
* $form_state->getValues() collection, a tree of data used to simulate the
|
||||
|
|
|
@ -41,11 +41,11 @@ abstract class ContextAwarePluginBase extends ComponentContextAwarePluginBase im
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return \Drupal\Core\Plugin\Context\ContextInterface
|
||||
* The context object.
|
||||
*
|
||||
* This code is identical to the Component in order to pick up a different
|
||||
* Context class.
|
||||
*
|
||||
* @return \Drupal\Core\Plugin\Context\ContextInterface
|
||||
* The context object.
|
||||
*/
|
||||
public function getContext($name) {
|
||||
// Check for a valid context value.
|
||||
|
|
|
@ -17,7 +17,7 @@ use Drupal\Core\Form\FormStateInterface;
|
|||
* @code
|
||||
* $form['high_school']['tests_taken'] = array(
|
||||
* '#type' => 'checkboxes',
|
||||
* '#options' => array('SAT' => $this->t('SAT'), 'ACT' => $this->t('ACT'))),
|
||||
* '#options' => array('SAT' => $this->t('SAT'), 'ACT' => $this->t('ACT')),
|
||||
* '#title' => $this->t('What standardized tests did you take?'),
|
||||
* ...
|
||||
* );
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace Drupal\Core\Render\Element;
|
|||
* $build['status_messages'] = [
|
||||
* '#type' => 'status_messages',
|
||||
* ];
|
||||
* @end
|
||||
* @endcode
|
||||
*
|
||||
* @RenderElement("status_messages")
|
||||
*/
|
||||
|
|
|
@ -64,7 +64,7 @@ interface RenderCacheInterface {
|
|||
* this array.
|
||||
*
|
||||
* @return bool|null
|
||||
* Returns FALSE if no cache item could be created, NULL otherwise.
|
||||
* Returns FALSE if no cache item could be created, NULL otherwise.
|
||||
*
|
||||
* @see ::get()
|
||||
*/
|
||||
|
|
|
@ -2,10 +2,27 @@
|
|||
|
||||
namespace Drupal\Core\Routing;
|
||||
|
||||
/**
|
||||
* Rebuilds the route information and dumps it.
|
||||
*
|
||||
* Rebuilding the route information is the process of gathering all routing data
|
||||
* from .routing.yml files, creating a
|
||||
* \Symfony\Component\Routing\RouteCollection object out of it, and dispatching
|
||||
* that object as a \Drupal\Core\Routing\RouteBuildEvent to all registered
|
||||
* listeners. After that, the \Symfony\Component\Routing\RouteCollection object
|
||||
* is used to dump the data. Examples of a dump include filling up the routing
|
||||
* table, auto-generating Apache mod_rewrite rules, or auto-generating a PHP
|
||||
* matcher class.
|
||||
*
|
||||
* @see \Drupal\Core\Routing\MatcherDumperInterface
|
||||
* @see \Drupal\Core\Routing\RouteProviderInterface
|
||||
*
|
||||
* @ingroup routing
|
||||
*/
|
||||
interface RouteBuilderInterface {
|
||||
|
||||
/**
|
||||
* Rebuilds the route info and dumps to dumper.
|
||||
* Rebuilds the route information and dumps it.
|
||||
*
|
||||
* @return bool
|
||||
* Returns TRUE if the rebuild succeeds, FALSE otherwise.
|
||||
|
@ -13,7 +30,7 @@ interface RouteBuilderInterface {
|
|||
public function rebuild();
|
||||
|
||||
/**
|
||||
* Rebuilds the route info and dumps to dumper if necessary.
|
||||
* Rebuilds the route information if necessary, and dumps it.
|
||||
*
|
||||
* @return bool
|
||||
* Returns TRUE if the rebuild occurs, FALSE otherwise.
|
||||
|
|
|
@ -229,10 +229,8 @@ class UrlGenerator implements UrlGeneratorInterface {
|
|||
|
||||
// Add a query string if needed, including extra parameters.
|
||||
$query_params += array_diff_key($parameters, $variables, $defaults);
|
||||
if ($query_params && $query = http_build_query($query_params, '', '&')) {
|
||||
// "/" and "?" can be left decoded for better user experience, see
|
||||
// http://tools.ietf.org/html/rfc3986#section-3.4
|
||||
$url .= '?' . strtr($query, array('%2F' => '/'));
|
||||
if ($query_params && $query = UrlHelper::buildQuery($query_params)) {
|
||||
$url .= '?' . $query;
|
||||
}
|
||||
|
||||
return $url;
|
||||
|
@ -253,7 +251,7 @@ class UrlGenerator implements UrlGeneratorInterface {
|
|||
* $parameters merged in.
|
||||
*
|
||||
* @return string
|
||||
* The url path corresponding to the route, without the base path.
|
||||
* The url path corresponding to the route, without the base path.
|
||||
*/
|
||||
protected function getInternalPathFromRoute($name, SymfonyRoute $route, $parameters = array(), $query_params = array()) {
|
||||
// The Route has a cache of its own and is not recompiled as long as it does
|
||||
|
|
|
@ -21,7 +21,7 @@ interface UrlGeneratorInterface extends VersatileGeneratorInterface {
|
|||
* \Symfony\Component\Routing\Generator\UrlGeneratorInterface::generate().
|
||||
*
|
||||
* @return string
|
||||
* The internal Drupal path corresponding to the route.
|
||||
* The internal Drupal path corresponding to the route.
|
||||
*/
|
||||
public function getPathFromRoute($name, $parameters = array());
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ interface PhpStreamWrapperInterface {
|
|||
public function stream_cast($cast_as);
|
||||
|
||||
/**
|
||||
* @return void
|
||||
* Closes stream.
|
||||
*/
|
||||
public function stream_close();
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ class FileTranslation extends StaticTranslation {
|
|||
* want to find translation files.
|
||||
*
|
||||
* @return string
|
||||
* String file pattern.
|
||||
* String file pattern.
|
||||
*/
|
||||
protected function getTranslationFilesPattern($langcode = NULL) {
|
||||
// The file name matches: drupal-[release version].[language code].po
|
||||
|
|
|
@ -272,7 +272,11 @@ class Url {
|
|||
if ($uri_parts === FALSE) {
|
||||
throw new \InvalidArgumentException("The URI '$uri' is malformed.");
|
||||
}
|
||||
if (empty($uri_parts['scheme'])) {
|
||||
// We support protocol-relative URLs.
|
||||
if (strpos($uri, '//') === 0) {
|
||||
$uri_parts['scheme'] = '';
|
||||
}
|
||||
elseif (empty($uri_parts['scheme'])) {
|
||||
throw new \InvalidArgumentException("The URI '$uri' is invalid. You must use a valid URI scheme.");
|
||||
}
|
||||
$uri_parts += ['path' => ''];
|
||||
|
|
|
@ -140,6 +140,7 @@ class LinkGenerator implements LinkGeneratorInterface {
|
|||
|
||||
// Allow other modules to modify the structure of the link.
|
||||
$this->moduleHandler->alter('link', $variables);
|
||||
$url = $variables['url'];
|
||||
|
||||
// Move attributes out of options since generateFromRoute() doesn't need
|
||||
// them. Include a placeholder for the href.
|
||||
|
|
Reference in a new issue