Merged 10.2.11.
commit
26d50b073f
|
@ -9635,8 +9635,8 @@
|
|||
},
|
||||
"prefer-stable": true,
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"platform": {},
|
||||
"platform-dev": {},
|
||||
"platform-overrides": {
|
||||
"php": "8.1.0"
|
||||
},
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace Drupal\Core\Ajax;
|
||||
|
||||
use Drupal\Component\Render\MarkupInterface;
|
||||
use Drupal\Component\Utility\Xss;
|
||||
use Drupal\Core\Asset\AttachedAssets;
|
||||
|
||||
/**
|
||||
|
@ -30,7 +32,7 @@ class MessageCommand implements CommandInterface, CommandWithAttachedAssetsInter
|
|||
/**
|
||||
* The message text.
|
||||
*
|
||||
* @var string
|
||||
* @var string|\Drupal\Component\Render\MarkupInterface
|
||||
*/
|
||||
protected $message;
|
||||
|
||||
|
@ -58,7 +60,7 @@ class MessageCommand implements CommandInterface, CommandWithAttachedAssetsInter
|
|||
/**
|
||||
* Constructs a MessageCommand object.
|
||||
*
|
||||
* @param string $message
|
||||
* @param string|\Drupal\Component\Render\MarkupInterface $message
|
||||
* The text of the message.
|
||||
* @param string|null $wrapper_query_selector
|
||||
* The query selector of the element to display messages in when they
|
||||
|
@ -82,7 +84,9 @@ class MessageCommand implements CommandInterface, CommandWithAttachedAssetsInter
|
|||
public function render() {
|
||||
return [
|
||||
'command' => 'message',
|
||||
'message' => $this->message,
|
||||
'message' => $this->message instanceof MarkupInterface
|
||||
? (string) $this->message
|
||||
: Xss::filterAdmin($this->message),
|
||||
'messageWrapperQuerySelector' => $this->wrapperQuerySelector,
|
||||
'messageOptions' => $this->options,
|
||||
'clearPrevious' => $this->clearPrevious,
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Drupal\Core\Config;
|
||||
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Cache\MemoryBackend;
|
||||
use Drupal\Core\Config\Entity\ConfigDependencyManager;
|
||||
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
|
||||
|
@ -79,7 +80,7 @@ class StorageComparer implements StorageComparerInterface {
|
|||
*
|
||||
* @var \Drupal\Core\Cache\MemoryBackend
|
||||
*/
|
||||
protected $targetCacheStorage;
|
||||
protected CacheBackendInterface $targetCacheStorage;
|
||||
|
||||
/**
|
||||
* Constructs the Configuration storage comparer.
|
||||
|
|
|
@ -801,6 +801,15 @@ class Select extends Query implements SelectInterface {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function __toString() {
|
||||
if (!is_array($this->fields) ||
|
||||
!is_array($this->expressions) ||
|
||||
!is_array($this->tables) ||
|
||||
!is_array($this->order) ||
|
||||
!is_array($this->group) ||
|
||||
!is_array($this->union)) {
|
||||
throw new \UnexpectedValueException();
|
||||
}
|
||||
|
||||
// For convenience, we compile the query ourselves if the caller forgot
|
||||
// to do it. This allows constructs like "(string) $query" to work. When
|
||||
// the query will be executed, it will be recompiled using the proper
|
||||
|
|
|
@ -164,6 +164,12 @@ class Update extends Query implements ConditionInterface {
|
|||
* The prepared statement.
|
||||
*/
|
||||
public function __toString() {
|
||||
if (!is_array($this->fields) ||
|
||||
!is_array($this->arguments) ||
|
||||
!is_array($this->expressionFields)) {
|
||||
throw new \UnexpectedValueException();
|
||||
}
|
||||
|
||||
// Create a sanitized comment string to prepend to the query.
|
||||
$comments = $this->connection->makeComment($this->comments);
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace Drupal\Core\Database;
|
|||
|
||||
use Drupal\Core\Database\Event\StatementExecutionEndEvent;
|
||||
use Drupal\Core\Database\Event\StatementExecutionStartEvent;
|
||||
use Drupal\Core\Site\Settings;
|
||||
|
||||
/**
|
||||
* An implementation of StatementInterface that pre-fetches all data.
|
||||
|
@ -344,6 +345,15 @@ class StatementPrefetch implements \Iterator, StatementInterface {
|
|||
$class_name = $this->fetchOptions['class'];
|
||||
}
|
||||
if (count($this->fetchOptions['constructor_args'])) {
|
||||
// Verify the current db connection to avoid this code being called
|
||||
// in an inappropriate context.
|
||||
$defaults = ['sqlite', 'oracle'];
|
||||
$extras = Settings::get('database_statement_prefetch_valid_db_drivers', []);
|
||||
$valid_db_drivers = array_merge($defaults, $extras);
|
||||
$db_connection_options = Database::getConnection()->getConnectionOptions();
|
||||
if (!in_array($db_connection_options['driver'], $valid_db_drivers)) {
|
||||
throw new \BadMethodCallException();
|
||||
}
|
||||
$reflector = new \ReflectionClass($class_name);
|
||||
$result = $reflector->newInstanceArgs($this->fetchOptions['constructor_args']);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ trait DependencySerializationTrait {
|
|||
* @var array
|
||||
*/
|
||||
// phpcs:ignore Drupal.Classes.PropertyDeclaration
|
||||
protected $_serviceIds = [];
|
||||
protected array $_serviceIds = [];
|
||||
|
||||
/**
|
||||
* An array of entity type IDs keyed by the property name of their storages.
|
||||
|
@ -25,7 +25,7 @@ trait DependencySerializationTrait {
|
|||
* @var array
|
||||
*/
|
||||
// phpcs:ignore Drupal.Classes.PropertyDeclaration
|
||||
protected $_entityStorages = [];
|
||||
protected array $_entityStorages = [];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
|
|
@ -73,7 +73,7 @@ class Attribute implements \ArrayAccess, \IteratorAggregate, MarkupInterface {
|
|||
*
|
||||
* @var \Drupal\Core\Template\AttributeValueBase[]
|
||||
*/
|
||||
protected $storage = [];
|
||||
protected array $storage = [];
|
||||
|
||||
/**
|
||||
* Constructs a \Drupal\Core\Template\Attribute object.
|
||||
|
|
|
@ -16,6 +16,16 @@ class UniqueFieldConstraint extends Constraint {
|
|||
|
||||
public $message = 'A @entity_type with @field_name %value already exists.';
|
||||
|
||||
/**
|
||||
* This constraint is case-insensitive by default.
|
||||
*
|
||||
* For example "FOO" and "foo" would be considered as equivalent, and
|
||||
* validation of the constraint would fail.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $caseSensitive = FALSE;
|
||||
|
||||
/**
|
||||
* Returns the name of the class that validates this constraint.
|
||||
*
|
||||
|
|
|
@ -64,12 +64,23 @@ class UniqueFieldValueValidator extends ConstraintValidator implements Container
|
|||
->getStorage($entity_type_id)
|
||||
->getAggregateQuery()
|
||||
->accessCheck(FALSE)
|
||||
->condition($field_name, $item_values, 'IN')
|
||||
->groupBy("$field_name.$property_name");
|
||||
if (!$is_new) {
|
||||
$entity_id = $entity->id();
|
||||
$query->condition($id_key, $entity_id, '<>');
|
||||
}
|
||||
|
||||
if ($constraint->caseSensitive) {
|
||||
$query->condition($field_name, $item_values, 'IN');
|
||||
}
|
||||
else {
|
||||
$or_group = $query->orConditionGroup();
|
||||
foreach ($item_values as $item_value) {
|
||||
$or_group->condition($field_name, \Drupal::database()->escapeLike($item_value), 'LIKE');
|
||||
}
|
||||
$query->condition($or_group);
|
||||
}
|
||||
|
||||
$results = $query->execute();
|
||||
|
||||
if (!empty($results)) {
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
namespace Drupal\file\Plugin\Validation\Constraint;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Drupal\Core\Validation\Plugin\Validation\Constraint\UniqueFieldConstraint;
|
||||
use Drupal\Core\Validation\Plugin\Validation\Constraint\UniqueFieldValueValidator;
|
||||
|
||||
/**
|
||||
* Supports validating file URIs.
|
||||
|
@ -12,15 +13,25 @@ use Symfony\Component\Validator\Constraint;
|
|||
* label = @Translation("File URI", context = "Validation")
|
||||
* )
|
||||
*/
|
||||
class FileUriUnique extends Constraint {
|
||||
class FileUriUnique extends UniqueFieldConstraint {
|
||||
|
||||
public $message = 'The file %value already exists. Enter a unique file URI.';
|
||||
|
||||
/**
|
||||
* This constraint is case-sensitive.
|
||||
*
|
||||
* For example "public://foo.txt" and "public://FOO.txt" are treated as
|
||||
* different values, and can co-exist.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $caseSensitive = TRUE;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validatedBy() {
|
||||
return '\Drupal\Core\Validation\Plugin\Validation\Constraint\UniqueFieldValueValidator';
|
||||
public function validatedBy(): string {
|
||||
return UniqueFieldValueValidator::class;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ class Connection extends DatabaseConnection implements SupportsTemporaryTablesIn
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $attachedDatabases = [];
|
||||
protected array $attachedDatabases = [];
|
||||
|
||||
/**
|
||||
* Whether or not a table has been dropped this request.
|
||||
|
|
|
@ -93,6 +93,50 @@ function user_install() {
|
|||
->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_requirements().
|
||||
*/
|
||||
function user_requirements($phase): array {
|
||||
if ($phase !== 'runtime') {
|
||||
return [];
|
||||
}
|
||||
$return = [];
|
||||
|
||||
$result = (bool) \Drupal::entityQuery('user')
|
||||
->accessCheck(FALSE)
|
||||
->condition('uid', 0)
|
||||
->range(0, 1)
|
||||
->execute();
|
||||
|
||||
if ($result === FALSE) {
|
||||
$return['anonymous user'] = [
|
||||
'title' => t('Anonymous user'),
|
||||
'description' => t('The anonymous user does not exist. See the <a href=":url">restore the anonymous (user ID 0) user record</a> for more information', [
|
||||
':url' => 'https://www.drupal.org/node/1029506',
|
||||
]),
|
||||
'severity' => REQUIREMENT_WARNING,
|
||||
];
|
||||
}
|
||||
|
||||
$query = \Drupal::database()->select('users_field_data');
|
||||
$query->addExpression('LOWER(mail)', 'lower_mail');
|
||||
$query->groupBy('lower_mail');
|
||||
$query->having('COUNT(uid) > :matches', [':matches' => 1]);
|
||||
$conflicts = $query->countQuery()->execute()->fetchField();
|
||||
|
||||
if ($conflicts > 0) {
|
||||
$return['conflicting emails'] = [
|
||||
'title' => t('Conflicting user emails'),
|
||||
'description' => t('Some user accounts have email addresses that differ only by case. For example, one account might have alice@example.com and another might have Alice@Example.com. See <a href=":url">Conflicting User Emails</a> for more information.', [
|
||||
':url' => 'https://www.drupal.org/node/3486109',
|
||||
]),
|
||||
'severity' => REQUIREMENT_WARNING,
|
||||
];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_update_last_removed().
|
||||
*/
|
||||
|
|
|
@ -8,6 +8,7 @@ use Drupal\Component\Utility\Tags;
|
|||
use Drupal\Core\Routing\RouteProviderInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\views\Plugin\views\display\DisplayRouterInterface;
|
||||
use Drupal\views\Plugin\views\query\QueryPluginBase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Exception\RouteNotFoundException;
|
||||
|
@ -199,7 +200,7 @@ class ViewExecutable {
|
|||
*
|
||||
* @var \Drupal\views\Plugin\views\query\QueryPluginBase
|
||||
*/
|
||||
public $query = NULL;
|
||||
public ?QueryPluginBase $query = NULL;
|
||||
|
||||
/**
|
||||
* The used pager plugin used by the current executed view.
|
||||
|
|
Loading…
Reference in New Issue