Update Composer, update everything
This commit is contained in:
parent
ea3e94409f
commit
dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions
|
@ -11,7 +11,7 @@ register_no_approval_required:
|
|||
body: "[user:display-name],\n\nThank you for registering at [site:name]. You may now log in by clicking this link or copying and pasting it into your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n-- [site:name] team"
|
||||
subject: 'Account details for [user:display-name] at [site:name]'
|
||||
register_pending_approval:
|
||||
body: "[user:display-name],\n\nThank you for registering at [site:name]. Your application for an account is currently pending approval. Once it has been approved, you will receive another email containing information about how to log in, set your password, and other details.\n\n\n-- [site:name] team"
|
||||
body: "[user:display-name],\n\nThank you for registering at [site:name]. Your application for an account is currently pending approval. Once it has been approved, you will receive another email containing information about how to log in, set your password, and other details.\n\n-- [site:name] team"
|
||||
subject: 'Account details for [user:display-name] at [site:name] (pending admin approval)'
|
||||
register_pending_approval_admin:
|
||||
body: "[user:display-name] has applied for an account.\n\n[user:edit-url]"
|
||||
|
|
|
@ -166,8 +166,10 @@ condition.plugin.user_role:
|
|||
sequence:
|
||||
type: string
|
||||
|
||||
# Schema for the entity reference 'default:user' selection handler settings.
|
||||
entity_reference_selection.default:user:
|
||||
type: entity_reference_selection
|
||||
type: entity_reference_selection.default
|
||||
label: 'User selection handler settings'
|
||||
mapping:
|
||||
filter:
|
||||
type: mapping
|
||||
|
|
|
@ -18,5 +18,5 @@
|
|||
/* Account settings */
|
||||
.user-admin-settings .details-description {
|
||||
font-size: 0.85em;
|
||||
padding-bottom: .5em;
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ label: Profile values
|
|||
class: Drupal\user\Plugin\migrate\ProfileValues
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Content
|
||||
source:
|
||||
plugin: d6_profile_field_values
|
||||
process:
|
|
@ -1,7 +1,9 @@
|
|||
id: d6_user
|
||||
label: User accounts
|
||||
audit: true
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Content
|
||||
source:
|
||||
plugin: d6_user
|
||||
process:
|
|
@ -2,6 +2,7 @@ id: d6_user_contact_settings
|
|||
label: User contact settings
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Content
|
||||
source:
|
||||
plugin: d6_user
|
||||
constants:
|
|
@ -2,6 +2,7 @@ id: d6_user_mail
|
|||
label: User mail configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
|
@ -19,6 +20,7 @@ source:
|
|||
- user_mail_register_pending_approval_body
|
||||
- user_mail_status_blocked_subject
|
||||
- user_mail_status_blocked_body
|
||||
source_module: user
|
||||
process:
|
||||
'status_activated/subject':
|
||||
plugin: convert_tokens
|
|
@ -2,6 +2,7 @@ id: d6_user_picture_file
|
|||
label: User pictures
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Content
|
||||
source:
|
||||
plugin: d6_user_picture_file
|
||||
constants:
|
|
@ -2,6 +2,7 @@ id: d6_user_role
|
|||
label: User roles
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Configuration
|
||||
source:
|
||||
plugin: d6_user_role
|
||||
process:
|
|
@ -2,6 +2,7 @@ id: d6_user_settings
|
|||
label: User configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
|
@ -10,6 +11,7 @@ source:
|
|||
- user_email_verification
|
||||
- user_register
|
||||
- anonymous
|
||||
source_module: user
|
||||
process:
|
||||
'notify/status_blocked': user_mail_status_blocked_notify
|
||||
'notify/status_activated': user_mail_status_activated_notify
|
|
@ -1,7 +1,9 @@
|
|||
id: d7_user
|
||||
label: User accounts
|
||||
audit: true
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
- Content
|
||||
class: Drupal\user\Plugin\migrate\User
|
||||
source:
|
||||
plugin: d7_user
|
||||
|
@ -19,7 +21,7 @@ process:
|
|||
timezone: timezone
|
||||
langcode:
|
||||
plugin: user_langcode
|
||||
source: language
|
||||
source: entity_language
|
||||
fallback_to_site_default: false
|
||||
preferred_langcode:
|
||||
plugin: user_langcode
|
||||
|
@ -55,4 +57,3 @@ migration_dependencies:
|
|||
- user_picture_field_instance
|
||||
- user_picture_entity_display
|
||||
- user_picture_entity_form_display
|
||||
- d7_field_instance
|
|
@ -2,6 +2,7 @@ id: d7_user_flood
|
|||
label: User flood configuration
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
|
@ -10,6 +11,7 @@ source:
|
|||
- user_failed_login_ip_window
|
||||
- user_failed_login_user_window
|
||||
- user_failed_login_user_limit
|
||||
source_module: user
|
||||
process:
|
||||
uid_only: user_failed_login_identifier_uid_only
|
||||
ip_limit: user_failed_login_ip_limit
|
|
@ -2,6 +2,7 @@ id: d7_user_mail
|
|||
label: User mail configuration
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
|
@ -19,6 +20,7 @@ source:
|
|||
- user_mail_register_pending_approval_body
|
||||
- user_mail_status_blocked_subject
|
||||
- user_mail_status_blocked_body
|
||||
source_module: user
|
||||
process:
|
||||
'status_activated/subject': user_mail_status_activated_subject
|
||||
'status_activated/body': user_mail_status_activated_body
|
|
@ -2,6 +2,7 @@ id: d7_user_role
|
|||
label: User roles
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: d7_user_role
|
||||
process:
|
|
@ -3,6 +3,7 @@ label: User picture display configuration
|
|||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: user_picture_instance
|
||||
constants:
|
|
@ -3,6 +3,7 @@ label: User picture form display configuration
|
|||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: user_picture_instance
|
||||
constants:
|
|
@ -3,6 +3,7 @@ label: User picture field configuration
|
|||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
# We do an empty source and a proper destination to have an idmap for
|
||||
# dependencies.
|
||||
|
@ -12,6 +13,7 @@ source:
|
|||
type: image
|
||||
name: user_picture
|
||||
cardinality: 1
|
||||
source_module: user
|
||||
process:
|
||||
entity_type: 'constants/entity_type'
|
||||
field_name: 'constants/name'
|
|
@ -3,6 +3,7 @@ label: User picture field instance configuration
|
|||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: user_picture_instance
|
||||
constants:
|
|
@ -3,6 +3,7 @@ label: User profile display configuration
|
|||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: profile_field
|
||||
constants:
|
||||
|
@ -16,7 +17,18 @@ process:
|
|||
entity_type: 'constants/entity_type'
|
||||
bundle: 'constants/bundle'
|
||||
view_mode: 'constants/view_mode'
|
||||
field_name: name
|
||||
field_name:
|
||||
-
|
||||
plugin: migration_lookup
|
||||
migration: user_profile_field
|
||||
source: fid
|
||||
-
|
||||
plugin: skip_on_empty
|
||||
method: row
|
||||
-
|
||||
plugin: extract
|
||||
index:
|
||||
- 1
|
||||
type:
|
||||
plugin: static_map
|
||||
source: type
|
|
@ -3,6 +3,7 @@ label: User profile form display configuration
|
|||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: profile_field
|
||||
constants:
|
||||
|
@ -13,7 +14,18 @@ source:
|
|||
process:
|
||||
entity_type: 'constants/entity_type'
|
||||
bundle: 'constants/bundle'
|
||||
field_name: name
|
||||
field_name:
|
||||
-
|
||||
plugin: migration_lookup
|
||||
migration: user_profile_field
|
||||
source: fid
|
||||
-
|
||||
plugin: skip_on_empty
|
||||
method: row
|
||||
-
|
||||
plugin: extract
|
||||
index:
|
||||
- 1
|
||||
form_mode: 'constants/form_mode'
|
||||
type:
|
||||
plugin: static_map
|
|
@ -3,13 +3,22 @@ label: User profile field configuration
|
|||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: profile_field
|
||||
constants:
|
||||
entity_type: user
|
||||
process:
|
||||
entity_type: 'constants/entity_type'
|
||||
field_name: name
|
||||
field_name:
|
||||
-
|
||||
plugin: machine_name
|
||||
source: name
|
||||
-
|
||||
plugin: make_unique_entity_field
|
||||
length: 30
|
||||
entity_type: field_storage_config
|
||||
field: field_name
|
||||
type:
|
||||
plugin: static_map
|
||||
source: type
|
|
@ -3,6 +3,7 @@ label: User profile field instance configuration
|
|||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: profile_field
|
||||
constants:
|
||||
|
@ -13,7 +14,18 @@ process:
|
|||
bundle: 'constants/bundle'
|
||||
label: title
|
||||
description: explanation
|
||||
field_name: name
|
||||
field_name:
|
||||
-
|
||||
plugin: migration_lookup
|
||||
migration: user_profile_field
|
||||
source: fid
|
||||
-
|
||||
plugin: skip_on_empty
|
||||
method: row
|
||||
-
|
||||
plugin: extract
|
||||
index:
|
||||
- 1
|
||||
required: required
|
||||
destination:
|
||||
plugin: entity:field_config
|
|
@ -26,7 +26,11 @@ class LoginStatusCheck implements AccessInterface {
|
|||
public function access(AccountInterface $account, Route $route) {
|
||||
$required_status = filter_var($route->getRequirement('_user_is_logged_in'), FILTER_VALIDATE_BOOLEAN);
|
||||
$actual_status = $account->isAuthenticated();
|
||||
return AccessResult::allowedIf($required_status === $actual_status)->addCacheContexts(['user.roles:authenticated']);
|
||||
$access_result = AccessResult::allowedIf($required_status === $actual_status)->addCacheContexts(['user.roles:authenticated']);
|
||||
if (!$access_result->isAllowed()) {
|
||||
$access_result->setReason($required_status === TRUE ? 'This route can only be accessed by authenticated users.' : 'This route can only be accessed by anonymous users.');
|
||||
}
|
||||
return $access_result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use Drupal\Component\Datetime\TimeInterface;
|
|||
use Drupal\Component\Utility\Crypt;
|
||||
use Drupal\Core\Entity\ContentEntityForm;
|
||||
use Drupal\Core\Entity\EntityConstraintViolationListInterface;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Entity\EntityRepositoryInterface;
|
||||
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
|
@ -31,8 +31,8 @@ abstract class AccountForm extends ContentEntityForm {
|
|||
/**
|
||||
* Constructs a new EntityForm object.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
|
||||
* The entity repository.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager.
|
||||
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
|
||||
|
@ -40,8 +40,8 @@ abstract class AccountForm extends ContentEntityForm {
|
|||
* @param \Drupal\Component\Datetime\TimeInterface $time
|
||||
* The time service.
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $entity_manager, LanguageManagerInterface $language_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL) {
|
||||
parent::__construct($entity_manager, $entity_type_bundle_info, $time);
|
||||
public function __construct(EntityRepositoryInterface $entity_repository, LanguageManagerInterface $language_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL) {
|
||||
parent::__construct($entity_repository, $entity_type_bundle_info, $time);
|
||||
$this->languageManager = $language_manager;
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ abstract class AccountForm extends ContentEntityForm {
|
|||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('entity.manager'),
|
||||
$container->get('entity.repository'),
|
||||
$container->get('language_manager'),
|
||||
$container->get('entity_type.bundle.info'),
|
||||
$container->get('datetime.time')
|
||||
|
@ -85,7 +85,7 @@ abstract class AccountForm extends ContentEntityForm {
|
|||
'#type' => 'email',
|
||||
'#title' => $this->t('Email address'),
|
||||
'#description' => $this->t('A valid email address. All emails from the system will be sent to this address. The email address is not made public and will only be used if you wish to receive a new password or wish to receive certain news or notifications by email.'),
|
||||
'#required' => !(!$account->getEmail() && $user->hasPermission('administer users')),
|
||||
'#required' => !(!$account->getEmail() && $admin),
|
||||
'#default_value' => (!$register ? $account->getEmail() : ''),
|
||||
];
|
||||
|
||||
|
@ -161,7 +161,7 @@ abstract class AccountForm extends ContentEntityForm {
|
|||
|
||||
// When not building the user registration form, prevent web browsers from
|
||||
// autofilling/prefilling the email, username, and password fields.
|
||||
if ($this->getOperation() != 'register') {
|
||||
if (!$register) {
|
||||
foreach (['mail', 'name', 'pass'] as $key) {
|
||||
if (isset($form['account'][$key])) {
|
||||
$form['account'][$key]['#attributes']['autocomplete'] = 'off';
|
||||
|
@ -222,7 +222,7 @@ abstract class AccountForm extends ContentEntityForm {
|
|||
'#open' => TRUE,
|
||||
// Display language selector when either creating a user on the admin
|
||||
// interface or editing a user account.
|
||||
'#access' => !$register || $user->hasPermission('administer users'),
|
||||
'#access' => !$register || $admin,
|
||||
];
|
||||
|
||||
$form['language']['preferred_langcode'] = [
|
||||
|
@ -347,7 +347,7 @@ abstract class AccountForm extends ContentEntityForm {
|
|||
'timezone',
|
||||
'langcode',
|
||||
'preferred_langcode',
|
||||
'preferred_admin_langcode'
|
||||
'preferred_admin_langcode',
|
||||
], parent::getEditedFieldNames($form_state));
|
||||
}
|
||||
|
||||
|
@ -365,7 +365,7 @@ abstract class AccountForm extends ContentEntityForm {
|
|||
'timezone',
|
||||
'langcode',
|
||||
'preferred_langcode',
|
||||
'preferred_admin_langcode'
|
||||
'preferred_admin_langcode',
|
||||
];
|
||||
foreach ($violations->getByFields($field_names) as $violation) {
|
||||
list($field_name) = explode('.', $violation->getPropertyPath(), 2);
|
||||
|
|
|
@ -11,6 +11,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
|
||||
/**
|
||||
* Configure user settings for this site.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class AccountSettingsForm extends ConfigFormBase {
|
||||
|
||||
|
@ -152,13 +154,13 @@ class AccountSettingsForm extends ConfigFormBase {
|
|||
USER_REGISTER_ADMINISTRATORS_ONLY => $this->t('Administrators only'),
|
||||
USER_REGISTER_VISITORS => $this->t('Visitors'),
|
||||
USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL => $this->t('Visitors, but administrator approval is required'),
|
||||
]
|
||||
],
|
||||
];
|
||||
$form['registration_cancellation']['user_email_verification'] = [
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Require email verification when a visitor creates an account'),
|
||||
'#default_value' => $config->get('verify_mail'),
|
||||
'#description' => $this->t('New users will be required to validate their email address prior to logging into the site, and will be assigned a system-generated password. With this setting disabled, users will be logged in immediately upon registering, and may select their own passwords during registration.')
|
||||
'#description' => $this->t('New users will be required to validate their email address prior to logging into the site, and will be assigned a system-generated password. With this setting disabled, users will be logged in immediately upon registering, and may select their own passwords during registration.'),
|
||||
];
|
||||
$form['registration_cancellation']['user_password_strength'] = [
|
||||
'#type' => 'checkbox',
|
||||
|
|
|
@ -4,9 +4,8 @@ namespace Drupal\user\ContextProvider;
|
|||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Plugin\Context\Context;
|
||||
use Drupal\Core\Plugin\Context\ContextDefinition;
|
||||
use Drupal\Core\Plugin\Context\ContextProviderInterface;
|
||||
use Drupal\Core\Plugin\Context\EntityContext;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
|
||||
|
@ -50,7 +49,13 @@ class CurrentUserContext implements ContextProviderInterface {
|
|||
public function getRuntimeContexts(array $unqualified_context_ids) {
|
||||
$current_user = $this->userStorage->load($this->account->id());
|
||||
|
||||
$context = new Context(new ContextDefinition('entity:user', $this->t('Current user')), $current_user);
|
||||
if ($current_user) {
|
||||
// @todo Do not validate protected fields to avoid bug in TypedData,
|
||||
// remove this in https://www.drupal.org/project/drupal/issues/2934192.
|
||||
$current_user->_skipProtectedUserFieldConstraint = TRUE;
|
||||
}
|
||||
|
||||
$context = EntityContext::fromEntity($current_user, $this->t('Current user'));
|
||||
$cacheability = new CacheableMetadata();
|
||||
$cacheability->setCacheContexts(['user']);
|
||||
$context->addCacheableDependency($cacheability);
|
||||
|
|
|
@ -10,6 +10,7 @@ use Drupal\Core\Routing\RouteProviderInterface;
|
|||
use Drupal\user\UserAuthInterface;
|
||||
use Drupal\user\UserInterface;
|
||||
use Drupal\user\UserStorageInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
@ -86,6 +87,13 @@ class UserAuthenticationController extends ControllerBase implements ContainerIn
|
|||
*/
|
||||
protected $serializerFormats = [];
|
||||
|
||||
/**
|
||||
* A logger instance.
|
||||
*
|
||||
* @var \Psr\Log\LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* Constructs a new UserAuthenticationController object.
|
||||
*
|
||||
|
@ -103,8 +111,10 @@ class UserAuthenticationController extends ControllerBase implements ContainerIn
|
|||
* The serializer.
|
||||
* @param array $serializer_formats
|
||||
* The available serialization formats.
|
||||
* @param \Psr\Log\LoggerInterface $logger
|
||||
* A logger instance.
|
||||
*/
|
||||
public function __construct(FloodInterface $flood, UserStorageInterface $user_storage, CsrfTokenGenerator $csrf_token, UserAuthInterface $user_auth, RouteProviderInterface $route_provider, Serializer $serializer, array $serializer_formats) {
|
||||
public function __construct(FloodInterface $flood, UserStorageInterface $user_storage, CsrfTokenGenerator $csrf_token, UserAuthInterface $user_auth, RouteProviderInterface $route_provider, Serializer $serializer, array $serializer_formats, LoggerInterface $logger) {
|
||||
$this->flood = $flood;
|
||||
$this->userStorage = $user_storage;
|
||||
$this->csrfToken = $csrf_token;
|
||||
|
@ -112,6 +122,7 @@ class UserAuthenticationController extends ControllerBase implements ContainerIn
|
|||
$this->serializer = $serializer;
|
||||
$this->serializerFormats = $serializer_formats;
|
||||
$this->routeProvider = $route_provider;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -135,7 +146,8 @@ class UserAuthenticationController extends ControllerBase implements ContainerIn
|
|||
$container->get('user.auth'),
|
||||
$container->get('router.route_provider'),
|
||||
$serializer,
|
||||
$formats
|
||||
$formats,
|
||||
$container->get('logger.factory')->get('user')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -207,6 +219,56 @@ class UserAuthenticationController extends ControllerBase implements ContainerIn
|
|||
throw new BadRequestHttpException('Sorry, unrecognized username or password.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets a user password.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The request.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* The response object.
|
||||
*/
|
||||
public function resetPassword(Request $request) {
|
||||
$format = $this->getRequestFormat($request);
|
||||
|
||||
$content = $request->getContent();
|
||||
$credentials = $this->serializer->decode($content, $format);
|
||||
|
||||
// Check if a name or mail is provided.
|
||||
if (!isset($credentials['name']) && !isset($credentials['mail'])) {
|
||||
throw new BadRequestHttpException('Missing credentials.name or credentials.mail');
|
||||
}
|
||||
|
||||
// Load by name if provided.
|
||||
if (isset($credentials['name'])) {
|
||||
$users = $this->userStorage->loadByProperties(['name' => trim($credentials['name'])]);
|
||||
}
|
||||
elseif (isset($credentials['mail'])) {
|
||||
$users = $this->userStorage->loadByProperties(['mail' => trim($credentials['mail'])]);
|
||||
}
|
||||
|
||||
/** @var \Drupal\Core\Session\AccountInterface $account */
|
||||
$account = reset($users);
|
||||
if ($account && $account->id()) {
|
||||
if ($this->userIsBlocked($account->getAccountName())) {
|
||||
throw new BadRequestHttpException('The user has not been activated or is blocked.');
|
||||
}
|
||||
|
||||
// Send the password reset email.
|
||||
$mail = _user_mail_notify('password_reset', $account, $account->getPreferredLangcode());
|
||||
if (empty($mail)) {
|
||||
throw new BadRequestHttpException('Unable to send email. Contact the site administrator if the problem persists.');
|
||||
}
|
||||
else {
|
||||
$this->logger->notice('Password reset instructions mailed to %name at %email.', ['%name' => $account->getAccountName(), '%email' => $account->getEmail()]);
|
||||
return new Response();
|
||||
}
|
||||
}
|
||||
|
||||
// Error if no users found with provided name or mail.
|
||||
throw new BadRequestHttpException('Unrecognized username or email address.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies if the user is blocked.
|
||||
*
|
||||
|
|
|
@ -120,12 +120,17 @@ class UserController extends ControllerBase {
|
|||
else {
|
||||
/** @var \Drupal\user\UserInterface $reset_link_user */
|
||||
if ($reset_link_user = $this->userStorage->load($uid)) {
|
||||
drupal_set_message($this->t('Another user (%other_user) is already logged into the site on this computer, but you tried to use a one-time link for user %resetting_user. Please <a href=":logout">log out</a> and try using the link again.',
|
||||
['%other_user' => $account->getUsername(), '%resetting_user' => $reset_link_user->getUsername(), ':logout' => $this->url('user.logout')]), 'warning');
|
||||
$this->messenger()
|
||||
->addWarning($this->t('Another user (%other_user) is already logged into the site on this computer, but you tried to use a one-time link for user %resetting_user. Please <a href=":logout">log out</a> and try using the link again.',
|
||||
[
|
||||
'%other_user' => $account->getUsername(),
|
||||
'%resetting_user' => $reset_link_user->getUsername(),
|
||||
':logout' => $this->url('user.logout'),
|
||||
]));
|
||||
}
|
||||
else {
|
||||
// Invalid one-time link specifies an unknown user.
|
||||
drupal_set_message($this->t('The one-time login link you clicked is invalid.'), 'error');
|
||||
$this->messenger()->addError($this->t('The one-time login link you clicked is invalid.'));
|
||||
}
|
||||
return $this->redirect('<front>');
|
||||
}
|
||||
|
@ -218,13 +223,13 @@ class UserController extends ControllerBase {
|
|||
$timeout = $this->config('user.settings')->get('password_reset_timeout');
|
||||
// No time out for first time login.
|
||||
if ($user->getLastLoginTime() && $current - $timestamp > $timeout) {
|
||||
drupal_set_message($this->t('You have tried to use a one-time login link that has expired. Please request a new one using the form below.'), 'error');
|
||||
$this->messenger()->addError($this->t('You have tried to use a one-time login link that has expired. Please request a new one using the form below.'));
|
||||
return $this->redirect('user.pass');
|
||||
}
|
||||
elseif ($user->isAuthenticated() && ($timestamp >= $user->getLastLoginTime()) && ($timestamp <= $current) && Crypt::hashEquals($hash, user_pass_rehash($user, $timestamp))) {
|
||||
user_login_finalize($user);
|
||||
$this->logger->notice('User %name used one-time login link at time %timestamp.', ['%name' => $user->getDisplayName(), '%timestamp' => $timestamp]);
|
||||
drupal_set_message($this->t('You have just used your one-time login link. It is no longer necessary to use this link to log in. Please change your password.'));
|
||||
$this->messenger()->addStatus($this->t('You have just used your one-time login link. It is no longer necessary to use this link to log in. Please change your password.'));
|
||||
// Let the user's password be changed without the current password
|
||||
// check.
|
||||
$token = Crypt::randomBytesBase64(55);
|
||||
|
@ -239,7 +244,7 @@ class UserController extends ControllerBase {
|
|||
);
|
||||
}
|
||||
|
||||
drupal_set_message($this->t('You have tried to use a one-time login link that has either been used or is no longer valid. Please request a new one using the form below.'), 'error');
|
||||
$this->messenger()->addError($this->t('You have tried to use a one-time login link that has either been used or is no longer valid. Please request a new one using the form below.'));
|
||||
return $this->redirect('user.pass');
|
||||
}
|
||||
|
||||
|
@ -268,7 +273,7 @@ class UserController extends ControllerBase {
|
|||
* NULL.
|
||||
*/
|
||||
public function userTitle(UserInterface $user = NULL) {
|
||||
return $user ? ['#markup' => $user->getUsername(), '#allowed_tags' => Xss::getHtmlTagList()] : '';
|
||||
return $user ? ['#markup' => $user->getDisplayName(), '#allowed_tags' => Xss::getHtmlTagList()] : '';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -312,10 +317,10 @@ class UserController extends ControllerBase {
|
|||
// Since user_cancel() is not invoked via Form API, batch processing
|
||||
// needs to be invoked manually and should redirect to the front page
|
||||
// after completion.
|
||||
return batch_process('');
|
||||
return batch_process('<front>');
|
||||
}
|
||||
else {
|
||||
drupal_set_message(t('You have tried to use an account cancellation link that has expired. Please request a new one using the form below.'), 'error');
|
||||
$this->messenger()->addError($this->t('You have tried to use an account cancellation link that has expired. Please request a new one using the form below.'));
|
||||
return $this->redirect('entity.user.cancel_form', ['user' => $user->id()], ['absolute' => TRUE]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,13 @@ use Drupal\user\RoleInterface;
|
|||
* @ConfigEntityType(
|
||||
* id = "user_role",
|
||||
* label = @Translation("Role"),
|
||||
* label_collection = @Translation("Roles"),
|
||||
* label_singular = @Translation("role"),
|
||||
* label_plural = @Translation("roles"),
|
||||
* label_count = @PluralTranslation(
|
||||
* singular = "@count role",
|
||||
* plural = "@count roles",
|
||||
* ),
|
||||
* handlers = {
|
||||
* "storage" = "Drupal\user\RoleStorage",
|
||||
* "access" = "Drupal\user\RoleAccessControlHandler",
|
||||
|
@ -173,7 +180,7 @@ class Role extends ConfigEntityBase implements RoleInterface {
|
|||
|
||||
if (!isset($this->weight) && ($roles = $storage->loadMultiple())) {
|
||||
// Set a role weight to make this new role last.
|
||||
$max = array_reduce($roles, function($max, $role) {
|
||||
$max = array_reduce($roles, function ($max, $role) {
|
||||
return $max > $role->weight ? $max : $role->weight;
|
||||
});
|
||||
$this->weight = $max + 1;
|
||||
|
|
|
@ -9,6 +9,8 @@ use Drupal\Core\Entity\EntityTypeInterface;
|
|||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\user\RoleInterface;
|
||||
use Drupal\user\StatusItem;
|
||||
use Drupal\user\TimeZoneItem;
|
||||
use Drupal\user\UserInterface;
|
||||
|
||||
/**
|
||||
|
@ -20,6 +22,13 @@ use Drupal\user\UserInterface;
|
|||
* @ContentEntityType(
|
||||
* id = "user",
|
||||
* label = @Translation("User"),
|
||||
* label_collection = @Translation("Users"),
|
||||
* label_singular = @Translation("user"),
|
||||
* label_plural = @Translation("users"),
|
||||
* label_count = @PluralTranslation(
|
||||
* singular = "@count user",
|
||||
* plural = "@count users",
|
||||
* ),
|
||||
* handlers = {
|
||||
* "storage" = "Drupal\user\UserStorage",
|
||||
* "storage_schema" = "Drupal\user\UserStorageSchema",
|
||||
|
@ -346,6 +355,7 @@ class User extends ContentEntityBase implements UserInterface {
|
|||
public function isAuthenticated() {
|
||||
return $this->id() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -418,7 +428,7 @@ class User extends ContentEntityBase implements UserInterface {
|
|||
'name' => [LanguageInterface::LANGCODE_DEFAULT => ''],
|
||||
// Explicitly set the langcode to ensure that field definitions do not
|
||||
// need to be fetched to figure out a default.
|
||||
'langcode' => [LanguageInterface::LANGCODE_DEFAULT => LanguageInterface::LANGCODE_NOT_SPECIFIED]
|
||||
'langcode' => [LanguageInterface::LANGCODE_DEFAULT => LanguageInterface::LANGCODE_NOT_SPECIFIED],
|
||||
], $entity_type->id());
|
||||
}
|
||||
return clone static::$anonymousUser;
|
||||
|
@ -498,11 +508,13 @@ class User extends ContentEntityBase implements UserInterface {
|
|||
->addPropertyConstraints('value', [
|
||||
'AllowedValues' => ['callback' => __CLASS__ . '::getAllowedTimezones'],
|
||||
]);
|
||||
$fields['timezone']->getItemDefinition()->setClass(TimeZoneItem::class);
|
||||
|
||||
$fields['status'] = BaseFieldDefinition::create('boolean')
|
||||
->setLabel(t('User status'))
|
||||
->setDescription(t('Whether the user is active or blocked.'))
|
||||
->setDefaultValue(FALSE);
|
||||
$fields['status']->getItemDefinition()->setClass(StatusItem::class);
|
||||
|
||||
$fields['created'] = BaseFieldDefinition::create('created')
|
||||
->setLabel(t('Created'))
|
||||
|
|
|
@ -7,6 +7,8 @@ use Drupal\Core\Form\FormStateInterface;
|
|||
|
||||
/**
|
||||
* Provides a confirmation form for cancelling user account.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class UserCancelForm extends ContentEntityConfirmFormBase {
|
||||
|
||||
|
@ -137,7 +139,7 @@ class UserCancelForm extends ContentEntityConfirmFormBase {
|
|||
$this->entity->user_cancel_notify = $form_state->getValue('user_cancel_notify');
|
||||
$this->entity->save();
|
||||
_user_mail_notify('cancel_confirm', $this->entity);
|
||||
drupal_set_message($this->t('A confirmation request to cancel your account has been sent to your email address.'));
|
||||
$this->messenger()->addStatus($this->t('A confirmation request to cancel your account has been sent to your email address.'));
|
||||
$this->logger('user')->notice('Sent account cancellation request to %name %email.', ['%name' => $this->entity->label(), '%email' => '<' . $this->entity->getEmail() . '>']);
|
||||
|
||||
$form_state->setRedirect(
|
||||
|
|
|
@ -12,6 +12,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
|
||||
/**
|
||||
* Provides a user login form.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class UserLoginForm extends FormBase {
|
||||
|
||||
|
|
|
@ -5,20 +5,23 @@ namespace Drupal\user\Form;
|
|||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Form\ConfirmFormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Messenger\MessengerInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\user\PrivateTempStoreFactory;
|
||||
use Drupal\Core\TempStore\PrivateTempStoreFactory;
|
||||
use Drupal\user\UserStorageInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides a confirmation form for cancelling multiple user accounts.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class UserMultipleCancelConfirm extends ConfirmFormBase {
|
||||
|
||||
/**
|
||||
* The temp store factory.
|
||||
*
|
||||
* @var \Drupal\user\PrivateTempStoreFactory
|
||||
* @var \Drupal\Core\TempStore\PrivateTempStoreFactory
|
||||
*/
|
||||
protected $tempStoreFactory;
|
||||
|
||||
|
@ -39,7 +42,7 @@ class UserMultipleCancelConfirm extends ConfirmFormBase {
|
|||
/**
|
||||
* Constructs a new UserMultipleCancelConfirm.
|
||||
*
|
||||
* @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory
|
||||
* @param \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory
|
||||
* The temp store factory.
|
||||
* @param \Drupal\user\UserStorageInterface $user_storage
|
||||
* The user storage.
|
||||
|
@ -57,7 +60,7 @@ class UserMultipleCancelConfirm extends ConfirmFormBase {
|
|||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('user.private_tempstore'),
|
||||
$container->get('tempstore.private'),
|
||||
$container->get('entity.manager')->getStorage('user'),
|
||||
$container->get('entity.manager')
|
||||
);
|
||||
|
@ -130,7 +133,7 @@ class UserMultipleCancelConfirm extends ConfirmFormBase {
|
|||
if (isset($root)) {
|
||||
$redirect = (count($accounts) == 1);
|
||||
$message = $this->t('The user account %name cannot be canceled.', ['%name' => $root->label()]);
|
||||
drupal_set_message($message, $redirect ? 'error' : 'warning');
|
||||
$this->messenger()->addMessage($message, $redirect ? MessengerInterface::TYPE_ERROR : MessengerInterface::TYPE_WARNING);
|
||||
// If only user 1 was selected, redirect to the overview.
|
||||
if ($redirect) {
|
||||
return $this->redirect('entity.user.collection');
|
||||
|
|
|
@ -11,6 +11,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
|
||||
/**
|
||||
* Provides a user password reset form.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class UserPasswordForm extends FormBase {
|
||||
|
||||
|
@ -60,9 +62,6 @@ class UserPasswordForm extends FormBase {
|
|||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The request object.
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$form['name'] = [
|
||||
|
@ -141,7 +140,7 @@ class UserPasswordForm extends FormBase {
|
|||
$mail = _user_mail_notify('password_reset', $account, $langcode);
|
||||
if (!empty($mail)) {
|
||||
$this->logger('user')->notice('Password reset instructions mailed to %name at %email.', ['%name' => $account->getUsername(), '%email' => $account->getEmail()]);
|
||||
drupal_set_message($this->t('Further instructions have been sent to your email address.'));
|
||||
$this->messenger()->addStatus($this->t('Further instructions have been sent to your email address.'));
|
||||
}
|
||||
|
||||
$form_state->setRedirect('user.page');
|
||||
|
|
|
@ -9,6 +9,8 @@ use Drupal\Core\Url;
|
|||
|
||||
/**
|
||||
* Form controller for the user password forms.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class UserPasswordResetForm extends FormBase {
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
|
||||
/**
|
||||
* Provides the user permissions administration form.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class UserPermissionsForm extends FormBase {
|
||||
|
||||
|
@ -127,16 +129,33 @@ class UserPermissionsForm extends FormBase {
|
|||
$permissions_by_provider[$permission['provider']][$permission_name] = $permission;
|
||||
}
|
||||
|
||||
// Move the access content permission to the Node module if it is installed.
|
||||
if ($this->moduleHandler->moduleExists('node')) {
|
||||
// Insert 'access content' before the 'view own unpublished content' key
|
||||
// in order to maintain the UI even though the permission is provided by
|
||||
// the system module.
|
||||
$keys = array_keys($permissions_by_provider['node']);
|
||||
$offset = (int) array_search('view own unpublished content', $keys);
|
||||
$permissions_by_provider['node'] = array_merge(
|
||||
array_slice($permissions_by_provider['node'], 0, $offset),
|
||||
['access content' => $permissions_by_provider['system']['access content']],
|
||||
array_slice($permissions_by_provider['node'], $offset)
|
||||
);
|
||||
unset($permissions_by_provider['system']['access content']);
|
||||
}
|
||||
|
||||
foreach ($permissions_by_provider as $provider => $permissions) {
|
||||
// Module name.
|
||||
$form['permissions'][$provider] = [[
|
||||
'#wrapper_attributes' => [
|
||||
'colspan' => count($role_names) + 1,
|
||||
'class' => ['module'],
|
||||
'id' => 'module-' . $provider,
|
||||
$form['permissions'][$provider] = [
|
||||
[
|
||||
'#wrapper_attributes' => [
|
||||
'colspan' => count($role_names) + 1,
|
||||
'class' => ['module'],
|
||||
'id' => 'module-' . $provider,
|
||||
],
|
||||
'#markup' => $this->moduleHandler->getName($provider),
|
||||
],
|
||||
'#markup' => $this->moduleHandler->getName($provider),
|
||||
]];
|
||||
];
|
||||
foreach ($permissions as $perm => $perm_item) {
|
||||
// Fill in default values for the permission.
|
||||
$perm_item += [
|
||||
|
@ -197,7 +216,7 @@ class UserPermissionsForm extends FormBase {
|
|||
user_role_change_permissions($role_name, (array) $form_state->getValue($role_name));
|
||||
}
|
||||
|
||||
drupal_set_message($this->t('The changes have been saved.'));
|
||||
$this->messenger()->addStatus($this->t('The changes have been saved.'));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ use Drupal\user\RoleInterface;
|
|||
|
||||
/**
|
||||
* Provides the user permissions administration form for a specific role.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class UserPermissionsRoleSpecificForm extends UserPermissionsForm {
|
||||
|
||||
|
@ -25,10 +27,14 @@ class UserPermissionsRoleSpecificForm extends UserPermissionsForm {
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* Builds the user permissions administration form for a specific role.
|
||||
*
|
||||
* @param string $role_id
|
||||
* The user role ID used for this form.
|
||||
* @param array $form
|
||||
* An associative array containing the structure of the form.
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The current state of the form.
|
||||
* @param \Drupal\user\RoleInterface|null $user_role
|
||||
* (optional) The user role used for this form. Defaults to NULL.
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state, RoleInterface $user_role = NULL) {
|
||||
$this->userRole = $user_role;
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace Drupal\user\Plugin\Action;
|
|||
use Drupal\Core\Action\ActionBase;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\user\PrivateTempStoreFactory;
|
||||
use Drupal\Core\TempStore\PrivateTempStoreFactory;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
|
@ -23,7 +23,7 @@ class CancelUser extends ActionBase implements ContainerFactoryPluginInterface {
|
|||
/**
|
||||
* The tempstore factory.
|
||||
*
|
||||
* @var \Drupal\user\PrivateTempStoreFactory
|
||||
* @var \Drupal\Core\TempStore\PrivateTempStoreFactory
|
||||
*/
|
||||
protected $tempStoreFactory;
|
||||
|
||||
|
@ -35,7 +35,7 @@ class CancelUser extends ActionBase implements ContainerFactoryPluginInterface {
|
|||
protected $currentUser;
|
||||
|
||||
/**
|
||||
* Constructs a DeleteNode object.
|
||||
* Constructs a CancelUser object.
|
||||
*
|
||||
* @param array $configuration
|
||||
* A configuration array containing information about the plugin instance.
|
||||
|
@ -43,9 +43,9 @@ class CancelUser extends ActionBase implements ContainerFactoryPluginInterface {
|
|||
* The plugin ID for the plugin instance.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
* @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory
|
||||
* @param \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory
|
||||
* The tempstore factory.
|
||||
* @param AccountInterface $current_user
|
||||
* @param \Drupal\Core\Session\AccountInterface $current_user
|
||||
* Current user.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, PrivateTempStoreFactory $temp_store_factory, AccountInterface $current_user) {
|
||||
|
@ -63,7 +63,7 @@ class CancelUser extends ActionBase implements ContainerFactoryPluginInterface {
|
|||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('user.private_tempstore'),
|
||||
$container->get('tempstore.private'),
|
||||
$container->get('current_user')
|
||||
);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ use Drupal\Core\Access\AccessResult;
|
|||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Routing\RedirectDestinationTrait;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Core\Routing\UrlGeneratorTrait;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Block\BlockBase;
|
||||
|
@ -23,7 +22,6 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
*/
|
||||
class UserLoginBlock extends BlockBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
use UrlGeneratorTrait;
|
||||
use RedirectDestinationTrait;
|
||||
|
||||
/**
|
||||
|
@ -66,7 +64,6 @@ class UserLoginBlock extends BlockBase implements ContainerFactoryPluginInterfac
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -94,7 +91,24 @@ class UserLoginBlock extends BlockBase implements ContainerFactoryPluginInterfac
|
|||
unset($form['pass']['#attributes']['aria-describedby']);
|
||||
$form['name']['#size'] = 15;
|
||||
$form['pass']['#size'] = 15;
|
||||
$form['#action'] = $this->url('<current>', [], ['query' => $this->getDestinationArray(), 'external' => FALSE]);
|
||||
|
||||
// Instead of setting an actual action URL, we set the placeholder, which
|
||||
// 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 placeholder uses a fixed string
|
||||
// that is
|
||||
// Crypt::hashBase64('\Drupal\user\Plugin\Block\UserLoginBlock::build');
|
||||
// This is based on the implementation in
|
||||
// \Drupal\Core\Form\FormBuilder::prepareForm(), but the user login block
|
||||
// requires different behavior for the destination query argument.
|
||||
$placeholder = 'form_action_p_4r8ITd22yaUvXM6SzwrSe9rnQWe48hz9k1Sxto3pBvE';
|
||||
|
||||
$form['#attached']['placeholders'][$placeholder] = [
|
||||
'#lazy_builder' => ['\Drupal\user\Plugin\Block\UserLoginBlock::renderPlaceholderFormAction', []],
|
||||
];
|
||||
$form['#action'] = $placeholder;
|
||||
|
||||
// Build action links.
|
||||
$items = [];
|
||||
if (\Drupal::config('user.settings')->get('register') != USER_REGISTER_ADMINISTRATORS_ONLY) {
|
||||
|
@ -128,4 +142,20 @@ class UserLoginBlock extends BlockBase implements ContainerFactoryPluginInterfac
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* #lazy_builder callback; renders a form action URL including destination.
|
||||
*
|
||||
* @return array
|
||||
* A renderable array representing the form action.
|
||||
*
|
||||
* @see \Drupal\Core\Form\FormBuilder::renderPlaceholderFormAction()
|
||||
*/
|
||||
public static function renderPlaceholderFormAction() {
|
||||
return [
|
||||
'#type' => 'markup',
|
||||
'#markup' => Url::fromRoute('<current>', [], ['query' => \Drupal::destination()->getAsArray(), 'external' => FALSE])->toString(),
|
||||
'#cache' => ['contexts' => ['url.path', 'url.query_args']],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Drupal\user\Plugin\EntityReferenceSelection;
|
||||
|
||||
use Drupal\Core\Database\Connection;
|
||||
use Drupal\Core\Database\Query\Condition;
|
||||
use Drupal\Core\Database\Query\SelectInterface;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection;
|
||||
|
@ -82,21 +83,26 @@ class UserSelection extends DefaultSelection {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
$selection_handler_settings = $this->configuration['handler_settings'];
|
||||
|
||||
// Merge in default values.
|
||||
$selection_handler_settings += [
|
||||
public function defaultConfiguration() {
|
||||
return [
|
||||
'filter' => [
|
||||
'type' => '_none',
|
||||
'role' => NULL,
|
||||
],
|
||||
'include_anonymous' => TRUE,
|
||||
];
|
||||
] + parent::defaultConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
$configuration = $this->getConfiguration();
|
||||
|
||||
$form['include_anonymous'] = [
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Include the anonymous user.'),
|
||||
'#default_value' => $selection_handler_settings['include_anonymous'],
|
||||
'#default_value' => $configuration['include_anonymous'],
|
||||
];
|
||||
|
||||
// Add user specific filter options.
|
||||
|
@ -109,7 +115,7 @@ class UserSelection extends DefaultSelection {
|
|||
],
|
||||
'#ajax' => TRUE,
|
||||
'#limit_validation_errors' => [],
|
||||
'#default_value' => $selection_handler_settings['filter']['type'],
|
||||
'#default_value' => $configuration['filter']['type'],
|
||||
];
|
||||
|
||||
$form['filter']['settings'] = [
|
||||
|
@ -118,18 +124,13 @@ class UserSelection extends DefaultSelection {
|
|||
'#process' => [['\Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem', 'formProcessMergeParent']],
|
||||
];
|
||||
|
||||
if ($selection_handler_settings['filter']['type'] == 'role') {
|
||||
// Merge in default values.
|
||||
$selection_handler_settings['filter'] += [
|
||||
'role' => NULL,
|
||||
];
|
||||
|
||||
if ($configuration['filter']['type'] == 'role') {
|
||||
$form['filter']['settings']['role'] = [
|
||||
'#type' => 'checkboxes',
|
||||
'#title' => $this->t('Restrict to the selected roles'),
|
||||
'#required' => TRUE,
|
||||
'#options' => array_diff_key(user_role_names(TRUE), [RoleInterface::AUTHENTICATED_ID => RoleInterface::AUTHENTICATED_ID]),
|
||||
'#default_value' => $selection_handler_settings['filter']['role'],
|
||||
'#default_value' => $configuration['filter']['role'],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -143,11 +144,12 @@ class UserSelection extends DefaultSelection {
|
|||
*/
|
||||
protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') {
|
||||
$query = parent::buildEntityQuery($match, $match_operator);
|
||||
$handler_settings = $this->configuration['handler_settings'];
|
||||
|
||||
$configuration = $this->getConfiguration();
|
||||
|
||||
// Filter out the Anonymous user if the selection handler is configured to
|
||||
// exclude it.
|
||||
if (isset($handler_settings['include_anonymous']) && !$handler_settings['include_anonymous']) {
|
||||
if (!$configuration['include_anonymous']) {
|
||||
$query->condition('uid', 0, '<>');
|
||||
}
|
||||
|
||||
|
@ -157,8 +159,8 @@ class UserSelection extends DefaultSelection {
|
|||
}
|
||||
|
||||
// Filter by role.
|
||||
if (!empty($handler_settings['filter']['role'])) {
|
||||
$query->condition('roles', $handler_settings['filter']['role'], 'IN');
|
||||
if (!empty($configuration['filter']['role'])) {
|
||||
$query->condition('roles', $configuration['filter']['role'], 'IN');
|
||||
}
|
||||
|
||||
// Adding the permission check is sadly insufficient for users: core
|
||||
|
@ -190,10 +192,10 @@ class UserSelection extends DefaultSelection {
|
|||
public function validateReferenceableNewEntities(array $entities) {
|
||||
$entities = parent::validateReferenceableNewEntities($entities);
|
||||
// Mirror the conditions checked in buildEntityQuery().
|
||||
if (!empty($this->configuration['handler_settings']['filter']['role'])) {
|
||||
$entities = array_filter($entities, function ($user) {
|
||||
if ($role = $this->getConfiguration()['filter']['role']) {
|
||||
$entities = array_filter($entities, function ($user) use ($role) {
|
||||
/** @var \Drupal\user\UserInterface $user */
|
||||
return !empty(array_intersect($user->getRoles(), $this->configuration['handler_settings']['filter']['role']));
|
||||
return !empty(array_intersect($user->getRoles(), $role));
|
||||
});
|
||||
}
|
||||
if (!$this->currentUser->hasPermission('administer users')) {
|
||||
|
@ -209,9 +211,10 @@ class UserSelection extends DefaultSelection {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function entityQueryAlter(SelectInterface $query) {
|
||||
parent::entityQueryAlter($query);
|
||||
|
||||
// Bail out early if we do not need to match the Anonymous user.
|
||||
$handler_settings = $this->configuration['handler_settings'];
|
||||
if (isset($handler_settings['include_anonymous']) && !$handler_settings['include_anonymous']) {
|
||||
if (!$this->getConfiguration()['include_anonymous']) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -228,18 +231,18 @@ class UserSelection extends DefaultSelection {
|
|||
// Re-add the condition and a condition on uid = 0 so that we end up
|
||||
// with a query in the form:
|
||||
// WHERE (name LIKE :name) OR (:anonymous_name LIKE :name AND uid = 0)
|
||||
$or = db_or();
|
||||
$or = new Condition('OR');
|
||||
$or->condition($condition['field'], $condition['value'], $condition['operator']);
|
||||
// Sadly, the Database layer doesn't allow us to build a condition
|
||||
// in the form ':placeholder = :placeholder2', because the 'field'
|
||||
// part of a condition is always escaped.
|
||||
// As a (cheap) workaround, we separately build a condition with no
|
||||
// field, and concatenate the field and the condition separately.
|
||||
$value_part = db_and();
|
||||
$value_part = new Condition('AND');
|
||||
$value_part->condition('anonymous_name', $condition['value'], $condition['operator']);
|
||||
$value_part->compile($this->connection, $query);
|
||||
$or->condition(db_and()
|
||||
->where(str_replace('anonymous_name', ':anonymous_name', (string) $value_part), $value_part->arguments() + [':anonymous_name' => \Drupal::config('user.settings')->get('anonymous')])
|
||||
$or->condition((new Condition('AND'))
|
||||
->where(str_replace($query->escapeField('anonymous_name'), ':anonymous_name', (string) $value_part), $value_part->arguments() + [':anonymous_name' => \Drupal::config('user.settings')->get('anonymous')])
|
||||
->condition('base_table.uid', 0)
|
||||
);
|
||||
$query->condition($or);
|
||||
|
|
|
@ -30,10 +30,9 @@ class LanguageNegotiationUser extends LanguageNegotiationMethodBase {
|
|||
|
||||
// User preference (only for authenticated users).
|
||||
if ($this->languageManager && $this->currentUser->isAuthenticated()) {
|
||||
$preferred_langcode = $this->currentUser->getPreferredLangcode();
|
||||
$default_langcode = $this->languageManager->getDefaultLanguage()->getId();
|
||||
$preferred_langcode = $this->currentUser->getPreferredLangcode(FALSE);
|
||||
$languages = $this->languageManager->getLanguages();
|
||||
if (!empty($preferred_langcode) && $preferred_langcode != $default_langcode && isset($languages[$preferred_langcode])) {
|
||||
if (!empty($preferred_langcode) && isset($languages[$preferred_langcode])) {
|
||||
$langcode = $preferred_langcode;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,10 +127,14 @@ class LanguageNegotiationUserAdmin extends LanguageNegotiationMethodBase impleme
|
|||
$route_match = $this->stackedRouteMatch->getRouteMatchFromRequest($request);
|
||||
if ($route_match && !$route_object = $route_match->getRouteObject()) {
|
||||
try {
|
||||
// Some inbound path processors make changes to the request. Make a
|
||||
// copy as we're not actually routing the request so we do not want to
|
||||
// make changes.
|
||||
$cloned_request = clone $request;
|
||||
// Process the path as an inbound path. This will remove any language
|
||||
// prefixes and other path components that inbound processing would
|
||||
// clear out, so we can attempt to load the route clearly.
|
||||
$path = $this->pathProcessorManager->processInbound(urldecode(rtrim($request->getPathInfo(), '/')), $request);
|
||||
$path = $this->pathProcessorManager->processInbound(urldecode(rtrim($cloned_request->getPathInfo(), '/')), $cloned_request);
|
||||
$attributes = $this->router->match($path);
|
||||
}
|
||||
catch (ResourceNotFoundException $e) {
|
||||
|
|
|
@ -52,7 +52,7 @@ class UserSearch extends SearchPluginBase implements AccessibleInterface {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
static public function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$container->get('database'),
|
||||
$container->get('entity.manager'),
|
||||
|
@ -67,11 +67,11 @@ class UserSearch extends SearchPluginBase implements AccessibleInterface {
|
|||
/**
|
||||
* Creates a UserSearch object.
|
||||
*
|
||||
* @param Connection $database
|
||||
* @param \Drupal\Core\Database\Connection $database
|
||||
* The database connection.
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* @param ModuleHandlerInterface $module_handler
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler.
|
||||
* @param \Drupal\Core\Session\AccountInterface $current_user
|
||||
* The current user.
|
||||
|
@ -162,13 +162,15 @@ class UserSearch extends SearchPluginBase implements AccessibleInterface {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getHelp() {
|
||||
$help = ['list' => [
|
||||
'#theme' => 'item_list',
|
||||
'#items' => [
|
||||
$this->t('User search looks for user names and partial user names. Example: mar would match usernames mar, delmar, and maryjane.'),
|
||||
$this->t('You can use * as a wildcard within your keyword. Example: m*r would match user names mar, delmar, and elementary.'),
|
||||
$help = [
|
||||
'list' => [
|
||||
'#theme' => 'item_list',
|
||||
'#items' => [
|
||||
$this->t('User search looks for user names and partial user names. Example: mar would match usernames mar, delmar, and maryjane.'),
|
||||
$this->t('You can use * as a wildcard within your keyword. Example: m*r would match user names mar, delmar, and elementary.'),
|
||||
],
|
||||
],
|
||||
]];
|
||||
];
|
||||
|
||||
return $help;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Drupal\user\Plugin\Validation\Constraint;
|
||||
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
|
||||
|
@ -53,7 +52,7 @@ class UserNameConstraintValidator extends ConstraintValidator {
|
|||
) {
|
||||
$this->context->addViolation($constraint->illegalMessage);
|
||||
}
|
||||
if (Unicode::strlen($name) > USERNAME_MAX_LENGTH) {
|
||||
if (mb_strlen($name) > USERNAME_MAX_LENGTH) {
|
||||
$this->context->addViolation($constraint->tooLongMessage, ['%name' => $name, '%max' => USERNAME_MAX_LENGTH]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
namespace Drupal\user\Plugin\migrate;
|
||||
|
||||
use Drupal\migrate\Exception\RequirementsException;
|
||||
use Drupal\migrate\MigrateExecutable;
|
||||
use Drupal\migrate\MigrateSkipRowException;
|
||||
use Drupal\migrate\Plugin\Migration;
|
||||
|
||||
/**
|
||||
|
@ -28,13 +30,31 @@ class ProfileValues extends Migration {
|
|||
'ignore_map' => TRUE,
|
||||
] + $this->source;
|
||||
$definition['destination']['plugin'] = 'null';
|
||||
$definition['idMap']['plugin'] = 'null';
|
||||
try {
|
||||
$profile_field_migration = $this->migrationPluginManager->createStubMigration($definition);
|
||||
$migrate_executable = new MigrateExecutable($profile_field_migration);
|
||||
$source_plugin = $profile_field_migration->getSourcePlugin();
|
||||
$source_plugin->checkRequirements();
|
||||
foreach ($source_plugin as $row) {
|
||||
$name = $row->getSourceProperty('name');
|
||||
$this->process[$name] = $name;
|
||||
$fid = $row->getSourceProperty('fid');
|
||||
// The user profile field name can be greater than 32 characters. Use
|
||||
// the migrated profile field name in the process pipeline.
|
||||
$configuration =
|
||||
[
|
||||
'migration' => 'user_profile_field',
|
||||
'source_ids' => $fid,
|
||||
];
|
||||
$plugin = $this->processPluginManager->createInstance('migration_lookup', $configuration, $profile_field_migration);
|
||||
$new_value = $plugin->transform($fid, $migrate_executable, $row, 'tmp');
|
||||
if (isset($new_value[1])) {
|
||||
// Set the destination to the migrated profile field name.
|
||||
$this->process[$new_value[1]] = $name;
|
||||
}
|
||||
else {
|
||||
throw new MigrateSkipRowException("Can't migrate source field $name.");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (RequirementsException $e) {
|
||||
|
|
|
@ -21,6 +21,7 @@ class User extends FieldMigration {
|
|||
'ignore_map' => TRUE,
|
||||
] + $this->source;
|
||||
$definition['destination']['plugin'] = 'null';
|
||||
$definition['idMap']['plugin'] = 'null';
|
||||
if (\Drupal::moduleHandler()->moduleExists('field')) {
|
||||
$definition['source']['plugin'] = 'd7_field_instance';
|
||||
$field_migration = $this->migrationPluginManager->createStubMigration($definition);
|
||||
|
@ -36,7 +37,7 @@ class User extends FieldMigration {
|
|||
}
|
||||
$info = $row->getSource();
|
||||
$this->fieldPluginCache[$field_type]
|
||||
->processFieldValues($this, $field_name, $info);
|
||||
->defineValueProcessPipeline($this, $field_name, $info);
|
||||
}
|
||||
else {
|
||||
if ($this->cckPluginManager->hasDefinition($field_type)) {
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Drupal\user\Plugin\migrate\destination;
|
||||
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
|
@ -15,6 +14,52 @@ use Drupal\migrate\Row;
|
|||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides a destination plugin for migrating user entities.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* The example below migrates users and preserves original passwords from a
|
||||
* source that has passwords as MD5 hashes without salt. The passwords will be
|
||||
* salted and re-hashed before they are saved to the destination Drupal
|
||||
* database. The MD5 hash used in the example is a hash of 'password'.
|
||||
*
|
||||
* The example uses the EmbeddedDataSource source plugin for the sake of
|
||||
* simplicity. The mapping between old user_ids and new Drupal uids is saved in
|
||||
* the migration map table.
|
||||
* @code
|
||||
* id: custom_user_migration
|
||||
* label: Custom user migration
|
||||
* source:
|
||||
* plugin: embedded_data
|
||||
* data_rows:
|
||||
* -
|
||||
* user_id: 1
|
||||
* name: johnsmith
|
||||
* mail: johnsmith@example.com
|
||||
* hash: '5f4dcc3b5aa765d61d8327deb882cf99'
|
||||
* ids:
|
||||
* user_id:
|
||||
* type: integer
|
||||
* process:
|
||||
* name: name
|
||||
* mail: mail
|
||||
* pass: hash
|
||||
* status:
|
||||
* plugin: default_value
|
||||
* default_value: 1
|
||||
* destination:
|
||||
* plugin: entity:user
|
||||
* md5_passwords: true
|
||||
* @endcode
|
||||
*
|
||||
* For configuration options inherited from the parent class, refer to
|
||||
* \Drupal\migrate\Plugin\migrate\destination\EntityContentBase.
|
||||
*
|
||||
* The example above is about migrating an MD5 password hash. For more examples
|
||||
* on different password hash types and a list of other user properties, refer
|
||||
* to the handbook documentation:
|
||||
* @see https://www.drupal.org/docs/8/api/migrate-api/migrate-destination-plugins-examples/migrating-users
|
||||
*
|
||||
* @MigrateDestination(
|
||||
* id = "entity:user"
|
||||
* )
|
||||
|
@ -39,7 +84,7 @@ class EntityUser extends EntityContentBase {
|
|||
* The plugin implementation definition.
|
||||
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
|
||||
* The migration.
|
||||
* @param EntityStorageInterface $storage
|
||||
* @param \Drupal\Core\Entity\EntityStorageInterface $storage
|
||||
* The storage for this entity type.
|
||||
* @param array $bundles
|
||||
* The list of bundles this entity type has.
|
||||
|
@ -122,9 +167,23 @@ class EntityUser extends EntityContentBase {
|
|||
if (is_array($name)) {
|
||||
$name = reset($name);
|
||||
}
|
||||
if (Unicode::strlen($name) > USERNAME_MAX_LENGTH) {
|
||||
$row->setDestinationProperty('name', Unicode::substr($name, 0, USERNAME_MAX_LENGTH));
|
||||
if (mb_strlen($name) > USERNAME_MAX_LENGTH) {
|
||||
$row->setDestinationProperty('name', mb_substr($name, 0, USERNAME_MAX_LENGTH));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getHighestId() {
|
||||
$highest_id = parent::getHighestId();
|
||||
|
||||
// Every Drupal site must have a user with UID of 1 and it's normal for
|
||||
// migrations to overwrite this user.
|
||||
if ($highest_id === 1) {
|
||||
return 0;
|
||||
}
|
||||
return $highest_id;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ class UserLangcode extends ProcessPluginBase implements ContainerFactoryPluginIn
|
|||
* @param string $plugin_id
|
||||
* The plugin ID.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin definiiton.
|
||||
* The plugin definition.
|
||||
* @param \Drupal\Core\Language\LanguageManager $language_manager
|
||||
* The language manager service.
|
||||
*/
|
||||
|
@ -74,7 +74,7 @@ class UserLangcode extends ProcessPluginBase implements ContainerFactoryPluginIn
|
|||
return 'en';
|
||||
}
|
||||
}
|
||||
// If the user's language does not exists, use the default language.
|
||||
// If the user's language does not exist, use the default language.
|
||||
elseif ($this->languageManager->getLanguage($value) === NULL) {
|
||||
return $this->languageManager->getDefaultLanguage()->getId();
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ class UserUpdate7002 extends ProcessPluginBase implements ContainerFactoryPlugin
|
|||
$container->get('config.factory')->get('system.date')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -10,7 +10,7 @@ use Drupal\migrate\Row;
|
|||
*
|
||||
* @MigrateSource(
|
||||
* id = "profile_field",
|
||||
* source_provider = "profile"
|
||||
* source_module = "profile"
|
||||
* )
|
||||
*/
|
||||
class ProfileField extends DrupalSqlBase {
|
||||
|
|
|
@ -11,7 +11,8 @@ use Drupal\migrate\Plugin\migrate\source\DummyQueryTrait;
|
|||
* @todo Support default picture?
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "user_picture_instance"
|
||||
* id = "user_picture_instance",
|
||||
* source_module = "user"
|
||||
* )
|
||||
*/
|
||||
class UserPictureInstance extends DrupalSqlBase {
|
||||
|
@ -28,7 +29,8 @@ class UserPictureInstance extends DrupalSqlBase {
|
|||
'file_directory' => $this->variableGet('user_picture_path', 'pictures'),
|
||||
'max_filesize' => $this->variableGet('user_picture_file_size', '30') . 'KB',
|
||||
'max_resolution' => $this->variableGet('user_picture_dimensions', '85x85'),
|
||||
]]);
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,7 +10,7 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
|||
*
|
||||
* @MigrateSource(
|
||||
* id = "d6_profile_field_values",
|
||||
* source_provider = "profile"
|
||||
* source_module = "profile"
|
||||
* )
|
||||
*/
|
||||
class ProfileFieldValues extends DrupalSqlBase {
|
||||
|
|
|
@ -9,7 +9,8 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
|||
* Drupal 6 role source from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d6_user_role"
|
||||
* id = "d6_user_role",
|
||||
* source_module = "user"
|
||||
* )
|
||||
*/
|
||||
class Role extends DrupalSqlBase {
|
||||
|
|
|
@ -9,7 +9,8 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
|||
* Drupal 6 user source from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d6_user"
|
||||
* id = "d6_user",
|
||||
* source_module = "user"
|
||||
* )
|
||||
*/
|
||||
class User extends DrupalSqlBase {
|
||||
|
@ -32,14 +33,6 @@ class User extends DrupalSqlBase {
|
|||
// Add roles field.
|
||||
$fields['roles'] = $this->t('Roles');
|
||||
|
||||
// Profile fields.
|
||||
if ($this->moduleExists('profile')) {
|
||||
$fields += $this->select('profile_fields', 'pf')
|
||||
->fields('pf', ['name', 'title'])
|
||||
->execute()
|
||||
->fetchAllKeyed();
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,8 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
|||
* @todo Support default picture?
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d6_user_picture"
|
||||
* id = "d6_user_picture",
|
||||
* source_module = "user"
|
||||
* )
|
||||
*/
|
||||
class UserPicture extends DrupalSqlBase {
|
||||
|
@ -36,6 +37,7 @@ class UserPicture extends DrupalSqlBase {
|
|||
'picture' => "Path to the user's uploaded picture.",
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -9,7 +9,8 @@ use Drupal\migrate\Row;
|
|||
* Drupal 6 user picture source from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d6_user_picture_file"
|
||||
* id = "d6_user_picture_file",
|
||||
* source_module = "user"
|
||||
* )
|
||||
*/
|
||||
class UserPictureFile extends DrupalSqlBase {
|
||||
|
@ -67,6 +68,7 @@ class UserPictureFile extends DrupalSqlBase {
|
|||
'filename' => 'The picture filename.',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -9,7 +9,8 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
|||
* Drupal 7 role source from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d7_user_role"
|
||||
* id = "d7_user_role",
|
||||
* source_module = "user"
|
||||
* )
|
||||
*/
|
||||
class Role extends DrupalSqlBase {
|
||||
|
|
|
@ -9,7 +9,8 @@ use Drupal\migrate_drupal\Plugin\migrate\source\d7\FieldableEntity;
|
|||
* Drupal 7 user source from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d7_user"
|
||||
* id = "d7_user",
|
||||
* source_module = "user"
|
||||
* )
|
||||
*/
|
||||
class User extends FieldableEntity {
|
||||
|
@ -61,18 +62,32 @@ class User extends FieldableEntity {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function prepareRow(Row $row) {
|
||||
$uid = $row->getSourceProperty('uid');
|
||||
|
||||
$roles = $this->select('users_roles', 'ur')
|
||||
->fields('ur', ['rid'])
|
||||
->condition('ur.uid', $row->getSourceProperty('uid'))
|
||||
->condition('ur.uid', $uid)
|
||||
->execute()
|
||||
->fetchCol();
|
||||
$row->setSourceProperty('roles', $roles);
|
||||
|
||||
$row->setSourceProperty('data', unserialize($row->getSourceProperty('data')));
|
||||
|
||||
// If this entity was translated using Entity Translation, we need to get
|
||||
// its source language to get the field values in the right language.
|
||||
// The translations will be migrated by the d7_user_entity_translation
|
||||
// migration.
|
||||
$entity_translatable = $this->isEntityTranslatable('user');
|
||||
$source_language = $this->getEntityTranslationSourceLanguage('user', $uid);
|
||||
$language = $entity_translatable && $source_language ? $source_language : $row->getSourceProperty('language');
|
||||
$row->setSourceProperty('entity_language', $language);
|
||||
|
||||
// Get Field API field values.
|
||||
foreach (array_keys($this->getFields('user')) as $field) {
|
||||
$row->setSourceProperty($field, $this->getFieldValues('user', $field, $row->getSourceProperty('uid')));
|
||||
foreach ($this->getFields('user') as $field_name => $field) {
|
||||
// Ensure we're using the right language if the entity and the field are
|
||||
// translatable.
|
||||
$field_language = $entity_translatable && $field['translatable'] ? $language : NULL;
|
||||
$row->setSourceProperty($field_name, $this->getFieldValues('user', $field_name, $uid, NULL, $field_language));
|
||||
}
|
||||
|
||||
// Get profile field values. This code is lifted directly from the D6
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\user\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\d7\FieldableEntity;
|
||||
|
||||
/**
|
||||
* Provides Drupal 7 user entity translations source plugin.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d7_user_entity_translation",
|
||||
* source_module = "entity_translation"
|
||||
* )
|
||||
*/
|
||||
class UserEntityTranslation extends FieldableEntity {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
$query = $this->select('entity_translation', 'et')
|
||||
->fields('et')
|
||||
->condition('et.entity_type', 'user')
|
||||
->condition('et.source', '', '<>');
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prepareRow(Row $row) {
|
||||
$uid = $row->getSourceProperty('entity_id');
|
||||
$language = $row->getSourceProperty('language');
|
||||
|
||||
// Get Field API field values.
|
||||
foreach ($this->getFields('user') as $field_name => $field) {
|
||||
// Ensure we're using the right language if the entity is translatable.
|
||||
$field_language = $field['translatable'] ? $language : NULL;
|
||||
$row->setSourceProperty($field_name, $this->getFieldValues('user', $field_name, $uid, NULL, $field_language));
|
||||
}
|
||||
|
||||
return parent::prepareRow($row);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return [
|
||||
'entity_type' => $this->t('The entity type this translation relates to'),
|
||||
'entity_id' => $this->t('The entity id this translation relates to'),
|
||||
'revision_id' => $this->t('The entity revision id this translation relates to'),
|
||||
'language' => $this->t('The target language for this translation.'),
|
||||
'source' => $this->t('The source language from which this translation was created.'),
|
||||
'uid' => $this->t('The author of this translation.'),
|
||||
'status' => $this->t('Boolean indicating whether the translation is published (visible to non-administrators).'),
|
||||
'translate' => $this->t('A boolean indicating whether this translation needs to be updated.'),
|
||||
'created' => $this->t('The Unix timestamp when the translation was created.'),
|
||||
'changed' => $this->t('The Unix timestamp when the translation was most recently saved.'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
return [
|
||||
'entity_id' => [
|
||||
'type' => 'integer',
|
||||
],
|
||||
'language' => [
|
||||
'type' => 'string',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -100,7 +100,6 @@ class Permission extends AccessPluginBase implements CacheableDependencyInterfac
|
|||
return $this->t($this->options['perm']);
|
||||
}
|
||||
|
||||
|
||||
protected function defineOptions() {
|
||||
$options = parent::defineOptions();
|
||||
$options['perm'] = ['default' => 'access content'];
|
||||
|
|
|
@ -96,7 +96,6 @@ class Role extends AccessPluginBase implements CacheableDependencyInterface {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
protected function defineOptions() {
|
||||
$options = parent::defineOptions();
|
||||
$options['role'] = ['default' => []];
|
||||
|
|
|
@ -23,7 +23,7 @@ class Uid extends NumericArgument {
|
|||
protected $storage;
|
||||
|
||||
/**
|
||||
* Constructs a Drupal\Component\Plugin\PluginBase object.
|
||||
* Constructs a \Drupal\user\Plugin\views\argument\Uid object.
|
||||
*
|
||||
* @param array $configuration
|
||||
* A configuration array containing information about the plugin instance.
|
||||
|
@ -51,10 +51,10 @@ class Uid extends NumericArgument {
|
|||
* Override the behavior of title(). Get the name of the user.
|
||||
*
|
||||
* @return array
|
||||
* A list of usernames.
|
||||
* A list of usernames.
|
||||
*/
|
||||
public function titleQuery() {
|
||||
return array_map(function($account) {
|
||||
return array_map(function ($account) {
|
||||
return $account->label();
|
||||
}, $this->storage->loadMultiple($this->value));
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ class Permissions extends PrerenderList {
|
|||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* Constructs a Drupal\Component\Plugin\PluginBase object.
|
||||
* Constructs a \Drupal\user\Plugin\views\field\Permissions object.
|
||||
*
|
||||
* @param array $configuration
|
||||
* A configuration array containing information about the plugin instance.
|
||||
|
|
|
@ -25,7 +25,7 @@ class Roles extends PrerenderList {
|
|||
protected $database;
|
||||
|
||||
/**
|
||||
* Constructs a Drupal\Component\Plugin\PluginBase object.
|
||||
* Constructs a \Drupal\user\Plugin\views\field\Roles object.
|
||||
*
|
||||
* @param array $configuration
|
||||
* A configuration array containing information about the plugin instance.
|
||||
|
@ -82,7 +82,7 @@ class Roles extends PrerenderList {
|
|||
$ordered_roles = array_flip(array_keys($roles));
|
||||
foreach ($this->items as &$user_roles) {
|
||||
// Create an array of rids that the user has in the role weight order.
|
||||
$sorted_keys = array_intersect_key($ordered_roles, $user_roles);
|
||||
$sorted_keys = array_intersect_key($ordered_roles, $user_roles);
|
||||
// Merge with the unsorted array of role information which has the
|
||||
// effect of sorting it.
|
||||
$user_roles = array_merge($sorted_keys, $user_roles);
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
namespace Drupal\user\Plugin\views\field;
|
||||
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\system\Plugin\views\field\BulkForm;
|
||||
use Drupal\user\UserInterface;
|
||||
use Drupal\views\Plugin\views\field\BulkForm;
|
||||
|
||||
/**
|
||||
* Defines a user operations bulk form element.
|
||||
|
|
|
@ -34,7 +34,6 @@ class UserData extends FieldPluginBase {
|
|||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Drupal\user\Plugin\views\filter;
|
||||
|
||||
use Drupal\Core\Database\Query\Condition;
|
||||
use Drupal\views\Plugin\views\display\DisplayPluginBase;
|
||||
use Drupal\views\ViewExecutable;
|
||||
use Drupal\views\Plugin\views\filter\BooleanOperator;
|
||||
|
@ -28,7 +29,7 @@ class Current extends BooleanOperator {
|
|||
$this->ensureMyTable();
|
||||
|
||||
$field = $this->tableAlias . '.' . $this->realField . ' ';
|
||||
$or = db_or();
|
||||
$or = new Condition('OR');
|
||||
|
||||
if (empty($this->value)) {
|
||||
$or->condition($field, '***CURRENT_USER***', '<>');
|
||||
|
|
|
@ -115,7 +115,8 @@ class Name extends InOperator {
|
|||
$this->valueOptions[$account->id()] = $account->label();
|
||||
}
|
||||
else {
|
||||
$this->valueOptions[$account->id()] = 'Anonymous'; // Intentionally NOT translated.
|
||||
// Intentionally NOT translated.
|
||||
$this->valueOptions[$account->id()] = 'Anonymous';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,10 +74,20 @@ class Roles extends ManyToOne {
|
|||
*/
|
||||
public function calculateDependencies() {
|
||||
$dependencies = [];
|
||||
|
||||
if (in_array($this->operator, ['empty', 'not empty'])) {
|
||||
return $dependencies;
|
||||
}
|
||||
foreach ($this->value as $role_id) {
|
||||
|
||||
// The value might be a string due to the wrong plugin being used for role
|
||||
// field data, and subsequently the incorrect config schema object and
|
||||
// value. In the empty case stop early. Otherwise we cast it to an array
|
||||
// later.
|
||||
if (is_string($this->value) && $this->value === '') {
|
||||
return [];
|
||||
}
|
||||
|
||||
foreach ((array) $this->value as $role_id) {
|
||||
$role = $this->roleStorage->load($role_id);
|
||||
$dependencies[$role->getConfigDependencyKey()][] = $role->getConfigDependencyName();
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ class Users extends WizardPluginBase {
|
|||
|
||||
/**
|
||||
* Set the created column.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $createdColumn = 'created';
|
||||
|
||||
|
@ -35,7 +37,7 @@ class Users extends WizardPluginBase {
|
|||
'plugin_id' => 'boolean',
|
||||
'entity_type' => 'user',
|
||||
'entity_field' => 'status',
|
||||
]
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,212 +2,25 @@
|
|||
|
||||
namespace Drupal\user;
|
||||
|
||||
use Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface;
|
||||
use Drupal\Core\Lock\LockBackendInterface;
|
||||
use Drupal\Core\Session\AccountProxyInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Drupal\Core\TempStore\PrivateTempStore as CorePrivateTempStore;
|
||||
|
||||
@trigger_error('\Drupal\user\PrivateTempStore is scheduled for removal in Drupal 9.0.0. Use \Drupal\Core\TempStore\PrivateTempStore instead. See https://www.drupal.org/node/2935639.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* In order to preserve BC alias the core exception.
|
||||
*/
|
||||
if (!class_exists('\Drupal\user\TempStoreException')) {
|
||||
class_alias('\Drupal\Core\TempStore\TempStoreException', '\Drupal\user\TempStoreException');
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores and retrieves temporary data for a given owner.
|
||||
*
|
||||
* A PrivateTempStore can be used to make temporary, non-cache data available
|
||||
* across requests. The data for the PrivateTempStore is stored in one
|
||||
* key/value collection. PrivateTempStore data expires automatically after a
|
||||
* given timeframe.
|
||||
* @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0.
|
||||
* Use \Drupal\Core\TempStore\PrivateTempStore instead.
|
||||
*
|
||||
* The PrivateTempStore is different from a cache, because the data in it is not
|
||||
* yet saved permanently and so it cannot be rebuilt. Typically, the
|
||||
* PrivateTempStore might be used to store work in progress that is later saved
|
||||
* permanently elsewhere, e.g. autosave data, multistep forms, or in-progress
|
||||
* changes to complex configuration that are not ready to be saved.
|
||||
*
|
||||
* The PrivateTempStore differs from the SharedTempStore in that all keys are
|
||||
* ensured to be unique for a particular user and users can never share data. If
|
||||
* you want to be able to share data between users or use it for locking, use
|
||||
* \Drupal\user\SharedTempStore.
|
||||
* @see \Drupal\Core\TempStore\PrivateTempStore
|
||||
* @see https://www.drupal.org/node/2935639
|
||||
*/
|
||||
class PrivateTempStore {
|
||||
|
||||
/**
|
||||
* The key/value storage object used for this data.
|
||||
*
|
||||
* @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface
|
||||
*/
|
||||
protected $storage;
|
||||
|
||||
/**
|
||||
* The lock object used for this data.
|
||||
*
|
||||
* @var \Drupal\Core\Lock\LockBackendInterface
|
||||
*/
|
||||
protected $lockBackend;
|
||||
|
||||
/**
|
||||
* The current user.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountProxyInterface
|
||||
*/
|
||||
protected $currentUser;
|
||||
|
||||
/**
|
||||
* The request stack.
|
||||
*
|
||||
* @var \Symfony\Component\HttpFoundation\RequestStack
|
||||
*/
|
||||
protected $requestStack;
|
||||
|
||||
/**
|
||||
* The time to live for items in seconds.
|
||||
*
|
||||
* By default, data is stored for one week (604800 seconds) before expiring.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $expire;
|
||||
|
||||
/**
|
||||
* Constructs a new object for accessing data from a key/value store.
|
||||
*
|
||||
* @param KeyValueStoreExpirableInterface $storage
|
||||
* The key/value storage object used for this data. Each storage object
|
||||
* represents a particular collection of data and will contain any number
|
||||
* of key/value pairs.
|
||||
* @param \Drupal\Core\Lock\LockBackendInterface $lock_backend
|
||||
* The lock object used for this data.
|
||||
* @param \Drupal\Core\Session\AccountProxyInterface $current_user
|
||||
* The current user account.
|
||||
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
|
||||
* The request stack.
|
||||
* @param int $expire
|
||||
* The time to live for items, in seconds.
|
||||
*/
|
||||
public function __construct(KeyValueStoreExpirableInterface $storage, LockBackendInterface $lock_backend, AccountProxyInterface $current_user, RequestStack $request_stack, $expire = 604800) {
|
||||
$this->storage = $storage;
|
||||
$this->lockBackend = $lock_backend;
|
||||
$this->currentUser = $current_user;
|
||||
$this->requestStack = $request_stack;
|
||||
$this->expire = $expire;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a value from this PrivateTempStore for a given key.
|
||||
*
|
||||
* @param string $key
|
||||
* The key of the data to retrieve.
|
||||
*
|
||||
* @return mixed
|
||||
* The data associated with the key, or NULL if the key does not exist.
|
||||
*/
|
||||
public function get($key) {
|
||||
$key = $this->createkey($key);
|
||||
if (($object = $this->storage->get($key)) && ($object->owner == $this->getOwner())) {
|
||||
return $object->data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a particular key/value pair in this PrivateTempStore.
|
||||
*
|
||||
* @param string $key
|
||||
* The key of the data to store.
|
||||
* @param mixed $value
|
||||
* The data to store.
|
||||
*
|
||||
* @throws \Drupal\user\TempStoreException
|
||||
* Thrown when a lock for the backend storage could not be acquired.
|
||||
*/
|
||||
public function set($key, $value) {
|
||||
$key = $this->createkey($key);
|
||||
if (!$this->lockBackend->acquire($key)) {
|
||||
$this->lockBackend->wait($key);
|
||||
if (!$this->lockBackend->acquire($key)) {
|
||||
throw new TempStoreException("Couldn't acquire lock to update item '$key' in '{$this->storage->getCollectionName()}' temporary storage.");
|
||||
}
|
||||
}
|
||||
|
||||
$value = (object) [
|
||||
'owner' => $this->getOwner(),
|
||||
'data' => $value,
|
||||
'updated' => (int) $this->requestStack->getMasterRequest()->server->get('REQUEST_TIME'),
|
||||
];
|
||||
$this->storage->setWithExpire($key, $value, $this->expire);
|
||||
$this->lockBackend->release($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the metadata associated with a particular key/value pair.
|
||||
*
|
||||
* @param string $key
|
||||
* The key of the data to store.
|
||||
*
|
||||
* @return mixed
|
||||
* An object with the owner and updated time if the key has a value, or
|
||||
* NULL otherwise.
|
||||
*/
|
||||
public function getMetadata($key) {
|
||||
$key = $this->createkey($key);
|
||||
// Fetch the key/value pair and its metadata.
|
||||
$object = $this->storage->get($key);
|
||||
if ($object) {
|
||||
// Don't keep the data itself in memory.
|
||||
unset($object->data);
|
||||
return $object;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes data from the store for a given key and releases the lock on it.
|
||||
*
|
||||
* @param string $key
|
||||
* The key of the data to delete.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the object was deleted or does not exist, FALSE if it exists but
|
||||
* is not owned by $this->owner.
|
||||
*
|
||||
* @throws \Drupal\user\TempStoreException
|
||||
* Thrown when a lock for the backend storage could not be acquired.
|
||||
*/
|
||||
public function delete($key) {
|
||||
$key = $this->createkey($key);
|
||||
if (!$object = $this->storage->get($key)) {
|
||||
return TRUE;
|
||||
}
|
||||
elseif ($object->owner != $this->getOwner()) {
|
||||
return FALSE;
|
||||
}
|
||||
if (!$this->lockBackend->acquire($key)) {
|
||||
$this->lockBackend->wait($key);
|
||||
if (!$this->lockBackend->acquire($key)) {
|
||||
throw new TempStoreException("Couldn't acquire lock to delete item '$key' from '{$this->storage->getCollectionName()}' temporary storage.");
|
||||
}
|
||||
}
|
||||
$this->storage->delete($key);
|
||||
$this->lockBackend->release($key);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the key is unique for a user.
|
||||
*
|
||||
* @param string $key
|
||||
* The key.
|
||||
*
|
||||
* @return string
|
||||
* The unique key for the user.
|
||||
*/
|
||||
protected function createkey($key) {
|
||||
return $this->getOwner() . ':' . $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current owner based on the current user or the session ID.
|
||||
*
|
||||
* @return string
|
||||
* The owner.
|
||||
*/
|
||||
protected function getOwner() {
|
||||
return $this->currentUser->id() ?: $this->requestStack->getCurrentRequest()->getSession()->getId();
|
||||
}
|
||||
|
||||
class PrivateTempStore extends CorePrivateTempStore {
|
||||
}
|
||||
|
|
|
@ -2,72 +2,20 @@
|
|||
|
||||
namespace Drupal\user;
|
||||
|
||||
use Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface;
|
||||
use Drupal\Core\Lock\LockBackendInterface;
|
||||
use Drupal\Core\Session\AccountProxyInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Drupal\Core\TempStore\PrivateTempStoreFactory as CorePrivateTempStoreFactory;
|
||||
|
||||
@trigger_error('\Drupal\user\PrivateTempStoreFactory is scheduled for removal in Drupal 9.0.0. Use \Drupal\Core\TempStore\PrivateTempStoreFactory instead. See https://www.drupal.org/node/2935639.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Creates a PrivateTempStore object for a given collection.
|
||||
*
|
||||
* @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0.
|
||||
* Use \Drupal\Core\TempStore\PrivateTempStoreFactory instead.
|
||||
*
|
||||
* @see \Drupal\Core\TempStore\PrivateTempStoreFactory
|
||||
* @see https://www.drupal.org/node/2935639
|
||||
*/
|
||||
class PrivateTempStoreFactory {
|
||||
|
||||
/**
|
||||
* The storage factory creating the backend to store the data.
|
||||
*
|
||||
* @var \Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface
|
||||
*/
|
||||
protected $storageFactory;
|
||||
|
||||
/**
|
||||
* The lock object used for this data.
|
||||
*
|
||||
* @var \Drupal\Core\Lock\LockBackendInterface $lockBackend
|
||||
*/
|
||||
protected $lockBackend;
|
||||
|
||||
/**
|
||||
* The current user.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountProxyInterface
|
||||
*/
|
||||
protected $currentUser;
|
||||
|
||||
/**
|
||||
* The request stack.
|
||||
*
|
||||
* @var \Symfony\Component\HttpFoundation\RequestStack
|
||||
*/
|
||||
protected $requestStack;
|
||||
|
||||
/**
|
||||
* The time to live for items in seconds.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $expire;
|
||||
|
||||
/**
|
||||
* Constructs a Drupal\user\PrivateTempStoreFactory object.
|
||||
*
|
||||
* @param \Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface $storage_factory
|
||||
* The key/value store factory.
|
||||
* @param \Drupal\Core\Lock\LockBackendInterface $lock_backend
|
||||
* The lock object used for this data.
|
||||
* @param \Drupal\Core\Session\AccountProxyInterface $current_user
|
||||
* The current account.
|
||||
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
|
||||
* The request stack.
|
||||
* @param int $expire
|
||||
* The time to live for items, in seconds.
|
||||
*/
|
||||
public function __construct(KeyValueExpirableFactoryInterface $storage_factory, LockBackendInterface $lock_backend, AccountProxyInterface $current_user, RequestStack $request_stack, $expire = 604800) {
|
||||
$this->storageFactory = $storage_factory;
|
||||
$this->lockBackend = $lock_backend;
|
||||
$this->currentUser = $current_user;
|
||||
$this->requestStack = $request_stack;
|
||||
$this->expire = $expire;
|
||||
}
|
||||
class PrivateTempStoreFactory extends CorePrivateTempStoreFactory {
|
||||
|
||||
/**
|
||||
* Creates a PrivateTempStore.
|
||||
|
|
|
@ -6,6 +6,8 @@ use Drupal\Core\Form\FormStateInterface;
|
|||
|
||||
/**
|
||||
* Form handler for the profile forms.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class ProfileForm extends AccountForm {
|
||||
|
||||
|
@ -36,7 +38,7 @@ class ProfileForm extends AccountForm {
|
|||
$account->save();
|
||||
$form_state->setValue('uid', $account->id());
|
||||
|
||||
drupal_set_message($this->t('The changes have been saved.'));
|
||||
$this->messenger()->addStatus($this->t('The changes have been saved.'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,6 +6,8 @@ use Drupal\Core\Form\FormStateInterface;
|
|||
|
||||
/**
|
||||
* Form handler for the user register forms.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class RegisterForm extends AccountForm {
|
||||
|
||||
|
@ -101,28 +103,28 @@ class RegisterForm extends AccountForm {
|
|||
|
||||
// New administrative account without notification.
|
||||
if ($admin && !$notify) {
|
||||
drupal_set_message($this->t('Created a new user account for <a href=":url">%name</a>. No email has been sent.', [':url' => $account->url(), '%name' => $account->getUsername()]));
|
||||
$this->messenger()->addStatus($this->t('Created a new user account for <a href=":url">%name</a>. No email has been sent.', [':url' => $account->url(), '%name' => $account->getUsername()]));
|
||||
}
|
||||
// No email verification required; log in user immediately.
|
||||
elseif (!$admin && !\Drupal::config('user.settings')->get('verify_mail') && $account->isActive()) {
|
||||
_user_mail_notify('register_no_approval_required', $account);
|
||||
user_login_finalize($account);
|
||||
drupal_set_message($this->t('Registration successful. You are now logged in.'));
|
||||
$this->messenger()->addStatus($this->t('Registration successful. You are now logged in.'));
|
||||
$form_state->setRedirect('<front>');
|
||||
}
|
||||
// No administrator approval required.
|
||||
elseif ($account->isActive() || $notify) {
|
||||
if (!$account->getEmail() && $notify) {
|
||||
drupal_set_message($this->t('The new user <a href=":url">%name</a> was created without an email address, so no welcome message was sent.', [':url' => $account->url(), '%name' => $account->getUsername()]));
|
||||
$this->messenger()->addStatus($this->t('The new user <a href=":url">%name</a> was created without an email address, so no welcome message was sent.', [':url' => $account->url(), '%name' => $account->getUsername()]));
|
||||
}
|
||||
else {
|
||||
$op = $notify ? 'register_admin_created' : 'register_no_approval_required';
|
||||
if (_user_mail_notify($op, $account)) {
|
||||
if ($notify) {
|
||||
drupal_set_message($this->t('A welcome message with further instructions has been emailed to the new user <a href=":url">%name</a>.', [':url' => $account->url(), '%name' => $account->getUsername()]));
|
||||
$this->messenger()->addStatus($this->t('A welcome message with further instructions has been emailed to the new user <a href=":url">%name</a>.', [':url' => $account->url(), '%name' => $account->getUsername()]));
|
||||
}
|
||||
else {
|
||||
drupal_set_message($this->t('A welcome message with further instructions has been sent to your email address.'));
|
||||
$this->messenger()->addStatus($this->t('A welcome message with further instructions has been sent to your email address.'));
|
||||
$form_state->setRedirect('<front>');
|
||||
}
|
||||
}
|
||||
|
@ -131,7 +133,7 @@ class RegisterForm extends AccountForm {
|
|||
// Administrator approval required.
|
||||
else {
|
||||
_user_mail_notify('register_pending_approval', $account);
|
||||
drupal_set_message($this->t('Thank you for applying for an account. Your account is currently pending approval by the site administrator.<br />In the meantime, a welcome message with further instructions has been sent to your email address.'));
|
||||
$this->messenger()->addStatus($this->t('Thank you for applying for an account. Your account is currently pending approval by the site administrator.<br />In the meantime, a welcome message with further instructions has been sent to your email address.'));
|
||||
$form_state->setRedirect('<front>');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ use Drupal\Core\Form\FormStateInterface;
|
|||
|
||||
/**
|
||||
* Form controller for the role entity edit forms.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class RoleForm extends EntityForm {
|
||||
|
||||
|
@ -55,11 +57,11 @@ class RoleForm extends EntityForm {
|
|||
|
||||
$edit_link = $this->entity->link($this->t('Edit'));
|
||||
if ($status == SAVED_UPDATED) {
|
||||
drupal_set_message($this->t('Role %label has been updated.', ['%label' => $entity->label()]));
|
||||
$this->messenger()->addStatus($this->t('Role %label has been updated.', ['%label' => $entity->label()]));
|
||||
$this->logger('user')->notice('Role %label has been updated.', ['%label' => $entity->label(), 'link' => $edit_link]);
|
||||
}
|
||||
else {
|
||||
drupal_set_message($this->t('Role %label has been added.', ['%label' => $entity->label()]));
|
||||
$this->messenger()->addStatus($this->t('Role %label has been added.', ['%label' => $entity->label()]));
|
||||
$this->logger('user')->notice('Role %label has been added.', ['%label' => $entity->label(), 'link' => $edit_link]);
|
||||
}
|
||||
$form_state->setRedirect('entity.user_role.collection');
|
||||
|
|
|
@ -4,7 +4,11 @@ namespace Drupal\user;
|
|||
|
||||
use Drupal\Core\Config\Entity\DraggableListBuilder;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Messenger\MessengerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Defines a class to build a listing of user role entities.
|
||||
|
@ -13,6 +17,41 @@ use Drupal\Core\Form\FormStateInterface;
|
|||
*/
|
||||
class RoleListBuilder extends DraggableListBuilder {
|
||||
|
||||
/**
|
||||
* The messenger.
|
||||
*
|
||||
* @var \Drupal\Core\Messenger\MessengerInterface
|
||||
*/
|
||||
protected $messenger;
|
||||
|
||||
/**
|
||||
* RoleListBuilder constructor.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entityType
|
||||
* The entity type definition.
|
||||
* @param \Drupal\Core\Entity\EntityStorageInterface $storage
|
||||
* The entity storage class.
|
||||
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
|
||||
* The messenger.
|
||||
*/
|
||||
public function __construct(EntityTypeInterface $entityType,
|
||||
EntityStorageInterface $storage,
|
||||
MessengerInterface $messenger) {
|
||||
parent::__construct($entityType, $storage);
|
||||
$this->messenger = $messenger;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
|
||||
return new static(
|
||||
$entity_type,
|
||||
$container->get('entity.manager')->getStorage($entity_type->id()),
|
||||
$container->get('messenger')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -58,7 +97,7 @@ class RoleListBuilder extends DraggableListBuilder {
|
|||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
parent::submitForm($form, $form_state);
|
||||
|
||||
drupal_set_message(t('The role settings have been updated.'));
|
||||
$this->messenger->addStatus($this->t('The role settings have been updated.'));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,278 +2,25 @@
|
|||
|
||||
namespace Drupal\user;
|
||||
|
||||
use Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface;
|
||||
use Drupal\Core\Lock\LockBackendInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Drupal\Core\TempStore\SharedTempStore as CoreSharedTempStore;
|
||||
|
||||
@trigger_error('\Drupal\user\SharedTempStore is scheduled for removal in Drupal 9.0.0. Use \Drupal\Core\TempStore\SharedTempStore instead. See https://www.drupal.org/node/2935639.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* In order to preserve BC alias the core exception.
|
||||
*/
|
||||
if (!class_exists('\Drupal\user\TempStoreException')) {
|
||||
class_alias('\Drupal\Core\TempStore\TempStoreException', '\Drupal\user\TempStoreException');
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores and retrieves temporary data for a given owner.
|
||||
*
|
||||
* A SharedTempStore can be used to make temporary, non-cache data available
|
||||
* across requests. The data for the SharedTempStore is stored in one key/value
|
||||
* collection. SharedTempStore data expires automatically after a given
|
||||
* timeframe.
|
||||
* @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0.
|
||||
* Use \Drupal\Core\TempStore\SharedTempStore instead.
|
||||
*
|
||||
* The SharedTempStore is different from a cache, because the data in it is not
|
||||
* yet saved permanently and so it cannot be rebuilt. Typically, the
|
||||
* SharedTempStore might be used to store work in progress that is later saved
|
||||
* permanently elsewhere, e.g. autosave data, multistep forms, or in-progress
|
||||
* changes to complex configuration that are not ready to be saved.
|
||||
*
|
||||
* Each SharedTempStore belongs to a particular owner (e.g. a user, session, or
|
||||
* process). Multiple owners may use the same key/value collection, and the
|
||||
* owner is stored along with the key/value pair.
|
||||
*
|
||||
* Every key is unique within the collection, so the SharedTempStore can check
|
||||
* whether a particular key is already set by a different owner. This is
|
||||
* useful for informing one owner that the data is already in use by another;
|
||||
* for example, to let one user know that another user is in the process of
|
||||
* editing certain data, or even to restrict other users from editing it at
|
||||
* the same time. It is the responsibility of the implementation to decide
|
||||
* when and whether one owner can use or update another owner's data.
|
||||
*
|
||||
* If you want to be able to ensure that the data belongs to the current user,
|
||||
* use \Drupal\user\PrivateTempStore.
|
||||
* @see \Drupal\Core\TempStore\SharedTempStore
|
||||
* @see https://www.drupal.org/node/2935639
|
||||
*/
|
||||
class SharedTempStore {
|
||||
|
||||
/**
|
||||
* The key/value storage object used for this data.
|
||||
*
|
||||
* @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface
|
||||
*/
|
||||
protected $storage;
|
||||
|
||||
/**
|
||||
* The lock object used for this data.
|
||||
*
|
||||
* @var \Drupal\Core\Lock\LockBackendInterface
|
||||
*/
|
||||
protected $lockBackend;
|
||||
|
||||
/**
|
||||
* The request stack.
|
||||
*
|
||||
* @var \Symfony\Component\HttpFoundation\RequestStack
|
||||
*/
|
||||
protected $requestStack;
|
||||
|
||||
/**
|
||||
* The owner key to store along with the data (e.g. a user or session ID).
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $owner;
|
||||
|
||||
/**
|
||||
* The time to live for items in seconds.
|
||||
*
|
||||
* By default, data is stored for one week (604800 seconds) before expiring.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $expire;
|
||||
|
||||
/**
|
||||
* Constructs a new object for accessing data from a key/value store.
|
||||
*
|
||||
* @param KeyValueStoreExpirableInterface $storage
|
||||
* The key/value storage object used for this data. Each storage object
|
||||
* represents a particular collection of data and will contain any number
|
||||
* of key/value pairs.
|
||||
* @param \Drupal\Core\Lock\LockBackendInterface $lock_backend
|
||||
* The lock object used for this data.
|
||||
* @param mixed $owner
|
||||
* The owner key to store along with the data (e.g. a user or session ID).
|
||||
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
|
||||
* The request stack.
|
||||
* @param int $expire
|
||||
* The time to live for items, in seconds.
|
||||
*/
|
||||
public function __construct(KeyValueStoreExpirableInterface $storage, LockBackendInterface $lock_backend, $owner, RequestStack $request_stack, $expire = 604800) {
|
||||
$this->storage = $storage;
|
||||
$this->lockBackend = $lock_backend;
|
||||
$this->owner = $owner;
|
||||
$this->requestStack = $request_stack;
|
||||
$this->expire = $expire;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a value from this SharedTempStore for a given key.
|
||||
*
|
||||
* @param string $key
|
||||
* The key of the data to retrieve.
|
||||
*
|
||||
* @return mixed
|
||||
* The data associated with the key, or NULL if the key does not exist.
|
||||
*/
|
||||
public function get($key) {
|
||||
if ($object = $this->storage->get($key)) {
|
||||
return $object->data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a value from this SharedTempStore for a given key.
|
||||
*
|
||||
* Only returns the value if the value is owned by $this->owner.
|
||||
*
|
||||
* @param string $key
|
||||
* The key of the data to retrieve.
|
||||
*
|
||||
* @return mixed
|
||||
* The data associated with the key, or NULL if the key does not exist.
|
||||
*/
|
||||
public function getIfOwner($key) {
|
||||
if (($object = $this->storage->get($key)) && ($object->owner == $this->owner)) {
|
||||
return $object->data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a particular key/value pair only if the key doesn't already exist.
|
||||
*
|
||||
* @param string $key
|
||||
* The key of the data to check and store.
|
||||
* @param mixed $value
|
||||
* The data to store.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the data was set, or FALSE if it already existed.
|
||||
*/
|
||||
public function setIfNotExists($key, $value) {
|
||||
$value = (object) [
|
||||
'owner' => $this->owner,
|
||||
'data' => $value,
|
||||
'updated' => (int) $this->requestStack->getMasterRequest()->server->get('REQUEST_TIME'),
|
||||
];
|
||||
return $this->storage->setWithExpireIfNotExists($key, $value, $this->expire);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a particular key/value pair in this SharedTempStore.
|
||||
*
|
||||
* Only stores the given key/value pair if it does not exist yet or is owned
|
||||
* by $this->owner.
|
||||
*
|
||||
* @param string $key
|
||||
* The key of the data to store.
|
||||
* @param mixed $value
|
||||
* The data to store.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the data was set, or FALSE if it already exists and is not owned
|
||||
* by $this->user.
|
||||
*
|
||||
* @throws \Drupal\user\TempStoreException
|
||||
* Thrown when a lock for the backend storage could not be acquired.
|
||||
*/
|
||||
public function setIfOwner($key, $value) {
|
||||
if ($this->setIfNotExists($key, $value)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (($object = $this->storage->get($key)) && ($object->owner == $this->owner)) {
|
||||
$this->set($key, $value);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a particular key/value pair in this SharedTempStore.
|
||||
*
|
||||
* @param string $key
|
||||
* The key of the data to store.
|
||||
* @param mixed $value
|
||||
* The data to store.
|
||||
*
|
||||
* @throws \Drupal\user\TempStoreException
|
||||
* Thrown when a lock for the backend storage could not be acquired.
|
||||
*/
|
||||
public function set($key, $value) {
|
||||
if (!$this->lockBackend->acquire($key)) {
|
||||
$this->lockBackend->wait($key);
|
||||
if (!$this->lockBackend->acquire($key)) {
|
||||
throw new TempStoreException("Couldn't acquire lock to update item '$key' in '{$this->storage->getCollectionName()}' temporary storage.");
|
||||
}
|
||||
}
|
||||
|
||||
$value = (object) [
|
||||
'owner' => $this->owner,
|
||||
'data' => $value,
|
||||
'updated' => (int) $this->requestStack->getMasterRequest()->server->get('REQUEST_TIME'),
|
||||
];
|
||||
$this->storage->setWithExpire($key, $value, $this->expire);
|
||||
$this->lockBackend->release($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the metadata associated with a particular key/value pair.
|
||||
*
|
||||
* @param string $key
|
||||
* The key of the data to store.
|
||||
*
|
||||
* @return mixed
|
||||
* An object with the owner and updated time if the key has a value, or
|
||||
* NULL otherwise.
|
||||
*/
|
||||
public function getMetadata($key) {
|
||||
// Fetch the key/value pair and its metadata.
|
||||
$object = $this->storage->get($key);
|
||||
if ($object) {
|
||||
// Don't keep the data itself in memory.
|
||||
unset($object->data);
|
||||
return $object;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes data from the store for a given key and releases the lock on it.
|
||||
*
|
||||
* @param string $key
|
||||
* The key of the data to delete.
|
||||
*
|
||||
* @throws \Drupal\user\TempStoreException
|
||||
* Thrown when a lock for the backend storage could not be acquired.
|
||||
*/
|
||||
public function delete($key) {
|
||||
if (!$this->lockBackend->acquire($key)) {
|
||||
$this->lockBackend->wait($key);
|
||||
if (!$this->lockBackend->acquire($key)) {
|
||||
throw new TempStoreException("Couldn't acquire lock to delete item '$key' from {$this->storage->getCollectionName()} temporary storage.");
|
||||
}
|
||||
}
|
||||
$this->storage->delete($key);
|
||||
$this->lockBackend->release($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes data from the store for a given key and releases the lock on it.
|
||||
*
|
||||
* Only delete the given key if it is owned by $this->owner.
|
||||
*
|
||||
* @param string $key
|
||||
* The key of the data to delete.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the object was deleted or does not exist, FALSE if it exists but
|
||||
* is not owned by $this->owner.
|
||||
*
|
||||
* @throws \Drupal\user\TempStoreException
|
||||
* Thrown when a lock for the backend storage could not be acquired.
|
||||
*/
|
||||
public function deleteIfOwner($key) {
|
||||
if (!$object = $this->storage->get($key)) {
|
||||
return TRUE;
|
||||
}
|
||||
elseif ($object->owner == $this->owner) {
|
||||
$this->delete($key);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
class SharedTempStore extends CoreSharedTempStore {
|
||||
}
|
||||
|
|
|
@ -2,61 +2,20 @@
|
|||
|
||||
namespace Drupal\user;
|
||||
|
||||
use Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface;
|
||||
use Drupal\Core\Lock\LockBackendInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Drupal\Core\TempStore\SharedTempStoreFactory as CoreSharedTempStoreFactory;
|
||||
|
||||
@trigger_error('\Drupal\user\SharedTempStoreFactory is scheduled for removal in Drupal 9.0.0. Use \Drupal\Core\TempStore\SharedTempStoreFactory instead. See https://www.drupal.org/node/2935639.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Creates a shared temporary storage for a collection.
|
||||
*
|
||||
* @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0.
|
||||
* Use \Drupal\Core\TempStore\SharedTempStoreFactory instead.
|
||||
*
|
||||
* @see \Drupal\Core\TempStore\SharedTempStoreFactory
|
||||
* @see https://www.drupal.org/node/2935639
|
||||
*/
|
||||
class SharedTempStoreFactory {
|
||||
|
||||
/**
|
||||
* The storage factory creating the backend to store the data.
|
||||
*
|
||||
* @var \Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface
|
||||
*/
|
||||
protected $storageFactory;
|
||||
|
||||
/**
|
||||
* The lock object used for this data.
|
||||
*
|
||||
* @var \Drupal\Core\Lock\LockBackendInterface $lockBackend
|
||||
*/
|
||||
protected $lockBackend;
|
||||
|
||||
/**
|
||||
* The request stack.
|
||||
*
|
||||
* @var \Symfony\Component\HttpFoundation\RequestStack
|
||||
*/
|
||||
protected $requestStack;
|
||||
|
||||
/**
|
||||
* The time to live for items in seconds.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $expire;
|
||||
|
||||
/**
|
||||
* Constructs a Drupal\user\SharedTempStoreFactory object.
|
||||
*
|
||||
* @param \Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface $storage_factory
|
||||
* The key/value store factory.
|
||||
* @param \Drupal\Core\Lock\LockBackendInterface $lock_backend
|
||||
* The lock object used for this data.
|
||||
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
|
||||
* The request stack.
|
||||
* @param int $expire
|
||||
* The time to live for items, in seconds.
|
||||
*/
|
||||
public function __construct(KeyValueExpirableFactoryInterface $storage_factory, LockBackendInterface $lock_backend, RequestStack $request_stack, $expire = 604800) {
|
||||
$this->storageFactory = $storage_factory;
|
||||
$this->lockBackend = $lock_backend;
|
||||
$this->requestStack = $request_stack;
|
||||
$this->expire = $expire;
|
||||
}
|
||||
class SharedTempStoreFactory extends CoreSharedTempStoreFactory {
|
||||
|
||||
/**
|
||||
* Creates a SharedTempStore for the current user or anonymous session.
|
||||
|
|
25
web/core/modules/user/src/StatusItem.php
Normal file
25
web/core/modules/user/src/StatusItem.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\user;
|
||||
|
||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
use Drupal\Core\Field\Plugin\Field\FieldType\BooleanItem;
|
||||
|
||||
/**
|
||||
* Defines the 'status' entity field type.
|
||||
*
|
||||
* @todo Consider making this a full field type plugin in
|
||||
* https://www.drupal.org/project/drupal/issues/2936864.
|
||||
*/
|
||||
class StatusItem extends BooleanItem {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function generateSampleValue(FieldDefinitionInterface $field_definition) {
|
||||
// Always generate a sample with an enabled status.
|
||||
$values['value'] = 1;
|
||||
return $values;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\user;
|
||||
|
||||
/**
|
||||
* Thrown by SharedTempStore and PrivateTempStore if they cannot acquire a lock.
|
||||
*
|
||||
* @see \Drupal\user\SharedTempStore
|
||||
* @see \Drupal\user\PrivateTempStore
|
||||
*/
|
||||
class TempStoreException extends \Exception {}
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Drupal\user\Tests;
|
||||
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\rest\Tests\RESTTestBase;
|
||||
use Drupal\user\Entity\Role;
|
||||
use Drupal\user\RoleInterface;
|
||||
|
@ -117,7 +118,7 @@ class RestRegisterUserTest extends RESTTestBase {
|
|||
* @param bool $include_password
|
||||
* Whether to include a password in the user values.
|
||||
*
|
||||
* @return string Serialized user values.
|
||||
* @return string
|
||||
* Serialized user values.
|
||||
*/
|
||||
protected function createSerializedUser($name, $include_password = TRUE) {
|
||||
|
@ -166,7 +167,7 @@ class RestRegisterUserTest extends RESTTestBase {
|
|||
*/
|
||||
protected function registerRequest($name, $include_password = TRUE) {
|
||||
$serialized = $this->createSerializedUser($name, $include_password);
|
||||
$this->httpRequest('/user/register', 'POST', $serialized, 'application/hal+json');
|
||||
$this->httpRequest(Url::fromRoute('rest.user_registration.POST', ['_format' => 'hal_json']), 'POST', $serialized, 'application/hal+json');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\user\Tests\Update;
|
||||
|
||||
use Drupal\system\Tests\Update\UpdatePathTestBase;
|
||||
use Drupal\user\Entity\Role;
|
||||
|
||||
/**
|
||||
* Tests user permissions sort upgrade path.
|
||||
*
|
||||
* @group Update
|
||||
*/
|
||||
class UserUpdateOrderPermissionsTest extends UpdatePathTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setDatabaseDumpFiles() {
|
||||
$this->databaseDumpFiles = [
|
||||
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8-rc1.bare.standard.php.gz',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that permissions are ordered by machine name.
|
||||
*/
|
||||
public function testPermissionsOrder() {
|
||||
$authenticated = Role::load('authenticated');
|
||||
$permissions = $authenticated->getPermissions();
|
||||
sort($permissions);
|
||||
$this->assertNotIdentical($permissions, $authenticated->getPermissions());
|
||||
|
||||
$this->runUpdates();
|
||||
$authenticated = Role::load('authenticated');
|
||||
$this->assertIdentical($permissions, $authenticated->getPermissions());
|
||||
}
|
||||
|
||||
}
|
36
web/core/modules/user/src/Tests/UserResetEmailTestTrait.php
Normal file
36
web/core/modules/user/src/Tests/UserResetEmailTestTrait.php
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\user\Tests;
|
||||
|
||||
@trigger_error(__NAMESPACE__ . '\UserResetEmailTestTrait is deprecated and scheduled for removal before Drupal 9.0.0. Add the method to the test class instead, see https://www.drupal.org/node/2999766', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Core\Test\AssertMailTrait;
|
||||
|
||||
/**
|
||||
* Helper function for logging in from reset password email.
|
||||
*
|
||||
* @deprecated Scheduled for removal before Drupal 9.0.0.
|
||||
* Add the method to the test class instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2999766
|
||||
*/
|
||||
trait UserResetEmailTestTrait {
|
||||
|
||||
use AssertMailTrait {
|
||||
getMails as drupalGetMails;
|
||||
}
|
||||
|
||||
/**
|
||||
* Login from reset password email.
|
||||
*/
|
||||
protected function loginFromResetEmail() {
|
||||
$_emails = $this->drupalGetMails();
|
||||
$email = end($_emails);
|
||||
$urls = [];
|
||||
preg_match('#.+user/reset/.+#', $email['body'], $urls);
|
||||
$resetURL = $urls[0];
|
||||
$this->drupalGet($resetURL);
|
||||
$this->drupalPostForm(NULL, NULL, 'Log in');
|
||||
}
|
||||
|
||||
}
|
24
web/core/modules/user/src/TimeZoneItem.php
Normal file
24
web/core/modules/user/src/TimeZoneItem.php
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\user;
|
||||
|
||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
use Drupal\Core\Field\Plugin\Field\FieldType\StringItem;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* Defines a custom field item class for the 'timezone' user entity field.
|
||||
*/
|
||||
class TimeZoneItem extends StringItem {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function generateSampleValue(FieldDefinitionInterface $field_definition) {
|
||||
$timezones = User::getAllowedTimezones();
|
||||
// We need to vary the selected timezones since we're generating a sample.
|
||||
$key = rand(0, count($timezones) - 1);
|
||||
return $timezones[$key];
|
||||
}
|
||||
|
||||
}
|
86
web/core/modules/user/src/ToolbarLinkBuilder.php
Normal file
86
web/core/modules/user/src/ToolbarLinkBuilder.php
Normal file
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\user;
|
||||
|
||||
use Drupal\Core\Session\AccountProxyInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\Core\Url;
|
||||
|
||||
/**
|
||||
* ToolbarLinkBuilder fills out the placeholders generated in user_toolbar().
|
||||
*/
|
||||
class ToolbarLinkBuilder {
|
||||
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* The current user.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountProxyInterface
|
||||
*/
|
||||
protected $account;
|
||||
|
||||
/**
|
||||
* ToolbarHandler constructor.
|
||||
*
|
||||
* @param \Drupal\Core\Session\AccountProxyInterface $account
|
||||
* The current user.
|
||||
*/
|
||||
public function __construct(AccountProxyInterface $account) {
|
||||
$this->account = $account;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy builder callback for rendering toolbar links.
|
||||
*
|
||||
* @return array
|
||||
* A renderable array as expected by the renderer service.
|
||||
*/
|
||||
public function renderToolbarLinks() {
|
||||
$links = [
|
||||
'account' => [
|
||||
'title' => $this->t('View profile'),
|
||||
'url' => Url::fromRoute('user.page'),
|
||||
'attributes' => [
|
||||
'title' => $this->t('User account'),
|
||||
],
|
||||
],
|
||||
'account_edit' => [
|
||||
'title' => $this->t('Edit profile'),
|
||||
'url' => Url::fromRoute('entity.user.edit_form', ['user' => $this->account->id()]),
|
||||
'attributes' => [
|
||||
'title' => $this->t('Edit user account'),
|
||||
],
|
||||
],
|
||||
'logout' => [
|
||||
'title' => $this->t('Log out'),
|
||||
'url' => Url::fromRoute('user.logout'),
|
||||
],
|
||||
];
|
||||
$build = [
|
||||
'#theme' => 'links__toolbar_user',
|
||||
'#links' => $links,
|
||||
'#attributes' => [
|
||||
'class' => ['toolbar-menu'],
|
||||
],
|
||||
'#cache' => [
|
||||
'contexts' => ['user'],
|
||||
],
|
||||
];
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy builder callback for rendering the username.
|
||||
*
|
||||
* @return array
|
||||
* A renderable array as expected by the renderer service.
|
||||
*/
|
||||
public function renderDisplayName() {
|
||||
return [
|
||||
'#markup' => $this->account->getDisplayName(),
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -58,7 +58,7 @@ class UserAccessControlHandler extends EntityAccessControlHandler {
|
|||
return AccessResult::allowed()->cachePerUser();
|
||||
}
|
||||
else {
|
||||
return AccessResultNeutral::neutral("The 'access user profiles' permission is required and the user must be active.");
|
||||
return AccessResultNeutral::neutral("The 'access user profiles' permission is required and the user must be active.")->cachePerPermissions()->addCacheableDependency($entity);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -106,7 +106,7 @@ class UserAccessControlHandler extends EntityAccessControlHandler {
|
|||
return AccessResult::allowed()->cachePerPermissions()->cachePerUser();
|
||||
}
|
||||
else {
|
||||
return AccessResult::forbidden();
|
||||
return AccessResult::neutral();
|
||||
}
|
||||
|
||||
case 'preferred_langcode':
|
||||
|
@ -116,7 +116,7 @@ class UserAccessControlHandler extends EntityAccessControlHandler {
|
|||
// Allow view access to own mail address and other personalization
|
||||
// settings.
|
||||
if ($operation == 'view') {
|
||||
return $is_own_account ? AccessResult::allowed()->cachePerUser() : AccessResult::forbidden();
|
||||
return $is_own_account ? AccessResult::allowed()->cachePerUser() : AccessResult::neutral();
|
||||
}
|
||||
// Anyone that can edit the user can also edit this field.
|
||||
return AccessResult::allowed()->cachePerPermissions();
|
||||
|
@ -127,14 +127,14 @@ class UserAccessControlHandler extends EntityAccessControlHandler {
|
|||
|
||||
case 'created':
|
||||
// Allow viewing the created date, but not editing it.
|
||||
return ($operation == 'view') ? AccessResult::allowed() : AccessResult::forbidden();
|
||||
return ($operation == 'view') ? AccessResult::allowed() : AccessResult::neutral();
|
||||
|
||||
case 'roles':
|
||||
case 'status':
|
||||
case 'access':
|
||||
case 'login':
|
||||
case 'init':
|
||||
return AccessResult::forbidden();
|
||||
return AccessResult::neutral();
|
||||
}
|
||||
|
||||
return parent::checkFieldAccess($operation, $field_definition, $account, $items);
|
||||
|
|
|
@ -40,7 +40,7 @@ class UserData implements UserDataInterface {
|
|||
$query->condition('name', $name);
|
||||
}
|
||||
$result = $query->execute();
|
||||
// If $module, $uid, and $name was passed, return the value.
|
||||
// If $module, $uid, and $name were passed, return the value.
|
||||
if (isset($name) && isset($uid)) {
|
||||
$result = $result->fetchAllAssoc('uid');
|
||||
if (isset($result[$uid])) {
|
||||
|
@ -48,40 +48,35 @@ class UserData implements UserDataInterface {
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
// If $module and $uid was passed, return the name/value pairs.
|
||||
elseif (isset($uid)) {
|
||||
$return = [];
|
||||
$return = [];
|
||||
// If $module and $uid were passed, return data keyed by name.
|
||||
if (isset($uid)) {
|
||||
foreach ($result as $record) {
|
||||
$return[$record->name] = ($record->serialized ? unserialize($record->value) : $record->value);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
// If $module and $name was passed, return the uid/value pairs.
|
||||
elseif (isset($name)) {
|
||||
$return = [];
|
||||
// If $module and $name were passed, return data keyed by uid.
|
||||
if (isset($name)) {
|
||||
foreach ($result as $record) {
|
||||
$return[$record->uid] = ($record->serialized ? unserialize($record->value) : $record->value);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
// If only $module was passed, return data keyed by uid and name.
|
||||
else {
|
||||
$return = [];
|
||||
foreach ($result as $record) {
|
||||
$return[$record->uid][$record->name] = ($record->serialized ? unserialize($record->value) : $record->value);
|
||||
}
|
||||
return $return;
|
||||
foreach ($result as $record) {
|
||||
$return[$record->uid][$record->name] = ($record->serialized ? unserialize($record->value) : $record->value);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function set($module, $uid, $name, $value) {
|
||||
$serialized = 0;
|
||||
if (!is_scalar($value)) {
|
||||
$serialized = (int) !is_scalar($value);
|
||||
if ($serialized) {
|
||||
$value = serialize($value);
|
||||
$serialized = 1;
|
||||
}
|
||||
$this->connection->merge('users_data')
|
||||
->keys([
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Drupal\user;
|
||||
|
||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
use Drupal\Core\Field\Plugin\Field\FieldType\StringItem;
|
||||
|
||||
/**
|
||||
|
@ -23,4 +24,14 @@ class UserNameItem extends StringItem {
|
|||
return $value === NULL || $value === '';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function generateSampleValue(FieldDefinitionInterface $field_definition) {
|
||||
$values = parent::generateSampleValue($field_definition);
|
||||
// User names larger than 60 characters won't pass validation.
|
||||
$values['value'] = substr($values['value'], 0, UserInterface::USERNAME_MAX_LENGTH);
|
||||
return $values;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,8 +1,25 @@
|
|||
<?php
|
||||
// @codingStandardsIgnoreFile
|
||||
// This class is intentionally empty so that it overwrites when sites are
|
||||
// updated from a zip/tarball without deleting the /core folder first.
|
||||
// @todo: remove in 8.3.x
|
||||
//
|
||||
|
||||
namespace Drupal\user;
|
||||
class UserServiceProvider {}
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\DependencyInjection\ServiceModifierInterface;
|
||||
|
||||
class UserServiceProvider implements ServiceModifierInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function alter(ContainerBuilder $container) {
|
||||
if ($container->hasParameter('user.tempstore.expire')) {
|
||||
@trigger_error('The container parameter "user.tempstore.expire" is deprecated. Use "tempstore.expire" instead. See https://www.drupal.org/node/2935639.', E_USER_DEPRECATED);
|
||||
$container->setParameter('tempstore.expire', $container->getParameter('user.tempstore.expire'));
|
||||
}
|
||||
else {
|
||||
// Ensure the user.tempstore.expire parameter is set to the same value
|
||||
// for modules that still rely on it.
|
||||
$container->setParameter('user.tempstore.expire', $container->getParameter('tempstore.expire'));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ class UserStorage extends SqlContentEntityStorage implements UserStorageInterfac
|
|||
// The anonymous user account is saved with the fixed user ID of 0.
|
||||
// Therefore we need to check for NULL explicitly.
|
||||
if ($entity->id() === NULL) {
|
||||
$entity->uid->value = $this->database->nextId($this->database->query('SELECT MAX(uid) FROM {users}')->fetchField());
|
||||
$entity->uid->value = $this->database->nextId($this->database->query('SELECT MAX(uid) FROM {' . $this->getBaseTable() . '}')->fetchField());
|
||||
$entity->enforceIsNew();
|
||||
}
|
||||
return parent::doSaveFieldItems($entity, $names);
|
||||
|
@ -39,7 +39,7 @@ class UserStorage extends SqlContentEntityStorage implements UserStorageInterfac
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function updateLastLoginTimestamp(UserInterface $account) {
|
||||
$this->database->update('users_field_data')
|
||||
$this->database->update($this->getDataTable())
|
||||
->fields(['login' => $account->getLastLoginTime()])
|
||||
->condition('uid', $account->id())
|
||||
->execute();
|
||||
|
@ -51,7 +51,7 @@ class UserStorage extends SqlContentEntityStorage implements UserStorageInterfac
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function updateLastAccessTimestamp(AccountInterface $account, $timestamp) {
|
||||
$this->database->update('users_field_data')
|
||||
$this->database->update($this->getDataTable())
|
||||
->fields([
|
||||
'access' => $timestamp,
|
||||
])
|
||||
|
|
|
@ -17,9 +17,11 @@ class UserStorageSchema extends SqlContentEntityStorageSchema {
|
|||
protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $reset = FALSE) {
|
||||
$schema = parent::getEntitySchema($entity_type, $reset);
|
||||
|
||||
$schema['users_field_data']['unique keys'] += [
|
||||
'user__name' => ['name', 'langcode'],
|
||||
];
|
||||
if ($data_table = $this->storage->getDataTable()) {
|
||||
$schema[$data_table]['unique keys'] += [
|
||||
'user__name' => ['name', 'langcode'],
|
||||
];
|
||||
}
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ class UserViewsData extends EntityViewsData {
|
|||
'argument field' => 'uid',
|
||||
'base' => 'node_field_data',
|
||||
'field' => 'nid',
|
||||
'relationship' => 'node_field_data:uid'
|
||||
'relationship' => 'node_field_data:uid',
|
||||
],
|
||||
];
|
||||
|
||||
|
@ -220,34 +220,20 @@ class UserViewsData extends EntityViewsData {
|
|||
],
|
||||
];
|
||||
|
||||
$data['user__roles']['table']['group'] = $this->t('User');
|
||||
// Alter the user roles target_id column.
|
||||
$data['user__roles']['roles_target_id']['field']['id'] = 'user_roles';
|
||||
$data['user__roles']['roles_target_id']['field']['no group by'] = TRUE;
|
||||
|
||||
$data['user__roles']['table']['join'] = [
|
||||
'users_field_data' => [
|
||||
'left_field' => 'uid',
|
||||
'field' => 'entity_id',
|
||||
],
|
||||
];
|
||||
$data['user__roles']['roles_target_id']['filter']['id'] = 'user_roles';
|
||||
$data['user__roles']['roles_target_id']['filter']['allow empty'] = TRUE;
|
||||
|
||||
$data['user__roles']['roles_target_id'] = [
|
||||
'title' => $this->t('Roles'),
|
||||
'help' => $this->t('Roles that a user belongs to.'),
|
||||
'field' => [
|
||||
'id' => 'user_roles',
|
||||
'no group by' => TRUE,
|
||||
],
|
||||
'filter' => [
|
||||
'id' => 'user_roles',
|
||||
'allow empty' => TRUE,
|
||||
],
|
||||
'argument' => [
|
||||
'id' => 'user__roles_rid',
|
||||
'name table' => 'role',
|
||||
'name field' => 'name',
|
||||
'empty field name' => $this->t('No role'),
|
||||
'zero is null' => TRUE,
|
||||
'numeric' => TRUE,
|
||||
],
|
||||
$data['user__roles']['roles_target_id']['argument'] = [
|
||||
'id' => 'user__roles_rid',
|
||||
'name table' => 'role',
|
||||
'name field' => 'name',
|
||||
'empty field name' => $this->t('No role'),
|
||||
'zero is null' => TRUE,
|
||||
'numeric' => TRUE,
|
||||
];
|
||||
|
||||
$data['user__roles']['permission'] = [
|
||||
|
|
|
@ -18,5 +18,5 @@ $connection->insert('config')
|
|||
->values([
|
||||
'collection' => '',
|
||||
'name' => 'user.mail',
|
||||
'data' => "a:10:{s:14:\"cancel_confirm\";a:2:{s:4:\"body\";s:369:\"[user:name],\n\nA request to cancel your account has been made at [site:name].\n\nYou may now cancel your account on [site:url-brief] by clicking this link or copying and pasting it into your browser:\n\n[user:cancel-url]\n\nNOTE: The cancellation of your account is not reversible.\n\nThis link expires in one day and nothing will happen if it is not used.\n\n-- [site:name] team\";s:7:\"subject\";s:59:\"Account cancellation request for [user:name] at [site:name]\";}s:14:\"password_reset\";a:2:{s:4:\"body\";s:397:\"[user:name],\n\nA request to reset the password for your account has been made at [site:name].\n\nYou may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password. It expires after one day and nothing will happen if it's not used.\n\n-- [site:name] team\";s:7:\"subject\";s:60:\"Replacement login information for [user:name] at [site:name]\";}s:22:\"register_admin_created\";a:2:{s:4:\"body\";s:463:\"[user:name],\n\nA site administrator at [site:name] has created an account for you. You may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n-- [site:name] team\";s:7:\"subject\";s:58:\"An administrator created an account for you at [site:name]\";}s:29:\"register_no_approval_required\";a:2:{s:4:\"body\";s:437:\"[user:name],\n\nThank you for registering at [site:name]. You may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n-- [site:name] team\";s:7:\"subject\";s:46:\"Account details for [user:name] at [site:name]\";}s:25:\"register_pending_approval\";a:2:{s:4:\"body\";s:281:\"[user:name],\n\nThank you for registering at [site:name]. Your application for an account is currently pending approval. Once it has been approved, you will receive another email containing information about how to log in, set your password, and other details.\n\n\n-- [site:name] team\";s:7:\"subject\";s:71:\"Account details for [user:name] at [site:name] (pending admin approval)\";}s:31:\"register_pending_approval_admin\";a:2:{s:4:\"body\";s:56:\"[user:name] has applied for an account.\n\n[user:edit-url]\";s:7:\"subject\";s:71:\"Account details for [user:name] at [site:name] (pending admin approval)\";}s:16:\"status_activated\";a:2:{s:4:\"body\";s:446:\"[user:name],\n\nYour account at [site:name] has been activated.\n\nYou may now log in by clicking this link or copying and pasting it into your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n-- [site:name] team\";s:7:\"subject\";s:57:\"Account details for [user:name] at [site:name] (approved)\";}s:14:\"status_blocked\";a:2:{s:4:\"body\";s:89:\"[user:name],\n\nYour account on [site:account-name] has been blocked.\n\n-- [site:name] team\";s:7:\"subject\";s:56:\"Account details for [user:name] at [site:name] (blocked)\";}s:15:\"status_canceled\";a:2:{s:4:\"body\";s:82:\"[user:name],\n\nYour account on [site:name] has been canceled.\n\n-- [site:name] team\";s:7:\"subject\";s:57:\"Account details for [user:name] at [site:name] (canceled)\";}s:8:\"langcode\";s:2:\"en\";}"
|
||||
'data' => "a:10:{s:14:\"cancel_confirm\";a:2:{s:4:\"body\";s:369:\"[user:name],\n\nA request to cancel your account has been made at [site:name].\n\nYou may now cancel your account on [site:url-brief] by clicking this link or copying and pasting it into your browser:\n\n[user:cancel-url]\n\nNOTE: The cancellation of your account is not reversible.\n\nThis link expires in one day and nothing will happen if it is not used.\n\n-- [site:name] team\";s:7:\"subject\";s:59:\"Account cancellation request for [user:name] at [site:name]\";}s:14:\"password_reset\";a:2:{s:4:\"body\";s:397:\"[user:name],\n\nA request to reset the password for your account has been made at [site:name].\n\nYou may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password. It expires after one day and nothing will happen if it's not used.\n\n-- [site:name] team\";s:7:\"subject\";s:60:\"Replacement login information for [user:name] at [site:name]\";}s:22:\"register_admin_created\";a:2:{s:4:\"body\";s:463:\"[user:name],\n\nA site administrator at [site:name] has created an account for you. You may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n-- [site:name] team\";s:7:\"subject\";s:58:\"An administrator created an account for you at [site:name]\";}s:29:\"register_no_approval_required\";a:2:{s:4:\"body\";s:437:\"[user:name],\n\nThank you for registering at [site:name]. You may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n-- [site:name] team\";s:7:\"subject\";s:46:\"Account details for [user:name] at [site:name]\";}s:25:\"register_pending_approval\";a:2:{s:4:\"body\";s:281:\"[user:name],\n\nThank you for registering at [site:name]. Your application for an account is currently pending approval. Once it has been approved, you will receive another email containing information about how to log in, set your password, and other details.\n\n\n-- [site:name] team\";s:7:\"subject\";s:71:\"Account details for [user:name] at [site:name] (pending admin approval)\";}s:31:\"register_pending_approval_admin\";a:2:{s:4:\"body\";s:56:\"[user:name] has applied for an account.\n\n[user:edit-url]\";s:7:\"subject\";s:71:\"Account details for [user:name] at [site:name] (pending admin approval)\";}s:16:\"status_activated\";a:2:{s:4:\"body\";s:446:\"[user:name],\n\nYour account at [site:name] has been activated.\n\nYou may now log in by clicking this link or copying and pasting it into your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n-- [site:name] team\";s:7:\"subject\";s:57:\"Account details for [user:name] at [site:name] (approved)\";}s:14:\"status_blocked\";a:2:{s:4:\"body\";s:89:\"[user:name],\n\nYour account on [site:account-name] has been blocked.\n\n-- [site:name] team\";s:7:\"subject\";s:56:\"Account details for [user:name] at [site:name] (blocked)\";}s:15:\"status_canceled\";a:2:{s:4:\"body\";s:82:\"[user:name],\n\nYour account on [site:name] has been canceled.\n\n-- [site:name] team\";s:7:\"subject\";s:57:\"Account details for [user:name] at [site:name] (canceled)\";}s:8:\"langcode\";s:2:\"en\";}",
|
||||
])->execute();
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
*/
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
|
@ -22,3 +25,16 @@ function user_access_test_user_access(User $entity, $operation, $account) {
|
|||
}
|
||||
return AccessResult::neutral();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_field_access().
|
||||
*/
|
||||
function user_access_test_entity_field_access($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) {
|
||||
// Account with role sub-admin can view the status, init and mail fields for user with no roles.
|
||||
if ($operation === 'view' && in_array($field_definition->getName(), ['status', 'init', 'mail'])) {
|
||||
if (($items == NULL) || (count($items->getEntity()->getRoles()) == 1)) {
|
||||
return AccessResult::allowedIfHasPermission($account, 'sub-admin');
|
||||
}
|
||||
}
|
||||
return AccessResult::neutral();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
sub-admin:
|
||||
title: 'Administer users with no roles'
|
|
@ -4,4 +4,3 @@ user_form_test.cancel:
|
|||
_entity_form: 'user.cancel'
|
||||
requirements:
|
||||
_permission: 'cancel other accounts'
|
||||
|
||||
|
|
|
@ -5,15 +5,16 @@
|
|||
* Support module for user hooks testing.
|
||||
*/
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
||||
/**
|
||||
* Implements hook_user_format_name_alter().
|
||||
*/
|
||||
function user_hooks_test_user_format_name_alter(&$name, $account) {
|
||||
function user_hooks_test_user_format_name_alter(&$name, AccountInterface $account) {
|
||||
if (\Drupal::state()->get('user_hooks_test_user_format_name_alter', FALSE)) {
|
||||
if (\Drupal::state()->get('user_hooks_test_user_format_name_alter_safe', FALSE)) {
|
||||
$name = SafeMarkup::format('<em>@uid</em>', ['@uid' => $account->id()]);
|
||||
$name = new FormattableMarkup('<em>@uid</em>', ['@uid' => $account->id()]);
|
||||
}
|
||||
else {
|
||||
$name = '<em>' . $account->id() . '</em>';
|
||||
|
|
|
@ -0,0 +1,478 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- user
|
||||
id: test_user_fields_access
|
||||
label: ''
|
||||
module: views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: users_field_data
|
||||
base_field: uid
|
||||
core: 8.x
|
||||
display:
|
||||
default:
|
||||
display_plugin: default
|
||||
id: default
|
||||
display_title: Master
|
||||
position: 0
|
||||
display_options:
|
||||
access:
|
||||
type: none
|
||||
options: { }
|
||||
cache:
|
||||
type: tag
|
||||
options: { }
|
||||
query:
|
||||
type: views_query
|
||||
options:
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
replica: false
|
||||
query_comment: ''
|
||||
query_tags: { }
|
||||
exposed_form:
|
||||
type: basic
|
||||
options:
|
||||
submit_button: Apply
|
||||
reset_button: false
|
||||
reset_button_label: Reset
|
||||
exposed_sorts_label: 'Sort by'
|
||||
expose_sort_order: true
|
||||
sort_asc_label: Asc
|
||||
sort_desc_label: Desc
|
||||
pager:
|
||||
type: mini
|
||||
options:
|
||||
items_per_page: 10
|
||||
offset: 0
|
||||
id: 0
|
||||
total_pages: null
|
||||
expose:
|
||||
items_per_page: false
|
||||
items_per_page_label: 'Items per page'
|
||||
items_per_page_options: '5, 10, 25, 50'
|
||||
items_per_page_options_all: false
|
||||
items_per_page_options_all_label: '- All -'
|
||||
offset: false
|
||||
offset_label: Offset
|
||||
tags:
|
||||
previous: ‹‹
|
||||
next: ››
|
||||
style:
|
||||
type: table
|
||||
options:
|
||||
grouping: { }
|
||||
row_class: ''
|
||||
default_row_class: true
|
||||
override: true
|
||||
sticky: false
|
||||
caption: ''
|
||||
summary: ''
|
||||
description: ''
|
||||
columns:
|
||||
name: name
|
||||
status: status
|
||||
mail: mail
|
||||
init: init
|
||||
created: created
|
||||
info:
|
||||
name:
|
||||
sortable: false
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
status:
|
||||
sortable: false
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
mail:
|
||||
sortable: false
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
init:
|
||||
sortable: false
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
created:
|
||||
sortable: false
|
||||
default_sort_order: asc
|
||||
align: ''
|
||||
separator: ''
|
||||
empty_column: false
|
||||
responsive: ''
|
||||
default: '-1'
|
||||
empty_table: false
|
||||
row:
|
||||
type: fields
|
||||
fields:
|
||||
name:
|
||||
id: name
|
||||
table: users_field_data
|
||||
field: name
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: Name
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
text: ''
|
||||
make_link: false
|
||||
path: ''
|
||||
absolute: false
|
||||
external: false
|
||||
replace_spaces: false
|
||||
path_case: none
|
||||
trim_whitespace: false
|
||||
alt: ''
|
||||
rel: ''
|
||||
link_class: ''
|
||||
prefix: ''
|
||||
suffix: ''
|
||||
target: ''
|
||||
nl2br: false
|
||||
max_length: 0
|
||||
word_boundary: false
|
||||
ellipsis: false
|
||||
more_link: false
|
||||
more_link_text: ''
|
||||
more_link_path: ''
|
||||
strip_tags: false
|
||||
trim: false
|
||||
preserve_tags: ''
|
||||
html: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: true
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
click_sort_column: value
|
||||
type: user_name
|
||||
settings:
|
||||
link_to_entity: true
|
||||
group_column: value
|
||||
group_columns: { }
|
||||
group_rows: true
|
||||
delta_limit: 0
|
||||
delta_offset: 0
|
||||
delta_reversed: false
|
||||
delta_first_last: false
|
||||
multi_type: separator
|
||||
separator: ', '
|
||||
field_api_classes: false
|
||||
entity_type: user
|
||||
entity_field: name
|
||||
plugin_id: field
|
||||
status:
|
||||
id: status
|
||||
table: users_field_data
|
||||
field: status
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: Status
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
text: ''
|
||||
make_link: false
|
||||
path: ''
|
||||
absolute: false
|
||||
external: false
|
||||
replace_spaces: false
|
||||
path_case: none
|
||||
trim_whitespace: false
|
||||
alt: ''
|
||||
rel: ''
|
||||
link_class: ''
|
||||
prefix: ''
|
||||
suffix: ''
|
||||
target: ''
|
||||
nl2br: false
|
||||
max_length: 0
|
||||
word_boundary: true
|
||||
ellipsis: true
|
||||
more_link: false
|
||||
more_link_text: ''
|
||||
more_link_path: ''
|
||||
strip_tags: false
|
||||
trim: false
|
||||
preserve_tags: ''
|
||||
html: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: true
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
click_sort_column: value
|
||||
type: boolean
|
||||
settings:
|
||||
format: default
|
||||
format_custom_true: ''
|
||||
format_custom_false: ''
|
||||
group_column: value
|
||||
group_columns: { }
|
||||
group_rows: true
|
||||
delta_limit: 0
|
||||
delta_offset: 0
|
||||
delta_reversed: false
|
||||
delta_first_last: false
|
||||
multi_type: separator
|
||||
separator: ', '
|
||||
field_api_classes: false
|
||||
entity_type: user
|
||||
entity_field: status
|
||||
plugin_id: field
|
||||
mail:
|
||||
id: mail
|
||||
table: users_field_data
|
||||
field: mail
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: Email
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
text: ''
|
||||
make_link: false
|
||||
path: ''
|
||||
absolute: false
|
||||
external: false
|
||||
replace_spaces: false
|
||||
path_case: none
|
||||
trim_whitespace: false
|
||||
alt: ''
|
||||
rel: ''
|
||||
link_class: ''
|
||||
prefix: ''
|
||||
suffix: ''
|
||||
target: ''
|
||||
nl2br: false
|
||||
max_length: 0
|
||||
word_boundary: true
|
||||
ellipsis: true
|
||||
more_link: false
|
||||
more_link_text: ''
|
||||
more_link_path: ''
|
||||
strip_tags: false
|
||||
trim: false
|
||||
preserve_tags: ''
|
||||
html: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: true
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
click_sort_column: value
|
||||
type: basic_string
|
||||
settings: { }
|
||||
group_column: value
|
||||
group_columns: { }
|
||||
group_rows: true
|
||||
delta_limit: 0
|
||||
delta_offset: 0
|
||||
delta_reversed: false
|
||||
delta_first_last: false
|
||||
multi_type: separator
|
||||
separator: ', '
|
||||
field_api_classes: false
|
||||
entity_type: user
|
||||
entity_field: mail
|
||||
plugin_id: field
|
||||
init:
|
||||
id: init
|
||||
table: users_field_data
|
||||
field: init
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: Init
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
text: ''
|
||||
make_link: false
|
||||
path: ''
|
||||
absolute: false
|
||||
external: false
|
||||
replace_spaces: false
|
||||
path_case: none
|
||||
trim_whitespace: false
|
||||
alt: ''
|
||||
rel: ''
|
||||
link_class: ''
|
||||
prefix: ''
|
||||
suffix: ''
|
||||
target: ''
|
||||
nl2br: false
|
||||
max_length: 0
|
||||
word_boundary: true
|
||||
ellipsis: true
|
||||
more_link: false
|
||||
more_link_text: ''
|
||||
more_link_path: ''
|
||||
strip_tags: false
|
||||
trim: false
|
||||
preserve_tags: ''
|
||||
html: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: true
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
click_sort_column: value
|
||||
type: basic_string
|
||||
settings: { }
|
||||
group_column: value
|
||||
group_columns: { }
|
||||
group_rows: true
|
||||
delta_limit: 0
|
||||
delta_offset: 0
|
||||
delta_reversed: false
|
||||
delta_first_last: false
|
||||
multi_type: separator
|
||||
separator: ', '
|
||||
field_api_classes: false
|
||||
entity_type: user
|
||||
entity_field: init
|
||||
plugin_id: field
|
||||
created:
|
||||
id: created
|
||||
table: users_field_data
|
||||
field: created
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: Created
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
text: ''
|
||||
make_link: false
|
||||
path: ''
|
||||
absolute: false
|
||||
external: false
|
||||
replace_spaces: false
|
||||
path_case: none
|
||||
trim_whitespace: false
|
||||
alt: ''
|
||||
rel: ''
|
||||
link_class: ''
|
||||
prefix: ''
|
||||
suffix: ''
|
||||
target: ''
|
||||
nl2br: false
|
||||
max_length: 0
|
||||
word_boundary: true
|
||||
ellipsis: true
|
||||
more_link: false
|
||||
more_link_text: ''
|
||||
more_link_path: ''
|
||||
strip_tags: false
|
||||
trim: false
|
||||
preserve_tags: ''
|
||||
html: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: true
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
click_sort_column: value
|
||||
type: timestamp
|
||||
settings:
|
||||
date_format: medium
|
||||
custom_date_format: ''
|
||||
timezone: ''
|
||||
group_column: value
|
||||
group_columns: { }
|
||||
group_rows: true
|
||||
delta_limit: 0
|
||||
delta_offset: 0
|
||||
delta_reversed: false
|
||||
delta_first_last: false
|
||||
multi_type: separator
|
||||
separator: ', '
|
||||
field_api_classes: false
|
||||
entity_type: user
|
||||
entity_field: created
|
||||
plugin_id: field
|
||||
filters: { }
|
||||
sorts: { }
|
||||
title: ''
|
||||
header: { }
|
||||
footer: { }
|
||||
empty: { }
|
||||
relationships: { }
|
||||
arguments: { }
|
||||
display_extenders: { }
|
||||
cache_metadata:
|
||||
max-age: 0
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url.query_args
|
||||
tags: { }
|
||||
page_1:
|
||||
display_plugin: page
|
||||
id: page_1
|
||||
display_title: Page
|
||||
position: 1
|
||||
display_options:
|
||||
display_extenders: { }
|
||||
path: test_user_fields_access
|
||||
cache_metadata:
|
||||
max-age: 0
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url.query_args
|
||||
tags: { }
|
|
@ -5,5 +5,5 @@ package: Testing
|
|||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- user
|
||||
- views
|
||||
- drupal:user
|
||||
- drupal:views
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\user\Tests\Views;
|
||||
namespace Drupal\Tests\user\Functional;
|
||||
|
||||
use Drupal\Tests\views_ui\Functional\UITestBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
use Drupal\views_ui\Tests\UITestBase;
|
||||
|
||||
/**
|
||||
* Tests views role access plugin UI.
|
||||
*
|
||||
* @group user
|
||||
* @see Drupal\user\Plugin\views\access\Role
|
||||
* @see \Drupal\user\Plugin\views\access\Role
|
||||
*/
|
||||
class AccessRoleUITest extends UITestBase {
|
||||
|
||||
|
@ -30,8 +30,8 @@ class AccessRoleUITest extends UITestBase {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
ViewTestData::createTestViews(get_class($this), ['user_test_views']);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue