updated core from 8.4 to 8.5 : bug with login_destination
This commit is contained in:
@@ -11,6 +11,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Configure user settings for this site.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class AccountSettingsForm extends ConfigFormBase {
|
||||
|
||||
|
||||
@@ -50,6 +50,12 @@ class CurrentUserContext implements ContextProviderInterface {
|
||||
public function getRuntimeContexts(array $unqualified_context_ids) {
|
||||
$current_user = $this->userStorage->load($this->account->id());
|
||||
|
||||
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 = new Context(new ContextDefinition('entity:user', $this->t('Current user')), $current_user);
|
||||
$cacheability = new CacheableMetadata();
|
||||
$cacheability->setCacheContexts(['user']);
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
@@ -498,11 +500,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 {
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides a user login form.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class UserLoginForm extends FormBase {
|
||||
|
||||
|
||||
@@ -6,19 +6,21 @@ use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Form\ConfirmFormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
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 +41,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 +59,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')
|
||||
);
|
||||
|
||||
@@ -11,6 +11,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides a user password reset form.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class UserPasswordForm extends FormBase {
|
||||
|
||||
|
||||
@@ -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,6 +129,21 @@ 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] = [
|
||||
|
||||
@@ -7,6 +7,8 @@ use Drupal\user\RoleInterface;
|
||||
|
||||
/**
|
||||
* Provides the user permissions administration form for a specific role.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class UserPermissionsRoleSpecificForm extends UserPermissionsForm {
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -43,7 +43,7 @@ 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 \Drupal\Core\Session\AccountInterface $current_user
|
||||
* 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')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ 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);
|
||||
$source_plugin = $profile_field_migration->getSourcePlugin();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -127,4 +127,18 @@ class EntityUser extends EntityContentBase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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 \Drupal\Core\KeyValueStore\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
|
||||
*/
|
||||
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 {
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Form handler for the user register forms.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class RegisterForm extends AccountForm {
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Form controller for the role entity edit forms.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class RoleForm extends EntityForm {
|
||||
|
||||
|
||||
@@ -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 \Drupal\Core\KeyValueStore\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
|
||||
*/
|
||||
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.
|
||||
|
||||
@@ -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;
|
||||
@@ -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,136 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests user-account links.
|
||||
*
|
||||
* @group user
|
||||
*/
|
||||
class UserAccountLinksTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['menu_ui', 'block', 'test_page_test'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->drupalPlaceBlock('system_menu_block:account');
|
||||
// Make test-page default.
|
||||
$this->config('system.site')->set('page.front', '/test-page')->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the secondary menu.
|
||||
*/
|
||||
public function testSecondaryMenu() {
|
||||
// Create a regular user.
|
||||
$user = $this->drupalCreateUser([]);
|
||||
|
||||
// Log in and get the homepage.
|
||||
$this->drupalLogin($user);
|
||||
$this->drupalGet('<front>');
|
||||
|
||||
// For a logged-in user, expect the secondary menu to have links for "My
|
||||
// account" and "Log out".
|
||||
$link = $this->xpath('//ul[@class=:menu_class]/li/a[contains(@href, :href) and text()=:text]', [
|
||||
':menu_class' => 'menu',
|
||||
':href' => 'user',
|
||||
':text' => 'My account',
|
||||
]);
|
||||
$this->assertEqual(count($link), 1, 'My account link is in secondary menu.');
|
||||
|
||||
$link = $this->xpath('//ul[@class=:menu_class]/li/a[contains(@href, :href) and text()=:text]', [
|
||||
':menu_class' => 'menu',
|
||||
':href' => 'user/logout',
|
||||
':text' => 'Log out',
|
||||
]);
|
||||
$this->assertEqual(count($link), 1, 'Log out link is in secondary menu.');
|
||||
|
||||
// Log out and get the homepage.
|
||||
$this->drupalLogout();
|
||||
$this->drupalGet('<front>');
|
||||
|
||||
// For a logged-out user, expect the secondary menu to have a "Log in" link.
|
||||
$link = $this->xpath('//ul[@class=:menu_class]/li/a[contains(@href, :href) and text()=:text]', [
|
||||
':menu_class' => 'menu',
|
||||
':href' => 'user/login',
|
||||
':text' => 'Log in',
|
||||
]);
|
||||
$this->assertEqual(count($link), 1, 'Log in link is in secondary menu.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests disabling the 'My account' link.
|
||||
*/
|
||||
public function testDisabledAccountLink() {
|
||||
// Create an admin user and log in.
|
||||
$this->drupalLogin($this->drupalCreateUser(['access administration pages', 'administer menu']));
|
||||
|
||||
// Verify that the 'My account' link exists before we check for its
|
||||
// disappearance.
|
||||
$link = $this->xpath('//ul[@class=:menu_class]/li/a[contains(@href, :href) and text()=:text]', [
|
||||
':menu_class' => 'menu',
|
||||
':href' => 'user',
|
||||
':text' => 'My account',
|
||||
]);
|
||||
$this->assertEqual(count($link), 1, 'My account link is in the secondary menu.');
|
||||
|
||||
// Verify that the 'My account' link is enabled. Do not assume the value of
|
||||
// auto-increment is 1. Use XPath to obtain input element id and name using
|
||||
// the consistent label text.
|
||||
$this->drupalGet('admin/structure/menu/manage/account');
|
||||
$label = $this->xpath('//label[contains(.,:text)]/@for', [':text' => 'Enable My account menu link']);
|
||||
$this->assertFieldChecked((string) $label[0], "The 'My account' link is enabled by default.");
|
||||
|
||||
// Disable the 'My account' link.
|
||||
$edit['links[menu_plugin_id:user.page][enabled]'] = FALSE;
|
||||
$this->drupalPostForm('admin/structure/menu/manage/account', $edit, t('Save'));
|
||||
|
||||
// Get the homepage.
|
||||
$this->drupalGet('<front>');
|
||||
|
||||
// Verify that the 'My account' link does not appear when disabled.
|
||||
$link = $this->xpath('//ul[@class=:menu_class]/li/a[contains(@href, :href) and text()=:text]', [
|
||||
':menu_class' => 'menu',
|
||||
':href' => 'user',
|
||||
':text' => 'My account',
|
||||
]);
|
||||
$this->assertEqual(count($link), 0, 'My account link is not in the secondary menu.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests page title is set correctly on user account tabs.
|
||||
*/
|
||||
public function testAccountPageTitles() {
|
||||
// Default page titles are suffixed with the site name - Drupal.
|
||||
$title_suffix = ' | Drupal';
|
||||
|
||||
$this->drupalGet('user');
|
||||
$this->assertTitle('Log in' . $title_suffix, "Page title of /user is 'Log in'");
|
||||
|
||||
$this->drupalGet('user/login');
|
||||
$this->assertTitle('Log in' . $title_suffix, "Page title of /user/login is 'Log in'");
|
||||
|
||||
$this->drupalGet('user/register');
|
||||
$this->assertTitle('Create new account' . $title_suffix, "Page title of /user/register is 'Create new account' for anonymous users.");
|
||||
|
||||
$this->drupalGet('user/password');
|
||||
$this->assertTitle('Reset your password' . $title_suffix, "Page title of /user/register is 'Reset your password' for anonymous users.");
|
||||
|
||||
// Check the page title for registered users is "My Account" in menus.
|
||||
$this->drupalLogin($this->drupalCreateUser());
|
||||
// After login, the client is redirected to /user.
|
||||
$this->assertLink(t('My account'), 0, "Page title of /user is 'My Account' in menus for registered users");
|
||||
$this->assertLinkByHref(\Drupal::urlGenerator()->generate('user.page'), 0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* Tests the user admin listing if views is not enabled.
|
||||
*
|
||||
* @group user
|
||||
* @see user_admin_account()
|
||||
*/
|
||||
class UserAdminListingTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Tests the listing.
|
||||
*/
|
||||
public function testUserListing() {
|
||||
$this->drupalGet('admin/people');
|
||||
$this->assertResponse(403, 'Anonymous user does not have access to the user admin listing.');
|
||||
|
||||
// Create a bunch of users.
|
||||
$accounts = [];
|
||||
for ($i = 0; $i < 3; $i++) {
|
||||
$account = $this->drupalCreateUser();
|
||||
$accounts[$account->label()] = $account;
|
||||
}
|
||||
// Create a blocked user.
|
||||
$account = $this->drupalCreateUser();
|
||||
$account->block();
|
||||
$account->save();
|
||||
$accounts[$account->label()] = $account;
|
||||
|
||||
// Create a user at a certain timestamp.
|
||||
$account = $this->drupalCreateUser();
|
||||
$account->created = 1363219200;
|
||||
$account->save();
|
||||
$accounts[$account->label()] = $account;
|
||||
$timestamp_user = $account->label();
|
||||
|
||||
$rid_1 = $this->drupalCreateRole([], 'custom_role_1', 'custom_role_1');
|
||||
$rid_2 = $this->drupalCreateRole([], 'custom_role_2', 'custom_role_2');
|
||||
|
||||
$account = $this->drupalCreateUser();
|
||||
$account->addRole($rid_1);
|
||||
$account->addRole($rid_2);
|
||||
$account->save();
|
||||
$accounts[$account->label()] = $account;
|
||||
$role_account_name = $account->label();
|
||||
|
||||
// Create an admin user and look at the listing.
|
||||
$admin_user = $this->drupalCreateUser(['administer users']);
|
||||
$accounts[$admin_user->label()] = $admin_user;
|
||||
|
||||
$accounts['admin'] = User::load(1);
|
||||
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
$this->drupalGet('admin/people');
|
||||
$this->assertResponse(200, 'The admin user has access to the user admin listing.');
|
||||
|
||||
$result = $this->xpath('//table[contains(@class, "responsive-enabled")]/tbody/tr');
|
||||
$result_accounts = [];
|
||||
foreach ($result as $account) {
|
||||
$name = (string) $account->td[0]->span;
|
||||
$roles = [];
|
||||
if (isset($account->td[2]->div->ul)) {
|
||||
foreach ($account->td[2]->div->ul->li as $element) {
|
||||
$roles[] = (string) $element;
|
||||
}
|
||||
}
|
||||
$result_accounts[$name] = [
|
||||
'name' => $name,
|
||||
'status' => (string) $account->td[1],
|
||||
'roles' => $roles,
|
||||
'member_for' => (string) $account->td[3],
|
||||
'last_access' => (string) $account->td[4],
|
||||
];
|
||||
}
|
||||
|
||||
$this->assertFalse(array_keys(array_diff_key($result_accounts, $accounts)), 'Ensure all accounts are listed.');
|
||||
foreach ($result_accounts as $name => $values) {
|
||||
$this->assertEqual($values['status'] == t('active'), $accounts[$name]->status->value, 'Ensure the status is displayed properly.');
|
||||
}
|
||||
|
||||
$expected_roles = ['custom_role_1', 'custom_role_2'];
|
||||
$this->assertEqual($result_accounts[$role_account_name]['roles'], $expected_roles, 'Ensure roles are listed properly.');
|
||||
|
||||
$this->assertEqual($result_accounts[$timestamp_user]['member_for'], \Drupal::service('date.formatter')->formatTimeDiffSince($accounts[$timestamp_user]->created->value), 'Ensure the right member time is displayed.');
|
||||
|
||||
$this->assertEqual($result_accounts[$timestamp_user]['last_access'], 'never', 'Ensure the last access time is "never".');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\user\RoleInterface;
|
||||
|
||||
/**
|
||||
* Tests user administration page functionality.
|
||||
*
|
||||
* @group user
|
||||
*/
|
||||
class UserAdminTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['taxonomy', 'views'];
|
||||
|
||||
/**
|
||||
* Registers a user and deletes it.
|
||||
*/
|
||||
public function testUserAdmin() {
|
||||
$config = $this->config('user.settings');
|
||||
$user_a = $this->drupalCreateUser();
|
||||
$user_a->name = 'User A';
|
||||
$user_a->mail = $this->randomMachineName() . '@example.com';
|
||||
$user_a->save();
|
||||
$user_b = $this->drupalCreateUser(['administer taxonomy']);
|
||||
$user_b->name = 'User B';
|
||||
$user_b->save();
|
||||
$user_c = $this->drupalCreateUser(['administer taxonomy']);
|
||||
$user_c->name = 'User C';
|
||||
$user_c->save();
|
||||
|
||||
$user_storage = $this->container->get('entity.manager')->getStorage('user');
|
||||
|
||||
// Create admin user to delete registered user.
|
||||
$admin_user = $this->drupalCreateUser(['administer users']);
|
||||
// Use a predictable name so that we can reliably order the user admin page
|
||||
// by name.
|
||||
$admin_user->name = 'Admin user';
|
||||
$admin_user->save();
|
||||
$this->drupalLogin($admin_user);
|
||||
$this->drupalGet('admin/people');
|
||||
$this->assertText($user_a->getUsername(), 'Found user A on admin users page');
|
||||
$this->assertText($user_b->getUsername(), 'Found user B on admin users page');
|
||||
$this->assertText($user_c->getUsername(), 'Found user C on admin users page');
|
||||
$this->assertText($admin_user->getUsername(), 'Found Admin user on admin users page');
|
||||
|
||||
// Test for existence of edit link in table.
|
||||
$link = $user_a->link(t('Edit'), 'edit-form', ['query' => ['destination' => $user_a->url('collection')]]);
|
||||
$this->assertRaw($link, 'Found user A edit link on admin users page');
|
||||
|
||||
// Test exposed filter elements.
|
||||
foreach (['user', 'role', 'permission', 'status'] as $field) {
|
||||
$this->assertField("edit-$field", "$field exposed filter found.");
|
||||
}
|
||||
// Make sure the reduce duplicates element from the ManyToOneHelper is not
|
||||
// displayed.
|
||||
$this->assertNoField('edit-reduce-duplicates', 'Reduce duplicates form element not found in exposed filters.');
|
||||
|
||||
// Filter the users by name/email.
|
||||
$this->drupalGet('admin/people', ['query' => ['user' => $user_a->getUsername()]]);
|
||||
$result = $this->xpath('//table/tbody/tr');
|
||||
$this->assertEqual(1, count($result), 'Filter by username returned the right amount.');
|
||||
$this->assertEqual($user_a->getUsername(), (string) $result[0]->td[1]->span, 'Filter by username returned the right user.');
|
||||
|
||||
$this->drupalGet('admin/people', ['query' => ['user' => $user_a->getEmail()]]);
|
||||
$result = $this->xpath('//table/tbody/tr');
|
||||
$this->assertEqual(1, count($result), 'Filter by username returned the right amount.');
|
||||
$this->assertEqual($user_a->getUsername(), (string) $result[0]->td[1]->span, 'Filter by username returned the right user.');
|
||||
|
||||
// Filter the users by permission 'administer taxonomy'.
|
||||
$this->drupalGet('admin/people', ['query' => ['permission' => 'administer taxonomy']]);
|
||||
|
||||
// Check if the correct users show up.
|
||||
$this->assertNoText($user_a->getUsername(), 'User A not on filtered by perm admin users page');
|
||||
$this->assertText($user_b->getUsername(), 'Found user B on filtered by perm admin users page');
|
||||
$this->assertText($user_c->getUsername(), 'Found user C on filtered by perm admin users page');
|
||||
|
||||
// Filter the users by role. Grab the system-generated role name for User C.
|
||||
$roles = $user_c->getRoles();
|
||||
unset($roles[array_search(RoleInterface::AUTHENTICATED_ID, $roles)]);
|
||||
$this->drupalGet('admin/people', ['query' => ['role' => reset($roles)]]);
|
||||
|
||||
// Check if the correct users show up when filtered by role.
|
||||
$this->assertNoText($user_a->getUsername(), 'User A not on filtered by role on admin users page');
|
||||
$this->assertNoText($user_b->getUsername(), 'User B not on filtered by role on admin users page');
|
||||
$this->assertText($user_c->getUsername(), 'User C on filtered by role on admin users page');
|
||||
|
||||
// Test blocking of a user.
|
||||
$account = $user_storage->load($user_c->id());
|
||||
$this->assertTrue($account->isActive(), 'User C not blocked');
|
||||
$edit = [];
|
||||
$edit['action'] = 'user_block_user_action';
|
||||
$edit['user_bulk_form[4]'] = TRUE;
|
||||
$config
|
||||
->set('notify.status_blocked', TRUE)
|
||||
->save();
|
||||
$this->drupalPostForm('admin/people', $edit, t('Apply to selected items'), [
|
||||
// Sort the table by username so that we know reliably which user will be
|
||||
// targeted with the blocking action.
|
||||
'query' => ['order' => 'name', 'sort' => 'asc']
|
||||
]);
|
||||
$site_name = $this->config('system.site')->get('name');
|
||||
$this->assertMailString('body', 'Your account on ' . $site_name . ' has been blocked.', 1, 'Blocked message found in the mail sent to user C.');
|
||||
$user_storage->resetCache([$user_c->id()]);
|
||||
$account = $user_storage->load($user_c->id());
|
||||
$this->assertTrue($account->isBlocked(), 'User C blocked');
|
||||
|
||||
// Test filtering on admin page for blocked users
|
||||
$this->drupalGet('admin/people', ['query' => ['status' => 2]]);
|
||||
$this->assertNoText($user_a->getUsername(), 'User A not on filtered by status on admin users page');
|
||||
$this->assertNoText($user_b->getUsername(), 'User B not on filtered by status on admin users page');
|
||||
$this->assertText($user_c->getUsername(), 'User C on filtered by status on admin users page');
|
||||
|
||||
// Test unblocking of a user from /admin/people page and sending of activation mail
|
||||
$editunblock = [];
|
||||
$editunblock['action'] = 'user_unblock_user_action';
|
||||
$editunblock['user_bulk_form[4]'] = TRUE;
|
||||
$this->drupalPostForm('admin/people', $editunblock, t('Apply to selected items'), [
|
||||
// Sort the table by username so that we know reliably which user will be
|
||||
// targeted with the blocking action.
|
||||
'query' => ['order' => 'name', 'sort' => 'asc']
|
||||
]);
|
||||
$user_storage->resetCache([$user_c->id()]);
|
||||
$account = $user_storage->load($user_c->id());
|
||||
$this->assertTrue($account->isActive(), 'User C unblocked');
|
||||
$this->assertMail("to", $account->getEmail(), "Activation mail sent to user C");
|
||||
|
||||
// Test blocking and unblocking another user from /user/[uid]/edit form and sending of activation mail
|
||||
$user_d = $this->drupalCreateUser([]);
|
||||
$user_storage->resetCache([$user_d->id()]);
|
||||
$account1 = $user_storage->load($user_d->id());
|
||||
$this->drupalPostForm('user/' . $account1->id() . '/edit', ['status' => 0], t('Save'));
|
||||
$user_storage->resetCache([$user_d->id()]);
|
||||
$account1 = $user_storage->load($user_d->id());
|
||||
$this->assertTrue($account1->isBlocked(), 'User D blocked');
|
||||
$this->drupalPostForm('user/' . $account1->id() . '/edit', ['status' => TRUE], t('Save'));
|
||||
$user_storage->resetCache([$user_d->id()]);
|
||||
$account1 = $user_storage->load($user_d->id());
|
||||
$this->assertTrue($account1->isActive(), 'User D unblocked');
|
||||
$this->assertMail("to", $account1->getEmail(), "Activation mail sent to user D");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the alternate notification email address for user mails.
|
||||
*/
|
||||
public function testNotificationEmailAddress() {
|
||||
// Test that the Notification Email address field is on the config page.
|
||||
$admin_user = $this->drupalCreateUser(['administer users', 'administer account settings']);
|
||||
$this->drupalLogin($admin_user);
|
||||
$this->drupalGet('admin/config/people/accounts');
|
||||
$this->assertRaw('id="edit-mail-notification-address"', 'Notification Email address field exists');
|
||||
$this->drupalLogout();
|
||||
|
||||
// Test custom user registration approval email address(es).
|
||||
$config = $this->config('user.settings');
|
||||
// Allow users to register with admin approval.
|
||||
$config
|
||||
->set('verify_mail', TRUE)
|
||||
->set('register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL)
|
||||
->save();
|
||||
// Set the site and notification email addresses.
|
||||
$system = $this->config('system.site');
|
||||
$server_address = $this->randomMachineName() . '@example.com';
|
||||
$notify_address = $this->randomMachineName() . '@example.com';
|
||||
$system
|
||||
->set('mail', $server_address)
|
||||
->set('mail_notification', $notify_address)
|
||||
->save();
|
||||
// Register a new user account.
|
||||
$edit = [];
|
||||
$edit['name'] = $this->randomMachineName();
|
||||
$edit['mail'] = $edit['name'] . '@example.com';
|
||||
$this->drupalPostForm('user/register', $edit, t('Create new account'));
|
||||
$subject = 'Account details for ' . $edit['name'] . ' at ' . $system->get('name') . ' (pending admin approval)';
|
||||
// Ensure that admin notification mail is sent to the configured
|
||||
// Notification Email address.
|
||||
$admin_mail = $this->drupalGetMails([
|
||||
'to' => $notify_address,
|
||||
'from' => $server_address,
|
||||
'subject' => $subject,
|
||||
]);
|
||||
$this->assertTrue(count($admin_mail), 'New user mail to admin is sent to configured Notification Email address');
|
||||
// Ensure that user notification mail is sent from the configured
|
||||
// Notification Email address.
|
||||
$user_mail = $this->drupalGetMails([
|
||||
'to' => $edit['mail'],
|
||||
'from' => $server_address,
|
||||
'reply-to' => $notify_address,
|
||||
'subject' => $subject,
|
||||
]);
|
||||
$this->assertTrue(count($user_mail), 'New user mail to user is sent from configured Notification Email address');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests user edit page.
|
||||
*
|
||||
* @group user
|
||||
*/
|
||||
class UserEditTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Test user edit page.
|
||||
*/
|
||||
public function testUserEdit() {
|
||||
// Test user edit functionality.
|
||||
$user1 = $this->drupalCreateUser(['change own username']);
|
||||
$user2 = $this->drupalCreateUser([]);
|
||||
$this->drupalLogin($user1);
|
||||
|
||||
// Test that error message appears when attempting to use a non-unique user name.
|
||||
$edit['name'] = $user2->getUsername();
|
||||
$this->drupalPostForm("user/" . $user1->id() . "/edit", $edit, t('Save'));
|
||||
$this->assertRaw(t('The username %name is already taken.', ['%name' => $edit['name']]));
|
||||
|
||||
// Check that the default value in user name field
|
||||
// is the raw value and not a formatted one.
|
||||
\Drupal::state()->set('user_hooks_test_user_format_name_alter', TRUE);
|
||||
\Drupal::service('module_installer')->install(['user_hooks_test']);
|
||||
$this->drupalGet('user/' . $user1->id() . '/edit');
|
||||
$this->assertFieldByName('name', $user1->getAccountName());
|
||||
|
||||
// Check that filling out a single password field does not validate.
|
||||
$edit = [];
|
||||
$edit['pass[pass1]'] = '';
|
||||
$edit['pass[pass2]'] = $this->randomMachineName();
|
||||
$this->drupalPostForm("user/" . $user1->id() . "/edit", $edit, t('Save'));
|
||||
$this->assertText(t("The specified passwords do not match."), 'Typing mismatched passwords displays an error message.');
|
||||
|
||||
$edit['pass[pass1]'] = $this->randomMachineName();
|
||||
$edit['pass[pass2]'] = '';
|
||||
$this->drupalPostForm("user/" . $user1->id() . "/edit", $edit, t('Save'));
|
||||
$this->assertText(t("The specified passwords do not match."), 'Typing mismatched passwords displays an error message.');
|
||||
|
||||
// Test that the error message appears when attempting to change the mail or
|
||||
// pass without the current password.
|
||||
$edit = [];
|
||||
$edit['mail'] = $this->randomMachineName() . '@new.example.com';
|
||||
$this->drupalPostForm("user/" . $user1->id() . "/edit", $edit, t('Save'));
|
||||
$this->assertRaw(t("Your current password is missing or incorrect; it's required to change the %name.", ['%name' => t('Email')]));
|
||||
|
||||
$edit['current_pass'] = $user1->pass_raw;
|
||||
$this->drupalPostForm("user/" . $user1->id() . "/edit", $edit, t('Save'));
|
||||
$this->assertRaw(t("The changes have been saved."));
|
||||
|
||||
// Test that the user must enter current password before changing passwords.
|
||||
$edit = [];
|
||||
$edit['pass[pass1]'] = $new_pass = $this->randomMachineName();
|
||||
$edit['pass[pass2]'] = $new_pass;
|
||||
$this->drupalPostForm("user/" . $user1->id() . "/edit", $edit, t('Save'));
|
||||
$this->assertRaw(t("Your current password is missing or incorrect; it's required to change the %name.", ['%name' => t('Password')]));
|
||||
|
||||
// Try again with the current password.
|
||||
$edit['current_pass'] = $user1->pass_raw;
|
||||
$this->drupalPostForm("user/" . $user1->id() . "/edit", $edit, t('Save'));
|
||||
$this->assertRaw(t("The changes have been saved."));
|
||||
|
||||
// Make sure the changed timestamp is updated.
|
||||
$this->assertEqual($user1->getChangedTime(), REQUEST_TIME, 'Changing a user sets "changed" timestamp.');
|
||||
|
||||
// Make sure the user can log in with their new password.
|
||||
$this->drupalLogout();
|
||||
$user1->pass_raw = $new_pass;
|
||||
$this->drupalLogin($user1);
|
||||
$this->drupalLogout();
|
||||
|
||||
// Test that the password strength indicator displays.
|
||||
$config = $this->config('user.settings');
|
||||
$this->drupalLogin($user1);
|
||||
|
||||
$config->set('password_strength', TRUE)->save();
|
||||
$this->drupalPostForm("user/" . $user1->id() . "/edit", $edit, t('Save'));
|
||||
$this->assertRaw(t('Password strength:'), 'The password strength indicator is displayed.');
|
||||
|
||||
$config->set('password_strength', FALSE)->save();
|
||||
$this->drupalPostForm("user/" . $user1->id() . "/edit", $edit, t('Save'));
|
||||
$this->assertNoRaw(t('Password strength:'), 'The password strength indicator is not displayed.');
|
||||
|
||||
// Check that the user status field has the correct value and that it is
|
||||
// properly displayed.
|
||||
$admin_user = $this->drupalCreateUser(['administer users']);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
$this->drupalGet('user/' . $user1->id() . '/edit');
|
||||
$this->assertNoFieldChecked('edit-status-0');
|
||||
$this->assertFieldChecked('edit-status-1');
|
||||
|
||||
$edit = ['status' => 0];
|
||||
$this->drupalPostForm('user/' . $user1->id() . '/edit', $edit, t('Save'));
|
||||
$this->assertText(t('The changes have been saved.'));
|
||||
$this->assertFieldChecked('edit-status-0');
|
||||
$this->assertNoFieldChecked('edit-status-1');
|
||||
|
||||
$edit = ['status' => 1];
|
||||
$this->drupalPostForm('user/' . $user1->id() . '/edit', $edit, t('Save'));
|
||||
$this->assertText(t('The changes have been saved.'));
|
||||
$this->assertNoFieldChecked('edit-status-0');
|
||||
$this->assertFieldChecked('edit-status-1');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests setting the password to "0".
|
||||
*
|
||||
* We discovered in https://www.drupal.org/node/2563751 that logging in with a
|
||||
* password that is literally "0" was not possible. This test ensures that
|
||||
* this regression can't happen again.
|
||||
*/
|
||||
public function testUserWith0Password() {
|
||||
$admin = $this->drupalCreateUser(['administer users']);
|
||||
$this->drupalLogin($admin);
|
||||
// Create a regular user.
|
||||
$user1 = $this->drupalCreateUser([]);
|
||||
|
||||
$edit = ['pass[pass1]' => '0', 'pass[pass2]' => '0'];
|
||||
$this->drupalPostForm("user/" . $user1->id() . "/edit", $edit, t('Save'));
|
||||
$this->assertRaw(t("The changes have been saved."));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests editing of a user account without an email address.
|
||||
*/
|
||||
public function testUserWithoutEmailEdit() {
|
||||
// Test that an admin can edit users without an email address.
|
||||
$admin = $this->drupalCreateUser(['administer users']);
|
||||
$this->drupalLogin($admin);
|
||||
// Create a regular user.
|
||||
$user1 = $this->drupalCreateUser([]);
|
||||
// This user has no email address.
|
||||
$user1->mail = '';
|
||||
$user1->save();
|
||||
$this->drupalPostForm("user/" . $user1->id() . "/edit", ['mail' => ''], t('Save'));
|
||||
$this->assertRaw(t("The changes have been saved."));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests;
|
||||
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests whether proper language is stored for new users and access to language
|
||||
* selector.
|
||||
*
|
||||
* @group user
|
||||
*/
|
||||
class UserLanguageCreationTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['user', 'language'];
|
||||
|
||||
/**
|
||||
* Functional test for language handling during user creation.
|
||||
*/
|
||||
public function testLocalUserCreation() {
|
||||
// User to add and remove language and create new users.
|
||||
$admin_user = $this->drupalCreateUser(['administer languages', 'access administration pages', 'administer users']);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Add predefined language.
|
||||
$langcode = 'fr';
|
||||
ConfigurableLanguage::createFromLangcode($langcode)->save();
|
||||
|
||||
// Set language negotiation.
|
||||
$edit = [
|
||||
'language_interface[enabled][language-url]' => TRUE,
|
||||
];
|
||||
$this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings'));
|
||||
$this->assertText(t('Language detection configuration saved.'), 'Set language negotiation.');
|
||||
|
||||
// Check if the language selector is available on admin/people/create and
|
||||
// set to the currently active language.
|
||||
$this->drupalGet($langcode . '/admin/people/create');
|
||||
$this->assertOptionSelected("edit-preferred-langcode", $langcode, 'Global language set in the language selector.');
|
||||
|
||||
// Create a user with the admin/people/create form and check if the correct
|
||||
// language is set.
|
||||
$username = $this->randomMachineName(10);
|
||||
$edit = [
|
||||
'name' => $username,
|
||||
'mail' => $this->randomMachineName(4) . '@example.com',
|
||||
'pass[pass1]' => $username,
|
||||
'pass[pass2]' => $username,
|
||||
];
|
||||
|
||||
$this->drupalPostForm($langcode . '/admin/people/create', $edit, t('Create new account'));
|
||||
|
||||
$user = user_load_by_name($username);
|
||||
$this->assertEqual($user->getPreferredLangcode(), $langcode, 'New user has correct preferred language set.');
|
||||
$this->assertEqual($user->language()->getId(), $langcode, 'New user has correct profile language set.');
|
||||
|
||||
// Register a new user and check if the language selector is hidden.
|
||||
$this->drupalLogout();
|
||||
|
||||
$this->drupalGet($langcode . '/user/register');
|
||||
$this->assertNoFieldByName('language[fr]', 'Language selector is not accessible.');
|
||||
|
||||
$username = $this->randomMachineName(10);
|
||||
$edit = [
|
||||
'name' => $username,
|
||||
'mail' => $this->randomMachineName(4) . '@example.com',
|
||||
];
|
||||
|
||||
$this->drupalPostForm($langcode . '/user/register', $edit, t('Create new account'));
|
||||
|
||||
$user = user_load_by_name($username);
|
||||
$this->assertEqual($user->getPreferredLangcode(), $langcode, 'New user has correct preferred language set.');
|
||||
$this->assertEqual($user->language()->getId(), $langcode, 'New user has correct profile language set.');
|
||||
|
||||
// Test if the admin can use the language selector and if the
|
||||
// correct language is was saved.
|
||||
$user_edit = $langcode . '/user/' . $user->id() . '/edit';
|
||||
|
||||
$this->drupalLogin($admin_user);
|
||||
$this->drupalGet($user_edit);
|
||||
$this->assertOptionSelected("edit-preferred-langcode", $langcode, 'Language selector is accessible and correct language is selected.');
|
||||
|
||||
// Set pass_raw so we can log in the new user.
|
||||
$user->pass_raw = $this->randomMachineName(10);
|
||||
$edit = [
|
||||
'pass[pass1]' => $user->pass_raw,
|
||||
'pass[pass2]' => $user->pass_raw,
|
||||
];
|
||||
|
||||
$this->drupalPostForm($user_edit, $edit, t('Save'));
|
||||
|
||||
$this->drupalLogin($user);
|
||||
$this->drupalGet($user_edit);
|
||||
$this->assertOptionSelected("edit-preferred-langcode", $langcode, 'Language selector is accessible and correct language is selected.');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* Ensure that login works as expected.
|
||||
*
|
||||
* @group user
|
||||
*/
|
||||
class UserLoginTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Tests login with destination.
|
||||
*/
|
||||
public function testLoginCacheTagsAndDestination() {
|
||||
$this->drupalGet('user/login');
|
||||
// The user login form says "Enter your <site name> username.", hence it
|
||||
// depends on config:system.site, and its cache tags should be present.
|
||||
$this->assertCacheTag('config:system.site');
|
||||
|
||||
$user = $this->drupalCreateUser([]);
|
||||
$this->drupalGet('user/login', ['query' => ['destination' => 'foo']]);
|
||||
$edit = ['name' => $user->getUserName(), 'pass' => $user->pass_raw];
|
||||
$this->drupalPostForm(NULL, $edit, t('Log in'));
|
||||
$this->assertUrl('foo', [], 'Redirected to the correct URL');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the global login flood control.
|
||||
*/
|
||||
public function testGlobalLoginFloodControl() {
|
||||
$this->config('user.flood')
|
||||
->set('ip_limit', 10)
|
||||
// Set a high per-user limit out so that it is not relevant in the test.
|
||||
->set('user_limit', 4000)
|
||||
->save();
|
||||
|
||||
$user1 = $this->drupalCreateUser([]);
|
||||
$incorrect_user1 = clone $user1;
|
||||
$incorrect_user1->pass_raw .= 'incorrect';
|
||||
|
||||
// Try 2 failed logins.
|
||||
for ($i = 0; $i < 2; $i++) {
|
||||
$this->assertFailedLogin($incorrect_user1);
|
||||
}
|
||||
|
||||
// A successful login will not reset the IP-based flood control count.
|
||||
$this->drupalLogin($user1);
|
||||
$this->drupalLogout();
|
||||
|
||||
// Try 8 more failed logins, they should not trigger the flood control
|
||||
// mechanism.
|
||||
for ($i = 0; $i < 8; $i++) {
|
||||
$this->assertFailedLogin($incorrect_user1);
|
||||
}
|
||||
|
||||
// The next login trial should result in an IP-based flood error message.
|
||||
$this->assertFailedLogin($incorrect_user1, 'ip');
|
||||
|
||||
// A login with the correct password should also result in a flood error
|
||||
// message.
|
||||
$this->assertFailedLogin($user1, 'ip');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the per-user login flood control.
|
||||
*/
|
||||
public function testPerUserLoginFloodControl() {
|
||||
$this->config('user.flood')
|
||||
// Set a high global limit out so that it is not relevant in the test.
|
||||
->set('ip_limit', 4000)
|
||||
->set('user_limit', 3)
|
||||
->save();
|
||||
|
||||
$user1 = $this->drupalCreateUser([]);
|
||||
$incorrect_user1 = clone $user1;
|
||||
$incorrect_user1->pass_raw .= 'incorrect';
|
||||
|
||||
$user2 = $this->drupalCreateUser([]);
|
||||
|
||||
// Try 2 failed logins.
|
||||
for ($i = 0; $i < 2; $i++) {
|
||||
$this->assertFailedLogin($incorrect_user1);
|
||||
}
|
||||
|
||||
// A successful login will reset the per-user flood control count.
|
||||
$this->drupalLogin($user1);
|
||||
$this->drupalLogout();
|
||||
|
||||
// Try 3 failed logins for user 1, they will not trigger flood control.
|
||||
for ($i = 0; $i < 3; $i++) {
|
||||
$this->assertFailedLogin($incorrect_user1);
|
||||
}
|
||||
|
||||
// Try one successful attempt for user 2, it should not trigger any
|
||||
// flood control.
|
||||
$this->drupalLogin($user2);
|
||||
$this->drupalLogout();
|
||||
|
||||
// Try one more attempt for user 1, it should be rejected, even if the
|
||||
// correct password has been used.
|
||||
$this->assertFailedLogin($user1, 'user');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that user password is re-hashed upon login after changing $count_log2.
|
||||
*/
|
||||
public function testPasswordRehashOnLogin() {
|
||||
// Determine default log2 for phpass hashing algorithm
|
||||
$default_count_log2 = 16;
|
||||
|
||||
// Retrieve instance of password hashing algorithm
|
||||
$password_hasher = $this->container->get('password');
|
||||
|
||||
// Create a new user and authenticate.
|
||||
$account = $this->drupalCreateUser([]);
|
||||
$password = $account->pass_raw;
|
||||
$this->drupalLogin($account);
|
||||
$this->drupalLogout();
|
||||
// Load the stored user. The password hash should reflect $default_count_log2.
|
||||
$user_storage = $this->container->get('entity.manager')->getStorage('user');
|
||||
$account = User::load($account->id());
|
||||
$this->assertIdentical($password_hasher->getCountLog2($account->getPassword()), $default_count_log2);
|
||||
|
||||
// Change the required number of iterations by loading a test-module
|
||||
// containing the necessary container builder code and then verify that the
|
||||
// users password gets rehashed during the login.
|
||||
$overridden_count_log2 = 19;
|
||||
\Drupal::service('module_installer')->install(['user_custom_phpass_params_test']);
|
||||
$this->resetAll();
|
||||
|
||||
$account->pass_raw = $password;
|
||||
$this->drupalLogin($account);
|
||||
// Load the stored user, which should have a different password hash now.
|
||||
$user_storage->resetCache([$account->id()]);
|
||||
$account = $user_storage->load($account->id());
|
||||
$this->assertIdentical($password_hasher->getCountLog2($account->getPassword()), $overridden_count_log2);
|
||||
$this->assertTrue($password_hasher->check($password, $account->getPassword()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an unsuccessful login attempt.
|
||||
*
|
||||
* @param \Drupal\user\Entity\User $account
|
||||
* A user object with name and pass_raw attributes for the login attempt.
|
||||
* @param mixed $flood_trigger
|
||||
* (optional) Whether or not to expect that the flood control mechanism
|
||||
* will be triggered. Defaults to NULL.
|
||||
* - Set to 'user' to expect a 'too many failed logins error.
|
||||
* - Set to any value to expect an error for too many failed logins per IP
|
||||
* .
|
||||
* - Set to NULL to expect a failed login.
|
||||
*/
|
||||
public function assertFailedLogin($account, $flood_trigger = NULL) {
|
||||
$edit = [
|
||||
'name' => $account->getUsername(),
|
||||
'pass' => $account->pass_raw,
|
||||
];
|
||||
$this->drupalPostForm('user/login', $edit, t('Log in'));
|
||||
$this->assertNoFieldByXPath("//input[@name='pass' and @value!='']", NULL, 'Password value attribute is blank.');
|
||||
if (isset($flood_trigger)) {
|
||||
if ($flood_trigger == 'user') {
|
||||
$this->assertRaw(\Drupal::translation()->formatPlural($this->config('user.flood')->get('user_limit'), 'There has been more than one failed login attempt for this account. It is temporarily blocked. Try again later or <a href=":url">request a new password</a>.', 'There have been more than @count failed login attempts for this account. It is temporarily blocked. Try again later or <a href=":url">request a new password</a>.', [':url' => \Drupal::url('user.pass')]));
|
||||
}
|
||||
else {
|
||||
// No uid, so the limit is IP-based.
|
||||
$this->assertRaw(t('Too many failed login attempts from your IP address. This IP address is temporarily blocked. Try again later or <a href=":url">request a new password</a>.', [':url' => \Drupal::url('user.pass')]));
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->assertText(t('Unrecognized username or password. Forgot your password?'));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -118,7 +118,7 @@ class UserPasswordResetTest extends PageCacheTagsTestBase {
|
||||
// invalidate the reset token.
|
||||
$image = current($this->drupalGetTestFiles('image'));
|
||||
$edit = [
|
||||
'files[user_picture_0]' => drupal_realpath($image->uri),
|
||||
'files[user_picture_0]' => \Drupal::service('file_system')->realpath($image->uri),
|
||||
];
|
||||
$this->drupalPostAjaxForm(NULL, $edit, 'user_picture_0_upload_button');
|
||||
|
||||
|
||||
@@ -1,167 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\user\RoleInterface;
|
||||
use Drupal\user\Entity\Role;
|
||||
|
||||
/**
|
||||
* Verify that role permissions can be added and removed via the permissions
|
||||
* page.
|
||||
*
|
||||
* @group user
|
||||
*/
|
||||
class UserPermissionsTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* User with admin privileges.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
/**
|
||||
* User's role ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rid;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->adminUser = $this->drupalCreateUser(['administer permissions', 'access user profiles', 'administer site configuration', 'administer modules', 'administer account settings']);
|
||||
|
||||
// Find the new role ID.
|
||||
$all_rids = $this->adminUser->getRoles();
|
||||
unset($all_rids[array_search(RoleInterface::AUTHENTICATED_ID, $all_rids)]);
|
||||
$this->rid = reset($all_rids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test changing user permissions through the permissions page.
|
||||
*/
|
||||
public function testUserPermissionChanges() {
|
||||
$permissions_hash_generator = $this->container->get('user_permissions_hash_generator');
|
||||
|
||||
$storage = $this->container->get('entity.manager')->getStorage('user_role');
|
||||
|
||||
// Create an additional role and mark it as admin role.
|
||||
Role::create(['is_admin' => TRUE, 'id' => 'administrator', 'label' => 'Administrator'])->save();
|
||||
$storage->resetCache();
|
||||
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$rid = $this->rid;
|
||||
$account = $this->adminUser;
|
||||
$previous_permissions_hash = $permissions_hash_generator->generate($account);
|
||||
$this->assertIdentical($previous_permissions_hash, $permissions_hash_generator->generate($this->loggedInUser));
|
||||
|
||||
// Add a permission.
|
||||
$this->assertFalse($account->hasPermission('administer users'), 'User does not have "administer users" permission.');
|
||||
$edit = [];
|
||||
$edit[$rid . '[administer users]'] = TRUE;
|
||||
$this->drupalPostForm('admin/people/permissions', $edit, t('Save permissions'));
|
||||
$this->assertText(t('The changes have been saved.'), 'Successful save message displayed.');
|
||||
$storage->resetCache();
|
||||
$this->assertTrue($account->hasPermission('administer users'), 'User now has "administer users" permission.');
|
||||
$current_permissions_hash = $permissions_hash_generator->generate($account);
|
||||
$this->assertIdentical($current_permissions_hash, $permissions_hash_generator->generate($this->loggedInUser));
|
||||
$this->assertNotEqual($previous_permissions_hash, $current_permissions_hash, 'Permissions hash has changed.');
|
||||
$previous_permissions_hash = $current_permissions_hash;
|
||||
|
||||
// Remove a permission.
|
||||
$this->assertTrue($account->hasPermission('access user profiles'), 'User has "access user profiles" permission.');
|
||||
$edit = [];
|
||||
$edit[$rid . '[access user profiles]'] = FALSE;
|
||||
$this->drupalPostForm('admin/people/permissions', $edit, t('Save permissions'));
|
||||
$this->assertText(t('The changes have been saved.'), 'Successful save message displayed.');
|
||||
$storage->resetCache();
|
||||
$this->assertFalse($account->hasPermission('access user profiles'), 'User no longer has "access user profiles" permission.');
|
||||
$current_permissions_hash = $permissions_hash_generator->generate($account);
|
||||
$this->assertIdentical($current_permissions_hash, $permissions_hash_generator->generate($this->loggedInUser));
|
||||
$this->assertNotEqual($previous_permissions_hash, $current_permissions_hash, 'Permissions hash has changed.');
|
||||
|
||||
// Ensure that the admin role doesn't have any checkboxes.
|
||||
$this->drupalGet('admin/people/permissions');
|
||||
foreach (array_keys($this->container->get('user.permissions')->getPermissions()) as $permission) {
|
||||
$this->assertNoFieldByName('administrator[' . $permission . ']');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test assigning of permissions for the administrator role.
|
||||
*/
|
||||
public function testAdministratorRole() {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalGet('admin/config/people/accounts');
|
||||
|
||||
// Verify that the administration role is none by default.
|
||||
$this->assertOptionSelected('edit-user-admin-role', '', 'Administration role defaults to none.');
|
||||
|
||||
$this->assertFalse(Role::load($this->rid)->isAdmin());
|
||||
|
||||
// Set the user's role to be the administrator role.
|
||||
$edit = [];
|
||||
$edit['user_admin_role'] = $this->rid;
|
||||
$this->drupalPostForm('admin/config/people/accounts', $edit, t('Save configuration'));
|
||||
|
||||
\Drupal::entityManager()->getStorage('user_role')->resetCache();
|
||||
$this->assertTrue(Role::load($this->rid)->isAdmin());
|
||||
|
||||
// Enable aggregator module and ensure the 'administer news feeds'
|
||||
// permission is assigned by default.
|
||||
\Drupal::service('module_installer')->install(['aggregator']);
|
||||
|
||||
$this->assertTrue($this->adminUser->hasPermission('administer news feeds'), 'The permission was automatically assigned to the administrator role');
|
||||
|
||||
// Ensure that selecting '- None -' removes the admin role.
|
||||
$edit = [];
|
||||
$edit['user_admin_role'] = '';
|
||||
$this->drupalPostForm('admin/config/people/accounts', $edit, t('Save configuration'));
|
||||
|
||||
\Drupal::entityManager()->getStorage('user_role')->resetCache();
|
||||
\Drupal::configFactory()->reset();
|
||||
$this->assertFalse(Role::load($this->rid)->isAdmin());
|
||||
|
||||
// Manually create two admin roles, in that case the single select should be
|
||||
// hidden.
|
||||
Role::create(['id' => 'admin_role_0', 'is_admin' => TRUE, 'label' => 'Admin role 0'])->save();
|
||||
Role::create(['id' => 'admin_role_1', 'is_admin' => TRUE, 'label' => 'Admin role 1'])->save();
|
||||
$this->drupalGet('admin/config/people/accounts');
|
||||
$this->assertNoFieldByName('user_admin_role');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify proper permission changes by user_role_change_permissions().
|
||||
*/
|
||||
public function testUserRoleChangePermissions() {
|
||||
$permissions_hash_generator = $this->container->get('user_permissions_hash_generator');
|
||||
|
||||
$rid = $this->rid;
|
||||
$account = $this->adminUser;
|
||||
$previous_permissions_hash = $permissions_hash_generator->generate($account);
|
||||
|
||||
// Verify current permissions.
|
||||
$this->assertFalse($account->hasPermission('administer users'), 'User does not have "administer users" permission.');
|
||||
$this->assertTrue($account->hasPermission('access user profiles'), 'User has "access user profiles" permission.');
|
||||
$this->assertTrue($account->hasPermission('administer site configuration'), 'User has "administer site configuration" permission.');
|
||||
|
||||
// Change permissions.
|
||||
$permissions = [
|
||||
'administer users' => 1,
|
||||
'access user profiles' => 0,
|
||||
];
|
||||
user_role_change_permissions($rid, $permissions);
|
||||
|
||||
// Verify proper permission changes.
|
||||
$this->assertTrue($account->hasPermission('administer users'), 'User now has "administer users" permission.');
|
||||
$this->assertFalse($account->hasPermission('access user profiles'), 'User no longer has "access user profiles" permission.');
|
||||
$this->assertTrue($account->hasPermission('administer site configuration'), 'User still has "administer site configuration" permission.');
|
||||
|
||||
// Verify the permissions hash has changed.
|
||||
$current_permissions_hash = $permissions_hash_generator->generate($account);
|
||||
$this->assertNotEqual($previous_permissions_hash, $current_permissions_hash, 'Permissions hash has changed.');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests;
|
||||
|
||||
use Drupal\image\Entity\ImageStyle;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\file\Entity\File;
|
||||
|
||||
/**
|
||||
* Tests user picture functionality.
|
||||
*
|
||||
* @group user
|
||||
*/
|
||||
class UserPictureTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* The profile to install as a basis for testing.
|
||||
*
|
||||
* Using the standard profile to test user picture config provided by the
|
||||
* standard profile.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $profile = 'standard';
|
||||
|
||||
/**
|
||||
* A regular user.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $webUser;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// This test expects unused managed files to be marked temporary and then
|
||||
// cleaned up by file_cron().
|
||||
$this->config('file.settings')
|
||||
->set('make_unused_managed_files_temporary', TRUE)
|
||||
->save();
|
||||
|
||||
$this->webUser = $this->drupalCreateUser([
|
||||
'access content',
|
||||
'access comments',
|
||||
'post comments',
|
||||
'skip comment approval',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests creation, display, and deletion of user pictures.
|
||||
*/
|
||||
public function testCreateDeletePicture() {
|
||||
$this->drupalLogin($this->webUser);
|
||||
|
||||
// Save a new picture.
|
||||
$image = current($this->drupalGetTestFiles('image'));
|
||||
$file = $this->saveUserPicture($image);
|
||||
|
||||
// Verify that the image is displayed on the user account page.
|
||||
$this->drupalGet('user');
|
||||
$this->assertRaw(file_uri_target($file->getFileUri()), 'User picture found on user account page.');
|
||||
|
||||
// Delete the picture.
|
||||
$edit = [];
|
||||
$this->drupalPostForm('user/' . $this->webUser->id() . '/edit', $edit, t('Remove'));
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
|
||||
// Call file_cron() to clean up the file. Make sure the timestamp
|
||||
// of the file is older than the system.file.temporary_maximum_age
|
||||
// configuration value.
|
||||
db_update('file_managed')
|
||||
->fields([
|
||||
'changed' => REQUEST_TIME - ($this->config('system.file')->get('temporary_maximum_age') + 1),
|
||||
])
|
||||
->condition('fid', $file->id())
|
||||
->execute();
|
||||
\Drupal::service('cron')->run();
|
||||
|
||||
// Verify that the image has been deleted.
|
||||
$this->assertFalse(File::load($file->id()), 'File was removed from the database.');
|
||||
// Clear out PHP's file stat cache so we see the current value.
|
||||
clearstatcache(TRUE, $file->getFileUri());
|
||||
$this->assertFalse(is_file($file->getFileUri()), 'File was removed from the file system.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests embedded users on node pages.
|
||||
*/
|
||||
public function testPictureOnNodeComment() {
|
||||
$this->drupalLogin($this->webUser);
|
||||
|
||||
// Save a new picture.
|
||||
$image = current($this->drupalGetTestFiles('image'));
|
||||
$file = $this->saveUserPicture($image);
|
||||
|
||||
$node = $this->drupalCreateNode(['type' => 'article']);
|
||||
|
||||
// Enable user pictures on nodes.
|
||||
$this->config('system.theme.global')->set('features.node_user_picture', TRUE)->save();
|
||||
|
||||
$image_style_id = $this->config('core.entity_view_display.user.user.compact')->get('content.user_picture.settings.image_style');
|
||||
$style = ImageStyle::load($image_style_id);
|
||||
$image_url = file_url_transform_relative($style->buildUrl($file->getfileUri()));
|
||||
$alt_text = 'Profile picture for user ' . $this->webUser->getUsername();
|
||||
|
||||
// Verify that the image is displayed on the node page.
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$elements = $this->cssSelect('.node__meta .field--name-user-picture img[alt="' . $alt_text . '"][src="' . $image_url . '"]');
|
||||
$this->assertEqual(count($elements), 1, 'User picture with alt text found on node page.');
|
||||
|
||||
// Enable user pictures on comments, instead of nodes.
|
||||
$this->config('system.theme.global')
|
||||
->set('features.node_user_picture', FALSE)
|
||||
->set('features.comment_user_picture', TRUE)
|
||||
->save();
|
||||
|
||||
$edit = [
|
||||
'comment_body[0][value]' => $this->randomString(),
|
||||
];
|
||||
$this->drupalPostForm('comment/reply/node/' . $node->id() . '/comment', $edit, t('Save'));
|
||||
$elements = $this->cssSelect('.comment__meta .field--name-user-picture img[alt="' . $alt_text . '"][src="' . $image_url . '"]');
|
||||
$this->assertEqual(count($elements), 1, 'User picture with alt text found on the comment.');
|
||||
|
||||
// Disable user pictures on comments and nodes.
|
||||
$this->config('system.theme.global')
|
||||
->set('features.node_user_picture', FALSE)
|
||||
->set('features.comment_user_picture', FALSE)
|
||||
->save();
|
||||
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$this->assertNoRaw(file_uri_target($file->getFileUri()), 'User picture not found on node and comment.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits the user picture for the test user.
|
||||
*/
|
||||
public function saveUserPicture($image) {
|
||||
$edit = ['files[user_picture_0]' => drupal_realpath($image->uri)];
|
||||
$this->drupalPostForm('user/' . $this->webUser->id() . '/edit', $edit, t('Save'));
|
||||
|
||||
// Load actual user data from database.
|
||||
$user_storage = $this->container->get('entity.manager')->getStorage('user');
|
||||
$user_storage->resetCache([$this->webUser->id()]);
|
||||
$account = $user_storage->load($this->webUser->id());
|
||||
return File::load($account->user_picture->target_id);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\user\Entity\Role;
|
||||
use Drupal\user\RoleInterface;
|
||||
|
||||
/**
|
||||
* Tests adding, editing and deleting user roles and changing role weights.
|
||||
*
|
||||
* @group user
|
||||
*/
|
||||
class UserRoleAdminTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* User with admin privileges.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
public static $modules = ['block'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->adminUser = $this->drupalCreateUser(['administer permissions', 'administer users']);
|
||||
$this->drupalPlaceBlock('local_tasks_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test adding, renaming and deleting roles.
|
||||
*/
|
||||
public function testRoleAdministration() {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$default_langcode = \Drupal::languageManager()->getDefaultLanguage()->getId();
|
||||
// Test presence of tab.
|
||||
$this->drupalGet('admin/people/permissions');
|
||||
$tabs = $this->xpath('//ul[@class=:classes and //a[contains(., :text)]]', [
|
||||
':classes' => 'tabs primary',
|
||||
':text' => t('Roles'),
|
||||
]);
|
||||
$this->assertEqual(count($tabs), 1, 'Found roles tab');
|
||||
|
||||
// Test adding a role. (In doing so, we use a role name that happens to
|
||||
// correspond to an integer, to test that the role administration pages
|
||||
// correctly distinguish between role names and IDs.)
|
||||
$role_name = '123';
|
||||
$edit = ['label' => $role_name, 'id' => $role_name];
|
||||
$this->drupalPostForm('admin/people/roles/add', $edit, t('Save'));
|
||||
$this->assertRaw(t('Role %label has been added.', ['%label' => 123]));
|
||||
$role = Role::load($role_name);
|
||||
$this->assertTrue(is_object($role), 'The role was successfully retrieved from the database.');
|
||||
|
||||
// Check that the role was created in site default language.
|
||||
$this->assertEqual($role->language()->getId(), $default_langcode);
|
||||
|
||||
// Try adding a duplicate role.
|
||||
$this->drupalPostForm('admin/people/roles/add', $edit, t('Save'));
|
||||
$this->assertRaw(t('The machine-readable name is already in use. It must be unique.'), 'Duplicate role warning displayed.');
|
||||
|
||||
// Test renaming a role.
|
||||
$role_name = '456';
|
||||
$edit = ['label' => $role_name];
|
||||
$this->drupalPostForm("admin/people/roles/manage/{$role->id()}", $edit, t('Save'));
|
||||
$this->assertRaw(t('Role %label has been updated.', ['%label' => $role_name]));
|
||||
\Drupal::entityManager()->getStorage('user_role')->resetCache([$role->id()]);
|
||||
$new_role = Role::load($role->id());
|
||||
$this->assertEqual($new_role->label(), $role_name, 'The role name has been successfully changed.');
|
||||
|
||||
// Test deleting a role.
|
||||
$this->drupalGet("admin/people/roles/manage/{$role->id()}");
|
||||
$this->clickLink(t('Delete'));
|
||||
$this->drupalPostForm(NULL, [], t('Delete'));
|
||||
$this->assertRaw(t('The role %label has been deleted.', ['%label' => $role_name]));
|
||||
$this->assertNoLinkByHref("admin/people/roles/manage/{$role->id()}", 'Role edit link removed.');
|
||||
\Drupal::entityManager()->getStorage('user_role')->resetCache([$role->id()]);
|
||||
$this->assertFalse(Role::load($role->id()), 'A deleted role can no longer be loaded.');
|
||||
|
||||
// Make sure that the system-defined roles can be edited via the user
|
||||
// interface.
|
||||
$this->drupalGet('admin/people/roles/manage/' . RoleInterface::ANONYMOUS_ID);
|
||||
$this->assertResponse(200, 'Access granted when trying to edit the built-in anonymous role.');
|
||||
$this->assertNoText(t('Delete role'), 'Delete button for the anonymous role is not present.');
|
||||
$this->drupalGet('admin/people/roles/manage/' . RoleInterface::AUTHENTICATED_ID);
|
||||
$this->assertResponse(200, 'Access granted when trying to edit the built-in authenticated role.');
|
||||
$this->assertNoText(t('Delete role'), 'Delete button for the authenticated role is not present.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test user role weight change operation and ordering.
|
||||
*/
|
||||
public function testRoleWeightOrdering() {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$roles = user_roles();
|
||||
$weight = count($roles);
|
||||
$new_role_weights = [];
|
||||
$saved_rids = [];
|
||||
|
||||
// Change the role weights to make the roles in reverse order.
|
||||
$edit = [];
|
||||
foreach ($roles as $role) {
|
||||
$edit['entities[' . $role->id() . '][weight]'] = $weight;
|
||||
$new_role_weights[$role->id()] = $weight;
|
||||
$saved_rids[] = $role->id();
|
||||
$weight--;
|
||||
}
|
||||
$this->drupalPostForm('admin/people/roles', $edit, t('Save'));
|
||||
$this->assertText(t('The role settings have been updated.'), 'The role settings form submitted successfully.');
|
||||
|
||||
// Load up the user roles with the new weights.
|
||||
drupal_static_reset('user_roles');
|
||||
$roles = user_roles();
|
||||
$rids = [];
|
||||
// Test that the role weights have been correctly saved.
|
||||
foreach ($roles as $role) {
|
||||
$this->assertEqual($role->getWeight(), $new_role_weights[$role->id()]);
|
||||
$rids[] = $role->id();
|
||||
}
|
||||
// The order of the roles should be reversed.
|
||||
$this->assertIdentical($rids, array_reverse($saved_rids));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests;
|
||||
|
||||
use Drupal\Core\Datetime\Entity\DateFormat;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Set a user time zone and verify that dates are displayed in local time.
|
||||
*
|
||||
* @group user
|
||||
*/
|
||||
class UserTimeZoneTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node', 'system_test'];
|
||||
|
||||
/**
|
||||
* Tests the display of dates and time when user-configurable time zones are set.
|
||||
*/
|
||||
public function testUserTimeZone() {
|
||||
// Setup date/time settings for Los Angeles time.
|
||||
$this->config('system.date')
|
||||
->set('timezone.user.configurable', 1)
|
||||
->set('timezone.default', 'America/Los_Angeles')
|
||||
->save();
|
||||
|
||||
// Load the 'medium' date format, which is the default for node creation
|
||||
// time, and override it. Since we are testing time zones with Daylight
|
||||
// Saving Time, and need to future proof against changes to the zoneinfo
|
||||
// database, we choose the 'I' format placeholder instead of a
|
||||
// human-readable zone name. With 'I', a 1 means the date is in DST, and 0
|
||||
// if not.
|
||||
DateFormat::load('medium')
|
||||
->setPattern('Y-m-d H:i I')
|
||||
->save();
|
||||
|
||||
// Create a user account and login.
|
||||
$web_user = $this->drupalCreateUser();
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
// Create some nodes with different authored-on dates.
|
||||
// Two dates in PST (winter time):
|
||||
$date1 = '2007-03-09 21:00:00 -0800';
|
||||
$date2 = '2007-03-11 01:00:00 -0800';
|
||||
// One date in PDT (summer time):
|
||||
$date3 = '2007-03-20 21:00:00 -0700';
|
||||
$this->drupalCreateContentType(['type' => 'article']);
|
||||
$node1 = $this->drupalCreateNode(['created' => strtotime($date1), 'type' => 'article']);
|
||||
$node2 = $this->drupalCreateNode(['created' => strtotime($date2), 'type' => 'article']);
|
||||
$node3 = $this->drupalCreateNode(['created' => strtotime($date3), 'type' => 'article']);
|
||||
|
||||
// Confirm date format and time zone.
|
||||
$this->drupalGet('node/' . $node1->id());
|
||||
$this->assertText('2007-03-09 21:00 0', 'Date should be PST.');
|
||||
$this->drupalGet('node/' . $node2->id());
|
||||
$this->assertText('2007-03-11 01:00 0', 'Date should be PST.');
|
||||
$this->drupalGet('node/' . $node3->id());
|
||||
$this->assertText('2007-03-20 21:00 1', 'Date should be PDT.');
|
||||
|
||||
// Change user time zone to Santiago time.
|
||||
$edit = [];
|
||||
$edit['mail'] = $web_user->getEmail();
|
||||
$edit['timezone'] = 'America/Santiago';
|
||||
$this->drupalPostForm("user/" . $web_user->id() . "/edit", $edit, t('Save'));
|
||||
$this->assertText(t('The changes have been saved.'), 'Time zone changed to Santiago time.');
|
||||
|
||||
// Confirm date format and time zone.
|
||||
$this->drupalGet('node/' . $node1->id());
|
||||
$this->assertText('2007-03-10 02:00 1', 'Date should be Chile summer time; five hours ahead of PST.');
|
||||
$this->drupalGet('node/' . $node2->id());
|
||||
$this->assertText('2007-03-11 05:00 0', 'Date should be Chile time; four hours ahead of PST');
|
||||
$this->drupalGet('node/' . $node3->id());
|
||||
$this->assertText('2007-03-21 00:00 0', 'Date should be Chile time; three hours ahead of PDT.');
|
||||
|
||||
// Ensure that anonymous users also use the default timezone.
|
||||
$this->drupalLogout();
|
||||
$this->drupalGet('node/' . $node1->id());
|
||||
$this->assertText('2007-03-09 21:00 0', 'Date should be PST.');
|
||||
$this->drupalGet('node/' . $node2->id());
|
||||
$this->assertText('2007-03-11 01:00 0', 'Date should be PST.');
|
||||
$this->drupalGet('node/' . $node3->id());
|
||||
$this->assertText('2007-03-20 21:00 1', 'Date should be PDT.');
|
||||
|
||||
// Format a date without accessing the current user at all and
|
||||
// ensure that it uses the default timezone.
|
||||
$this->drupalGet('/system-test/date');
|
||||
$this->assertText('2016-01-13 08:29 0', 'Date should be PST.');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests;
|
||||
|
||||
use Drupal\content_translation\Tests\ContentTranslationUITestBase;
|
||||
|
||||
/**
|
||||
* Tests the User Translation UI.
|
||||
*
|
||||
* @group user
|
||||
*/
|
||||
class UserTranslationUITest extends ContentTranslationUITestBase {
|
||||
|
||||
/**
|
||||
* The user name of the test user.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['language', 'content_translation', 'user', 'views'];
|
||||
|
||||
protected function setUp() {
|
||||
$this->entityTypeId = 'user';
|
||||
$this->testLanguageSelector = FALSE;
|
||||
$this->name = $this->randomMachineName();
|
||||
parent::setUp();
|
||||
|
||||
\Drupal::entityManager()->getStorage('user')->resetCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getTranslatorPermissions() {
|
||||
return array_merge(parent::getTranslatorPermissions(), ['administer users']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNewEntityValues($langcode) {
|
||||
// User name is not translatable hence we use a fixed value.
|
||||
return ['name' => $this->name] + parent::getNewEntityValues($langcode);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function doTestTranslationEdit() {
|
||||
$storage = $this->container->get('entity_type.manager')
|
||||
->getStorage($this->entityTypeId);
|
||||
$storage->resetCache([$this->entityId]);
|
||||
$entity = $storage->load($this->entityId);
|
||||
$languages = $this->container->get('language_manager')->getLanguages();
|
||||
|
||||
foreach ($this->langcodes as $langcode) {
|
||||
// We only want to test the title for non-english translations.
|
||||
if ($langcode != 'en') {
|
||||
$options = ['language' => $languages[$langcode]];
|
||||
$url = $entity->urlInfo('edit-form', $options);
|
||||
$this->drupalGet($url);
|
||||
|
||||
$title = t('@title [%language translation]', [
|
||||
'@title' => $entity->getTranslation($langcode)->label(),
|
||||
'%language' => $languages[$langcode]->getName(),
|
||||
]);
|
||||
$this->assertRaw($title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests\Views;
|
||||
|
||||
use Drupal\user\Plugin\views\access\Permission;
|
||||
use Drupal\views\Plugin\views\display\DisplayPluginBase;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests views perm access plugin.
|
||||
*
|
||||
* @group user
|
||||
* @see \Drupal\user\Plugin\views\access\Permission
|
||||
*/
|
||||
class AccessPermissionTest extends AccessTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_access_perm'];
|
||||
|
||||
/**
|
||||
* Tests perm access plugin.
|
||||
*/
|
||||
public function testAccessPerm() {
|
||||
$view = Views::getView('test_access_perm');
|
||||
$view->setDisplay();
|
||||
|
||||
$access_plugin = $view->display_handler->getPlugin('access');
|
||||
$this->assertTrue($access_plugin instanceof Permission, 'Make sure the right class got instantiated.');
|
||||
$this->assertEqual($access_plugin->pluginTitle(), t('Permission'));
|
||||
|
||||
$this->assertFalse($view->display_handler->access($this->webUser));
|
||||
$this->assertTrue($view->display_handler->access($this->normalUser));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests access on render caching.
|
||||
*/
|
||||
public function testRenderCaching() {
|
||||
$view = Views::getView('test_access_perm');
|
||||
$display = &$view->storage->getDisplay('default');
|
||||
$display['display_options']['cache'] = [
|
||||
'type' => 'tag',
|
||||
];
|
||||
|
||||
/** @var \Drupal\Core\Render\RendererInterface $renderer */
|
||||
$renderer = \Drupal::service('renderer');
|
||||
/** @var \Drupal\Core\Session\AccountSwitcherInterface $account_switcher */
|
||||
$account_switcher = \Drupal::service('account_switcher');
|
||||
|
||||
// First access as user without access.
|
||||
$build = DisplayPluginBase::buildBasicRenderable('test_access_perm', 'default');
|
||||
$account_switcher->switchTo($this->normalUser);
|
||||
$result = $renderer->renderPlain($build);
|
||||
$this->assertNotEqual($result, '');
|
||||
|
||||
// Then with access.
|
||||
$build = DisplayPluginBase::buildBasicRenderable('test_access_perm', 'default');
|
||||
$account_switcher->switchTo($this->webUser);
|
||||
$result = $renderer->renderPlain($build);
|
||||
$this->assertEqual($result, '');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests\Views;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\user\Plugin\views\access\Role;
|
||||
use Drupal\views\Plugin\views\display\DisplayPluginBase;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests views role access plugin.
|
||||
*
|
||||
* @group user
|
||||
* @see \Drupal\user\Plugin\views\access\Role
|
||||
*/
|
||||
class AccessRoleTest extends AccessTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_access_role'];
|
||||
|
||||
/**
|
||||
* Tests role access plugin.
|
||||
*/
|
||||
public function testAccessRole() {
|
||||
/** @var \Drupal\views\ViewEntityInterface $view */
|
||||
$view = \Drupal::entityManager()->getStorage('view')->load('test_access_role');
|
||||
$display = &$view->getDisplay('default');
|
||||
$display['display_options']['access']['options']['role'] = [
|
||||
$this->normalRole => $this->normalRole,
|
||||
];
|
||||
$view->save();
|
||||
$this->container->get('router.builder')->rebuildIfNeeded();
|
||||
$expected = [
|
||||
'config' => ['user.role.' . $this->normalRole],
|
||||
'module' => ['user'],
|
||||
];
|
||||
$this->assertIdentical($expected, $view->calculateDependencies()->getDependencies());
|
||||
|
||||
$executable = Views::executableFactory()->get($view);
|
||||
$executable->setDisplay('page_1');
|
||||
|
||||
$access_plugin = $executable->display_handler->getPlugin('access');
|
||||
$this->assertTrue($access_plugin instanceof Role, 'Make sure the right class got instantiated.');
|
||||
|
||||
// Test the access() method on the access plugin.
|
||||
$this->assertFalse($executable->display_handler->access($this->webUser));
|
||||
$this->assertTrue($executable->display_handler->access($this->normalUser));
|
||||
|
||||
$this->drupalLogin($this->webUser);
|
||||
$this->drupalGet('test-role');
|
||||
$this->assertResponse(403);
|
||||
$this->assertCacheContext('user.roles');
|
||||
|
||||
$this->drupalLogin($this->normalUser);
|
||||
$this->drupalGet('test-role');
|
||||
$this->assertResponse(200);
|
||||
$this->assertCacheContext('user.roles');
|
||||
|
||||
// Test allowing multiple roles.
|
||||
$view = Views::getView('test_access_role')->storage;
|
||||
$display = &$view->getDisplay('default');
|
||||
$display['display_options']['access']['options']['role'] = [
|
||||
$this->normalRole => $this->normalRole,
|
||||
'anonymous' => 'anonymous',
|
||||
];
|
||||
$view->save();
|
||||
$this->container->get('router.builder')->rebuildIfNeeded();
|
||||
|
||||
// Ensure that the list of roles is sorted correctly, if the generated role
|
||||
// ID comes before 'anonymous', see https://www.drupal.org/node/2398259.
|
||||
$roles = ['user.role.anonymous', 'user.role.' . $this->normalRole];
|
||||
sort($roles);
|
||||
$expected = [
|
||||
'config' => $roles,
|
||||
'module' => ['user'],
|
||||
];
|
||||
$this->assertIdentical($expected, $view->calculateDependencies()->getDependencies());
|
||||
$this->drupalLogin($this->webUser);
|
||||
$this->drupalGet('test-role');
|
||||
$this->assertResponse(403);
|
||||
$this->assertCacheContext('user.roles');
|
||||
$this->drupalLogout();
|
||||
$this->drupalGet('test-role');
|
||||
$this->assertResponse(200);
|
||||
$this->assertCacheContext('user.roles');
|
||||
$this->drupalLogin($this->normalUser);
|
||||
$this->drupalGet('test-role');
|
||||
$this->assertResponse(200);
|
||||
$this->assertCacheContext('user.roles');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests access on render caching.
|
||||
*/
|
||||
public function testRenderCaching() {
|
||||
$view = Views::getView('test_access_role');
|
||||
$display = &$view->storage->getDisplay('default');
|
||||
$display['display_options']['cache'] = [
|
||||
'type' => 'tag',
|
||||
];
|
||||
$display['display_options']['access']['options']['role'] = [
|
||||
$this->normalRole => $this->normalRole,
|
||||
];
|
||||
$view->save();
|
||||
|
||||
/** @var \Drupal\Core\Render\RendererInterface $renderer */
|
||||
$renderer = \Drupal::service('renderer');
|
||||
/** @var \Drupal\Core\Session\AccountSwitcherInterface $account_switcher */
|
||||
$account_switcher = \Drupal::service('account_switcher');
|
||||
|
||||
// First access as user with access.
|
||||
$build = DisplayPluginBase::buildBasicRenderable('test_access_role', 'default');
|
||||
$account_switcher->switchTo($this->normalUser);
|
||||
$result = $renderer->renderPlain($build);
|
||||
$this->assertTrue(in_array('user.roles', $build['#cache']['contexts']));
|
||||
$this->assertEqual(['config:views.view.test_access_role'], $build['#cache']['tags']);
|
||||
$this->assertEqual(Cache::PERMANENT, $build['#cache']['max-age']);
|
||||
$this->assertNotEqual($result, '');
|
||||
|
||||
// Then without access.
|
||||
$build = DisplayPluginBase::buildBasicRenderable('test_access_role', 'default');
|
||||
$account_switcher->switchTo($this->webUser);
|
||||
$result = $renderer->renderPlain($build);
|
||||
// @todo Fix this in https://www.drupal.org/node/2551037,
|
||||
// DisplayPluginBase::applyDisplayCacheabilityMetadata() is not invoked when
|
||||
// using buildBasicRenderable() and a Views access plugin returns FALSE.
|
||||
// $this->assertTrue(in_array('user.roles', $build['#cache']['contexts']));
|
||||
// $this->assertEqual([], $build['#cache']['tags']);
|
||||
$this->assertEqual(Cache::PERMANENT, $build['#cache']['max-age']);
|
||||
$this->assertEqual($result, '');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests\Views;
|
||||
|
||||
/**
|
||||
* A common test base class for the user access plugin tests.
|
||||
*/
|
||||
abstract class AccessTestBase extends UserTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['block'];
|
||||
|
||||
/**
|
||||
* Contains a user object that has no special permissions.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $webUser;
|
||||
|
||||
/**
|
||||
* Contains a user object that has the 'views_test_data test permission'.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $normalUser;
|
||||
|
||||
/**
|
||||
* Contains a role ID that is used by the webUser.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $webRole;
|
||||
|
||||
/**
|
||||
* Contains a role ID that is used by the normalUser.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $normalRole;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->drupalPlaceBlock('system_breadcrumb_block');
|
||||
|
||||
$this->enableViewsTestModule();
|
||||
|
||||
$this->webUser = $this->drupalCreateUser();
|
||||
$roles = $this->webUser->getRoles();
|
||||
$this->webRole = $roles[0];
|
||||
|
||||
$this->normalRole = $this->drupalCreateRole([]);
|
||||
$this->normalUser = $this->drupalCreateUser(['views_test_data test permission']);
|
||||
$this->normalUser->addRole($this->normalRole);
|
||||
$this->normalUser->save();
|
||||
// @todo when all the plugin information is cached make a reset function and
|
||||
// call it here.
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests\Views;
|
||||
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests views user argument default plugin.
|
||||
*
|
||||
* @group user
|
||||
*/
|
||||
class ArgumentDefaultTest extends UserTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_plugin_argument_default_current_user'];
|
||||
|
||||
public function test_plugin_argument_default_current_user() {
|
||||
// Create a user to test.
|
||||
$account = $this->drupalCreateUser();
|
||||
|
||||
// Switch the user.
|
||||
\Drupal::service('account_switcher')->switchTo($account);
|
||||
|
||||
$view = Views::getView('test_plugin_argument_default_current_user');
|
||||
$view->initHandlers();
|
||||
|
||||
$this->assertEqual($view->argument['null']->getDefaultArgument(), $account->id(), 'Uid of the current user is used.');
|
||||
// Switch back.
|
||||
\Drupal::service('account_switcher')->switchBack();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests\Views;
|
||||
|
||||
use Drupal\Core\Form\FormState;
|
||||
use Drupal\views\Plugin\views\argument\ArgumentPluginBase;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests user argument validators for ID and name.
|
||||
*
|
||||
* @group user
|
||||
*/
|
||||
class ArgumentValidateTest extends UserTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_view_argument_validate_user', 'test_view_argument_validate_username'];
|
||||
|
||||
/**
|
||||
* A user for this test.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $account;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->account = $this->drupalCreateUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the User (ID) argument validator.
|
||||
*/
|
||||
public function testArgumentValidateUserUid() {
|
||||
$account = $this->account;
|
||||
|
||||
$view = Views::getView('test_view_argument_validate_user');
|
||||
$this->executeView($view);
|
||||
|
||||
$this->assertTrue($view->argument['null']->validateArgument($account->id()));
|
||||
// Reset argument validation.
|
||||
$view->argument['null']->argument_validated = NULL;
|
||||
// Fail for a valid numeric, but for a user that doesn't exist
|
||||
$this->assertFalse($view->argument['null']->validateArgument(32));
|
||||
|
||||
$form = [];
|
||||
$form_state = new FormState();
|
||||
$view->argument['null']->buildOptionsForm($form, $form_state);
|
||||
$sanitized_id = ArgumentPluginBase::encodeValidatorId('entity:user');
|
||||
$this->assertTrue($form['validate']['options'][$sanitized_id]['roles']['#states']['visible'][':input[name="options[validate][options][' . $sanitized_id . '][restrict_roles]"]']['checked']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the UserName argument validator.
|
||||
*/
|
||||
public function testArgumentValidateUserName() {
|
||||
$account = $this->account;
|
||||
|
||||
$view = Views::getView('test_view_argument_validate_username');
|
||||
$this->executeView($view);
|
||||
|
||||
$this->assertTrue($view->argument['null']->validateArgument($account->getUsername()));
|
||||
// Reset argument validation.
|
||||
$view->argument['null']->argument_validated = NULL;
|
||||
// Fail for a valid string, but for a user that doesn't exist
|
||||
$this->assertFalse($view->argument['null']->validateArgument($this->randomMachineName()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests\Views;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* Tests if entity access is respected on a user bulk form.
|
||||
*
|
||||
* @group user
|
||||
* @see \Drupal\user\Plugin\views\field\UserBulkForm
|
||||
* @see \Drupal\user\Tests\Views\BulkFormTest
|
||||
*/
|
||||
class BulkFormAccessTest extends UserTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['user_access_test'];
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_user_bulk_form'];
|
||||
|
||||
/**
|
||||
* Tests if users that may not be edited, can not be edited in bulk.
|
||||
*/
|
||||
public function testUserEditAccess() {
|
||||
// Create an authenticated user.
|
||||
$no_edit_user = $this->drupalCreateUser([], 'no_edit');
|
||||
// Ensure this account is not blocked.
|
||||
$this->assertFalse($no_edit_user->isBlocked(), 'The user is not blocked.');
|
||||
|
||||
// Log in as user admin.
|
||||
$admin_user = $this->drupalCreateUser(['administer users']);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Ensure that the account "no_edit" can not be edited.
|
||||
$this->drupalGet('user/' . $no_edit_user->id() . '/edit');
|
||||
$this->assertFalse($no_edit_user->access('update', $admin_user));
|
||||
$this->assertResponse(403, 'The user may not be edited.');
|
||||
|
||||
// Test blocking the account "no_edit".
|
||||
$edit = [
|
||||
'user_bulk_form[' . ($no_edit_user->id() - 1) . ']' => TRUE,
|
||||
'action' => 'user_block_user_action',
|
||||
];
|
||||
$this->drupalPostForm('test-user-bulk-form', $edit, t('Apply to selected items'));
|
||||
$this->assertResponse(200);
|
||||
|
||||
$this->assertRaw(SafeMarkup::format('No access to execute %action on the @entity_type_label %entity_label.', [
|
||||
'%action' => 'Block the selected user(s)',
|
||||
'@entity_type_label' => 'User',
|
||||
'%entity_label' => $no_edit_user->label(),
|
||||
]));
|
||||
|
||||
// Re-load the account "no_edit" and ensure it is not blocked.
|
||||
$no_edit_user = User::load($no_edit_user->id());
|
||||
$this->assertFalse($no_edit_user->isBlocked(), 'The user is not blocked.');
|
||||
|
||||
// Create a normal user which can be edited by the admin user
|
||||
$normal_user = $this->drupalCreateUser();
|
||||
$this->assertTrue($normal_user->access('update', $admin_user));
|
||||
|
||||
$edit = [
|
||||
'user_bulk_form[' . ($normal_user->id() - 1) . ']' => TRUE,
|
||||
'action' => 'user_block_user_action',
|
||||
];
|
||||
$this->drupalPostForm('test-user-bulk-form', $edit, t('Apply to selected items'));
|
||||
|
||||
$normal_user = User::load($normal_user->id());
|
||||
$this->assertTrue($normal_user->isBlocked(), 'The user is blocked.');
|
||||
|
||||
// Log in as user without the 'administer users' permission.
|
||||
$this->drupalLogin($this->drupalCreateUser());
|
||||
|
||||
$edit = [
|
||||
'user_bulk_form[' . ($normal_user->id() - 1) . ']' => TRUE,
|
||||
'action' => 'user_unblock_user_action',
|
||||
];
|
||||
$this->drupalPostForm('test-user-bulk-form', $edit, t('Apply to selected items'));
|
||||
|
||||
// Re-load the normal user and ensure it is still blocked.
|
||||
$normal_user = User::load($normal_user->id());
|
||||
$this->assertTrue($normal_user->isBlocked(), 'The user is still blocked.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if users that may not be deleted, can not be deleted in bulk.
|
||||
*/
|
||||
public function testUserDeleteAccess() {
|
||||
// Create two authenticated users.
|
||||
$account = $this->drupalCreateUser([], 'no_delete');
|
||||
$account2 = $this->drupalCreateUser([], 'may_delete');
|
||||
|
||||
// Log in as user admin.
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer users']));
|
||||
|
||||
// Ensure that the account "no_delete" can not be deleted.
|
||||
$this->drupalGet('user/' . $account->id() . '/cancel');
|
||||
$this->assertResponse(403, 'The user "no_delete" may not be deleted.');
|
||||
// Ensure that the account "may_delete" *can* be deleted.
|
||||
$this->drupalGet('user/' . $account2->id() . '/cancel');
|
||||
$this->assertResponse(200, 'The user "may_delete" may be deleted.');
|
||||
|
||||
// Test deleting the accounts "no_delete" and "may_delete".
|
||||
$edit = [
|
||||
'user_bulk_form[' . ($account->id() - 1) . ']' => TRUE,
|
||||
'user_bulk_form[' . ($account2->id() - 1) . ']' => TRUE,
|
||||
'action' => 'user_cancel_user_action',
|
||||
];
|
||||
$this->drupalPostForm('test-user-bulk-form', $edit, t('Apply to selected items'));
|
||||
$edit = [
|
||||
'user_cancel_method' => 'user_cancel_delete',
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, t('Cancel accounts'));
|
||||
|
||||
// Ensure the account "no_delete" still exists.
|
||||
$account = User::load($account->id());
|
||||
$this->assertNotNull($account, 'The user "no_delete" is not deleted.');
|
||||
// Ensure the account "may_delete" no longer exists.
|
||||
$account = User::load($account2->id());
|
||||
$this->assertNull($account, 'The user "may_delete" is deleted.');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests\Views;
|
||||
|
||||
use Drupal\user\Entity\User;
|
||||
use Drupal\user\RoleInterface;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests a user bulk form.
|
||||
*
|
||||
* @group user
|
||||
* @see \Drupal\user\Plugin\views\field\UserBulkForm
|
||||
*/
|
||||
class BulkFormTest extends UserTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['views_ui'];
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_user_bulk_form', 'test_user_bulk_form_combine_filter'];
|
||||
|
||||
/**
|
||||
* Tests the user bulk form.
|
||||
*/
|
||||
public function testBulkForm() {
|
||||
// Log in as a user without 'administer users'.
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer permissions']));
|
||||
$user_storage = $this->container->get('entity.manager')->getStorage('user');
|
||||
|
||||
// Create an user which actually can change users.
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer users']));
|
||||
$this->drupalGet('test-user-bulk-form');
|
||||
$result = $this->cssSelect('#edit-action option');
|
||||
$this->assertTrue(count($result) > 0);
|
||||
|
||||
// Test submitting the page with no selection.
|
||||
$edit = [
|
||||
'action' => 'user_block_user_action',
|
||||
];
|
||||
$this->drupalPostForm('test-user-bulk-form', $edit, t('Apply to selected items'));
|
||||
$this->assertText(t('No users selected.'));
|
||||
|
||||
// Assign a role to a user.
|
||||
$account = $user_storage->load($this->users[0]->id());
|
||||
$roles = user_role_names(TRUE);
|
||||
unset($roles[RoleInterface::AUTHENTICATED_ID]);
|
||||
$role = key($roles);
|
||||
|
||||
$this->assertFalse($account->hasRole($role), 'The user currently does not have a custom role.');
|
||||
$edit = [
|
||||
'user_bulk_form[1]' => TRUE,
|
||||
'action' => 'user_add_role_action.' . $role,
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, t('Apply to selected items'));
|
||||
// Re-load the user and check their roles.
|
||||
$user_storage->resetCache([$account->id()]);
|
||||
$account = $user_storage->load($account->id());
|
||||
$this->assertTrue($account->hasRole($role), 'The user now has the custom role.');
|
||||
|
||||
$edit = [
|
||||
'user_bulk_form[1]' => TRUE,
|
||||
'action' => 'user_remove_role_action.' . $role,
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, t('Apply to selected items'));
|
||||
// Re-load the user and check their roles.
|
||||
$user_storage->resetCache([$account->id()]);
|
||||
$account = $user_storage->load($account->id());
|
||||
$this->assertFalse($account->hasRole($role), 'The user no longer has the custom role.');
|
||||
|
||||
// Block a user using the bulk form.
|
||||
$this->assertTrue($account->isActive(), 'The user is not blocked.');
|
||||
$this->assertRaw($account->label(), 'The user is found in the table.');
|
||||
$edit = [
|
||||
'user_bulk_form[1]' => TRUE,
|
||||
'action' => 'user_block_user_action',
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, t('Apply to selected items'));
|
||||
// Re-load the user and check their status.
|
||||
$user_storage->resetCache([$account->id()]);
|
||||
$account = $user_storage->load($account->id());
|
||||
$this->assertTrue($account->isBlocked(), 'The user is blocked.');
|
||||
$this->assertNoRaw($account->label(), 'The user is not found in the table.');
|
||||
|
||||
// Remove the user status filter from the view.
|
||||
$view = Views::getView('test_user_bulk_form');
|
||||
$view->removeHandler('default', 'filter', 'status');
|
||||
$view->storage->save();
|
||||
|
||||
// Ensure the anonymous user is found.
|
||||
$this->drupalGet('test-user-bulk-form');
|
||||
$this->assertText($this->config('user.settings')->get('anonymous'));
|
||||
|
||||
// Attempt to block the anonymous user.
|
||||
$edit = [
|
||||
'user_bulk_form[0]' => TRUE,
|
||||
'action' => 'user_block_user_action',
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, t('Apply to selected items'));
|
||||
$anonymous_account = $user_storage->load(0);
|
||||
$this->assertTrue($anonymous_account->isBlocked(), 'Ensure the anonymous user got blocked.');
|
||||
|
||||
// Test the list of available actions with a value that contains a dot.
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer permissions', 'administer views', 'administer users']));
|
||||
$action_id = 'user_add_role_action.' . $role;
|
||||
$edit = [
|
||||
'options[include_exclude]' => 'exclude',
|
||||
"options[selected_actions][$action_id]" => $action_id,
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/views/nojs/handler/test_user_bulk_form/default/field/user_bulk_form', $edit, t('Apply'));
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
$this->drupalGet('test-user-bulk-form');
|
||||
$this->assertNoOption('edit-action', $action_id);
|
||||
$edit['options[include_exclude]'] = 'include';
|
||||
$this->drupalPostForm('admin/structure/views/nojs/handler/test_user_bulk_form/default/field/user_bulk_form', $edit, t('Apply'));
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
$this->drupalGet('test-user-bulk-form');
|
||||
$this->assertOption('edit-action', $action_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the user bulk form with a combined field filter on the bulk column.
|
||||
*/
|
||||
public function testBulkFormCombineFilter() {
|
||||
// Add a user.
|
||||
User::load($this->users[0]->id());
|
||||
$view = Views::getView('test_user_bulk_form_combine_filter');
|
||||
$errors = $view->validate();
|
||||
$this->assertEqual(reset($errors['default']), t('Field %field set in %filter is not usable for this filter type. Combined field filter only works for simple fields.', ['%field' => 'User: Bulk update', '%filter' => 'Global: Combine fields filter']));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests\Views;
|
||||
|
||||
use Drupal\views\Tests\ViewTestBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
|
||||
/**
|
||||
* Tests the permission field handler ui.
|
||||
*
|
||||
* @group user
|
||||
* @see \Drupal\user\Plugin\views\filter\Permissions
|
||||
*/
|
||||
class FilterPermissionUiTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_filter_permission'];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['user', 'user_test_views', 'views_ui'];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp(TRUE);
|
||||
|
||||
ViewTestData::createTestViews(get_class($this), ['user_test_views']);
|
||||
$this->enableViewsTestModule();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests basic filter handler settings in the UI.
|
||||
*/
|
||||
public function testHandlerUI() {
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer views', 'administer users']));
|
||||
|
||||
$this->drupalGet('admin/structure/views/view/test_filter_permission/edit/default');
|
||||
// Verify that the handler summary is correctly displaying the selected
|
||||
// permission.
|
||||
$this->assertLink('User: Permission (= View user information)');
|
||||
$this->drupalPostForm(NULL, [], 'Save');
|
||||
// Verify that we can save the view.
|
||||
$this->assertNoText('No valid values found on filter: User: Permission.');
|
||||
$this->assertText('The view test_filter_permission has been saved.');
|
||||
|
||||
// Verify that the handler summary is also correct when multiple values are
|
||||
// selected in the filter.
|
||||
$edit = [
|
||||
'options[value][]' => [
|
||||
'access user profiles',
|
||||
'administer views',
|
||||
],
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/views/nojs/handler/test_filter_permission/default/filter/permission', $edit, 'Apply');
|
||||
$this->assertLink('User: Permission (or View us…)');
|
||||
$this->drupalPostForm(NULL, [], 'Save');
|
||||
// Verify that we can save the view.
|
||||
$this->assertNoText('No valid values found on filter: User: Permission.');
|
||||
$this->assertText('The view test_filter_permission has been saved.');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests\Views;
|
||||
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the handler of the user: uid Argument.
|
||||
*
|
||||
* @group user
|
||||
*/
|
||||
class HandlerArgumentUserUidTest extends UserTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_user_uid_argument'];
|
||||
|
||||
/**
|
||||
* Tests the generated title of an user: uid argument.
|
||||
*/
|
||||
public function testArgumentTitle() {
|
||||
$view = Views::getView('test_user_uid_argument');
|
||||
|
||||
// Tests an invalid user uid.
|
||||
$this->executeView($view, [rand(1000, 10000)]);
|
||||
$this->assertFalse($view->getTitle());
|
||||
$view->destroy();
|
||||
|
||||
// Tests a valid user.
|
||||
$account = $this->drupalCreateUser();
|
||||
$this->executeView($view, [$account->id()]);
|
||||
$this->assertEqual($view->getTitle(), $account->label());
|
||||
$view->destroy();
|
||||
|
||||
// Tests the anonymous user.
|
||||
$anonymous = $this->config('user.settings')->get('anonymous');
|
||||
$this->executeView($view, [0]);
|
||||
$this->assertEqual($view->getTitle(), $anonymous);
|
||||
$view->destroy();
|
||||
|
||||
$view->getDisplay()->getHandler('argument', 'uid')->options['break_phrase'] = TRUE;
|
||||
$this->executeView($view, [$account->id() . ',0']);
|
||||
$this->assertEqual($view->getTitle(), $account->label() . ', ' . $anonymous);
|
||||
$view->destroy();
|
||||
|
||||
$view->getDisplay()->getHandler('argument', 'uid')->options['break_phrase'] = TRUE;
|
||||
$this->executeView($view, ['0,' . $account->id()]);
|
||||
$this->assertEqual($view->getTitle(), $anonymous . ', ' . $account->label());
|
||||
$view->destroy();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests\Views;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* Tests the handler of the user: role field.
|
||||
*
|
||||
* @group user
|
||||
* @see views_handler_field_user_name
|
||||
*/
|
||||
class HandlerFieldRoleTest extends UserTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_views_handler_field_role'];
|
||||
|
||||
public function testRole() {
|
||||
// Create a couple of roles for the view.
|
||||
$rolename_a = 'a' . $this->randomMachineName(8);
|
||||
$this->drupalCreateRole(['access content'], $rolename_a, '<em>' . $rolename_a . '</em>', 9);
|
||||
|
||||
$rolename_b = 'b' . $this->randomMachineName(8);
|
||||
$this->drupalCreateRole(['access content'], $rolename_b, $rolename_b, 8);
|
||||
|
||||
$rolename_not_assigned = $this->randomMachineName(8);
|
||||
$this->drupalCreateRole(['access content'], $rolename_not_assigned, $rolename_not_assigned);
|
||||
|
||||
// Add roles to user 1.
|
||||
$user = User::load(1);
|
||||
$user->addRole($rolename_a);
|
||||
$user->addRole($rolename_b);
|
||||
$user->save();
|
||||
|
||||
$this->drupalLogin($this->createUser(['access user profiles']));
|
||||
$this->drupalGet('/test-views-handler-field-role');
|
||||
$this->assertText($rolename_b . Html::escape('<em>' . $rolename_a . '</em>'), 'View test_views_handler_field_role renders role assigned to user in the correct order and markup in role names is escaped.');
|
||||
$this->assertNoText($rolename_not_assigned, 'View test_views_handler_field_role does not render a role not assigned to a user.');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests\Views;
|
||||
|
||||
use Drupal\Core\Render\RenderContext;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the handler of the user: name field.
|
||||
*
|
||||
* @group user
|
||||
* @see views_handler_field_user_name
|
||||
*/
|
||||
class HandlerFieldUserNameTest extends UserTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_views_handler_field_user_name'];
|
||||
|
||||
public function testUserName() {
|
||||
/** @var \Drupal\Core\Render\RendererInterface $renderer */
|
||||
$renderer = \Drupal::service('renderer');
|
||||
|
||||
$new_user = $this->drupalCreateUser(['access user profiles']);
|
||||
$this->drupalLogin($new_user);
|
||||
|
||||
// Set defaults.
|
||||
$view = Views::getView('test_views_handler_field_user_name');
|
||||
$view->initHandlers();
|
||||
$view->field['name']->options['link_to_user'] = TRUE;
|
||||
$view->field['name']->options['type'] = 'user_name';
|
||||
$view->field['name']->init($view, $view->getDisplay('default'));
|
||||
$view->field['name']->options['id'] = 'name';
|
||||
$this->executeView($view);
|
||||
|
||||
$anon_name = $this->config('user.settings')->get('anonymous');
|
||||
$view->result[0]->_entity->setUsername('');
|
||||
$view->result[0]->_entity->uid->value = 0;
|
||||
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
|
||||
return $view->field['name']->advancedRender($view->result[0]);
|
||||
});
|
||||
$this->assertTrue(strpos($render, $anon_name) !== FALSE, 'For user 0 it should use the default anonymous name by default.');
|
||||
|
||||
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view, $new_user) {
|
||||
return $view->field['name']->advancedRender($view->result[$new_user->id()]);
|
||||
});
|
||||
$this->assertTrue(strpos($render, $new_user->getDisplayName()) !== FALSE, 'If link to user is checked the username should be part of the output.');
|
||||
$this->assertTrue(strpos($render, 'user/' . $new_user->id()) !== FALSE, 'If link to user is checked the link to the user should appear as well.');
|
||||
|
||||
$view->field['name']->options['link_to_user'] = FALSE;
|
||||
$view->field['name']->options['type'] = 'string';
|
||||
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view, $new_user) {
|
||||
return $view->field['name']->advancedRender($view->result[$new_user->id()]);
|
||||
});
|
||||
$this->assertEqual($render, $new_user->getDisplayName(), 'If the user is not linked the username should be printed out for a normal user.');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the field handler works when no additional fields are added.
|
||||
*/
|
||||
public function testNoAdditionalFields() {
|
||||
/** @var \Drupal\Core\Render\RendererInterface $renderer */
|
||||
$renderer = \Drupal::service('renderer');
|
||||
|
||||
$view = Views::getView('test_views_handler_field_user_name');
|
||||
$this->executeView($view);
|
||||
|
||||
$username = $this->randomMachineName();
|
||||
$view->result[0]->_entity->setUsername($username);
|
||||
$view->result[0]->_entity->uid->value = 1;
|
||||
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
|
||||
return $view->field['name']->advancedRender($view->result[0]);
|
||||
});
|
||||
$this->assertTrue(strpos($render, $username) !== FALSE, 'If link to user is checked the username should be part of the output.');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,184 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests\Views;
|
||||
|
||||
use Drupal\views\Views;
|
||||
use Drupal\views\Tests\ViewTestBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
|
||||
/**
|
||||
* Tests the handler of the user: name filter.
|
||||
*
|
||||
* @group user
|
||||
* @see Views\user\Plugin\views\filter\Name
|
||||
*/
|
||||
class HandlerFilterUserNameTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['views_ui', 'user_test_views'];
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_user_name'];
|
||||
|
||||
/**
|
||||
* Accounts used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $accounts = [];
|
||||
|
||||
/**
|
||||
* Usernames of $accounts.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $names = [];
|
||||
|
||||
/**
|
||||
* Stores the column map for this testCase.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $columnMap = [
|
||||
'uid' => 'uid',
|
||||
];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
ViewTestData::createTestViews(get_class($this), ['user_test_views']);
|
||||
|
||||
$this->enableViewsTestModule();
|
||||
|
||||
$this->accounts = [];
|
||||
$this->names = [];
|
||||
for ($i = 0; $i < 3; $i++) {
|
||||
$this->accounts[] = $account = $this->drupalCreateUser();
|
||||
$this->names[] = $account->label();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests just using the filter.
|
||||
*/
|
||||
public function testUserNameApi() {
|
||||
$view = Views::getView('test_user_name');
|
||||
|
||||
$view->initHandlers();
|
||||
$view->filter['uid']->value = [$this->accounts[0]->id()];
|
||||
|
||||
$this->executeView($view);
|
||||
$this->assertIdenticalResultset($view, [['uid' => $this->accounts[0]->id()]], $this->columnMap);
|
||||
|
||||
$this->assertEqual($view->filter['uid']->getValueOptions(), NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests using the user interface.
|
||||
*/
|
||||
public function testAdminUserInterface() {
|
||||
$admin_user = $this->drupalCreateUser(['administer views', 'administer site configuration']);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
$path = 'admin/structure/views/nojs/handler/test_user_name/default/filter/uid';
|
||||
$this->drupalGet($path);
|
||||
|
||||
// Pass in an invalid username, the validation should catch it.
|
||||
$users = [$this->randomMachineName()];
|
||||
$users = array_map('strtolower', $users);
|
||||
$edit = [
|
||||
'options[value]' => implode(', ', $users)
|
||||
];
|
||||
$this->drupalPostForm($path, $edit, t('Apply'));
|
||||
$this->assertRaw(t('There are no entities matching "%value".', ['%value' => implode(', ', $users)]));
|
||||
|
||||
// Pass in an invalid username and a valid username.
|
||||
$random_name = $this->randomMachineName();
|
||||
$users = [$random_name, $this->names[0]];
|
||||
$users = array_map('strtolower', $users);
|
||||
$edit = [
|
||||
'options[value]' => implode(', ', $users)
|
||||
];
|
||||
$users = [$users[0]];
|
||||
$this->drupalPostForm($path, $edit, t('Apply'));
|
||||
$this->assertRaw(t('There are no entities matching "%value".', ['%value' => implode(', ', $users)]));
|
||||
|
||||
// Pass in just valid usernames.
|
||||
$users = $this->names;
|
||||
$users = array_map('strtolower', $users);
|
||||
$edit = [
|
||||
'options[value]' => implode(', ', $users)
|
||||
];
|
||||
$this->drupalPostForm($path, $edit, t('Apply'));
|
||||
$this->assertNoRaw(t('There are no entities matching "%value".', ['%value' => implode(', ', $users)]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests exposed filters.
|
||||
*/
|
||||
public function testExposedFilter() {
|
||||
$path = 'test_user_name';
|
||||
|
||||
$options = [];
|
||||
|
||||
// Pass in an invalid username, the validation should catch it.
|
||||
$users = [$this->randomMachineName()];
|
||||
$users = array_map('strtolower', $users);
|
||||
$options['query']['uid'] = implode(', ', $users);
|
||||
$this->drupalGet($path, $options);
|
||||
$this->assertRaw(t('There are no entities matching "%value".', ['%value' => implode(', ', $users)]));
|
||||
|
||||
// Pass in an invalid target_id in for the entity_autocomplete value format.
|
||||
// There should be no errors, but all results should be returned as the
|
||||
// default value for the autocomplete will not match any users so should
|
||||
// be empty.
|
||||
$options['query']['uid'] = [['target_id' => 9999]];
|
||||
$this->drupalGet($path, $options);
|
||||
// The actual result should contain all of the user ids.
|
||||
foreach ($this->accounts as $account) {
|
||||
$this->assertRaw($account->id());
|
||||
}
|
||||
|
||||
// Pass in an invalid username and a valid username.
|
||||
$users = [$this->randomMachineName(), $this->names[0]];
|
||||
$users = array_map('strtolower', $users);
|
||||
$options['query']['uid'] = implode(', ', $users);
|
||||
$users = [$users[0]];
|
||||
|
||||
$this->drupalGet($path, $options);
|
||||
$this->assertRaw(t('There are no entities matching "%value".', ['%value' => implode(', ', $users)]));
|
||||
|
||||
// Pass in just valid usernames.
|
||||
$users = $this->names;
|
||||
$options['query']['uid'] = implode(', ', $users);
|
||||
|
||||
$this->drupalGet($path, $options);
|
||||
$this->assertNoRaw('Unable to find user');
|
||||
// The actual result should contain all of the user ids.
|
||||
foreach ($this->accounts as $account) {
|
||||
$this->assertRaw($account->id());
|
||||
}
|
||||
|
||||
// Pass in just valid user IDs in the entity_autocomplete target_id format.
|
||||
$options['query']['uid'] = array_map(function ($account) {
|
||||
return ['target_id' => $account->id()];
|
||||
}, $this->accounts);
|
||||
|
||||
$this->drupalGet($path, $options);
|
||||
$this->assertNoRaw('Unable to find user');
|
||||
// The actual result should contain all of the user ids.
|
||||
foreach ($this->accounts as $account) {
|
||||
$this->assertRaw($account->id());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests\Views;
|
||||
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the representative node relationship for users.
|
||||
*
|
||||
* @group user
|
||||
*/
|
||||
class RelationshipRepresentativeNodeTest extends UserTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_groupwise_user'];
|
||||
|
||||
/**
|
||||
* Tests the relationship.
|
||||
*/
|
||||
public function testRelationship() {
|
||||
$view = Views::getView('test_groupwise_user');
|
||||
$this->executeView($view);
|
||||
$map = ['node_field_data_users_field_data_nid' => 'nid', 'uid' => 'uid'];
|
||||
$expected_result = [
|
||||
[
|
||||
'uid' => $this->users[1]->id(),
|
||||
'nid' => $this->nodes[1]->id(),
|
||||
],
|
||||
[
|
||||
'uid' => $this->users[0]->id(),
|
||||
'nid' => $this->nodes[0]->id(),
|
||||
],
|
||||
];
|
||||
$this->assertIdenticalResultset($view, $expected_result, $map);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests\Views;
|
||||
|
||||
/**
|
||||
* Tests the handler of the user: roles argument.
|
||||
*
|
||||
* @group user
|
||||
* @see \Drupal\user\Plugin\views\argument\RolesRid
|
||||
*/
|
||||
class RolesRidArgumentTest extends UserTestBase {
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_user_roles_rid'];
|
||||
|
||||
/**
|
||||
* Tests the generated title of a user: roles argument.
|
||||
*/
|
||||
public function testArgumentTitle() {
|
||||
$role_id = $this->createRole([], 'markup_role_name', '<em>Role name with markup</em>');
|
||||
$user = $this->createUser();
|
||||
$user->addRole($role_id);
|
||||
$user->save();
|
||||
|
||||
$this->drupalGet('/user_roles_rid_test/markup_role_name');
|
||||
$this->assertEscaped('<em>Role name with markup</em>');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests\Views;
|
||||
|
||||
use Drupal\views\Tests\ViewTestBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
|
||||
/**
|
||||
* Tests the changed field.
|
||||
*
|
||||
* @group user
|
||||
*/
|
||||
class UserChangedTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['views_ui', 'user_test_views'];
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_user_changed'];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
ViewTestData::createTestViews(get_class($this), ['user_test_views']);
|
||||
|
||||
$this->enableViewsTestModule();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests changed field.
|
||||
*/
|
||||
public function testChangedField() {
|
||||
$path = 'test_user_changed';
|
||||
|
||||
$options = [];
|
||||
|
||||
$this->drupalGet($path, $options);
|
||||
|
||||
$this->assertText(t('Updated date') . ': ' . date('Y-m-d', REQUEST_TIME));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests\Views;
|
||||
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the user data service field handler.
|
||||
*
|
||||
* @group user
|
||||
* @see \Drupal\user\Plugin\views\field\UserData
|
||||
*/
|
||||
class UserDataTest extends UserTestBase {
|
||||
|
||||
/**
|
||||
* Provides the user data service object.
|
||||
*
|
||||
* @var \Drupal\user\UserDataInterface
|
||||
*/
|
||||
protected $userData;
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_user_data'];
|
||||
|
||||
/**
|
||||
* Tests field handler.
|
||||
*/
|
||||
public function testDataField() {
|
||||
// But some random values into the user data service.
|
||||
$this->userData = $this->container->get('user.data');
|
||||
$random_value = $this->randomMachineName();
|
||||
$this->userData->set('views_test_config', $this->users[0]->id(), 'test_value_name', $random_value);
|
||||
|
||||
$view = Views::getView('test_user_data');
|
||||
$this->executeView($view);
|
||||
|
||||
$output = $view->field['data']->render($view->result[0]);
|
||||
$this->assertEqual($output, $random_value, 'A valid user data got rendered.');
|
||||
|
||||
$view->field['data']->options['data_name'] = $this->randomMachineName();
|
||||
$output = $view->field['data']->render($view->result[0]);
|
||||
$this->assertFalse($output, 'An invalid configuration does not return anything');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\user\Tests\Views;
|
||||
|
||||
use Drupal\views\Tests\ViewTestBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* @todo.
|
||||
*/
|
||||
abstract class UserTestBase extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['user_test_views', 'node'];
|
||||
|
||||
/**
|
||||
* Users to use during this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $users = [];
|
||||
|
||||
/**
|
||||
* Nodes to use during this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $nodes = [];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
ViewTestData::createTestViews(get_class($this), ['user_test_views']);
|
||||
|
||||
$this->users[] = $this->drupalCreateUser();
|
||||
$this->users[] = User::load(1);
|
||||
$this->nodes[] = $this->drupalCreateNode(['uid' => $this->users[0]->id()]);
|
||||
$this->nodes[] = $this->drupalCreateNode(['uid' => 1]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -48,30 +48,26 @@ class UserData implements UserDataInterface {
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
$return = [];
|
||||
// If $module and $uid were passed, return data keyed by name.
|
||||
elseif (isset($uid)) {
|
||||
$return = [];
|
||||
if (isset($uid)) {
|
||||
foreach ($result as $record) {
|
||||
$return[$record->name] = ($record->serialized ? unserialize($record->value) : $record->value);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
// If $module and $name were passed, return data keyed by uid.
|
||||
elseif (isset($name)) {
|
||||
$return = [];
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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'));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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'] = [
|
||||
|
||||
Reference in New Issue
Block a user