Projet

Général

Profil

Paste
Télécharger (42 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / ldap / ldap_user / LdapUserConfAdmin.class.php @ 91af538d

1 85ad3d82 Assos Assos
<?php
2
3
/**
4
 * @file
5 32700c57 Assos Assos
 * This classextends by LdapUserConf for configuration and other admin functions.
6 85ad3d82 Assos Assos
 */
7
8
module_load_include('php', 'ldap_user', 'LdapUserConf.class');
9
module_load_include('inc', 'user', 'user.pages');
10 32700c57 Assos Assos
/**
11
 *
12
 */
13 85ad3d82 Assos Assos
class LdapUserConfAdmin extends LdapUserConf {
14
15
  /**
16 32700c57 Assos Assos
   * Basic settings.
17 85ad3d82 Assos Assos
   */
18
19
  protected $drupalAcctProvisionServerDescription;
20 32700c57 Assos Assos
  protected $drupalAcctProvisionServerOptions = [];
21
  protected $ldapEntryProvisionServerOptions = [];
22 85ad3d82 Assos Assos
23
  protected $drupalAccountProvisionEventsDescription;
24 32700c57 Assos Assos
  protected $drupalAccountProvisionEventsOptions = [];
25 85ad3d82 Assos Assos
26
  protected $ldapEntryProvisionTriggersDescription;
27 32700c57 Assos Assos
  protected $ldapEntryProvisionTriggersOptions = [];
28 85ad3d82 Assos Assos
29
  protected $synchFormRow = 0;
30
31 32700c57 Assos Assos
  /**
32
   * 3. Drupal Account Provisioning and Syncing.
33 85ad3d82 Assos Assos
   */
34 32700c57 Assos Assos
35 85ad3d82 Assos Assos
  public $userConflictResolveDescription;
36
  public $userConflictResolveDefault = LDAP_USER_CONFLICT_RESOLVE_DEFAULT;
37
  public $userConflictOptions;
38
39 b42754b9 Assos Assos
  public $accountsWithSameEmailDescription;
40
  public $accountsWithSameEmailOptions;
41
42 85ad3d82 Assos Assos
  public $acctCreationDescription = '';
43
  public $acctCreationDefault = LDAP_USER_ACCT_CREATION_LDAP_BEHAVIOR_DEFAULT;
44
  public $acctCreationOptions;
45
46
47
  public $errorMsg = NULL;
48
  public $hasError = FALSE;
49
  public $errorName = NULL;
50
51 32700c57 Assos Assos
  /**
52
   *
53
   */
54 85ad3d82 Assos Assos
  public function clearError() {
55
    $this->hasError = FALSE;
56
    $this->errorMsg = NULL;
57
    $this->errorName = NULL;
58
  }
59
60 32700c57 Assos Assos
  /**
61
   *
62
   */
63 85ad3d82 Assos Assos
  public function save() {
64
    foreach ($this->saveable as $property) {
65
      $save[$property] = $this->{$property};
66
    }
67
    variable_set('ldap_user_conf', $save);
68
    ldap_user_conf_cache_clear();
69
  }
70
71 32700c57 Assos Assos
  /**
72
   *
73
   */
74
  public static function uninstall() {
75 85ad3d82 Assos Assos
    variable_del('ldap_user_conf');
76
  }
77
78 32700c57 Assos Assos
  /**
79
   *
80
   */
81 85ad3d82 Assos Assos
  public function __construct() {
82
    parent::__construct();
83
    $this->setTranslatableProperties();
84
85
    if ($servers = ldap_servers_get_servers(NULL, 'enabled')) {
86
      $this->drupalAcctProvisionServerOptions[LDAP_USER_AUTH_SERVER_SID] = t('Use server which performed the authentication. Useful for multi-domain environments.');
87
      foreach ($servers as $sid => $ldap_server) {
88
        $enabled = ($ldap_server->status) ? 'Enabled' : 'Disabled';
89
        $this->drupalAcctProvisionServerOptions[$sid] = $ldap_server->name . ' (' . $ldap_server->address . ') Status: ' . $enabled;
90
        $this->ldapEntryProvisionServerOptions[$sid] = $ldap_server->name . ' (' . $ldap_server->address . ') Status: ' . $enabled;
91
      }
92
    }
93
    $this->drupalAcctProvisionServerOptions['none'] = t('None');
94
    $this->ldapEntryProvisionServerOptions['none'] = t('None');
95
96
  }
97
98 32700c57 Assos Assos
  /**
99
   * Generate admin form for ldapUserConf object.
100
   *
101
   * @return array $form as drupal form api form array
102
   */
103 85ad3d82 Assos Assos
  public function drupalForm() {
104
    if (count($this->drupalAcctProvisionServerOptions) == 0) {
105
      $message = ldap_servers_no_enabled_servers_msg('configure LDAP User');
106 32700c57 Assos Assos
      $form['intro'] = [
107 85ad3d82 Assos Assos
        '#type' => 'item',
108
        '#markup' => t('<h1>LDAP User Settings</h1>') . $message,
109 32700c57 Assos Assos
      ];
110 85ad3d82 Assos Assos
      return $form;
111
    }
112 32700c57 Assos Assos
    $form['#storage'] = [];
113 85ad3d82 Assos Assos
    $form['#theme'] = 'ldap_user_conf_form';
114
115 32700c57 Assos Assos
    $form['intro'] = [
116 85ad3d82 Assos Assos
      '#type' => 'item',
117
      '#markup' => t('<h1>LDAP User Settings</h1>'),
118 32700c57 Assos Assos
    ];
119 85ad3d82 Assos Assos
120 32700c57 Assos Assos
    $form['manual_drupal_account_editing'] = [
121 85ad3d82 Assos Assos
      '#type' => 'fieldset',
122
      '#title' => t('Manual Drupal Account Creation and Updates'),
123
      '#collapsible' => TRUE,
124
      '#collapsed' => FALSE,
125 32700c57 Assos Assos
    ];
126 85ad3d82 Assos Assos
127 32700c57 Assos Assos
    $form['manual_drupal_account_editing']['manualAccountConflict'] = [
128 85ad3d82 Assos Assos
      '#type' => 'radios',
129
      '#options' => $this->manualAccountConflictOptions,
130
      '#title' => t('How to resolve LDAP conflicts with manually  created Drupal accounts.'),
131
      '#description' => t('This applies only to accounts created manually through admin/people/create
132
        for which an LDAP entry can be found on the LDAP server selected in "LDAP Servers Providing Provisioning Data"'),
133
      '#default_value' => $this->manualAccountConflict,
134 32700c57 Assos Assos
    ];
135 85ad3d82 Assos Assos
136 32700c57 Assos Assos
    $form['basic_to_drupal'] = [
137 85ad3d82 Assos Assos
      '#type' => 'fieldset',
138
      '#title' => t('Basic Provisioning to Drupal Account Settings'),
139
      '#collapsible' => TRUE,
140
      '#collapsed' => FALSE,
141 32700c57 Assos Assos
    ];
142 85ad3d82 Assos Assos
143
    $default_value = ($this->drupalAcctProvisionServer) ? $this->drupalAcctProvisionServer : 'none';
144 32700c57 Assos Assos
    $form['basic_to_drupal']['drupalAcctProvisionServer'] = [
145 85ad3d82 Assos Assos
      '#type' => 'radios',
146
      '#title' => t('LDAP Servers Providing Provisioning Data'),
147
      '#required' => 1,
148
      '#default_value' => $default_value,
149
      '#options' => $this->drupalAcctProvisionServerOptions,
150
      '#description' => $this->drupalAcctProvisionServerDescription,
151 32700c57 Assos Assos
      '#states' => [
152
        'enabled' => [
153
          ':input[name=drupalAcctProvisionTriggers]' => ['value' => LDAP_USER_DRUPAL_USER_PROV_ON_AUTHENTICATE],
154
        ],
155
      ],
156
    ];
157
158
    $form['basic_to_drupal']['drupalAcctProvisionTriggers'] = [
159 85ad3d82 Assos Assos
      '#type' => 'checkboxes',
160
      '#title' => t('Drupal Account Provisioning Events'),
161
      '#required' => FALSE,
162
      '#default_value' => $this->drupalAcctProvisionTriggers,
163
      '#options' => $this->drupalAccountProvisionEventsOptions,
164
      '#description' => $this->drupalAccountProvisionEventsDescription,
165 32700c57 Assos Assos
    ];
166 85ad3d82 Assos Assos
167 32700c57 Assos Assos
    $form['basic_to_drupal']['disableAdminPasswordField'] = [
168 85ad3d82 Assos Assos
      '#type' => 'checkbox',
169
      '#title' => t('Disable the password fields at /admin/create/people since the password is going to be randomly generated anyway. This is useful if you are synching data to Drupal from LDAP, and not bringing the user password from LDAP.'),
170
      '#default_value' => $this->disableAdminPasswordField,
171 32700c57 Assos Assos
    ];
172 85ad3d82 Assos Assos
173 32700c57 Assos Assos
    $form['basic_to_drupal']['userConflictResolve'] = [
174 85ad3d82 Assos Assos
      '#type' => 'radios',
175
      '#title' => t('Existing Drupal User Account Conflict'),
176
      '#required' => 1,
177
      '#default_value' => $this->userConflictResolve,
178
      '#options' => $this->userConflictOptions,
179 32700c57 Assos Assos
      '#description' => t($this->userConflictResolveDescription),
180
    ];
181 85ad3d82 Assos Assos
182 32700c57 Assos Assos
    $form['basic_to_drupal']['accountsWithSameEmail'] = [
183 b42754b9 Assos Assos
      '#type' => 'radios',
184
      '#title' => t('Existing Account with Same Email Address'),
185
      '#default_value' => $this->accountsWithSameEmail,
186
      '#options' => $this->accountsWithSameEmailOptions,
187
      '#description' => t($this->accountsWithSameEmailDescription),
188
      '#disabled' => (module_exists('sharedemail') === FALSE),
189 32700c57 Assos Assos
    ];
190 b42754b9 Assos Assos
191 32700c57 Assos Assos
    $form['basic_to_drupal']['acctCreation'] = [
192 85ad3d82 Assos Assos
      '#type' => 'radios',
193
      '#title' => t('Application of Drupal Account settings to LDAP Authenticated Users'),
194
      '#required' => 1,
195
      '#default_value' => $this->acctCreation,
196
      '#options' => $this->acctCreationOptions,
197
      '#description' => t($this->acctCreationDescription),
198 32700c57 Assos Assos
    ];
199 85ad3d82 Assos Assos
200 32700c57 Assos Assos
    $account_options = [];
201 85ad3d82 Assos Assos
    $account_options['ldap_user_orphan_do_not_check'] = t('Do not check for orphaned Drupal accounts.');
202
    $account_options['ldap_user_orphan_email'] = t('Perform no action, but email list of orphaned accounts. (All the other options will send email summaries also.)');
203
    foreach (user_cancel_methods() as $option_name => $option) {
204
      $account_options[$option_name] = $option['#title'];
205
    }
206
207 32700c57 Assos Assos
    // @todo these 2 options are removed until this feature is better tested in
208 85ad3d82 Assos Assos
    // actual production environments; it has potentially disastrous effects
209
    unset($account_options['user_cancel_reassign']);
210
    unset($account_options['user_cancel_delete']);
211
212 32700c57 Assos Assos
    $form['basic_to_drupal']['orphanedDrupalAcctBehavior'] = [
213 85ad3d82 Assos Assos
      '#type' => 'radios',
214
      '#title' => t('Action to perform on Drupal account that no longer have a
215
        corresponding LDAP entry'),
216
      '#required' => 0,
217
      '#default_value' => $this->orphanedDrupalAcctBehavior,
218
      '#options' => $account_options,
219
      '#description' => t($this->orphanedDrupalAcctBehaviorDescription),
220 32700c57 Assos Assos
    ];
221 85ad3d82 Assos Assos
222 32700c57 Assos Assos
    $form['basic_to_drupal']['orphanedCheckQty'] = [
223 85ad3d82 Assos Assos
      '#type' => 'textfield',
224
      '#size' => 10,
225
      '#title' => t('Number of users to check each cron run.'),
226
      '#description' => t(''),
227
      '#default_value' => $this->orphanedCheckQty,
228
      '#required' => FALSE,
229 32700c57 Assos Assos
    ];
230 85ad3d82 Assos Assos
231 32700c57 Assos Assos
    $form['basic_to_ldap'] = [
232 85ad3d82 Assos Assos
      '#type' => 'fieldset',
233
      '#title' => t('Basic Provisioning to LDAP Settings'),
234
      '#collapsible' => TRUE,
235
      '#collapsed' => !($this->ldapEntryProvisionServer),
236 32700c57 Assos Assos
    ];
237 85ad3d82 Assos Assos
238
    $default_value = ($this->ldapEntryProvisionServer) ? $this->ldapEntryProvisionServer : 'none';
239 32700c57 Assos Assos
    $form['basic_to_ldap']['ldapEntryProvisionServer'] = [
240 85ad3d82 Assos Assos
      '#type' => 'radios',
241
      '#title' => t('LDAP Servers to Provision LDAP Entries on'),
242
      '#required' => 1,
243
      '#default_value' => $default_value,
244
      '#options' => $this->ldapEntryProvisionServerOptions,
245
      '#description' => $this->ldapEntryProvisionServerDescription,
246 32700c57 Assos Assos
    ];
247 85ad3d82 Assos Assos
248 32700c57 Assos Assos
    $form['basic_to_ldap']['ldapEntryProvisionTriggers'] = [
249 85ad3d82 Assos Assos
      '#type' => 'checkboxes',
250
      '#title' => t('LDAP Entry Provisioning Events'),
251
      '#required' => FALSE,
252
      '#default_value' => $this->ldapEntryProvisionTriggers,
253
      '#options' => $this->ldapEntryProvisionTriggersOptions,
254 32700c57 Assos Assos
      '#description' => $this->ldapEntryProvisionTriggersDescription,
255
    ];
256 85ad3d82 Assos Assos
257 32700c57 Assos Assos
    $form['basic_to_drupal']['server_mapping_preamble'] = [
258 85ad3d82 Assos Assos
      '#type' => 'markup',
259
      '#markup' => t('
260
The relationship between a Drupal user and an LDAP entry is defined within the LDAP server configurations.
261

262

263
The mappings below are for user fields, properties, and profile2 data that are not automatically mapped elsewhere.
264
Mappings such as username or email address that are configured elsewhere are shown at the top for clarity.
265
When more than one ldap server is enabled for provisioning data (or simply more than one configuration for the same ldap server),
266
mappings need to be setup for each server.  If no tables are listed below, you have not enabled any provisioning servers at
267
the top of this form.
268
'),
269 32700c57 Assos Assos
    ];
270 85ad3d82 Assos Assos
271 32700c57 Assos Assos
    foreach ([LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER, LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY] as $direction) {
272 85ad3d82 Assos Assos
      $sid = $this->provisionSidFromDirection[$direction];
273
      $ldap_server = ($sid) ? ldap_servers_get_servers($sid, NULL, TRUE) : FALSE;
274 32700c57 Assos Assos
      $ldap_server_selected = (boolean) $ldap_server;
275 85ad3d82 Assos Assos
276
      if ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) {
277
        $parent_fieldset = 'basic_to_drupal';
278 bc175c27 Assos Assos
        $description = t('Provisioning from LDAP to Drupal Mappings:');
279 85ad3d82 Assos Assos
      }
280
      elseif ($direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) {
281
        $parent_fieldset = 'basic_to_ldap';
282 bc175c27 Assos Assos
        $description = t('Provisioning from Drupal to LDAP Mappings:');
283 85ad3d82 Assos Assos
      }
284
285 32700c57 Assos Assos
      $form[$parent_fieldset]['mappings__' . $direction] = [
286 85ad3d82 Assos Assos
        '#type' => 'fieldset',
287 bc175c27 Assos Assos
        '#title' => $description,
288 85ad3d82 Assos Assos
        '#collapsible' => TRUE,
289
        '#collapsed' => FALSE,
290
        '#description' => '',
291 32700c57 Assos Assos
        'table__' . $direction => [
292 85ad3d82 Assos Assos
          '#type' => 'markup',
293
          '#markup' => '[replace_with_table__' . $direction . ']',
294 32700c57 Assos Assos
        ],
295
      ];
296 85ad3d82 Assos Assos
297 32700c57 Assos Assos
      $password_notes = '<h3>' . t('Password Tokens') . '</h3><ul>' .
298
      '<li>' . t('Pwd: Random -- Uses a random Drupal generated password') . '</li>' .
299
      '<li>' . t('Pwd: User or Random -- Uses password supplied on user forms.
300 85ad3d82 Assos Assos
  If none available uses random password.') . '</li></ul>' .
301 32700c57 Assos Assos
      '<h3>' . t('Password Concerns') . '</h3>' .
302
      '<ul>' .
303
      '<li>' . t('Provisioning passwords to LDAP means passwords must meet the LDAP\'s
304 85ad3d82 Assos Assos
password requirements.  Password Policy module can be used to add requirements.') . '</li>' .
305 32700c57 Assos Assos
      '<li>' . t('Some LDAPs require a user to reset their password if it has been changed
306 85ad3d82 Assos Assos
by someone other that user.  Consider this when provisioning LDAP passwords.') . '</li>' .
307 32700c57 Assos Assos
      '</ul></p>';
308 85ad3d82 Assos Assos
309
      $source_drupal_token_notes = <<<EOT
310
<p>Examples in form: Source Drupal User token => Target LDAP Token (notes)</p>
311
<ul>
312
<li>Source Drupal User token => Target LDAP Token</li>
313
<li>cn=[property.name],ou=test,dc=ad,dc=mycollege,dc=edu => [dn] (example of token and constants)</li>
314
<li>top => [objectclass:0] (example of constants mapped to multivalued attribute)</li>
315
<li>person => [objectclass:1] (example of constants mapped to multivalued attribute)</li>
316
<li>organizationalPerson => [objectclass:2] (example of constants mapped to multivalued attribute)</li>
317
<li>user => [objectclass:3] (example of constants mapped to multivalued attribute)</li>
318
<li>Drupal Provisioned LDAP Account => [description] (example of constant)</li>
319
<li>[field.field_lname] => [sn]</li>
320

321
</ul>
322
EOT;
323
324 32700c57 Assos Assos
      // Add some password notes.
325
      if ($direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) {
326
        $form[$parent_fieldset]['password_notes'] = [
327 85ad3d82 Assos Assos
          '#type' => 'fieldset',
328 bc175c27 Assos Assos
          '#title' => t('Password Notes'),
329 85ad3d82 Assos Assos
          '#collapsible' => TRUE,
330
          '#collapsed' => TRUE,
331 32700c57 Assos Assos
          'directions' => [
332 85ad3d82 Assos Assos
            '#type' => 'markup',
333
            '#markup' => $password_notes,
334 32700c57 Assos Assos
          ],
335
        ];
336
        $form[$parent_fieldset]['source_drupal_token_notes'] = [
337 85ad3d82 Assos Assos
          '#type' => 'fieldset',
338 bc175c27 Assos Assos
          '#title' => t('Source Drupal User Tokens and Corresponding Target LDAP Tokens'),
339 85ad3d82 Assos Assos
          '#collapsible' => TRUE,
340
          '#collapsed' => TRUE,
341 32700c57 Assos Assos
          'directions' => [
342 85ad3d82 Assos Assos
            '#type' => 'markup',
343
            '#markup' => $source_drupal_token_notes,
344 32700c57 Assos Assos
          ],
345
        ];
346 85ad3d82 Assos Assos
      }
347
      $this->addServerMappingFields($form, $direction);
348
    }
349
350 32700c57 Assos Assos
    foreach (['orphanedCheckQty', 'orphanedDrupalAcctBehavior', 'acctCreation', 'userConflictResolve', 'accountsWithSameEmail', 'drupalAcctProvisionTriggers', 'mappings__' . LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER] as $input_name) {
351 85ad3d82 Assos Assos
      $form['basic_to_drupal'][$input_name]['#states']['invisible'] =
352 32700c57 Assos Assos
        [
353
          ':input[name=drupalAcctProvisionServer]' => ['value' => 'none'],
354
        ];
355 85ad3d82 Assos Assos
    }
356
357 32700c57 Assos Assos
    foreach (['ldapEntryProvisionTriggers', 'password_notes', 'source_drupal_token_notes', 'mappings__' . LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY] as $input_name) {
358 85ad3d82 Assos Assos
      $form['basic_to_ldap'][$input_name]['#states']['invisible'] =
359 32700c57 Assos Assos
        [
360
          ':input[name=ldapEntryProvisionServer]' => ['value' => 'none'],
361
        ];
362 85ad3d82 Assos Assos
    }
363
364 32700c57 Assos Assos
    $form['submit'] = [
365 85ad3d82 Assos Assos
      '#type' => 'submit',
366
      '#value' => 'Save',
367 32700c57 Assos Assos
    ];
368 85ad3d82 Assos Assos
369 32700c57 Assos Assos
    return $form;
370
  }
371 85ad3d82 Assos Assos
372 bc175c27 Assos Assos
  /**
373
   * @param $sid
374
   * @param $orphan_handling
375
   */
376
  private function checkPuidOrphans($sid, $orphan_handling) {
377
    $ldap_server = ldap_servers_get_servers($sid, NULL, TRUE);
378
    if ($ldap_server && empty($ldap_server->unique_persistent_attr)
379
      && $orphan_handling != 'ldap_user_orphan_do_not_check') {
380
      drupal_set_message(t('You\'ve configured the orphan check but are missing the required persistent user ID property.'), 'error');
381
    }
382
  }
383 85ad3d82 Assos Assos
384 32700c57 Assos Assos
  /**
385
   * Validate submitted form.
386
   *
387
   * @param array $values
388
   *   as $form_state['values'] from drupal form api.
389
   * @param array $storage
390
   *   as $form_state['storage'] from drupal form api.
391
   *
392
   * @return array in form array($errors, $warnings)to be thrown by form api
393
   */
394
  public function drupalFormValidate($values, $storage) {
395 85ad3d82 Assos Assos
    $this->populateFromDrupalForm($values, $storage);
396
    list($errors, $warnings) = $this->validate($values);
397
398 bc175c27 Assos Assos
    $this->checkPuidOrphans($values['drupalAcctProvisionServer'], $values['orphanedDrupalAcctBehavior']);
399
400 32700c57 Assos Assos
    // Since failed mapping rows in form, don't populate ->ldapUserSynchMappings, need to validate these from values.
401 85ad3d82 Assos Assos
    foreach ($values as $field => $value) {
402
      $parts = explode('__', $field);
403 32700c57 Assos Assos
      // Since synch mapping fields are in n-tuples, process entire n-tuple at once (on field == configurable_to_drupal)
404 85ad3d82 Assos Assos
      if (count($parts) != 4 || $parts[1] !== 'sm' || $parts[2] != 'configurable_to_drupal') {
405
        continue;
406
      }
407
      list($direction, $discard, $column_name, $i) = $parts;
408
      $action = $storage['synch_mapping_fields'][$direction][$i]['action'];
409 32700c57 Assos Assos
      $tokens = [];
410
      $row_mappings = [];
411
      foreach (['remove', 'configurable_to_drupal', 'configurable_to_ldap', 'convert', 'direction', 'ldap_attr', 'user_attr', 'user_tokens'] as $column_name) {
412
        $input_name = join('__', ['sm', $column_name, $i]);
413 85ad3d82 Assos Assos
        $row_mappings[$column_name] = isset($values[$input_name]) ? $values[$input_name] : NULL;
414
      }
415
416
      $has_values = $row_mappings['ldap_attr'] || $row_mappings['user_attr'];
417
      if ($has_values) {
418
        $tokens['%ldap_attr'] = $row_mappings['ldap_attr'];
419
        $row_descriptor = t("server %sid row mapping to ldap attribute %ldap_attr", $tokens);
420
        $tokens['!row_descriptor'] = $row_descriptor;
421
        if (!$row_mappings['direction']) {
422 32700c57 Assos Assos
          $input_name = join('__', ['sm', 'direction', $i]);
423 85ad3d82 Assos Assos
          $errors[$input_name] = t('No mapping direction given in !row_descriptor', $tokens);
424
        }
425
        if ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER && $row_mappings['user_attr'] == 'user_tokens') {
426 32700c57 Assos Assos
          $input_name = join('__', ['sm', 'user_attr', $i]);
427 bc175c27 Assos Assos
          $errors[$input_name] = t('User tokens not allowed when mapping to Drupal user.  Location: !row_descriptor', $tokens);
428 85ad3d82 Assos Assos
        }
429
        if (!$row_mappings['ldap_attr']) {
430 32700c57 Assos Assos
          $input_name = join('__', ['sm', 'ldap_attr', $i]);
431 85ad3d82 Assos Assos
          $errors[$input_name] = t('No ldap attribute given in !row_descriptor', $tokens);
432
        }
433
        if (!$row_mappings['user_attr']) {
434 32700c57 Assos Assos
          $input_name = join('__', ['sm', 'user_attr', $i]);
435 85ad3d82 Assos Assos
          $errors[$input_name] = t('No user attribute given in !row_descriptor', $tokens);
436
        }
437
      }
438
439
    }
440 32700c57 Assos Assos
    return [$errors, $warnings];
441 85ad3d82 Assos Assos
  }
442
443 32700c57 Assos Assos
  /**
444
   * Validate object, not form.
445
   *
446
   * @param array $values
447
   *   as $form_state['values'] from drupal form api.
448
   *
449
   * @return array in form array($errors, $warnings)to be thrown by form api
450
   *
451
   * @todo validate that a user field exists, such as field.field_user_lname
452
   */
453 85ad3d82 Assos Assos
  public function validate($values) {
454 32700c57 Assos Assos
    $errors = [];
455
    $warnings = [];
456
    $tokens = [];
457 85ad3d82 Assos Assos
458 32700c57 Assos Assos
    $has_drupal_acct_prov_servers = (boolean) ($this->drupalAcctProvisionServer);
459
    $has_drupal_acct_prov_settings_options = (count(array_filter($this->drupalAcctProvisionTriggers)) > 0);
460 85ad3d82 Assos Assos
461
    if (!$has_drupal_acct_prov_servers && $has_drupal_acct_prov_settings_options) {
462 bc175c27 Assos Assos
      $warnings['drupalAcctProvisionServer'] = t('No Servers are enabled to provide provisioning to Drupal, but Drupal Account Provisioning Options are selected.', $tokens);
463 85ad3d82 Assos Assos
    }
464
    if ($has_drupal_acct_prov_servers && !$has_drupal_acct_prov_settings_options) {
465 bc175c27 Assos Assos
      $warnings['drupalAcctProvisionTriggers'] = t('Servers are enabled to provide provisioning to Drupal, but no Drupal Account Provisioning Options are selected.  This will result in no synching happening.', $tokens);
466 85ad3d82 Assos Assos
    }
467
468 32700c57 Assos Assos
    $has_ldap_prov_servers = (boolean) ($this->ldapEntryProvisionServer);
469 85ad3d82 Assos Assos
    $has_ldap_prov_settings_options = (count(array_filter($this->ldapEntryProvisionTriggers)) > 0);
470
    if (!$has_ldap_prov_servers && $has_ldap_prov_settings_options) {
471 bc175c27 Assos Assos
      $warnings['ldapEntryProvisionServer'] = t('No Servers are enabled to provide provisioning to ldap, but LDAP Entry Options are selected.', $tokens);
472 85ad3d82 Assos Assos
    }
473
    if ($has_ldap_prov_servers && !$has_ldap_prov_settings_options) {
474 bc175c27 Assos Assos
      $warnings['ldapEntryProvisionTriggers'] = t('Servers are enabled to provide provisioning to ldap, but no LDAP Entry Options are selected.  This will result in no synching happening.', $tokens);
475 85ad3d82 Assos Assos
    }
476
477
    if (isset($this->ldapUserSynchMappings)) {
478
      $to_ldap_entries_mappings_exist = FALSE;
479
      foreach ($this->ldapUserSynchMappings as $synch_direction => $mappings) {
480 32700c57 Assos Assos
        $map_index = [];
481
        // Format ['%sid' => $sid].
482
        $tokens = [];
483 85ad3d82 Assos Assos
        $to_drupal_user_mappings_exist = FALSE;
484
        $to_ldap_entries_mappings_exist = FALSE;
485
486
        foreach ($mappings as $target_attr => $mapping) {
487
          if ($mapping['direction'] == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) {
488
            $attr_value = $mapping['user_attr'];
489
            $attr_name = 'user_attr';
490
          }
491
          if ($mapping['direction'] == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) {
492
            $attr_value = $mapping['ldap_attr'];
493
            $attr_name = 'ldap_attr';
494
          }
495
          foreach ($values as $field => $value) {
496
            $parts = explode('__', $field);
497
            if (count($parts) == 4 && $parts[2] == $attr_name && $value == $attr_value) {
498
              $map_index[$attr_value] = $parts[3];
499
            }
500
          }
501
        }
502
503
        foreach ($mappings as $target_attr => $mapping) {
504
          foreach ($mapping as $key => $value) {
505
            if (is_scalar($value)) {
506
              $tokens['%' . $key] = $value;
507
            }
508
          }
509
          $row_descriptor = t("server %sid row mapping to ldap attribute %ldap_attr", $tokens);
510
          $tokens['!row_descriptor'] = $row_descriptor;
511 32700c57 Assos Assos
          $ldap_attribute_maps_in_token = [];
512 85ad3d82 Assos Assos
          ldap_servers_token_extract_attributes($ldap_attribute_maps_in_token, $mapping['ldap_attr']);
513
514
          if ($mapping['direction'] == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) {
515
            $row_id = $map_index[$mapping['user_attr']];
516
            $to_drupal_user_mappings_exist = TRUE;
517
          }
518
          if ($mapping['direction'] == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) {
519
            $row_id = $map_index[$mapping['ldap_attr']];
520
            $to_ldap_entries_mappings_exist = TRUE;
521
522
            if (count(array_keys($ldap_attribute_maps_in_token)) != 1) {
523 32700c57 Assos Assos
              $token_field_id = join('__', ['sm', 'user_tokens', $row_id]);
524 bc175c27 Assos Assos
              $errors[$token_field_id] = t('When provisioning to ldap, ldap attribute column must be singular token such as [cn]. %ldap_attr is not.
525 85ad3d82 Assos Assos
                Do not use compound tokens such as "[displayName] [sn]" or literals such as "physics". Location: !row_descriptor', $tokens);
526
            }
527
528
          }
529 32700c57 Assos Assos
          $ldap_attr_field_id = join('__', ['sm', 'ldap_attr', $row_id]);
530
          $user_attr_field_id = join('__', ['sm', 'user_attr', $row_id]);
531
          $first_context_field_id = join('__', ['sm', 1, $row_id]);
532
          $user_tokens_field_id = join('__', ['sm', 'user_tokens', $row_id]);
533 85ad3d82 Assos Assos
534
          if (!$mapping['ldap_attr']) {
535 bc175c27 Assos Assos
            $errors[$ldap_attr_field_id] = t('No LDAP Attribute given in !row_descriptor', $tokens);
536 85ad3d82 Assos Assos
          }
537
          if ($mapping['user_attr'] == 'user_tokens' && !$mapping['user_tokens']) {
538 bc175c27 Assos Assos
            $errors[$user_tokens_field_id] = t('User tokens selected in !row_descriptor, but user tokens column empty.', $tokens);
539 85ad3d82 Assos Assos
          }
540
541
          if (isset($mapping['prov_events']) && count($mapping['prov_events']) == 0) {
542 bc175c27 Assos Assos
            $warnings[$first_context_field_id] = t('No synchronization events checked in !row_descriptor.
543 85ad3d82 Assos Assos
              This field will not be synchronized until some are checked.', $tokens);
544
          }
545
        }
546
      }
547
      if ($to_ldap_entries_mappings_exist && !isset($mappings['[dn]'])) {
548 bc175c27 Assos Assos
        $errors['mappings__' . $synch_direction] = t('Mapping rows exist for provisioning to ldap, but no ldap attribute is targetted for [dn].
549 85ad3d82 Assos Assos
          One row must map to [dn].  This row will have a user token like cn=[property.name],ou=users,dc=ldap,dc=mycompany,dc=com');
550
      }
551
    }
552 32700c57 Assos Assos
    return [$errors, $warnings];
553 85ad3d82 Assos Assos
  }
554
555
  /**
556 32700c57 Assos Assos
   * Populate object with data from form values.
557 85ad3d82 Assos Assos
   *
558 32700c57 Assos Assos
   * @param array $values
559
   *   as $form_state['values'] from drupal form api.
560
   * @param array $storage
561
   *   as $form_state['storage'] from drupal form api.
562 85ad3d82 Assos Assos
   */
563
  protected function populateFromDrupalForm($values, $storage) {
564
    $this->drupalAcctProvisionServer = ($values['drupalAcctProvisionServer'] == 'none') ? 0 : $values['drupalAcctProvisionServer'];
565 bc175c27 Assos Assos
    $this->ldapEntryProvisionServer = ($values['ldapEntryProvisionServer'] == 'none') ? 0 : $values['ldapEntryProvisionServer'];
566 85ad3d82 Assos Assos
567
    $this->drupalAcctProvisionTriggers = $values['drupalAcctProvisionTriggers'];
568
    $this->ldapEntryProvisionTriggers = $values['ldapEntryProvisionTriggers'];
569
    $this->orphanedDrupalAcctBehavior = $values['orphanedDrupalAcctBehavior'];
570
    $this->orphanedCheckQty = $values['orphanedCheckQty'];
571
572
    $this->manualAccountConflict = $values['manualAccountConflict'];
573 32700c57 Assos Assos
    $this->userConflictResolve = ($values['userConflictResolve']) ? (int) $values['userConflictResolve'] : NULL;
574
    $this->accountsWithSameEmail = ($values['accountsWithSameEmail']) ? (int) $values['accountsWithSameEmail'] : NULL;
575
    $this->acctCreation = ($values['acctCreation']) ? (int) $values['acctCreation'] : NULL;
576 85ad3d82 Assos Assos
    $this->disableAdminPasswordField = $values['disableAdminPasswordField'];
577
578
    $this->ldapUserSynchMappings = $this->synchMappingsFromForm($values, $storage);
579
580
  }
581
582 32700c57 Assos Assos
  /**
583
   * Extract synch mappings array from mapping table in admin form.
584
   *
585
   * @param array $values
586
   *   as $form_state['values'] from drupal form api.
587
   * @param array $storage
588
   *   as $form_state['storage'] from drupal form api
589
   *
590
   *   $values input names in form:
591
   *   1__sm__configurable__5,
592
   *   1__sm__remove__5,
593
   *   1__sm__ldap_attr__5,
594
   *   1__sm__convert__5,
595
   *   1__sm__direction__5,
596
   *   1__sm__user_attr__5,
597
   *   1__sm__user_tokens__5
598
   *   1__sm__1__5,
599
   *   1__sm__2__5,
600
   *   ...where
601
   *   -- first arg is direction, eg 1 or 2 LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER or LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY
602
   *   -- second arg is discarded ('sm')
603
   *   -- third part is field, e.g. user_attr
604
   *   -- fourth is the row in the configuration form, e.g. 5
605
   *
606
   *   where additiond data is in $form['#storage'][<direction>]['synch_mapping_fields'][N]
607
   *   $form['#storage']['synch_mapping_fields'][<direction>][N] = array(
608
   *   'sid' => $sid,
609
   *   'action' => 'add',
610
   *   );.
611
   */
612 85ad3d82 Assos Assos
  private function synchMappingsFromForm($values, $storage) {
613
614 32700c57 Assos Assos
    $mappings = [];
615 85ad3d82 Assos Assos
    foreach ($values as $field => $value) {
616
617
      $parts = explode('__', $field);
618 32700c57 Assos Assos
      // Since synch mapping fields are in n-tuples, process entire n-tuple at once.
619 85ad3d82 Assos Assos
      if (count($parts) != 4 || $parts[1] !== 'sm') {
620
        continue;
621
      }
622
623
      list($direction, $discard, $column_name, $i) = $parts;
624
      $action = $storage['synch_mapping_fields'][$direction][$i]['action'];
625
626 32700c57 Assos Assos
      $row_mappings = [];
627
      foreach (['remove', 'configurable_to_drupal', 'configurable_to_ldap', 'convert', 'ldap_attr', 'user_attr', 'user_tokens'] as $column_name) {
628
        $input_name = join('__', [$direction, 'sm', $column_name, $i]);
629 85ad3d82 Assos Assos
        $row_mappings[$column_name] = isset($values[$input_name]) ? $values[$input_name] : NULL;
630
      }
631
632
      if ($row_mappings['remove']) {
633
        continue;
634
      }
635
636
      $key = ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) ? $row_mappings['user_attr'] : $row_mappings['ldap_attr'];
637
      if ($row_mappings['configurable_to_drupal'] && $row_mappings['ldap_attr'] && $row_mappings['user_attr']) {
638 32700c57 Assos Assos
        $mappings[$direction][$key] = [
639 85ad3d82 Assos Assos
          'ldap_attr' => $row_mappings['ldap_attr'],
640
          'user_attr' => $row_mappings['user_attr'],
641
          'convert' => $row_mappings['convert'],
642
          'direction' => $direction,
643
          'user_tokens' => $row_mappings['user_tokens'],
644
          'config_module' => 'ldap_user',
645
          'prov_module' => 'ldap_user',
646
          'enabled' => 1,
647 32700c57 Assos Assos
        ];
648 85ad3d82 Assos Assos
649
        $synchEvents = ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) ? $this->provisionsDrupalEvents : $this->provisionsLdapEvents;
650
        foreach ($synchEvents as $prov_event => $discard) {
651 32700c57 Assos Assos
          $input_name = join('__', [$direction, 'sm', $prov_event, $i]);
652 85ad3d82 Assos Assos
          if (isset($values[$input_name]) && $values[$input_name]) {
653
            $mappings[$direction][$key]['prov_events'][] = $prov_event;
654
          }
655
        }
656
      }
657
    }
658
659
    return $mappings;
660
  }
661
662
  /**
663 32700c57 Assos Assos
   * Method to respond to successfully validated form submit.
664 85ad3d82 Assos Assos
   *
665 32700c57 Assos Assos
   * @param array $values
666
   *   as $form_state['values'] from drupal form api.
667
   * @param array $storage
668
   *   as $form_state['storage'] from drupal form api.
669 85ad3d82 Assos Assos
   *
670
   * @return by reference to $form array
671
   */
672
  public function drupalFormSubmit($values, $storage) {
673
674
    $this->populateFromDrupalForm($values, $storage);
675
676
    try {
677
      $save_result = $this->save();
678
    }
679
    catch (Exception $e) {
680
      $this->errorName = 'Save Error';
681
      $this->errorMsg = t('Failed to save object.  Your form data was not saved.');
682
      $this->hasError = TRUE;
683
    }
684
685
  }
686
687
  /**
688 32700c57 Assos Assos
   * Add existing mappings to ldap user provisioning mapping admin form table.
689 85ad3d82 Assos Assos
   *
690
   * @param drupal form array $form
691 32700c57 Assos Assos
   * @param enum $direction
692
   *   LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER or LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY.
693 85ad3d82 Assos Assos
   *
694
   * @return by reference to $form array
695
   */
696
  private function addServerMappingFields(&$form, $direction) {
697
698
    if ($direction == LDAP_USER_PROV_DIRECTION_NONE) {
699
      return;
700
    }
701
702
    $text = ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) ? 'target' : 'source';
703 32700c57 Assos Assos
    $user_attr_options = ['0' => t('Select') . ' ' . $text];
704 85ad3d82 Assos Assos
705
    if (!empty($this->synchMapping[$direction])) {
706
      foreach ($this->synchMapping[$direction] as $target_id => $mapping) {
707
        if (!isset($mapping['name']) || isset($mapping['exclude_from_mapping_ui']) && $mapping['exclude_from_mapping_ui']) {
708
          continue;
709
        }
710
        if (
711
          (isset($mapping['configurable_to_drupal']) && $mapping['configurable_to_drupal'] && $direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER)
712
          ||
713
          (isset($mapping['configurable_to_ldap']) && $mapping['configurable_to_ldap']  && $direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY)
714
          ) {
715 b42754b9 Assos Assos
          $user_attr_options[$target_id] = substr($target_id, 1, -1);
716 85ad3d82 Assos Assos
        }
717
      }
718
    }
719 b42754b9 Assos Assos
720
    if ($direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) {
721
      $user_attr_options['user_tokens'] = '-- user tokens --';
722
    }
723 85ad3d82 Assos Assos
724
    $row = 0;
725
726 32700c57 Assos Assos
    // 1. non configurable mapping rows.
727 85ad3d82 Assos Assos
    foreach ($this->synchMapping[$direction] as $target_id => $mapping) {
728
      if (isset($mapping['exclude_from_mapping_ui']) && $mapping['exclude_from_mapping_ui']) {
729
        continue;
730
      }
731 32700c57 Assos Assos
      // Is configurable by ldap_user module (not direction to ldap_user)
732
      if (!$this->isMappingConfigurable($mapping, 'ldap_user') && ($mapping['direction'] == $direction || $mapping['direction'] == LDAP_USER_PROV_DIRECTION_ALL)) {
733 85ad3d82 Assos Assos
        $this->addSynchFormRow($form, 'nonconfigurable', $direction, $mapping, $user_attr_options, $row);
734
        $row++;
735
      }
736
    }
737
738 32700c57 Assos Assos
    // 2. existing configurable mappings rows.
739 85ad3d82 Assos Assos
    if (!empty($this->ldapUserSynchMappings[$direction])) {
740 32700c57 Assos Assos
      // Key could be ldap attribute name or user attribute name.
741
      foreach ($this->ldapUserSynchMappings[$direction] as $target_attr_token => $mapping) {
742 85ad3d82 Assos Assos
        if (isset($mapping['enabled']) && $mapping['enabled'] && $this->isMappingConfigurable($this->synchMapping[$direction][$target_attr_token], 'ldap_user')) {
743
          $this->addSynchFormRow($form, 'update', $direction, $mapping, $user_attr_options, $row);
744
          $row++;
745
        }
746
      }
747
    }
748
749 32700c57 Assos Assos
    // 3. leave 4 rows for adding more mappings.
750 bc175c27 Assos Assos
    for ($i = 0; $i < 4; $i++) {
751 85ad3d82 Assos Assos
      $this->addSynchFormRow($form, 'add', $direction, NULL, $user_attr_options, $row);
752
      $row++;
753
    }
754
755
  }
756
757
  /**
758 32700c57 Assos Assos
   * Add mapping form row to ldap user provisioning mapping admin form table.
759 85ad3d82 Assos Assos
   *
760
   * @param drupal form array $form
761 32700c57 Assos Assos
   * @param string $action
762
   *   is 'add', 'update', or 'nonconfigurable'.
763
   * @param enum $direction
764
   *   LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER or LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY.
765
   * @param array $mapping
766
   *   is current setting for updates or nonconfigurable items.
767
   * @param array $user_attr_options
768
   *   of drupal user target options.
769
   * @param int $row
770
   *   is current row in table.
771 85ad3d82 Assos Assos
   *
772
   * @return by reference to $form
773
   */
774
  private function addSynchFormRow(&$form, $action, $direction, $mapping, $user_attr_options, $row) {
775
776
    $id_prefix = $direction . '__';
777
778
    $id = $id_prefix . 'sm__remove__' . $row;
779 32700c57 Assos Assos
    $form[$id] = [
780 85ad3d82 Assos Assos
      '#id' => $id,
781
      '#row' => $row,
782
      '#col' => 0,
783
      '#type' => 'checkbox',
784
      '#default_value' => NULL,
785
      '#disabled' => ($action == 'add' || $action == 'nonconfigurable'),
786 32700c57 Assos Assos
    ];
787 85ad3d82 Assos Assos
788 bc175c27 Assos Assos
    $id = $id_prefix . 'sm__convert__' . $row;
789 32700c57 Assos Assos
    $form[$id] = [
790 85ad3d82 Assos Assos
      '#id' => $id,
791
      '#row' => $row,
792
      '#col' => ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) ? 2 : 3,
793
      '#type' => 'checkbox',
794 bc175c27 Assos Assos
      '#default_value' => isset($mapping['convert']) ? $mapping['convert'] : '',
795 85ad3d82 Assos Assos
      '#disabled' => ($action == 'nonconfigurable'),
796 32700c57 Assos Assos
      '#attributes' => ['class' => ['convert']],
797
    ];
798 85ad3d82 Assos Assos
799 bc175c27 Assos Assos
    $id = $id_prefix . 'sm__ldap_attr__' . $row;
800 85ad3d82 Assos Assos
    $col = ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) ? 1 : 4;
801
    if ($action == 'nonconfigurable') {
802 32700c57 Assos Assos
      $form[$id] = [
803 85ad3d82 Assos Assos
        '#id' => $id,
804
        '#row' => $row,
805
        '#col' => $col,
806
        '#type' => 'item',
807
        '#markup' => isset($mapping['source']) ? $mapping['source'] : '?',
808 32700c57 Assos Assos
        '#attributes' => ['class' => ['source']],
809
      ];
810 85ad3d82 Assos Assos
    }
811
    else {
812 32700c57 Assos Assos
      $form[$id] = [
813 85ad3d82 Assos Assos
        '#id' => $id,
814
        '#row' => $row,
815
        '#col' => $col,
816
        '#type' => 'textfield',
817
        '#default_value' => isset($mapping['ldap_attr']) ? $mapping['ldap_attr'] : '',
818
        '#size' => 20,
819
        '#maxlength' => 255,
820 32700c57 Assos Assos
        '#attributes' => ['class' => ['ldap-attr']],
821
      ];
822 85ad3d82 Assos Assos
    }
823
824 bc175c27 Assos Assos
    $user_attr_input_id = $id_prefix . 'sm__user_attr__' . $row;
825 85ad3d82 Assos Assos
    $col = ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) ? 3 : 1;
826
    if ($action == 'nonconfigurable') {
827 32700c57 Assos Assos
      $form[$user_attr_input_id] = [
828 85ad3d82 Assos Assos
        '#id' => $user_attr_input_id,
829
        '#row' => $row,
830
        '#col' => $col,
831
        '#type' => 'item',
832
        '#markup' => isset($mapping['name']) ? $mapping['name'] : '?',
833 32700c57 Assos Assos
      ];
834 85ad3d82 Assos Assos
    }
835
    else {
836 32700c57 Assos Assos
      $form[$user_attr_input_id] = [
837 85ad3d82 Assos Assos
        '#id' => $user_attr_input_id,
838
        '#row' => $row,
839
        '#col' => $col,
840
        '#type' => 'select',
841
        '#default_value' => isset($mapping['user_attr']) ? $mapping['user_attr'] : '',
842
        '#options' => $user_attr_options,
843 32700c57 Assos Assos
      ];
844 85ad3d82 Assos Assos
    }
845
846
    if ($direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) {
847 bc175c27 Assos Assos
      $id = $id_prefix . 'sm__user_tokens__' . $row;
848 32700c57 Assos Assos
      $form[$id] = [
849 85ad3d82 Assos Assos
        '#id' => $id,
850
        '#row' => $row,
851 bc175c27 Assos Assos
        '#col' => 2,
852 85ad3d82 Assos Assos
        '#type' => 'textfield',
853
        '#default_value' => isset($mapping['user_tokens']) ? $mapping['user_tokens'] : '',
854
        '#size' => 40,
855
        '#maxlength' => 255,
856
        '#disabled' => ($action == 'nonconfigurable'),
857 32700c57 Assos Assos
        '#states' => [
858
          'visible' => [
859
            ':input[name="' . $user_attr_input_id . '"]' => ['value' => 'user_tokens'],
860
          ],
861
        ],
862
        '#attributes' => ['class' => ['tokens']],
863
      ];
864 85ad3d82 Assos Assos
    }
865
866 32700c57 Assos Assos
    $form['#storage']['synch_mapping_fields'][$direction][$row] = [
867 85ad3d82 Assos Assos
      'action' => $action,
868
      'direction' => $direction,
869 32700c57 Assos Assos
    ];
870 85ad3d82 Assos Assos
871
    $id = $id_prefix . 'sm__configurable_to_drupal__' . $row;
872 32700c57 Assos Assos
    $form[$id] = [
873 85ad3d82 Assos Assos
      '#id' => $id,
874
      '#type' => 'hidden',
875
      '#default_value' => ($action != 'nonconfigurable'),
876 32700c57 Assos Assos
    ];
877 85ad3d82 Assos Assos
878
    $col = ($direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) ? 5 : 4;
879
    $synchEvents = ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) ? $this->provisionsDrupalEvents : $this->provisionsLdapEvents;
880
881
    foreach ($synchEvents as $prov_event => $prov_event_name) {
882
      $col++;
883 32700c57 Assos Assos
      $id = $id_prefix . join('__', ['sm', $prov_event, $row]);
884
      $form[$id] = [
885 85ad3d82 Assos Assos
        '#id' => $id ,
886
        '#type' => 'checkbox',
887 32700c57 Assos Assos
        '#default_value' => isset($mapping['prov_events']) ? (int) (in_array($prov_event, $mapping['prov_events'])) : '',
888 85ad3d82 Assos Assos
        '#row' => $row,
889
        '#col' => $col,
890
        '#disabled' => (!$this->provisionEventConfigurable($prov_event, $mapping) || ($action == 'nonconfigurable')),
891 32700c57 Assos Assos
        '#attributes' => ['class' => ['synch-method']],
892
      ];
893 85ad3d82 Assos Assos
    }
894
  }
895
896
  /**
897
   * Is a mapping configurable by a given module?
898
   *
899 32700c57 Assos Assos
   * @param array $mapping
900
   *   as mapping configuration for field, attribute, property, etc.
901
   * @param string $module
902
   *   machine name such as ldap_user.
903 85ad3d82 Assos Assos
   *
904 32700c57 Assos Assos
   * @return bool
905 85ad3d82 Assos Assos
   */
906
  private function isMappingConfigurable($mapping = NULL, $module = 'ldap_user') {
907
    $configurable = (
908
      (
909
        (!isset($mapping['configurable_to_drupal']) && !isset($mapping['configurable_to_ldap'])) ||
910
        (isset($mapping['configurable_to_drupal']) && $mapping['configurable_to_drupal']) ||
911
        (isset($mapping['configurable_to_ldap']) && $mapping['configurable_to_ldap'])
912
      )
913
      &&
914
      (
915
        !isset($mapping['config_module']) ||
916
        (isset($mapping['config_module']) && $mapping['config_module'] == $module)
917
      )
918
    );
919
    return $configurable;
920
  }
921
922
  /**
923
   * Is a particular synch method viable for a given mapping?
924
   * That is, Can it be enabled in the UI by admins?
925
   *
926
   * @param int $prov_event
927 32700c57 Assos Assos
   * @param array $mapping
928
   *   is array of mapping configuration.
929 85ad3d82 Assos Assos
   *
930 32700c57 Assos Assos
   * @return bool
931 85ad3d82 Assos Assos
   */
932
  private function provisionEventConfigurable($prov_event, $mapping = NULL) {
933
934
    if ($mapping) {
935
      if ($prov_event == LDAP_USER_EVENT_CREATE_LDAP_ENTRY || $prov_event == LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY) {
936 32700c57 Assos Assos
        $configurable = (boolean) (!isset($mapping['configurable_to_ldap']) || $mapping['configurable_to_ldap']);
937 85ad3d82 Assos Assos
      }
938
      elseif ($prov_event == LDAP_USER_EVENT_CREATE_DRUPAL_USER || $prov_event == LDAP_USER_EVENT_SYNCH_TO_DRUPAL_USER) {
939 32700c57 Assos Assos
        $configurable = (boolean) (!isset($mapping['configurable_to_drupal']) || $mapping['configurable_to_drupal']);
940 85ad3d82 Assos Assos
      }
941
    }
942
    else {
943
      $configurable = TRUE;
944
    }
945
946
    return $configurable;
947
  }
948
949 32700c57 Assos Assos
  /**
950
   *
951
   */
952 85ad3d82 Assos Assos
  protected function setTranslatableProperties() {
953
954
    $values['drupalAcctProvisionServerDescription'] = t('Check ONE LDAP server configuration to use
955
      in provisioning Drupal users and their user fields.');
956
    $values['ldapEntryProvisionServerDescription'] = t('Check ONE LDAP server configuration to create ldap entries on.');
957
958
    $values['drupalAccountProvisionEventsDescription'] = t('Which user fields and properties are synched on create or synch is determined in the
959
      "Provisioning from LDAP to Drupal mappings" table below in the right two columns. If you are synching only from LDAP to Drupal, and not 
960
      retrieving the user password from LDAP into their Drupal account, a 20 character random password will be generated automatically for
961
      the user\'s Drupal account since Drupal requires a password for the "users" table. Check the watchdog at /admin/reports/dblog to
962
      confirm that a random password was generated when the user account was created.');
963
964 32700c57 Assos Assos
    $values['drupalAccountProvisionEventsOptions'] = [
965 85ad3d82 Assos Assos
      LDAP_USER_DRUPAL_USER_PROV_ON_AUTHENTICATE => t('Create or Synch to Drupal user on successful authentication with LDAP
966
        credentials. (Requires LDAP Authentication module).'),
967
      LDAP_USER_DRUPAL_USER_PROV_ON_USER_UPDATE_CREATE => t('Create or Synch to Drupal user anytime a Drupal user account
968
        is created or updated. Requires a server with binding method of "Service Account Bind" or "Anonymous Bind".'),
969 32700c57 Assos Assos
    ];
970 85ad3d82 Assos Assos
971
    $values['ldapEntryProvisionTriggersDescription'] = t('Which LDAP attributes are synched on create or synch is determined in the
972
      "Provisioning from Drupal to LDAP mappings" table below in the right two columns.');
973
974 32700c57 Assos Assos
    $values['ldapEntryProvisionTriggersOptions'] = [
975 85ad3d82 Assos Assos
      LDAP_USER_LDAP_ENTRY_PROV_ON_USER_UPDATE_CREATE => t('Create or Synch to LDAP entry when a Drupal account is created or updated.
976
        Only applied to accounts with a status of approved.'),
977
      LDAP_USER_LDAP_ENTRY_PROV_ON_AUTHENTICATE => t('Create or Synch to LDAP entry when a user authenticates.'),
978
      LDAP_USER_LDAP_ENTRY_DELETE_ON_USER_DELETE => t('Delete LDAP entry when the corresponding Drupal Account is deleted.  This only applies when the LDAP entry was provisioned by Drupal by the LDAP User module.'),
979
      LDAP_USER_DRUPAL_USER_PROV_ON_ALLOW_MANUAL_CREATE => t('Provide option on admin/people/create to create corresponding LDAP Entry.'),
980
981 32700c57 Assos Assos
    ];
982 85ad3d82 Assos Assos
983 be58a50c Assos Assos
    $values['orphanedDrupalAcctBehaviorDescription'] = t('It is highly recommended to use the "Perform no action, but email list of orphaned accounts" for some time before considering switching to "Disable the account" options.');
984 85ad3d82 Assos Assos
985 32700c57 Assos Assos
    $values['manualAccountConflictOptions'] = [
986 85ad3d82 Assos Assos
      LDAP_USER_MANUAL_ACCT_CONFLICT_REJECT => t('Reject manual creation of Drupal accounts that conflict with LDAP Accounts. This only applies to accounts created on user logon;  Account conflicts can still be generated by manually creating users that conflict with ldap users and these users will have their data synched with LDAP data.'),
987
      LDAP_USER_MANUAL_ACCT_CONFLICT_LDAP_ASSOCIATE => t('Associate manually created Drupal accounts with related LDAP Account if one exists.'),
988
      LDAP_USER_MANUAL_ACCT_CONFLICT_SHOW_OPTION_ON_FORM => t('Show option on user create form to determine how account conflict is resolved.'),
989 32700c57 Assos Assos
    ];
990 85ad3d82 Assos Assos
991
    /**
992
    *  Drupal Account Provisioning and Synching
993
    */
994
    $values['userConflictResolveDescription'] = t('What should be done if a local Drupal or other external
995
      user account already exists with the same login name.');
996 32700c57 Assos Assos
    $values['userConflictOptions'] = [
997 85ad3d82 Assos Assos
      LDAP_USER_CONFLICT_LOG => t('Don\'t associate Drupal account with LDAP.  Require user to use Drupal password. Log the conflict'),
998
      LDAP_USER_CONFLICT_RESOLVE => t('Associate Drupal account with the LDAP entry.  This option
999
      is useful for creating accounts and assigning roles before an LDAP user authenticates.'),
1000 32700c57 Assos Assos
    ];
1001 b42754b9 Assos Assos
    $values['accountsWithSameEmailDescription'] = t('Allows provisioning a Drupal user account from LDAP regardless of whether another Drupal user account has the same email address. This setting depends on the "sharedemail" contrib module being enabled. ');
1002
    if (!module_exists('sharedemail')) {
1003
      $values['accountsWithSameEmailDescription'] .= t('The module is not currently enabled; you must install/enable it if you want to use this setting.');
1004
    }
1005 32700c57 Assos Assos
    $values['accountsWithSameEmailOptions'] = [
1006 b42754b9 Assos Assos
      LDAP_USER_ACCOUNTS_WITH_SAME_EMAIL_DISABLED => t('Prevent provisioning a user account if an existing account has the same email address.'),
1007
      LDAP_USER_ACCOUNTS_WITH_SAME_EMAIL_ENABLED => t('Allow provisioning a user account that has the same email address as another user account.'),
1008 32700c57 Assos Assos
    ];
1009
    $values['acctCreationOptions'] = [
1010 85ad3d82 Assos Assos
      LDAP_USER_ACCT_CREATION_LDAP_BEHAVIOR => t('Account creation settings at
1011
        /admin/config/people/accounts/settings do not affect "LDAP Associated" Drupal accounts.'),
1012
      LDAP_USER_ACCT_CREATION_USER_SETTINGS_FOR_LDAP => t('Account creation policy
1013
         at /admin/config/people/accounts/settings applies to both Drupal and LDAP Authenticated users.
1014
         "Visitors" option automatically creates and account when they successfully LDAP authenticate.
1015
         "Admin" and "Admin with approval" do not allow user to authenticate until the account is approved.'),
1016
1017 32700c57 Assos Assos
    ];
1018 85ad3d82 Assos Assos
1019 32700c57 Assos Assos
    foreach ($values as $property => $default_value) {
1020
      $this->$property = $default_value;
1021 85ad3d82 Assos Assos
    }
1022 32700c57 Assos Assos
  }
1023 85ad3d82 Assos Assos
1024
}