Issue #1479454 by Hugo Wetterberg, galooph, dawehner, andypost, marcingy, heyrocker...
[project/drupal.git] / core / modules / user / lib / Drupal / user / Plugin / views / argument_validator / User.php
1 <?php
2
3 /**
4 * @file
5 * Definition of Drupal\user\Plugin\views\argument_validator\User.
6 */
7
8 namespace Drupal\user\Plugin\views\argument_validator;
9
10 use Drupal\Core\Annotation\Plugin;
11 use Drupal\Core\Annotation\Translation;
12 use Drupal\views\Plugin\views\argument_validator\ArgumentValidatorPluginBase;
13
14 /**
15 * Validate whether an argument is a valid user.
16 *
17 * This supports either numeric arguments (UID) or strings (username) and
18 * converts either one into the user's UID. This validator also sets the
19 * argument's title to the username.
20 *
21 * @Plugin(
22 * id = "user",
23 * module = "user",
24 * title = @Translation("User")
25 * )
26 */
27 class User extends ArgumentValidatorPluginBase {
28
29 protected function defineOptions() {
30 $options = parent::defineOptions();
31 $options['type'] = array('default' => 'uid');
32 $options['restrict_roles'] = array('default' => FALSE, 'bool' => TRUE);
33 $options['roles'] = array('default' => array());
34
35 return $options;
36 }
37
38 public function buildOptionsForm(&$form, &$form_state) {
39 $form['type'] = array(
40 '#type' => 'radios',
41 '#title' => t('Type of user filter value to allow'),
42 '#options' => array(
43 'uid' => t('Only allow numeric UIDs'),
44 'name' => t('Only allow string usernames'),
45 'either' => t('Allow both numeric UIDs and string usernames'),
46 ),
47 '#default_value' => $this->options['type'],
48 );
49
50 $form['restrict_roles'] = array(
51 '#type' => 'checkbox',
52 '#title' => t('Restrict user based on role'),
53 '#default_value' => $this->options['restrict_roles'],
54 );
55
56 $form['roles'] = array(
57 '#type' => 'checkboxes',
58 '#title' => t('Restrict to the selected roles'),
59 '#options' => array_map('check_plain', user_role_names(TRUE)),
60 '#default_value' => $this->options['roles'],
61 '#description' => t('If no roles are selected, users from any role will be allowed.'),
62 '#states' => array(
63 'visible' => array(
64 ':input[name="options[validate][options][user][restrict_roles]"]' => array('checked' => TRUE),
65 ),
66 ),
67 );
68 }
69
70 public function submitOptionsForm(&$form, &$form_state, &$options = array()) {
71 // filter trash out of the options so we don't store giant unnecessary arrays
72 $options['roles'] = array_filter($options['roles']);
73 }
74
75 function validate_argument($argument) {
76 $type = $this->options['type'];
77 // is_numeric() can return false positives, so we ensure it's an integer.
78 // However, is_integer() will always fail, since $argument is a string.
79 if (is_numeric($argument) && $argument == (int)$argument) {
80 if ($type == 'uid' || $type == 'either') {
81 if ($argument == $GLOBALS['user']->uid) {
82 // If you assign an object to a variable in PHP, the variable
83 // automatically acts as a reference, not a copy, so we use
84 // clone to ensure that we don't actually mess with the
85 // real global $user object.
86 $account = clone $GLOBALS['user'];
87 }
88 $condition = 'uid';
89 }
90 }
91 else {
92 if ($type == 'name' || $type == 'either') {
93 $name = !empty($GLOBALS['user']->name) ? $GLOBALS['user']->name : config('user.settings')->get('anonymous');
94 if ($argument == $name) {
95 $account = clone $GLOBALS['user'];
96 }
97 $condition = 'name';
98 }
99 }
100
101 // If we don't have a WHERE clause, the argument is invalid.
102 if (empty($condition)) {
103 return FALSE;
104 }
105
106 if (!isset($account)) {
107 $account = db_select('users', 'u')
108 ->fields('u', array('uid', 'name'))
109 ->condition($condition, $argument)
110 ->execute()
111 ->fetchObject();
112 }
113 if (empty($account)) {
114 // User not found.
115 return FALSE;
116 }
117
118 // See if we're filtering users based on roles.
119 if (!empty($this->options['restrict_roles']) && !empty($this->options['roles'])) {
120 $roles = $this->options['roles'];
121 $account->roles = array();
122 $account->roles[] = $account->uid ? DRUPAL_AUTHENTICATED_RID : DRUPAL_ANONYMOUS_RID;
123 $query = db_select('users_roles', 'u');
124 $query->addField('u', 'rid');
125 $query->condition('u.uid', $account->uid);
126 $result = $query->execute();
127 foreach ($result as $role) {
128 $account->roles[] = $role->rid;
129 }
130 if (!(bool) array_intersect($account->roles, $roles)) {
131 return FALSE;
132 }
133 }
134
135 $this->argument->argument = $account->uid;
136 $this->argument->validated_title = check_plain(user_format_name($account));
137 return TRUE;
138 }
139
140 function process_summary_arguments(&$args) {
141 // If the validation says the input is an username, we should reverse the
142 // argument so it works for example for generation summary urls.
143 $uids_arg_keys = array_flip($args);
144 if ($this->options['type'] == 'name') {
145 $users = user_load_multiple($args);
146 foreach ($users as $uid => $account) {
147 $args[$uids_arg_keys[$uid]] = $account->name;
148 }
149 }
150 }
151
152 }