Drupal 8.0.0 beta 12. More info: https://www.drupal.org/node/2514176

This commit is contained in:
Pantheon Automation 2015-08-17 17:00:26 -07:00 committed by Greg Anderson
commit 9921556621
13277 changed files with 1459781 additions and 0 deletions

View file

@ -0,0 +1,40 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\Action\AddRoleUser.
*/
namespace Drupal\user\Plugin\Action;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Session\AccountInterface;
use Drupal\user\Plugin\Action\ChangeUserRoleBase;
/**
* Adds a role to a user.
*
* @Action(
* id = "user_add_role_action",
* label = @Translation("Add a role to the selected users"),
* type = "user"
* )
*/
class AddRoleUser extends ChangeUserRoleBase {
/**
* {@inheritdoc}
*/
public function execute($account = NULL) {
$rid = $this->configuration['rid'];
// Skip adding the role to the user if they already have it.
if ($account !== FALSE && !$account->hasRole($rid)) {
// For efficiency manually save the original account before applying
// any changes.
$account->original = clone $account;
$account->addRole($rid);
$account->save();
}
}
}

View file

@ -0,0 +1,49 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\Action\BlockUser.
*/
namespace Drupal\user\Plugin\Action;
use Drupal\Core\Action\ActionBase;
use Drupal\Core\Session\AccountInterface;
/**
* Blocks a user.
*
* @Action(
* id = "user_block_user_action",
* label = @Translation("Block the selected users"),
* type = "user"
* )
*/
class BlockUser extends ActionBase {
/**
* {@inheritdoc}
*/
public function execute($account = NULL) {
// Skip blocking user if they are already blocked.
if ($account !== FALSE && $account->isActive()) {
// For efficiency manually save the original account before applying any
// changes.
$account->original = clone $account;
$account->block();
$account->save();
}
}
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
/** @var \Drupal\user\UserInterface $object */
$access = $object->status->access('edit', $account, TRUE)
->andIf($object->access('update', $account, TRUE));
return $return_as_object ? $access : $access->isAllowed();
}
}

View file

@ -0,0 +1,98 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\Action\CancelUser.
*/
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 Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Cancels a user account.
*
* @Action(
* id = "user_cancel_user_action",
* label = @Translation("Cancel the selected user accounts"),
* type = "user",
* confirm_form_route_name = "user.multiple_cancel_confirm"
* )
*/
class CancelUser extends ActionBase implements ContainerFactoryPluginInterface {
/**
* The tempstore factory.
*
* @var \Drupal\user\PrivateTempStoreFactory
*/
protected $tempStoreFactory;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* Constructs a DeleteNode object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin ID for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory
* The tempstore factory.
* @param AccountInterface $current_user
* Current user.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, PrivateTempStoreFactory $temp_store_factory, AccountInterface $current_user) {
$this->currentUser = $current_user;
$this->tempStoreFactory = $temp_store_factory;
parent::__construct($configuration, $plugin_id, $plugin_definition);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('user.private_tempstore'),
$container->get('current_user')
);
}
/**
* {@inheritdoc}
*/
public function executeMultiple(array $entities) {
$this->tempStoreFactory->get('user_user_operations_cancel')->set($this->currentUser->id(), $entities);
}
/**
* {@inheritdoc}
*/
public function execute($object = NULL) {
$this->executeMultiple(array($object));
}
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
/** @var \Drupal\user\UserInterface $object */
return $object->access('delete', $account, $return_as_object);
}
}

View file

@ -0,0 +1,107 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\Action\ChangeUserRoleBase.
*/
namespace Drupal\user\Plugin\Action;
use Drupal\Core\Action\ConfigurableActionBase;
use Drupal\Core\Entity\DependencyTrait;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\user\RoleInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides a base class for operations to change a user's role.
*/
abstract class ChangeUserRoleBase extends ConfigurableActionBase implements ContainerFactoryPluginInterface {
use DependencyTrait;
/**
* The user role entity type.
*
* @var \Drupal\Core\Entity\EntityTypeInterface
*/
protected $entityType;
/**
* {@inheritdoc}
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeInterface $entity_type) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->entityType = $entity_type;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('entity.manager')->getDefinition('user_role')
);
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return array(
'rid' => '',
);
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$roles = user_role_names(TRUE);
unset($roles[RoleInterface::AUTHENTICATED_ID]);
$form['rid'] = array(
'#type' => 'radios',
'#title' => t('Role'),
'#options' => $roles,
'#default_value' => $this->configuration['rid'],
'#required' => TRUE,
);
return $form;
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
$this->configuration['rid'] = $form_state->getValue('rid');
}
/**
* {@inheritdoc}
*/
public function calculateDependencies() {
if (!empty($this->configuration['rid'])) {
$prefix = $this->entityType->getConfigPrefix() . '.';
$this->addDependency('config', $prefix . $this->configuration['rid']);
}
return $this->dependencies;
}
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
/** @var \Drupal\user\UserInterface $object */
$access = $object->access('update', $account, TRUE)
->andIf($object->roles->access('edit', $account, TRUE));
return $return_as_object ? $access : $access->isAllowed();
}
}

View file

@ -0,0 +1,40 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\Action\RemoveRoleUser.
*/
namespace Drupal\user\Plugin\Action;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Session\AccountInterface;
use Drupal\user\Plugin\Action\ChangeUserRoleBase;
/**
* Removes a role from a user.
*
* @Action(
* id = "user_remove_role_action",
* label = @Translation("Remove a role from the selected users"),
* type = "user"
* )
*/
class RemoveRoleUser extends ChangeUserRoleBase {
/**
* {@inheritdoc}
*/
public function execute($account = NULL) {
$rid = $this->configuration['rid'];
// Skip removing the role from the user if they already don't have it.
if ($account !== FALSE && $account->hasRole($rid)) {
// For efficiency manually save the original account before applying
// any changes.
$account->original = clone $account;
$account->removeRole($rid);
$account->save();
}
}
}

View file

@ -0,0 +1,46 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\Action\UnblockUser.
*/
namespace Drupal\user\Plugin\Action;
use Drupal\Core\Action\ActionBase;
use Drupal\Core\Session\AccountInterface;
/**
* Unblocks a user.
*
* @Action(
* id = "user_unblock_user_action",
* label = @Translation("Unblock the selected users"),
* type = "user"
* )
*/
class UnblockUser extends ActionBase {
/**
* {@inheritdoc}
*/
public function execute($account = NULL) {
// Skip unblocking user if they are already unblocked.
if ($account !== FALSE && $account->isBlocked()) {
$account->activate();
$account->save();
}
}
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
/** @var \Drupal\user\UserInterface $object */
$access = $object->status->access('edit', $account, TRUE)
->andIf($object->access('update', $account, TRUE));
return $return_as_object ? $access : $access->isAllowed();
}
}

View file

@ -0,0 +1,132 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\Block\UserLoginBlock.
*/
namespace Drupal\user\Plugin\Block;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Routing\RedirectDestinationTrait;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Routing\UrlGeneratorTrait;
use Drupal\Core\Url;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Block\BlockBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides a 'User login' block.
*
* @Block(
* id = "user_login_block",
* admin_label = @Translation("User login"),
* category = @Translation("Forms")
* )
*/
class UserLoginBlock extends BlockBase implements ContainerFactoryPluginInterface {
use UrlGeneratorTrait;
use RedirectDestinationTrait;
/**
* The route match.
*
* @var \Drupal\Core\Routing\RouteMatchInterface
*/
protected $routeMatch;
/**
* Constructs a new UserLoginBlock instance.
*
* @param array $configuration
* The plugin configuration, i.e. an array with configuration values keyed
* by configuration option name. The special key 'context' may be used to
* initialize the defined contexts by setting it to an array of context
* values keyed by context names.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteMatchInterface $route_match) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->routeMatch = $route_match;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('current_route_match')
);
}
/**
* {@inheritdoc}
*/
protected function blockAccess(AccountInterface $account) {
$route_name = $this->routeMatch->getRouteName();
if ($account->isAnonymous() && !in_array($route_name, array('user.register', 'user.login', 'user.logout'))) {
return AccessResult::allowed()
->addCacheContexts(['route', 'user.roles:anonymous']);
}
return AccessResult::forbidden();
}
/**
* {@inheritdoc}
*/
public function build() {
$form = \Drupal::formBuilder()->getForm('Drupal\user\Form\UserLoginForm');
unset($form['name']['#attributes']['autofocus']);
unset($form['name']['#description']);
unset($form['pass']['#description']);
$form['name']['#size'] = 15;
$form['pass']['#size'] = 15;
$form['#action'] = $this->url('<current>', [], ['query' => $this->getDestinationArray(), 'external' => FALSE]);
// Build action links.
$items = array();
if (\Drupal::config('user.settings')->get('register') != USER_REGISTER_ADMINISTRATORS_ONLY) {
$items['create_account'] = \Drupal::l($this->t('Create new account'), new Url('user.register', array(), array(
'attributes' => array(
'title' => $this->t('Create a new user account.'),
'class' => array('create-account-link'),
),
)));
}
$items['request_password'] = \Drupal::l($this->t('Reset your password'), new Url('user.pass', array(), array(
'attributes' => array(
'title' => $this->t('Send password reset instructions via e-mail.'),
'class' => array('request-password-link'),
),
)));
return array(
'user_login_form' => $form,
'user_links' => array(
'#theme' => 'item_list',
'#items' => $items,
),
);
}
/**
* {@inheritdoc}
*
* @todo Make cacheable once https://www.drupal.org/node/2351015 lands.
*/
public function getCacheMaxAge() {
return 0;
}
}

