Merged 11.0.8.

merge-requests/8400/merge
Dave Long 2024-11-20 17:59:39 +00:00
commit c3c6801a47
No known key found for this signature in database
GPG Key ID: ED52AE211E142771
8 changed files with 74 additions and 20 deletions

4
composer.lock generated
View File

@ -9336,8 +9336,8 @@
},
"prefer-stable": true,
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"platform": {},
"platform-dev": {},
"platform-overrides": {
"php": "8.3.0"
},

View File

@ -2,6 +2,8 @@
namespace Drupal\Core\Ajax;
use Drupal\Component\Render\MarkupInterface;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Asset\AttachedAssets;
/**
@ -68,7 +70,7 @@ class MessageCommand implements CommandInterface, CommandWithAttachedAssetsInter
/**
* The message text.
*
* @var string
* @var string|\Drupal\Component\Render\MarkupInterface
*/
protected $message;
@ -96,7 +98,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
@ -120,7 +122,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,

View File

@ -4,6 +4,7 @@ namespace Drupal\Core\Config;
use Drupal\Component\Datetime\Time;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Cache\MemoryBackend;
use Drupal\Core\Cache\NullBackend;
use Drupal\Core\Config\Entity\ConfigDependencyManager;
@ -85,7 +86,7 @@ class StorageComparer implements StorageComparerInterface {
*
* @var \Drupal\Core\Cache\CacheBackendInterface
*/
protected $targetCacheStorage;
protected CacheBackendInterface $targetCacheStorage;
/**
* Indicates whether the target storage should be wrapped in a cache.

View File

@ -17,6 +17,16 @@ class UniqueFieldConstraint extends SymfonyConstraint {
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;
/**
* {@inheritdoc}
*/

View File

@ -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)) {

View File

@ -4,7 +4,8 @@ namespace Drupal\file\Plugin\Validation\Constraint;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Validation\Attribute\Constraint;
use Symfony\Component\Validator\Constraint as SymfonyConstraint;
use Drupal\Core\Validation\Plugin\Validation\Constraint\UniqueFieldConstraint;
use Drupal\Core\Validation\Plugin\Validation\Constraint\UniqueFieldValueValidator;
/**
* Supports validating file URIs.
@ -13,15 +14,25 @@ use Symfony\Component\Validator\Constraint as SymfonyConstraint;
id: 'FileUriUnique',
label: new TranslatableMarkup('File URI', [], ['context' => 'Validation'])
)]
class FileUriUnique extends SymfonyConstraint {
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(): string {
return '\Drupal\Core\Validation\Plugin\Validation\Constraint\UniqueFieldValueValidator';
return UniqueFieldValueValidator::class;
}
}

View File

@ -98,6 +98,7 @@ function user_requirements($phase): array {
if ($phase !== 'runtime') {
return [];
}
$return = [];
$result = (bool) \Drupal::entityQuery('user')
->accessCheck(FALSE)
@ -106,17 +107,32 @@ function user_requirements($phase): array {
->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,
],
$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,
];
}
return [];
$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;
}
/**

View File

@ -8,6 +8,7 @@ use Drupal\Core\Logger\LoggerChannelTrait;
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 Drupal\views\Plugin\ViewsPluginManager;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@ -219,7 +220,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.