View file

@ -0,0 +1,90 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\Condition\UserRole.
*/
namespace Drupal\user\Plugin\Condition;
use Drupal\Core\Condition\ConditionPluginBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\Context\ContextDefinition;
/**
* Provides a 'User Role' condition.
*
* @Condition(
* id = "user_role",
* label = @Translation("User Role"),
* context = {
* "user" = @ContextDefinition("entity:user", label = @Translation("User"))
* }
* )
*
*/
class UserRole extends ConditionPluginBase {
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form['roles'] = array(
'#type' => 'checkboxes',
'#title' => $this->t('When the user has the following roles'),
'#default_value' => $this->configuration['roles'],
'#options' => array_map('\Drupal\Component\Utility\SafeMarkup::checkPlain', user_role_names()),
'#description' => $this->t('If you select no roles, the condition will evaluate to TRUE for all users.'),
);
return parent::buildConfigurationForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return array(
'roles' => array(),
) + parent::defaultConfiguration();
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
$this->configuration['roles'] = array_filter($form_state->getValue('roles'));
parent::submitConfigurationForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function summary() {
// Use the role labels. They will be sanitized below.
$roles = array_intersect_key(user_role_names(), $this->configuration['roles']);
if (count($roles) > 1) {
$roles = implode(', ', $roles);
}
else {
$roles = reset($roles);
}
if (!empty($this->configuration['negate'])) {
return $this->t('The user is not a member of @roles', array('@roles' => $roles));
}
else {
return $this->t('The user is a member of @roles', array('@roles' => $roles));
}
}
/**
* {@inheritdoc}
*/
public function evaluate() {
if (empty($this->configuration['roles']) && !$this->isNegated()) {
return TRUE;
}
$user = $this->getContextValue('user');
return (bool) array_intersect($this->configuration['roles'], $user->getRoles());
}
}

View file

@ -0,0 +1,214 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\EntityReferenceSelection\UserSelection.
*/
namespace Drupal\user\Plugin\EntityReferenceSelection;
use Drupal\Core\Database\Connection;
use Drupal\Core\Database\Query\SelectInterface;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\Plugin\EntityReferenceSelection\SelectionBase;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\user\RoleInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides specific access control for the user entity type.
*
* @EntityReferenceSelection(
* id = "default:user",
* label = @Translation("User selection"),
* entity_types = {"user"},
* group = "default",
* weight = 1
* )
*/
class UserSelection extends SelectionBase {
/**
* The database connection.
*
* @var \Drupal\Core\Database\Connection
*/
protected $connection;
/**
* The user storage.
*
* @var \Drupal\user\UserStorageInterface
*/
protected $userStorage;
/**
* Constructs a new UserSelection object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager service.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler service.
* @param \Drupal\Core\Session\AccountInterface $current_user
* The current user.
* @param \Drupal\Core\Database\Connection $connection
* The database connection.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, AccountInterface $current_user, Connection $connection) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_manager, $module_handler, $current_user);
$this->connection = $connection;
$this->userStorage = $entity_manager->getStorage('user');
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('entity.manager'),
$container->get('module_handler'),
$container->get('current_user'),
$container->get('database')
);
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$selection_handler_settings = $this->configuration['handler_settings'];
// Merge in default values.
$selection_handler_settings += array(
'filter' => array(
'type' => '_none',
),
'include_anonymous' => TRUE,
);
$form['include_anonymous'] = array(
'#type' => 'checkbox',
'#title' => $this->t('Include the anonymous user.'),
'#default_value' => $selection_handler_settings['include_anonymous'],
);
// Add user specific filter options.
$form['filter']['type'] = array(
'#type' => 'select',
'#title' => $this->t('Filter by'),
'#options' => array(
'_none' => $this->t('- None -'),
'role' => $this->t('User role'),
),
'#ajax' => TRUE,
'#limit_validation_errors' => array(),
'#default_value' => $selection_handler_settings['filter']['type'],
);
$form['filter']['settings'] = array(
'#type' => 'container',
'#attributes' => array('class' => array('entity_reference-settings')),
'#process' => array('_entity_reference_form_process_merge_parent'),
);
if ($selection_handler_settings['filter']['type'] == 'role') {
// Merge in default values.
$selection_handler_settings['filter'] += array(
'role' => NULL,
);
$form['filter']['settings']['role'] = array(
'#type' => 'checkboxes',
'#title' => $this->t('Restrict to the selected roles'),
'#required' => TRUE,
'#options' => array_diff_key(user_role_names(TRUE), array(RoleInterface::AUTHENTICATED_ID => RoleInterface::AUTHENTICATED_ID)),
'#default_value' => $selection_handler_settings['filter']['role'],
);
}
$form += parent::buildConfigurationForm($form, $form_state);
return $form;
}
/**
* {@inheritdoc}
*/
protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') {
$query = parent::buildEntityQuery($match, $match_operator);
// The user entity doesn't have a label column.
if (isset($match)) {
$query->condition('name', $match, $match_operator);
}
// Filter by role.
$handler_settings = $this->configuration['handler_settings'];
if (!empty($handler_settings['filter']['role'])) {
$query->condition('roles', $handler_settings['filter']['role'], 'IN');
}
// Adding the permission check is sadly insufficient for users: core
// requires us to also know about the concept of 'blocked' and 'active'.
if (!$this->currentUser->hasPermission('administer users')) {
$query->condition('status', 1);
}
return $query;
}
/**
* {@inheritdoc}
*/
public function entityQueryAlter(SelectInterface $query) {
// Bail out early if we do not need to match the Anonymous user.
$handler_settings = $this->configuration['handler_settings'];
if (isset($handler_settings['include_anonymous']) && !$handler_settings['include_anonymous']) {
return;
}
if ($this->currentUser->hasPermission('administer users')) {
// In addition, if the user is administrator, we need to make sure to
// match the anonymous user, that doesn't actually have a name in the
// database.
$conditions = &$query->conditions();
foreach ($conditions as $key => $condition) {
if ($key !== '#conjunction' && is_string($condition['field']) && $condition['field'] === 'users_field_data.name') {
// Remove the condition.
unset($conditions[$key]);
// Re-add the condition and a condition on uid = 0 so that we end up
// with a query in the form:
// WHERE (name LIKE :name) OR (:anonymous_name LIKE :name AND uid = 0)
$or = db_or();
$or->condition($condition['field'], $condition['value'], $condition['operator']);
// Sadly, the Database layer doesn't allow us to build a condition
// in the form ':placeholder = :placeholder2', because the 'field'
// part of a condition is always escaped.
// As a (cheap) workaround, we separately build a condition with no
// field, and concatenate the field and the condition separately.
$value_part = db_and();
$value_part->condition('anonymous_name', $condition['value'], $condition['operator']);
$value_part->compile($this->connection, $query);
$or->condition(db_and()
->where(str_replace('anonymous_name', ':anonymous_name', (string) $value_part), $value_part->arguments() + array(':anonymous_name' => user_format_name($this->userStorage->load(0))))
->condition('base_table.uid', 0)
);
$query->condition($or);
}
}
}
}
}

View file

@ -0,0 +1,67 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\Field\FieldFormatter\AuthorFormatter.
*/
namespace Drupal\user\Plugin\Field\FieldFormatter;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\Plugin\Field\FieldFormatter\EntityReferenceFormatterBase;
/**
* Plugin implementation of the 'author' formatter.
*
* @FieldFormatter(
* id = "author",
* label = @Translation("Author"),
* description = @Translation("Display the referenced author user entity."),
* field_types = {
* "entity_reference"
* }
* )
*/
class AuthorFormatter extends EntityReferenceFormatterBase {
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items) {
$elements = array();
foreach ($this->getEntitiesToView($items) as $delta => $entity) {
/** @var $referenced_user \Drupal\user\UserInterface */
$elements[$delta] = array(
'#theme' => 'username',
'#account' => $entity,
'#link_options' => array('attributes' => array('rel' => 'author')),
'#cache' => array(
'tags' => $entity->getCacheTags(),
),
);
}
return $elements;
}
/**
* {@inheritdoc}
*/
public static function isApplicable(FieldDefinitionInterface $field_definition) {
return $field_definition->getFieldStorageDefinition()->getSetting('target_type') == 'user';
}
/**
* {@inheritdoc}
*/
protected function checkAccess(EntityInterface $entity) {
// Always allow an entity author's username to be read, even if the current
// user does not have permission to view the entity author's profile.
return AccessResult::allowed();
}
}

View file

@ -0,0 +1,94 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\Field\FieldFormatter\UserNameFormatter.
*/
namespace Drupal\user\Plugin\Field\FieldFormatter;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Plugin implementation of the 'user_name' formatter.
*
* @FieldFormatter(
* id = "user_name",
* label = @Translation("User name"),
* description = @Translation("Display the user or author name."),
* field_types = {
* "string"
* }
* )
*/
class UserNameFormatter extends FormatterBase {
/**
* {@inheritdoc}
*/
public static function defaultSettings() {
$options = parent::defaultSettings();
$options['link_to_entity'] = TRUE;
return $options;
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
$form = parent::settingsForm($form, $form_state);
$form['link_to_entity'] = [
'#type' => 'checkbox',
'#title' => $this->t('Link to the user'),
'#default_value' => $this->getSetting('link_to_entity'),
];
return $form;
}
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items) {
$elements = [];
foreach ($items as $delta => $item) {
/** @var $user \Drupal\user\UserInterface */
if ($user = $item->getEntity()) {
if ($this->getSetting('link_to_entity')) {
$elements[$delta] = [
'#theme' => 'username',
'#account' => $user,
'#link_options' => ['attributes' => ['rel' => 'user']],
'#cache' => [
'tags' => $user->getCacheTags(),
],
];
}
else {
$elements[$delta] = [
'#markup' => $user->getUsername(),
'#cache' => [
'tags' => $user->getCacheTags(),
],
];
}
}
}
return $elements;
}
/**
* {@inheritdoc}
*/
public static function isApplicable(FieldDefinitionInterface $field_definition) {
return $field_definition->getTargetEntityTypeId() === 'user' && $field_definition->getName() === 'name';
}
}

View file

@ -0,0 +1,50 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\LanguageNegotiation\LanguageNegotiationUser.
*/
namespace Drupal\user\Plugin\LanguageNegotiation;
use Drupal\language\LanguageNegotiationMethodBase;
use Symfony\Component\HttpFoundation\Request;
/**
* Class for identifying language from the user preferences.
*
* @LanguageNegotiation(
* id = \Drupal\user\Plugin\LanguageNegotiation\LanguageNegotiationUser::METHOD_ID,
* weight = -4,
* name = @Translation("User"),
* description = @Translation("Follow the user's language preference.")
* )
*/
class LanguageNegotiationUser extends LanguageNegotiationMethodBase {
/**
* The language negotiation method id.
*/
const METHOD_ID = 'language-user';
/**
* {@inheritdoc}
*/
public function getLangcode(Request $request = NULL) {
$langcode = NULL;
// User preference (only for authenticated users).
if ($this->languageManager && $this->currentUser->isAuthenticated()) {
$preferred_langcode = $this->currentUser->getPreferredLangcode();
$default_langcode = $this->languageManager->getDefaultLanguage()->getId();
$languages = $this->languageManager->getLanguages();
if (!empty($preferred_langcode) && $preferred_langcode != $default_langcode && isset($languages[$preferred_langcode])) {
$langcode = $preferred_langcode;
}
}
// No language preference from the user.
return $langcode;
}
}

View file

@ -0,0 +1,155 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\LanguageNegotiation\LanguageNegotiationUserAdmin.
*/
namespace Drupal\user\Plugin\LanguageNegotiation;
use Drupal\Core\PathProcessor\PathProcessorManager;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Routing\AdminContext;
use Drupal\Core\Routing\RouteMatch;
use Drupal\Core\Routing\StackedRouteMatchInterface;
use Drupal\language\LanguageNegotiationMethodBase;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
/**
* Identifies admin language from the user preferences.
*
* @LanguageNegotiation(
* id = Drupal\user\Plugin\LanguageNegotiation\LanguageNegotiationUserAdmin::METHOD_ID,
* types = {Drupal\Core\Language\LanguageInterface::TYPE_INTERFACE},
* weight = -10,
* name = @Translation("Account administration pages"),
* description = @Translation("Account administration pages language setting.")
* )
*/
class LanguageNegotiationUserAdmin extends LanguageNegotiationMethodBase implements ContainerFactoryPluginInterface {
/**
* The language negotiation method id.
*/
const METHOD_ID = 'language-user-admin';
/**
* The admin context.
*
* @var \Drupal\Core\Routing\AdminContext
*/
protected $adminContext;
/**
* The router.
*
* This is only used when called from an event subscriber, before the request
* has been populated with the route info.
*
* @var \Symfony\Component\Routing\Matcher\UrlMatcherInterface
*/
protected $router;
/**
* The path processor manager.
*
* @var \Drupal\Core\PathProcessor\PathProcessorManager
*/
protected $pathProcessorManager;
/**
* The stacked route match.
*
* @var \Drupal\Core\Routing\StackedRouteMatchInterface
*/
protected $stackedRouteMatch;
/**
* Constructs a new LanguageNegotiationUserAdmin instance.
*
* @param \Drupal\Core\Routing\AdminContext $admin_context
* The admin context.
* @param \Symfony\Component\Routing\Matcher\UrlMatcherInterface $router
* The router.
* @param \Drupal\Core\PathProcessor\PathProcessorManager $path_processor_manager
* The path processor manager.
* @param \Drupal\Core\Routing\StackedRouteMatchInterface $stacked_route_match
* The stacked route match.
*/
public function __construct(AdminContext $admin_context, UrlMatcherInterface $router, PathProcessorManager $path_processor_manager, StackedRouteMatchInterface $stacked_route_match) {
$this->adminContext = $admin_context;
$this->router = $router;
$this->pathProcessorManager = $path_processor_manager;
$this->stackedRouteMatch = $stacked_route_match;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$container->get('router.admin_context'),
$container->get('router'),
$container->get('path_processor_manager'),
$container->get('current_route_match')
);
}
/**
* {@inheritdoc}
*/
public function getLangcode(Request $request = NULL) {
$langcode = NULL;
// User preference (only for administrators).
if ($this->currentUser->hasPermission('access administration pages') && ($preferred_admin_langcode = $this->currentUser->getPreferredAdminLangcode(FALSE)) && $this->isAdminPath($request)) {
$langcode = $preferred_admin_langcode;
}
// Not an admin, no admin language preference or not on an admin path.
return $langcode;
}
/**
* Checks whether the given path is an administrative one.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The request object.
*
* @return bool
* TRUE if the path is administrative, FALSE otherwise.
*/
protected function isAdminPath(Request $request) {
$result = FALSE;
if ($request && $this->adminContext) {
// If called from an event subscriber, the request may not have the route
// object yet (it is still being built), so use the router to look up
// based on the path.
$route_match = $this->stackedRouteMatch->getRouteMatchFromRequest($request);
if ($route_match && !$route_object = $route_match->getRouteObject()) {
try {
// Process the path as an inbound path. This will remove any language
// prefixes and other path components that inbound processing would
// clear out, so we can attempt to load the route clearly.
$path = $this->pathProcessorManager->processInbound(urldecode(rtrim($request->getPathInfo(), '/')), $request);
$attributes = $this->router->match($path);
}
catch (ResourceNotFoundException $e) {
return FALSE;
}
catch (AccessDeniedHttpException $e) {
return FALSE;
}
$route_object = $attributes[RouteObjectInterface::ROUTE_OBJECT];
}
$result = $this->adminContext->isAdminRoute($route_object);
}
return $result;
}
}

View file

@ -0,0 +1,178 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\Search\UserSearch.
*/
namespace Drupal\user\Plugin\Search;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Access\AccessibleInterface;
use Drupal\search\Plugin\SearchPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Executes a keyword search for users against the {users} database table.
*
* @SearchPlugin(
* id = "user_search",
* title = @Translation("Users")
* )
*/
class UserSearch extends SearchPluginBase implements AccessibleInterface {
/**
* The database connection.
*
* @var \Drupal\Core\Database\Connection
*/
protected $database;
/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
*/
protected $entityManager;
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* {@inheritdoc}
*/
static public function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$container->get('database'),
$container->get('entity.manager'),
$container->get('module_handler'),
$container->get('current_user'),
$configuration,
$plugin_id,
$plugin_definition
);
}
/**
* Creates a UserSearch object.
*
* @param Connection $database
* The database connection.
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager.
* @param ModuleHandlerInterface $module_handler
* The module handler.
* @param \Drupal\Core\Session\AccountInterface $current_user
* The current user.
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
*/
public function __construct(Connection $database, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, AccountInterface $current_user, array $configuration, $plugin_id, $plugin_definition) {
$this->database = $database;
$this->entityManager = $entity_manager;
$this->moduleHandler = $module_handler;
$this->currentUser = $current_user;
parent::__construct($configuration, $plugin_id, $plugin_definition);
}
/**
* {@inheritdoc}
*/
public function access($operation = 'view', AccountInterface $account = NULL, $return_as_object = FALSE) {
$result = AccessResult::allowedIf(!empty($account) && $account->hasPermission('access user profiles'))->cachePerPermissions();
return $return_as_object ? $result : $result->isAllowed();
}
/**
* {@inheritdoc}
*/
public function execute() {
$results = array();
if (!$this->isSearchExecutable()) {
return $results;
}
// Process the keywords.
$keys = $this->keywords;
// Escape for LIKE matching.
$keys = $this->database->escapeLike($keys);
// Replace wildcards with MySQL/PostgreSQL wildcards.
$keys = preg_replace('!\*+!', '%', $keys);
// Run the query to find matching users.
$query = $this->database
->select('users_field_data', 'users')
->extend('Drupal\Core\Database\Query\PagerSelectExtender');
$query->fields('users', array('uid'));
$query->condition('default_langcode', 1);
if ($this->currentUser->hasPermission('administer users')) {
// Administrators can also search in the otherwise private email field,
// and they don't need to be restricted to only active users.
$query->fields('users', array('mail'));
$query->condition($query->orConditionGroup()
->condition('name', '%' . $keys . '%', 'LIKE')
->condition('mail', '%' . $keys . '%', 'LIKE')
);
}
else {
// Regular users can only search via usernames, and we do not show them
// blocked accounts.
$query->condition('name', '%' . $keys . '%', 'LIKE')
->condition('status', 1);
}
$uids = $query
->limit(15)
->execute()
->fetchCol();
$accounts = $this->entityManager->getStorage('user')->loadMultiple($uids);
foreach ($accounts as $account) {
$result = array(
'title' => $account->getUsername(),
'link' => $account->url('canonical', array('absolute' => TRUE)),
);
if ($this->currentUser->hasPermission('administer users')) {
$result['title'] .= ' (' . $account->getEmail() . ')';
}
$results[] = $result;
}
return $results;
}
/*
* {@inheritdoc}
*/
public function getHelp() {
$help = array('list' => array(
'#theme' => 'item_list',
'#items' => array(
$this->t('User search looks for user names and partial user names. Example: mar would match usernames mar, delmar, and maryjane.'),
$this->t('You can use * as a wildcard within your keyword. Example: m*r would match user names mar, delmar, and elementary.'),
),
));
return $help;
}
}

View file

@ -0,0 +1,29 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\Validation\Constraint\ProtectedUserFieldConstraint.
*/
namespace Drupal\user\Plugin\Validation\Constraint;
use Symfony\Component\Validator\Constraint;
/**
* Checks if the plain text password is provided for editing a protected field.
*
* @Constraint(
* id = "ProtectedUserField",
* label = @Translation("Password required for protected field change", context = "Validation")
* )
*/
class ProtectedUserFieldConstraint extends Constraint {
/**
* Violation message.
*
* @var string
*/
public $message = "Your current password is missing or incorrect; it's required to change the %name.";
}

View file

@ -0,0 +1,98 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\Validation\Constraint\ProtectedUserFieldConstraintValidator.
*/
namespace Drupal\user\Plugin\Validation\Constraint;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\user\UserStorageInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
/**
* Validates the ProtectedUserFieldConstraint constraint.
*/
class ProtectedUserFieldConstraintValidator extends ConstraintValidator implements ContainerInjectionInterface {
/**
* User storage handler.
*
* @var \Drupal\user\UserStorageInterface
*/
protected $userStorage;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected $currentUser;
/**
* Constructs the object.
*
* @param \Drupal\user\UserStorageInterface $user_storage
* The user storage handler.
* @param \Drupal\Core\Session\AccountProxyInterface $current_user
* The current user.
*/
public function __construct(UserStorageInterface $user_storage, AccountProxyInterface $current_user) {
$this->userStorage = $user_storage;
$this->currentUser = $current_user;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity.manager')->getStorage('user'),
$container->get('current_user')
);
}
/**
* {@inheritdoc}
*/
public function validate($items, Constraint $constraint) {
if (!isset($items)) {
return;
}
/* @var \Drupal\Core\Field\FieldItemListInterface $items */
$field = $items->getFieldDefinition();
/* @var \Drupal\user\UserInterface $account */
$account = $items->getEntity();
if (!isset($account) || !empty($account->_skipProtectedUserFieldConstraint)) {
// Looks like we are validating a field not being part of a user, or the
// constraint should be skipped, so do nothing.
return;
}
// Only validate for existing entities and if this is the current user.
if (!$account->isNew() && $account->id() == $this->currentUser->id()) {
/* @var \Drupal\user\UserInterface $account_unchanged */
$account_unchanged = $this->userStorage
->loadUnchanged($account->id());
$changed = FALSE;
// Special case for the password, it being empty means that the existing
// password should not be changed, ignore empty password fields.
$value = $items->value;
if ($field->getName() != 'pass' || !empty($value)) {
// Compare the values of the field this is being validated on.
$changed = $items->getValue() != $account_unchanged->get($field->getName())->getValue();
}
if ($changed && (!$account->checkExistingPassword($account_unchanged))) {
$this->context->addViolation($constraint->message, array('%name' => $field->getLabel()));
}
}
}
}

View file

@ -0,0 +1,77 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\Validation\Constraint\UserMailRequired.
*/
namespace Drupal\user\Plugin\Validation\Constraint;
use Drupal\Component\Utility\SafeMarkup;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidatorInterface;
use Symfony\Component\Validator\ExecutionContextInterface;
/**
* Checks if the user's email address is provided if required.
*
* The user mail field is NOT required if account originally had no mail set
* and the user performing the edit has 'administer users' permission.
* This allows users without email address to be edited and deleted.
*
* @Constraint(
* id = "UserMailRequired",
* label = @Translation("User email required", context = "Validation")
* )
*/
class UserMailRequired extends Constraint implements ConstraintValidatorInterface {
/**
* Violation message. Use the same message as FormValidator.
*
* @var string
*/
public $message = '!name field is required.';
/**
* @var \Symfony\Component\Validator\ExecutionContextInterface
*/
protected $context;
/**
* {@inheritDoc}
*/
public function initialize(ExecutionContextInterface $context) {
$this->context = $context;
}
/**
* {@inheritdoc}
*/
public function validatedBy() {
return get_class($this);
}
/**
* {@inheritdoc}
*/
public function validate($items, Constraint $constraint) {
/** @var \Drupal\Core\Field\FieldItemListInterface $items */
/** @var \Drupal\user\UserInterface $account */
$account = $items->getEntity();
$existing_value = NULL;
if ($account->id()) {
$account_unchanged = \Drupal::entityManager()
->getStorage('user')
->loadUnchanged($account->id());
$existing_value = $account_unchanged->getEmail();
}
$required = !(!$existing_value && \Drupal::currentUser()->hasPermission('administer users'));
if ($required && (!isset($items) || $items->isEmpty())) {
$this->context->addViolation($this->message, array('!name' => SafeMarkup::placeholder($account->getFieldDefinition('mail')->getLabel())));
}
}
}

View file

@ -0,0 +1,30 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\Validation\Constraint\UserMailUnique.
*/
namespace Drupal\user\Plugin\Validation\Constraint;
use Symfony\Component\Validator\Constraint;
/**
* Checks if a user's email address is unique on the site.
*
* @Constraint(
* id = "UserMailUnique",
* label = @Translation("User email unique", context = "Validation")
* )
*/
class UserMailUnique extends Constraint {
public $message = 'The email address %value is already taken.';
/**
* {@inheritdoc}
*/
public function validatedBy() {
return '\Drupal\Core\Validation\Plugin\Validation\Constraint\UniqueFieldValueValidator';
}
}

View file

@ -0,0 +1,28 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\Validation\Constraint\UserNameConstraint.
*/
namespace Drupal\user\Plugin\Validation\Constraint;
use Symfony\Component\Validator\Constraint;
/**
* Checks if a value is a valid user name.
*
* @Constraint(
* id = "UserName",
* label = @Translation("User name", context = "Validation"),
* )
*/
class UserNameConstraint extends Constraint {
public $emptyMessage = 'You must enter a username.';
public $spaceBeginMessage = 'The username cannot begin with a space.';
public $spaceEndMessage = 'The username cannot end with a space.';
public $multipleSpacesMessage = 'The username cannot contain multiple spaces in a row.';
public $illegalMessage = 'The username contains an illegal character.';
public $tooLongMessage = 'The username %name is too long: it must be %max characters or less.';
}

View file

@ -0,0 +1,56 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\Validation\Constraint\UserNameConstraintValidator.
*/
namespace Drupal\user\Plugin\Validation\Constraint;
use Drupal\Component\Utility\Unicode;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
/**
* Validates the UserName constraint.
*/
class UserNameConstraintValidator extends ConstraintValidator {
/**
* {@inheritdoc}
*/
public function validate($items, Constraint $constraint) {
if (!isset($items) || !$items->value) {
$this->context->addViolation($constraint->emptyMessage);
return;
}
$name = $items->first()->value;
if (substr($name, 0, 1) == ' ') {
$this->context->addViolation($constraint->spaceBeginMessage);
}
if (substr($name, -1) == ' ') {
$this->context->addViolation($constraint->spaceEndMessage);
}
if (strpos($name, ' ') !== FALSE) {
$this->context->addViolation($constraint->multipleSpacesMessage);
}
if (preg_match('/[^\x{80}-\x{F7} a-z0-9@_.\'-]/i', $name)
|| preg_match(
'/[\x{80}-\x{A0}' . // Non-printable ISO-8859-1 + NBSP
'\x{AD}' . // Soft-hyphen
'\x{2000}-\x{200F}' . // Various space characters
'\x{2028}-\x{202F}' . // Bidirectional text overrides
'\x{205F}-\x{206F}' . // Various text hinting characters
'\x{FEFF}' . // Byte order mark
'\x{FF01}-\x{FF60}' . // Full-width latin
'\x{FFF9}-\x{FFFD}' . // Replacement characters
'\x{0}-\x{1F}]/u', // NULL byte and control characters
$name)
) {
$this->context->addViolation($constraint->illegalMessage);
}
if (Unicode::strlen($name) > USERNAME_MAX_LENGTH) {
$this->context->addViolation($constraint->tooLongMessage, array('%name' => $name, '%max' => USERNAME_MAX_LENGTH));
}
}
}

View file

@ -0,0 +1,30 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\Validation\Constraint\UserNameUnique.
*/
namespace Drupal\user\Plugin\Validation\Constraint;
use Symfony\Component\Validator\Constraint;
/**
* Checks if a user name is unique on the site.
*
* @Constraint(
* id = "UserNameUnique",
* label = @Translation("User name unique", context = "Validation"),
* )
*/
class UserNameUnique extends Constraint {
public $message = 'The username %value is already taken.';
/**
* {@inheritdoc}
*/
public function validatedBy() {
return '\Drupal\Core\Validation\Plugin\Validation\Constraint\UniqueFieldValueValidator';
}
}

View file

@ -0,0 +1,150 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\views\access\Permission.
*/
namespace Drupal\user\Plugin\views\access;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\user\PermissionHandlerInterface;
use Drupal\views\Plugin\CacheablePluginInterface;
use Drupal\views\Plugin\views\access\AccessPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Routing\Route;
/**
* Access plugin that provides permission-based access control.
*
* @ingroup views_access_plugins
*
* @ViewsAccess(
* id = "perm",
* title = @Translation("Permission"),
* help = @Translation("Access will be granted to users with the specified permission string.")
* )
*/
class Permission extends AccessPluginBase implements CacheablePluginInterface {
/**
* Overrides Drupal\views\Plugin\Plugin::$usesOptions.
*/
protected $usesOptions = TRUE;
/**
* The permission handler.
*
* @var \Drupal\user\PermissionHandlerInterface
*/
protected $permissionHandler;
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* Constructs a Permission object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\user\PermissionHandlerInterface $permission_handler
* The permission handler.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, PermissionHandlerInterface $permission_handler, ModuleHandlerInterface $module_handler) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->permissionHandler = $permission_handler;
$this->moduleHandler = $module_handler;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('user.permissions'),
$container->get('module_handler')
);
}
/**
* {@inheritdoc}
*/
public function access(AccountInterface $account) {
return $account->hasPermission($this->options['perm']);
}
/**
* {@inheritdoc}
*/
public function alterRouteDefinition(Route $route) {
$route->setRequirement('_permission', $this->options['perm']);
}
public function summaryTitle() {
$permissions = $this->permissionHandler->getPermissions();
if (isset($permissions[$this->options['perm']])) {
return $permissions[$this->options['perm']]['title'];
}
return $this->t($this->options['perm']);
}
protected function defineOptions() {
$options = parent::defineOptions();
$options['perm'] = array('default' => 'access content');
return $options;
}
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
parent::buildOptionsForm($form, $form_state);
// Get list of permissions
$perms = [];
$permissions = $this->permissionHandler->getPermissions();
foreach ($permissions as $perm => $perm_item) {
$provider = $perm_item['provider'];
$display_name = $this->moduleHandler->getName($provider);
$perms[$display_name][$perm] = SafeMarkup::checkPlain(strip_tags($perm_item['title']));
}
$form['perm'] = array(
'#type' => 'select',
'#options' => $perms,
'#title' => $this->t('Permission'),
'#default_value' => $this->options['perm'],
'#description' => $this->t('Only users with the selected permission flag will be able to access this display.'),
);
}
/**
* {@inheritdoc}
*/
public function isCacheable() {
return TRUE;
}
/**
* {@inheritdoc}
*/
public function getCacheContexts() {
return ['user.permissions'];
}
}

View file

@ -0,0 +1,164 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\views\access\Role.
*/
namespace Drupal\user\Plugin\views\access;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Form\FormStateInterface;
use Drupal\user\RoleStorageInterface;
use Drupal\views\Plugin\CacheablePluginInterface;
use Drupal\views\Plugin\views\access\AccessPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Routing\Route;
use Drupal\Core\Session\AccountInterface;
/**
* Access plugin that provides role-based access control.
*
* @ingroup views_access_plugins
*
* @ViewsAccess(
* id = "role",
* title = @Translation("Role"),
* help = @Translation("Access will be granted to users with any of the specified roles.")
* )
*/
class Role extends AccessPluginBase implements CacheablePluginInterface {
/**
* Overrides Drupal\views\Plugin\Plugin::$usesOptions.
*/
protected $usesOptions = TRUE;
/**
* The role storage.
*
* @var \Drupal\user\RoleStorageInterface
*/
protected $roleStorage;
/**
* Constructs a Role object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\user\RoleStorageInterface $role_storage
* The role storage.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, RoleStorageInterface $role_storage) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->roleStorage = $role_storage;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('entity.manager')->getStorage('user_role')
);
}
/**
* {@inheritdoc}
*/
public function access(AccountInterface $account) {
return array_intersect(array_filter($this->options['role']), $account->getRoles());
}
/**
* {@inheritdoc}
*/
public function alterRouteDefinition(Route $route) {
if ($this->options['role']) {
$route->setRequirement('_role', (string) implode('+', $this->options['role']));
}
}
public function summaryTitle() {
$count = count($this->options['role']);
if ($count < 1) {
return $this->t('No role(s) selected');
}
elseif ($count > 1) {
return $this->t('Multiple roles');
}
else {
$rids = user_role_names();
$rid = reset($this->options['role']);
return SafeMarkup::checkPlain($rids[$rid]);
}
}
protected function defineOptions() {
$options = parent::defineOptions();
$options['role'] = array('default' => array());
return $options;
}
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
parent::buildOptionsForm($form, $form_state);
$form['role'] = array(
'#type' => 'checkboxes',
'#title' => $this->t('Role'),
'#default_value' => $this->options['role'],
'#options' => array_map('\Drupal\Component\Utility\SafeMarkup::checkPlain', user_role_names()),
'#description' => $this->t('Only the checked roles will be able to access this display.'),
);
}
public function validateOptionsForm(&$form, FormStateInterface $form_state) {
$role = $form_state->getValue(array('access_options', 'role'));
$role = array_filter($role);
if (!$role) {
$form_state->setError($form['role'], $this->t('You must select at least one role if type is "by role"'));
}
$form_state->setValue(array('access_options', 'role'), $role);
}
/**
* {@inheritdoc}
*/
public function calculateDependencies() {
$dependencies = parent::calculateDependencies();
foreach (array_keys($this->options['role']) as $rid) {
if ($role = $this->roleStorage->load($rid)) {
$dependencies[$role->getConfigDependencyKey()][] = $role->getConfigDependencyName();
}
}
return $dependencies;
}
/**
* {@inheritdoc}
*/
public function isCacheable() {
return TRUE;
}
/**
* {@inheritdoc}
*/
public function getCacheContexts() {
return ['user.roles'];
}
}

View file

@ -0,0 +1,68 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\views\argument\RolesRid.
*/
namespace Drupal\user\Plugin\views\argument;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\views\Plugin\views\argument\ManyToOne;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Allow role ID(s) as argument.
*
* @ingroup views_argument_handlers
*
* @ViewsArgument("user__roles_rid")
*/
class RolesRid extends ManyToOne {
/**
* The role entity storage
*
* @var \Drupal\user\RoleStorage
*/
protected $roleStorage;
/**
* Constructs a \Drupal\user\Plugin\views\argument\RolesRid object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityManagerInterface $entity_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->roleStorage = $entity_manager->getStorage('user_role');
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return parent::create($container, $configuration, $plugin_id, $plugin_definition, $container->get('entity.manager'));
}
/**
* {@inheritdoc}
*/
public function title_query() {
$entities = $this->roleStorage->loadMultiple($this->value);
$titles = array();
foreach ($entities as $entity) {
$titles[] = SafeMarkup::checkPlain($entity->label());
}
return $titles;
}
}

View file

@ -0,0 +1,68 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\views\argument\Uid.
*/
namespace Drupal\user\Plugin\views\argument;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\views\Plugin\views\argument\NumericArgument;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Argument handler to accept a user id.
*
* @ingroup views_argument_handlers
*
* @ViewsArgument("user_uid")
*/
class Uid extends NumericArgument {
/**
* The user storage.
*
* @var \Drupal\Core\Entity\EntityStorageInterface
*/
protected $storage;
/**
* Constructs a Drupal\Component\Plugin\PluginBase object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Entity\EntityStorageInterface $storage
* The user storage.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityStorageInterface $storage) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->storage = $storage;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition,
$container->get('entity.manager')->getStorage('user'));
}
/**
* Override the behavior of title(). Get the name of the user.
*
* @return array
* A list of usernames.
*/
public function titleQuery() {
return array_map(function($account) {
return SafeMarkup::checkPlain($account->label());
}, $this->storage->loadMultiple($this->value));
}
}

View file

@ -0,0 +1,43 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\views\argument_default\CurrentUser.
*/
namespace Drupal\user\Plugin\views\argument_default;
use Drupal\views\Plugin\CacheablePluginInterface;
use Drupal\views\Plugin\views\argument_default\ArgumentDefaultPluginBase;
/**
* Default argument plugin to extract the current user
*
* This plugin actually has no options so it odes not need to do a great deal.
*
* @ViewsArgumentDefault(
* id = "current_user",
* title = @Translation("User ID from logged in user")
* )
*/
class CurrentUser extends ArgumentDefaultPluginBase implements CacheablePluginInterface {
public function getArgument() {
return \Drupal::currentUser()->id();
}
/**
* {@inheritdoc}
*/
public function isCacheable() {
return TRUE;
}
/**
* {@inheritdoc}
*/
public function getCacheContexts() {
return ['user'];
}
}

View file

@ -0,0 +1,122 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\views\argument_default\User.
*/
namespace Drupal\user\Plugin\views\argument_default;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\views\Plugin\CacheablePluginInterface;
use Drupal\views\Plugin\views\argument_default\ArgumentDefaultPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Drupal\user\UserInterface;
use Drupal\node\NodeInterface;
/**
* Default argument plugin to extract a user from request.
*
* @ViewsArgumentDefault(
* id = "user",
* title = @Translation("User ID from route context")
* )
*/
class User extends ArgumentDefaultPluginBase implements CacheablePluginInterface {
/**
* The route match.
*
* @var \Drupal\Core\Routing\RouteMatchInterface
*/
protected $routeMatch;
/**
* Constructs a new User instance.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteMatchInterface $route_match) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->routeMatch = $route_match;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('current_route_match')
);
}
/**
* {@inheritdoc}
*/
protected function defineOptions() {
$options = parent::defineOptions();
$options['user'] = array('default' => '');
return $options;
}
/**
* {@inheritdoc}
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
$form['user'] = array(
'#type' => 'checkbox',
'#title' => $this->t('Also look for a node and use the node author'),
'#default_value' => $this->options['user'],
);
}
/**
* {@inheritdoc}
*/
public function getArgument() {
// If there is a user object in the current route.
if ($user = $this->routeMatch->getParameter('user')) {
if ($user instanceof UserInterface) {
return $user->id();
}
}
// If option to use node author; and node in current route.
if (!empty($this->options['user']) && $node = $this->routeMatch->getParameter('node')) {
if ($node instanceof NodeInterface) {
return $node->getOwnerId();
}
}
}
/**
* {@inheritdoc}
*/
public function isCacheable() {
return TRUE;
}
/**
* {@inheritdoc}
*/
public function getCacheContexts() {
return ['url'];
}
}

View file

@ -0,0 +1,118 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\views\argument_validator\User.
*/
namespace Drupal\user\Plugin\views\argument_validator;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\views\Plugin\views\argument\ArgumentPluginBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\views\Plugin\views\argument_validator\Entity;
/**
* Validate whether an argument is a valid user.
*
* This supports either numeric arguments (UID) or strings (username) and
* converts either one into the user's UID. This validator also sets the
* argument's title to the username.
*/
class User extends Entity {
/**
* The user storage.
*
* @var \Drupal\Core\Entity\EntityStorageInterface
*/
protected $userStorage;
/**
* {@inheritdoc}
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityManagerInterface $entity_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_manager);
$this->userStorage = $entity_manager->getStorage('user');
}
/**
* {@inheritdoc}
*/
protected function defineOptions() {
$options = parent::defineOptions();
$options['restrict_roles'] = array('default' => FALSE);
$options['roles'] = array('default' => array());
return $options;
}
/**
* {@inheritdoc}
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
parent::buildOptionsForm($form, $form_state);
$sanitized_id = ArgumentPluginBase::encodeValidatorId($this->definition['id']);
$form['restrict_roles'] = array(
'#type' => 'checkbox',
'#title' => $this->t('Restrict user based on role'),
'#default_value' => $this->options['restrict_roles'],
);
$form['roles'] = array(
'#type' => 'checkboxes',
'#title' => $this->t('Restrict to the selected roles'),
'#options' => array_map(array('\Drupal\Component\Utility\SafeMarkup', 'checkPlain'), user_role_names(TRUE)),
'#default_value' => $this->options['roles'],
'#description' => $this->t('If no roles are selected, users from any role will be allowed.'),
'#states' => array(
'visible' => array(
':input[name="options[validate][options][' . $sanitized_id . '][restrict_roles]"]' => array('checked' => TRUE),
),
),
);
}
/**
* {@inheritdoc}
*/
public function submitOptionsForm(&$form, FormStateInterface $form_state, &$options = array()) {
// filter trash out of the options so we don't store giant unnecessary arrays
$options['roles'] = array_filter($options['roles']);
}
/**
* {@inheritdoc}
*/
protected function validateEntity(EntityInterface $entity) {
/** @var \Drupal\user\UserInterface $entity */
$role_check_success = TRUE;
// See if we're filtering users based on roles.
if (!empty($this->options['restrict_roles']) && !empty($this->options['roles'])) {
$roles = $this->options['roles'];
if (!(bool) array_intersect($entity->getRoles(), $roles)) {
$role_check_success = FALSE;
}
}
return $role_check_success && parent::validateEntity($entity);
}
/**
* {@inheritdoc}
*/
public function calculateDependencies() {
$dependencies = parent::calculateDependencies();
foreach ($this->entityManager->getStorage('user_role')->loadMultiple(array_keys($this->options['roles'])) as $role) {
$dependencies[$role->getConfigDependencyKey()][] = $role->getConfigDependencyName();
}
return $dependencies;
}
}

View file

@ -0,0 +1,85 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\views\argument_validator\UserName.
*/
namespace Drupal\user\Plugin\views\argument_validator;
use Drupal\Core\Form\FormStateInterface;
/**
* Validates whether a user name is valid.
*
* @ViewsArgumentValidator(
* id = "user_name",
* title = @Translation("User name"),
* entity_type = "user"
* )
*/
class UserName extends User {
/**
* {@inheritdoc}
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
parent::buildOptionsForm($form, $form_state);
$entity_type = $this->entityManager->getDefinition('user');
$form['multiple']['#options'] = array(
0 => $this->t('Single name', array('%type' => $entity_type->getLabel())),
1 => $this->t('One or more names separated by , or +', array('%type' => $entity_type->getLabel())),
);
}
/**
* {@inheritdoc}
*/
public function validateArgument($argument) {
if ($this->multipleCapable && $this->options['multiple']) {
// At this point only interested in individual IDs no matter what type,
// just splitting by the allowed delimiters.
$names = array_filter(preg_split('/[,+ ]/', $argument));
}
elseif ($argument) {
$names = array($argument);
}
// No specified argument should be invalid.
else {
return FALSE;
}
$accounts = $this->userStorage->loadByProperties(array('name' => $names));
// If there are no accounts, return FALSE now. As we will not enter the
// loop below otherwise.
if (empty($accounts)) {
return FALSE;
}
// Validate each account. If any fails break out and return false.
foreach ($accounts as $account) {
if (!in_array($account->getUserName(), $names) || !$this->validateEntity($account)) {
return FALSE;
}
}
return TRUE;
}
/**
* {@inheritdoc}
*/
public function processSummaryArguments(&$args) {
// If the validation says the input is an username, we should reverse the
// argument so it works for example for generation summary urls.
$uids_arg_keys = array_flip($args);
foreach ($this->userStorage->loadMultiple($args) as $uid => $account) {
$args[$uids_arg_keys[$uid]] = $account->label();
}
}
}

View file

@ -0,0 +1,132 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\views\field\Permissions.
*/
namespace Drupal\user\Plugin\views\field;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\views\Plugin\views\display\DisplayPluginBase;
use Drupal\views\ViewExecutable;
use Drupal\views\Plugin\views\field\PrerenderList;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Field handler to provide a list of permissions.
*
* @ingroup views_field_handlers
*
* @ViewsField("user_permissions")
*/
class Permissions extends PrerenderList {
/**
* The role storage.
*
* @var \Drupal\user\RoleStorageInterface
*/
protected $roleStorage;
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* Constructs a Drupal\Component\Plugin\PluginBase object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, ModuleHandlerInterface $module_handler, EntityManagerInterface $entity_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->roleStorage = $entity_manager->getStorage('user_role');
$this->moduleHandler = $module_handler;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container->get('module_handler'), $container->get('entity.manager'));
}
/**
* Overrides Drupal\views\Plugin\views\field\FieldPluginBase::init().
*/
public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
parent::init($view, $display, $options);
$this->additional_fields['uid'] = array('table' => 'users_field_data', 'field' => 'uid');
}
public function query() {
$this->addAdditionalFields();
$this->field_alias = $this->aliases['uid'];
}
public function preRender(&$values) {
$uids = array();
$this->items = array();
$permission_names = \Drupal::service('user.permissions')->getPermissions();
$rids = array();
foreach ($values as $result) {
$user_rids = $this->getEntity($result)->getRoles();
$uid = $this->getValue($result);
foreach ($user_rids as $rid) {
$rids[$rid][] = $uid;
}
}
if ($rids) {
$roles = $this->roleStorage->loadMultiple(array_keys($rids));
foreach ($rids as $rid => $role_uids) {
foreach ($roles[$rid]->getPermissions() as $permission) {
foreach ($role_uids as $uid) {
$this->items[$uid][$permission]['permission'] = $permission_names[$permission]['title'];
}
}
}
foreach ($uids as $uid) {
if (isset($this->items[$uid])) {
ksort($this->items[$uid]);
}
}
}
}
function render_item($count, $item) {
return $item['permission'];
}
/*
protected function documentSelfTokens(&$tokens) {
$tokens['[' . $this->options['id'] . '-role' . ']'] = $this->t('The name of the role.');
$tokens['[' . $this->options['id'] . '-rid' . ']'] = $this->t('The role ID of the role.');
}
protected function addSelfTokens(&$tokens, $item) {
$tokens['[' . $this->options['id'] . '-role' . ']'] = $item['role'];
$tokens['[' . $this->options['id'] . '-rid' . ']'] = $item['rid'];
}
*/
}

View file

@ -0,0 +1,115 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\views\field\Roles.
*/
namespace Drupal\user\Plugin\views\field;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Database\Connection;
use Drupal\views\Plugin\views\display\DisplayPluginBase;
use Drupal\views\ViewExecutable;
use Drupal\views\Plugin\views\field\PrerenderList;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Field handler to provide a list of roles.
*
* @ingroup views_field_handlers
*
* @ViewsField("user_roles")
*/
class Roles extends PrerenderList {
/**
* Database Service Object.
*
* @var \Drupal\Core\Database\Connection
*/
protected $database;
/**
* Constructs a Drupal\Component\Plugin\PluginBase object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Database\Connection $database
* Database Service Object.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, Connection $database) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->database = $database;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container->get('database'));
}
/**
* Overrides Drupal\views\Plugin\views\field\FieldPluginBase::init().
*/
public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
parent::init($view, $display, $options);
$this->additional_fields['uid'] = array('table' => 'users_field_data', 'field' => 'uid');
}
public function query() {
$this->addAdditionalFields();
$this->field_alias = $this->aliases['uid'];
}
public function preRender(&$values) {
$uids = array();
$this->items = array();
foreach ($values as $result) {
$uids[] = $this->getValue($result);
}
if ($uids) {
$roles = user_roles();
$result = $this->database->query('SELECT u.entity_id as uid, u.roles_target_id as rid FROM {user__roles} u WHERE u.entity_id IN ( :uids[] ) AND u.roles_target_id IN ( :rids[] )', array(':uids[]' => $uids, ':rids[]' => array_keys($roles)));
foreach ($result as $role) {
$this->items[$role->uid][$role->rid]['role'] = SafeMarkup::checkPlain($roles[$role->rid]->label());
$this->items[$role->uid][$role->rid]['rid'] = $role->rid;
}
// Sort the roles for each user by role weight.
$ordered_roles = array_flip(array_keys($roles));
foreach ($this->items as &$user_roles) {
// Create an array of rids that the user has in the role weight order.
$sorted_keys = array_intersect_key($ordered_roles, $user_roles);
// Merge with the unsorted array of role information which has the
// effect of sorting it.
$user_roles = array_merge($sorted_keys, $user_roles);
}
}
}
function render_item($count, $item) {
return $item['role'];
}
protected function documentSelfTokens(&$tokens) {
$tokens['[' . $this->options['id'] . '-role' . ']'] = $this->t('The name of the role.');
$tokens['[' . $this->options['id'] . '-rid' . ']'] = $this->t('The role machine-name of the role.');
}
protected function addSelfTokens(&$tokens, $item) {
if (!empty($item['role'])) {
$tokens['[' . $this->options['id'] . '-role' . ']'] = $item['role'];
$tokens['[' . $this->options['id'] . '-rid' . ']'] = $item['rid'];
}
}
}

View file

@ -0,0 +1,47 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\views\field\UserBulkForm.
*/
namespace Drupal\user\Plugin\views\field;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\system\Plugin\views\field\BulkForm;
use Drupal\user\UserInterface;
/**
* Defines a user operations bulk form element.
*
* @ViewsField("user_bulk_form")
*/
class UserBulkForm extends BulkForm {
/**
* {@inheritdoc}
*
* Provide a more useful title to improve the accessibility.
*/
public function viewsForm(&$form, FormStateInterface $form_state) {
parent::viewsForm($form, $form_state);
if (!empty($this->view->result)) {
foreach ($this->view->result as $row_index => $result) {
$account = $result->_entity;
if ($account instanceof UserInterface) {
$form[$this->options['id']][$row_index]['#title'] = $this->t('Update the user %name', array('%name' => $account->label()));
}
}
}
}
/**
* {@inheritdoc}
*/
protected function emptySelectedMessage() {
return $this->t('No users selected.');
}
}

View file

@ -0,0 +1,115 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\views\field\UserData.
*/
namespace Drupal\user\Plugin\views\field;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\views\Plugin\views\display\DisplayPluginBase;
use Drupal\views\Plugin\views\field\FieldPluginBase;
use Drupal\views\ResultRow;
use Drupal\views\ViewExecutable;
use Drupal\user\UserDataInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides access to the user data service.
*
* @ingroup views_field_handlers
*
* @see \Drupal\user\UserDataInterface
*
* @ViewsField("user_data")
*/
class UserData extends FieldPluginBase {
/**
* Provides the user data service object.
*
* @var \Drupal\user\UserDataInterface
*/
protected $userData;
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container->get('user.data'), $container->get('module_handler'));
}
/**
* Constructs a UserData object.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, UserDataInterface $user_data, ModuleHandlerInterface $module_handler) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->userData = $user_data;
$this->moduleHandler = $module_handler;
}
/**
* {@inheritdoc}
*/
protected function defineOptions() {
$options = parent::defineOptions();
$options['data_module'] = array('default' => '');
$options['data_name'] = array('default' => '');
return $options;
}
/**
* {@inheritdoc}
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
parent::buildOptionsForm($form, $form_state);
$modules = $this->moduleHandler->getModuleList();
$names = array();
foreach (array_keys($modules) as $name) {
$names[$name] = $this->moduleHandler->getName($name);
}
$form['data_module'] = array(
'#title' => $this->t('Module name'),
'#type' => 'select',
'#description' => $this->t('The module which sets this user data.'),
'#default_value' => $this->options['data_module'],
'#options' => $names,
);
$form['data_name'] = array(
'#title' => $this->t('Name'),
'#type' => 'textfield',
'#description' => $this->t('The name of the data key.'),
'#default_value' => $this->options['data_name'],
);
}
/**
* {@inheritdoc}
*/
public function render(ResultRow $values) {
$uid = $this->getValue($values);
$data = $this->userData->get($this->options['data_module'], $uid, $this->options['data_name']);
// Don't sanitize if no value was found.
if (isset($data)) {
return $this->sanitizeValue($data);
}
}
}

View file

@ -0,0 +1,62 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\views\filter\Current.
*/
namespace Drupal\user\Plugin\views\filter;
use Drupal\views\Plugin\views\display\DisplayPluginBase;
use Drupal\views\ViewExecutable;
use Drupal\views\Plugin\views\filter\BooleanOperator;
/**
* Filter handler for the current user.
*
* @ingroup views_filter_handlers
*
* @ViewsFilter("user_current")
*/
class Current extends BooleanOperator {
/**
* Overrides Drupal\views\Plugin\views\filter\BooleanOperator::init().
*/
public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
parent::init($view, $display, $options);
$this->value_value = $this->t('Is the logged in user');
}
public function query() {
$this->ensureMyTable();
$field = $this->tableAlias . '.' . $this->realField . ' ';
$or = db_or();
if (empty($this->value)) {
$or->condition($field, '***CURRENT_USER***', '<>');
if ($this->accept_null) {
$or->isNull($field);
}
}
else {
$or->condition($field, '***CURRENT_USER***', '=');
}
$this->query->addWhere($this->options['group'], $or);
}
/**
* {@inheritdoc}
*/
public function getCacheContexts() {
$contexts = parent::getCacheContexts();
// This filter depends on the current user.
$contexts[] = 'user';
return $contexts;
}
}

View file

@ -0,0 +1,127 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\views\filter\Name.
*/
namespace Drupal\user\Plugin\views\filter;
use Drupal\Component\Utility\Tags;
use Drupal\Core\Entity\Element\EntityAutocomplete;
use Drupal\Core\Form\FormStateInterface;
use Drupal\user\Entity\User;
use Drupal\views\Plugin\views\filter\InOperator;
/**
* Filter handler for usernames.
*
* @ingroup views_filter_handlers
*
* @ViewsFilter("user_name")
*/
class Name extends InOperator {
protected $alwaysMultiple = TRUE;
protected function valueForm(&$form, FormStateInterface $form_state) {
$users = $this->value ? User::loadMultiple($this->value) : array();
$default_value = EntityAutocomplete::getEntityLabels($users);
$form['value'] = array(
'#type' => 'entity_autocomplete',
'#title' => $this->t('Usernames'),
'#description' => $this->t('Enter a comma separated list of user names.'),
'#target_type' => 'user',
'#tags' => TRUE,
'#default_value' => $default_value,
'#process_default_value' => FALSE,
);
$user_input = $form_state->getUserInput();
if ($form_state->get('exposed') && !isset($user_input[$this->options['expose']['identifier']])) {
$user_input[$this->options['expose']['identifier']] = $default_value;
$form_state->setUserInput($user_input);
}
}
protected function valueValidate($form, FormStateInterface $form_state) {
$uids = [];
if ($values = $form_state->getValue(array('options', 'value'))) {
foreach ($values as $value) {
$uids[] = $value['target_id'];
}
sort($uids);
}
$form_state->setValue(array('options', 'value'), $uids);
}
public function acceptExposedInput($input) {
$rc = parent::acceptExposedInput($input);
if ($rc) {
// If we have previously validated input, override.
if (isset($this->validated_exposed_input)) {
$this->value = $this->validated_exposed_input;
}
}
return $rc;
}
public function validateExposed(&$form, FormStateInterface $form_state) {
if (empty($this->options['exposed'])) {
return;
}
if (empty($this->options['expose']['identifier'])) {
return;
}
$identifier = $this->options['expose']['identifier'];
$input = $form_state->getValue($identifier);
if ($this->options['is_grouped'] && isset($this->options['group_info']['group_items'][$input])) {
$this->operator = $this->options['group_info']['group_items'][$input]['operator'];
$input = $this->options['group_info']['group_items'][$input]['value'];
}
$uids = [];
$values = $form_state->getValue($identifier);
if ($values && (!$this->options['is_grouped'] || ($this->options['is_grouped'] && ($input != 'All')))) {
foreach ($values as $value) {
$uids[] = $value['target_id'];
}
}
if ($uids) {
$this->validated_exposed_input = $uids;
}
}
protected function valueSubmit($form, FormStateInterface $form_state) {
// prevent array filter from removing our anonymous user.
}
// Override to do nothing.
public function getValueOptions() { }
public function adminSummary() {
// set up $this->valueOptions for the parent summary
$this->valueOptions = array();
if ($this->value) {
$result = entity_load_multiple_by_properties('user', array('uid' => $this->value));
foreach ($result as $account) {
if ($account->id()) {
$this->valueOptions[$account->id()] = $account->label();
}
else {
$this->valueOptions[$account->id()] = 'Anonymous'; // Intentionally NOT translated.
}
}
}
return parent::adminSummary();
}
}

View file

@ -0,0 +1,108 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\views\filter\Permissions.
*/
namespace Drupal\user\Plugin\views\filter;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\user\PermissionHandlerInterface;
use Drupal\views\Plugin\views\filter\ManyToOne;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Filter handler for user roles.
*
* @ingroup views_filter_handlers
*
* @ViewsFilter("user_permissions")
*/
class Permissions extends ManyToOne {
/**
* The permission handler.
*
* @var \Drupal\user\PermissionHandlerInterface
*/
protected $permissionHandler;
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* Constructs a Permissions object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\user\PermissionHandlerInterface $permission_handler
* The permission handler.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, PermissionHandlerInterface $permission_handler, ModuleHandlerInterface $module_handler) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->permissionHandler = $permission_handler;
$this->moduleHandler = $module_handler;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('user.permissions'),
$container->get('module_handler')
);
}
public function getValueOptions() {
if (!isset($this->valueOptions)) {
$permissions = $this->permissionHandler->getPermissions();
foreach ($permissions as $perm => $perm_item) {
$provider = $perm_item['provider'];
$display_name = $this->moduleHandler->getName($provider);
$this->valueOptions[$display_name][$perm] = SafeMarkup::checkPlain(strip_tags($perm_item['title']));
}
}
else {
return $this->valueOptions;
}
}
/**
* {@inheritdoc}
*
* Replace the configured permission with a filter by all roles that have this
* permission.
*/
public function query() {
// @todo user_role_names() should maybe support multiple permissions.
$rids = array();
// Get all roles, that have the configured permissions.
foreach ($this->value as $permission) {
$roles = user_role_names(FALSE, $permission);
$rids += array_keys($roles);
}
$rids = array_unique($rids);
$this->value = $rids;
// $this->value contains the role IDs that have the configured permission.
parent::query();
}
}

View file

@ -0,0 +1,87 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\views\filter\Roles.
*/
namespace Drupal\user\Plugin\views\filter;
use Drupal\user\RoleInterface;
use Drupal\user\RoleStorageInterface;
use Drupal\views\Plugin\views\filter\ManyToOne;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Filter handler for user roles.
*
* @ingroup views_filter_handlers
*
* @ViewsFilter("user_roles")
*/
class Roles extends ManyToOne {
/**
* The role storage.
*
* @var \Drupal\user\RoleStorageInterface
*/
protected $roleStorage;
/**
* Constructs a Roles object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\user\RoleStorageInterface $role_storage
* The role storage.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, RoleStorageInterface $role_storage) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->roleStorage = $role_storage;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('entity.manager')->getStorage('user_role')
);
}
public function getValueOptions() {
$this->valueOptions = user_role_names(TRUE);
unset($this->valueOptions[RoleInterface::AUTHENTICATED_ID]);
}
/**
* Override empty and not empty operator labels to be clearer for user roles.
*/
function operators() {
$operators = parent::operators();
$operators['empty']['title'] = $this->t("Only has the 'authenticated user' role");
$operators['not empty']['title'] = $this->t("Has roles in addition to 'authenticated user'");
return $operators;
}
/**
* {@inheritdoc}
*/
public function calculateDependencies() {
$dependencies = array();
foreach ($this->value as $role_id) {
$role = $this->roleStorage->load($role_id);
$dependencies[$role->getConfigDependencyKey()][] = $role->getConfigDependencyName();
}
return $dependencies;
}
}

View file

@ -0,0 +1,33 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\views\row\UserRow.
*/
namespace Drupal\user\Plugin\views\row;
use Drupal\views\Plugin\views\row\EntityRow;
/**
* A row plugin which renders a user.
*
* @ingroup views_row_plugins
*
* @ViewsRow(
* id = "entity:user",
* )
*/
class UserRow extends EntityRow {
/**
* {@inheritdoc}
*/
protected function defineOptions() {
$options = parent::defineOptions();
$options['view_mode']['default'] = 'full';
return $options;
}
}

View file

@ -0,0 +1,81 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\views\wizard\Users.
*/
namespace Drupal\user\Plugin\views\wizard;
use Drupal\views\Plugin\views\wizard\WizardPluginBase;
/**
* @todo: replace numbers with constants.
*/
/**
* Tests creating user views with the wizard.
*
* @ViewsWizard(
* id = "users",
* base_table = "users_field_data",
* title = @Translation("Users")
* )
*/
class Users extends WizardPluginBase {
/**
* Set the created column.
*/
protected $createdColumn = 'created';
/**
* Set default values for the filters.
*/
protected $filters = array(
'status' => array(
'value' => TRUE,
'table' => 'users_field_data',
'field' => 'status',
'plugin_id' => 'boolean',
'entity_type' => 'user',
'entity_field' => 'status',
)
);
/**
* Overrides Drupal\views\Plugin\views\wizard\WizardPluginBase::defaultDisplayOptions().
*/
protected function defaultDisplayOptions() {
$display_options = parent::defaultDisplayOptions();
// Add permission-based access control.
$display_options['access']['type'] = 'perm';
$display_options['access']['options']['perm'] = 'access user profiles';
// Remove the default fields, since we are customizing them here.
unset($display_options['fields']);
/* Field: User: Name */
$display_options['fields']['name']['id'] = 'name';
$display_options['fields']['name']['table'] = 'users_field_data';
$display_options['fields']['name']['field'] = 'name';
$display_options['fields']['name']['entity_type'] = 'user';
$display_options['fields']['name']['entity_field'] = 'name';
$display_options['fields']['name']['label'] = '';
$display_options['fields']['name']['alter']['alter_text'] = 0;
$display_options['fields']['name']['alter']['make_link'] = 0;
$display_options['fields']['name']['alter']['absolute'] = 0;
$display_options['fields']['name']['alter']['trim'] = 0;
$display_options['fields']['name']['alter']['word_boundary'] = 0;
$display_options['fields']['name']['alter']['ellipsis'] = 0;
$display_options['fields']['name']['alter']['strip_tags'] = 0;
$display_options['fields']['name']['alter']['html'] = 0;
$display_options['fields']['name']['hide_empty'] = 0;
$display_options['fields']['name']['empty_zero'] = 0;
$display_options['fields']['name']['plugin_id'] = 'field';
return $display_options;
}
}