Projet

Général

Profil

Paste
Télécharger (43,5 ko) Statistiques
| Branche: | Révision:

root / htmltest / sites / all / modules / ldap / ldap_user / LdapUserConfAdmin.class.php @ dd54aff9

1
<?php
2

    
3
/**
4
 * @file
5
 * This classextends by LdapUserConf for configuration and other admin functions
6
 */
7

    
8
module_load_include('php', 'ldap_user', 'LdapUserConf.class');
9
module_load_include('inc', 'user', 'user.pages');
10

    
11
class LdapUserConfAdmin extends LdapUserConf {
12

    
13
  /**
14
   * basic settings
15
   */
16

    
17
  protected $drupalAcctProvisionServerDescription;
18
  protected $drupalAcctProvisionServerOptions = array();
19
  protected $ldapEntryProvisionServerOptions = array();
20

    
21
  protected $drupalAccountProvisionEventsDescription;
22
  protected $drupalAccountProvisionEventsOptions = array();
23

    
24
  protected $ldapEntryProvisionTriggersDescription;
25
  protected $ldapEntryProvisionTriggersOptions = array();
26

    
27
  protected $synchFormRow = 0;
28

    
29
  /*
30
   * 3. Drupal Account Provisioning and Syncing
31
   */
32
  public $userConflictResolveDescription;
33
  public $userConflictResolveDefault = LDAP_USER_CONFLICT_RESOLVE_DEFAULT;
34
  public $userConflictOptions;
35

    
36
  public $acctCreationDescription = '';
37
  public $acctCreationDefault = LDAP_USER_ACCT_CREATION_LDAP_BEHAVIOR_DEFAULT;
38
  public $acctCreationOptions;
39

    
40

    
41
  public $errorMsg = NULL;
42
  public $hasError = FALSE;
43
  public $errorName = NULL;
44

    
45
  public function clearError() {
46
    $this->hasError = FALSE;
47
    $this->errorMsg = NULL;
48
    $this->errorName = NULL;
49
  }
50

    
51
  public function save() {
52
    foreach ($this->saveable as $property) {
53
      $save[$property] = $this->{$property};
54
    }
55
    variable_set('ldap_user_conf', $save);
56
    ldap_user_conf_cache_clear();
57
  }
58

    
59
  static public function uninstall() {
60
    variable_del('ldap_user_conf');
61
  }
62

    
63
  public function __construct() {
64
    parent::__construct();
65
    $this->setTranslatableProperties();
66

    
67
    if ($servers = ldap_servers_get_servers(NULL, 'enabled')) {
68
      $this->drupalAcctProvisionServerOptions[LDAP_USER_AUTH_SERVER_SID] = t('Use server which performed the authentication. Useful for multi-domain environments.');
69
      foreach ($servers as $sid => $ldap_server) {
70
        $enabled = ($ldap_server->status) ? 'Enabled' : 'Disabled';
71
        $this->drupalAcctProvisionServerOptions[$sid] = $ldap_server->name . ' (' . $ldap_server->address . ') Status: ' . $enabled;
72
        $this->ldapEntryProvisionServerOptions[$sid] = $ldap_server->name . ' (' . $ldap_server->address . ') Status: ' . $enabled;
73
      }
74
    }
75
    $this->drupalAcctProvisionServerOptions['none'] = t('None');
76
    $this->ldapEntryProvisionServerOptions['none'] = t('None');
77

    
78
  }
79

    
80

    
81
/**
82
 * generate admin form for ldapUserConf object
83
 *
84
 * @return array $form as drupal form api form array
85
 */
86
  public function drupalForm() {
87
    if (count($this->drupalAcctProvisionServerOptions) == 0) {
88
      $message = ldap_servers_no_enabled_servers_msg('configure LDAP User');
89
      $form['intro'] = array(
90
        '#type' => 'item',
91
        '#markup' => t('<h1>LDAP User Settings</h1>') . $message,
92
      );
93
      return $form;
94
    }
95
    $form['#storage'] = array();
96
    $form['#theme'] = 'ldap_user_conf_form';
97

    
98
    $form['intro'] = array(
99
      '#type' => 'item',
100
      '#markup' => t('<h1>LDAP User Settings</h1>'),
101
    );
102

    
103
    $form['manual_drupal_account_editing'] = array(
104
      '#type' => 'fieldset',
105
      '#title' => t('Manual Drupal Account Creation and Updates'),
106
      '#collapsible' => TRUE,
107
      '#collapsed' => FALSE,
108
    );
109

    
110
    $form['manual_drupal_account_editing']['manualAccountConflict'] = array(
111
      '#type' => 'radios',
112
      '#options' => $this->manualAccountConflictOptions,
113
      '#title' => t('How to resolve LDAP conflicts with manually  created Drupal accounts.'),
114
      '#description' => t('This applies only to accounts created manually through admin/people/create
115
        for which an LDAP entry can be found on the LDAP server selected in "LDAP Servers Providing Provisioning Data"'),
116
      '#default_value' => $this->manualAccountConflict,
117
    );
118

    
119
    $form['basic_to_drupal'] = array(
120
      '#type' => 'fieldset',
121
      '#title' => t('Basic Provisioning to Drupal Account Settings'),
122
      '#collapsible' => TRUE,
123
      '#collapsed' => FALSE,
124
    );
125

    
126
    $default_value = ($this->drupalAcctProvisionServer) ? $this->drupalAcctProvisionServer : 'none';
127
    $form['basic_to_drupal']['drupalAcctProvisionServer'] = array(
128
      '#type' => 'radios',
129
      '#title' => t('LDAP Servers Providing Provisioning Data'),
130
      '#required' => 1,
131
      '#default_value' => $default_value,
132
      '#options' => $this->drupalAcctProvisionServerOptions,
133
      '#description' => $this->drupalAcctProvisionServerDescription,
134
      '#states' => array(
135
        'enabled' => array(   // action to take.
136
          ':input[name=drupalAcctProvisionTriggers]' => array('value' => LDAP_USER_DRUPAL_USER_PROV_ON_AUTHENTICATE),
137
        ),
138
      ),
139
    );
140

    
141

    
142
    $form['basic_to_drupal']['drupalAcctProvisionTriggers'] = array(
143
      '#type' => 'checkboxes',
144
      '#title' => t('Drupal Account Provisioning Events'),
145
      '#required' => FALSE,
146
      '#default_value' => $this->drupalAcctProvisionTriggers,
147
      '#options' => $this->drupalAccountProvisionEventsOptions,
148
      '#description' => $this->drupalAccountProvisionEventsDescription,
149
    );
150

    
151
    $form['basic_to_drupal']['disableAdminPasswordField'] = array(
152
      '#type' => 'checkbox',
153
      '#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.'),
154
      '#default_value' => $this->disableAdminPasswordField,
155
    );
156

    
157
    $form['basic_to_drupal']['userConflictResolve'] = array(
158
      '#type' => 'radios',
159
      '#title' => t('Existing Drupal User Account Conflict'),
160
      '#required' => 1,
161
      '#default_value' => $this->userConflictResolve,
162
      '#options' => $this->userConflictOptions,
163
      '#description' => t( $this->userConflictResolveDescription),
164
    );
165

    
166
    $form['basic_to_drupal']['acctCreation'] = array(
167
      '#type' => 'radios',
168
      '#title' => t('Application of Drupal Account settings to LDAP Authenticated Users'),
169
      '#required' => 1,
170
      '#default_value' => $this->acctCreation,
171
      '#options' => $this->acctCreationOptions,
172
      '#description' => t($this->acctCreationDescription),
173
    );
174

    
175
    $account_options = array();
176
    $account_options['ldap_user_orphan_do_not_check'] = t('Do not check for orphaned Drupal accounts.');
177
    $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.)');
178
    foreach (user_cancel_methods() as $option_name => $option) {
179
      $account_options[$option_name] = $option['#title'];
180
    }
181

    
182
    //@todo these 2 options are removed until this feature is better tested in
183
    // actual production environments; it has potentially disastrous effects
184
    unset($account_options['user_cancel_reassign']);
185
    unset($account_options['user_cancel_delete']);
186

    
187
    $form['basic_to_drupal']['orphanedDrupalAcctBehavior'] = array(
188
      '#type' => 'radios',
189
      '#title' => t('Action to perform on Drupal account that no longer have a
190
        corresponding LDAP entry'),
191
      '#required' => 0,
192
      '#default_value' => $this->orphanedDrupalAcctBehavior,
193
      '#options' => $account_options,
194
      '#description' => t($this->orphanedDrupalAcctBehaviorDescription),
195
    );
196

    
197

    
198
    $form['basic_to_drupal']['orphanedCheckQty'] = array(
199
      '#type' => 'textfield',
200
      '#size' => 10,
201
      '#title' => t('Number of users to check each cron run.'),
202
      '#description' => t(''),
203
      '#default_value' => $this->orphanedCheckQty,
204
      '#required' => FALSE,
205
    );
206

    
207

    
208
    $form['basic_to_ldap'] = array(
209
      '#type' => 'fieldset',
210
      '#title' => t('Basic Provisioning to LDAP Settings'),
211
      '#collapsible' => TRUE,
212
      '#collapsed' => !($this->ldapEntryProvisionServer),
213
    );
214

    
215
    $default_value = ($this->ldapEntryProvisionServer) ? $this->ldapEntryProvisionServer : 'none';
216
    $form['basic_to_ldap']['ldapEntryProvisionServer'] = array(
217
      '#type' => 'radios',
218
      '#title' => t('LDAP Servers to Provision LDAP Entries on'),
219
      '#required' => 1,
220
      '#default_value' => $default_value,
221
      '#options' => $this->ldapEntryProvisionServerOptions,
222
      '#description' => $this->ldapEntryProvisionServerDescription,
223
    );
224

    
225
    $form['basic_to_ldap']['ldapEntryProvisionTriggers'] = array(
226
      '#type' => 'checkboxes',
227
      '#title' => t('LDAP Entry Provisioning Events'),
228
      '#required' => FALSE,
229
      '#default_value' => $this->ldapEntryProvisionTriggers,
230
      '#options' => $this->ldapEntryProvisionTriggersOptions,
231
      '#description' => $this->ldapEntryProvisionTriggersDescription
232
    );
233

    
234
/**
235
    $form['ws'] = array(
236
      '#type' => 'fieldset',
237
      '#title' => t('[Untested and Unfinished Code] REST Webservice for Provisioning and Synching.'),
238
      '#collapsible' => TRUE,
239
      '#collapsed' => !$this->wsEnabled,
240
      '#description' => t('Once configured, this webservice can be used to trigger creation, synching, deletion, etc of an LDAP associated Drupal account.'),
241
    );
242

243
    $form['ws']['wsEnabled'] = array(
244
      '#type' => 'checkbox',
245
      '#title' => t('Enable REST Webservice'),
246
      '#required' => FALSE,
247
      '#default_value' => $this->wsEnabled,
248
    );
249

250
    $form['ws']['wsUserIps'] = array(
251
      '#type' => 'textarea',
252
      '#title' => t('Allowed IP Addresses to request webservice.'),
253
      '#required' => FALSE,
254
      '#default_value' => join("\n", $this->wsUserIps),
255
      '#description' => t('One Per Line. The current server address is LOCAL_ADDR and the client ip requesting this page is REMOTE_ADDR .', $_SERVER),
256
      '#cols' => 20,
257
      '#rows' => 2,
258
      '#states' => array(
259
        'visible' => array(   // action to take.
260
          ':input[name="wsEnabled"]' => array('checked' => TRUE),
261
        ),
262
      ),
263
    );
264

265
    if (!$this->wsKey) {
266
      $urls = t('URLs are not available until a key is create a key and urls will be generated');
267
    }
268
    else {
269
      $urls = theme('item_list',
270
        array(
271
          'items' => ldap_user_ws_urls_item_list(),
272
          'title' => 'REST urls',
273
          'type' => 'ul',
274
        ));
275
    }
276

277
    $form['ws']['wsKey'] = array(
278
      '#type' => 'textfield',
279
      '#title' => t('Key for webservice'),
280
      '#required' => FALSE,
281
      '#default_value' => $this->wsKey,
282
      '#description' => t('Any random string of characters.') . $urls,
283
      '#states' => array(
284
        'visible' => array(   // action to take.
285
          ':input[name="wsEnabled"]' => array('checked' => TRUE),
286
        ),
287
      ),
288
    );
289
*/
290

    
291
    $form['server_mapping_preamble'] = array(
292
      '#type' => 'markup',
293
      '#markup' => t('
294
The relationship between a Drupal user and an LDAP entry is defined within the LDAP server configurations.
295

296

297
The mappings below are for user fields, properties, and profile2 data that are not automatically mapped elsewhere.
298
Mappings such as username or email address that are configured elsewhere are shown at the top for clarity.
299
When more than one ldap server is enabled for provisioning data (or simply more than one configuration for the same ldap server),
300
mappings need to be setup for each server.  If no tables are listed below, you have not enabled any provisioning servers at
301
the top of this form.
302
'),
303

    
304
    );
305

    
306
    foreach (array(LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER, LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) as $direction) {
307
      $sid = $this->provisionSidFromDirection[$direction];
308
      $ldap_server = ($sid) ? ldap_servers_get_servers($sid, NULL, TRUE) : FALSE;
309
      $ldap_server_selected = (boolean)$ldap_server;
310

    
311
      if ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) {
312
        $parent_fieldset = 'basic_to_drupal';
313
        $description =  t('Provisioning from LDAP to Drupal Mappings:');
314
      }
315
      elseif ($direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) {
316
        $parent_fieldset = 'basic_to_ldap';
317
        $description =   t('Provisioning from Drupal to LDAP Mappings:');
318
      }
319

    
320
      $form[$parent_fieldset]['mappings__' . $direction] = array(
321
        '#type' => 'fieldset',
322
        '#title' =>  $description,
323
        '#collapsible' => TRUE,
324
        '#collapsed' => FALSE,
325
        '#description' => '',
326
        'table__' . $direction => array(
327
          '#type' => 'markup',
328
          '#markup' => '[replace_with_table__' . $direction . ']',
329
        ),
330
      );
331

    
332

    
333
$password_notes = '<h3>' . t('Password Tokens') . '</h3><ul>' .
334
'<li>' . t('Pwd: Random -- Uses a random Drupal generated password') . '</li>' .
335
'<li>' . t('Pwd: User or Random -- Uses password supplied on user forms.
336
  If none available uses random password.') . '</li></ul>' .
337
'<h3>' . t('Password Concerns') . '</h3>' .
338
'<ul>' .
339
'<li>' . t('Provisioning passwords to LDAP means passwords must meet the LDAP\'s
340
password requirements.  Password Policy module can be used to add requirements.') . '</li>' .
341
'<li>' . t('Some LDAPs require a user to reset their password if it has been changed
342
by someone other that user.  Consider this when provisioning LDAP passwords.') . '</li>' .
343
'</ul></p>';
344

    
345

    
346
      $source_drupal_token_notes = <<<EOT
347
<p>Examples in form: Source Drupal User token => Target LDAP Token (notes)</p>
348
<ul>
349
<li>Source Drupal User token => Target LDAP Token</li>
350
<li>cn=[property.name],ou=test,dc=ad,dc=mycollege,dc=edu => [dn] (example of token and constants)</li>
351
<li>top => [objectclass:0] (example of constants mapped to multivalued attribute)</li>
352
<li>person => [objectclass:1] (example of constants mapped to multivalued attribute)</li>
353
<li>organizationalPerson => [objectclass:2] (example of constants mapped to multivalued attribute)</li>
354
<li>user => [objectclass:3] (example of constants mapped to multivalued attribute)</li>
355
<li>Drupal Provisioned LDAP Account => [description] (example of constant)</li>
356
<li>[field.field_lname] => [sn]</li>
357

358
</ul>
359
EOT;
360

    
361
      if ($direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) { // add some password notes
362
        $form[$parent_fieldset]['password_notes'] = array(
363
          '#type' => 'fieldset',
364
          '#title' =>  t('Password Notes'),
365
          '#collapsible' => TRUE,
366
          '#collapsed' => TRUE,
367
          'directions' => array(
368
            '#type' => 'markup',
369
            '#markup' => $password_notes,
370
          ),
371
        );
372
        $form[$parent_fieldset]['source_drupal_token_notes'] = array(
373
          '#type' => 'fieldset',
374
          '#title' =>  t('Source Drupal User Tokens and Corresponding Target LDAP Tokens'),
375
          '#collapsible' => TRUE,
376
          '#collapsed' => TRUE,
377
          'directions' => array(
378
            '#type' => 'markup',
379
            '#markup' => $source_drupal_token_notes,
380
          ),
381
        );
382
      }
383
      $this->addServerMappingFields($form, $direction);
384
    }
385

    
386
    foreach (array('orphanedCheckQty', 'orphanedDrupalAcctBehavior', 'acctCreation', 'userConflictResolve', 'drupalAcctProvisionTriggers', 'mappings__' . LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) as $input_name) {
387
      $form['basic_to_drupal'][$input_name]['#states']['invisible'] =
388
        array(
389
          ':input[name=drupalAcctProvisionServer]' => array('value' => 'none'),
390
        );
391
    }
392

    
393
    foreach (array('ldapEntryProvisionTriggers', 'password_notes', 'source_drupal_token_notes', 'mappings__' . LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) as $input_name) {
394
      $form['basic_to_ldap'][$input_name]['#states']['invisible'] =
395
        array(
396
          ':input[name=ldapEntryProvisionServer]' => array('value' => 'none'),
397
        );
398
    }
399

    
400
    $form['submit'] = array(
401
      '#type' => 'submit',
402
      '#value' => 'Save',
403
    );
404

    
405
  return $form;
406
}
407

    
408

    
409

    
410
/**
411
 * validate submitted form
412
 *
413
 * @param array $values as $form_state['values'] from drupal form api
414
 * @param array $storage as $form_state['storage'] from drupal form api
415
 *
416
 * @return array in form array($errors, $warnings)to be thrown by form api
417
 */
418
  public function drupalFormValidate($values, $storage)  {
419
    $this->populateFromDrupalForm($values, $storage);
420
    list($errors, $warnings) = $this->validate($values);
421

    
422
    // since failed mapping rows in form, don't populate ->ldapUserSynchMappings, need to validate these from values
423
    foreach ($values as $field => $value) {
424
      $parts = explode('__', $field);
425
      // since synch mapping fields are in n-tuples, process entire n-tuple at once (on field == configurable_to_drupal)
426
      if (count($parts) != 4 || $parts[1] !== 'sm' || $parts[2] != 'configurable_to_drupal') {
427
        continue;
428
      }
429
      list($direction, $discard, $column_name, $i) = $parts;
430
      $action = $storage['synch_mapping_fields'][$direction][$i]['action'];
431
      $tokens = array();
432
      $row_mappings = array();
433
      foreach (array('remove', 'configurable_to_drupal', 'configurable_to_ldap', 'convert', 'direction', 'ldap_attr', 'user_attr', 'user_tokens') as $column_name) {
434
        $input_name = join('__', array('sm', $column_name, $i));
435
        $row_mappings[$column_name] = isset($values[$input_name]) ? $values[$input_name] : NULL;
436
      }
437

    
438
      $has_values = $row_mappings['ldap_attr'] || $row_mappings['user_attr'];
439
      if ($has_values) {
440
        $tokens['%ldap_attr'] = $row_mappings['ldap_attr'];
441
        $row_descriptor = t("server %sid row mapping to ldap attribute %ldap_attr", $tokens);
442
        $tokens['!row_descriptor'] = $row_descriptor;
443
        if (!$row_mappings['direction']) {
444
          $input_name = join('__', array('sm', 'direction', $i));
445
          $errors[$input_name] = t('No mapping direction given in !row_descriptor', $tokens);
446
        }
447
        if ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER && $row_mappings['user_attr'] == 'user_tokens') {
448
          $input_name = join('__', array('sm', 'user_attr', $i));
449
          $errors[$input_name] =  t('User tokens not allowed when mapping to Drupal user.  Location: !row_descriptor', $tokens);
450
        }
451
        if (!$row_mappings['ldap_attr']) {
452
          $input_name = join('__', array('sm', 'ldap_attr', $i));
453
          $errors[$input_name] = t('No ldap attribute given in !row_descriptor', $tokens);
454
        }
455
        if (!$row_mappings['user_attr']) {
456
          $input_name = join('__', array('sm', 'user_attr', $i));
457
          $errors[$input_name] = t('No user attribute given in !row_descriptor', $tokens);
458
        }
459
      }
460

    
461
    }
462
    return array($errors, $warnings);
463
  }
464

    
465
/**
466
 * validate object, not form
467
 * @param array $values as $form_state['values'] from drupal form api
468
 * @return array in form array($errors, $warnings)to be thrown by form api
469
 *
470
 * @todo validate that a user field exists, such as field.field_user_lname
471
 *
472
 */
473
  public function validate($values) {
474
    $errors = array();
475
    $warnings = array();
476
    $tokens = array();
477

    
478
    $has_drupal_acct_prov_servers  = (boolean)($this->drupalAcctProvisionServer);
479
    $has_drupal_acct_prov_settings_options  = (count(array_filter($this->drupalAcctProvisionTriggers)) > 0);
480

    
481
    if (!$has_drupal_acct_prov_servers && $has_drupal_acct_prov_settings_options) {
482
      $warnings['drupalAcctProvisionServer'] =  t('No Servers are enabled to provide provisioning to Drupal, but Drupal Account Provisioning Options are selected.', $tokens);
483
    }
484
    if ($has_drupal_acct_prov_servers && !$has_drupal_acct_prov_settings_options) {
485
      $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);
486
    }
487

    
488
    $has_ldap_prov_servers = (boolean)($this->ldapEntryProvisionServer);
489
    $has_ldap_prov_settings_options = (count(array_filter($this->ldapEntryProvisionTriggers)) > 0);
490
    if (!$has_ldap_prov_servers && $has_ldap_prov_settings_options) {
491
      $warnings['ldapEntryProvisionServer'] =  t('No Servers are enabled to provide provisioning to ldap, but LDAP Entry Options are selected.', $tokens);
492
    }
493
    if ($has_ldap_prov_servers && !$has_ldap_prov_settings_options) {
494
      $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);
495
    }
496

    
497
    if (isset($this->ldapUserSynchMappings)) {
498
      $to_ldap_entries_mappings_exist = FALSE;
499
      foreach ($this->ldapUserSynchMappings as $synch_direction => $mappings) {
500
        $map_index = array();
501
        $tokens = array(); // array('%sid' => $sid);
502
        $to_drupal_user_mappings_exist = FALSE;
503
        $to_ldap_entries_mappings_exist = FALSE;
504

    
505
        foreach ($mappings as $target_attr => $mapping) {
506
          if ($mapping['direction'] == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) {
507
            $attr_value = $mapping['user_attr'];
508
            $attr_name = 'user_attr';
509
          }
510
          if ($mapping['direction'] == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) {
511
            $attr_value = $mapping['ldap_attr'];
512
            $attr_name = 'ldap_attr';
513
          }
514
          foreach ($values as $field => $value) {
515
            $parts = explode('__', $field);
516
            if (count($parts) == 4 && $parts[2] == $attr_name && $value == $attr_value) {
517
              $map_index[$attr_value] = $parts[3];
518
            }
519
          }
520
        }
521

    
522
        foreach ($mappings as $target_attr => $mapping) {
523
          foreach ($mapping as $key => $value) {
524
            if (is_scalar($value)) {
525
              $tokens['%' . $key] = $value;
526
            }
527
          }
528
          $row_descriptor = t("server %sid row mapping to ldap attribute %ldap_attr", $tokens);
529
          $tokens['!row_descriptor'] = $row_descriptor;
530
          $ldap_attribute_maps_in_token = array();
531
         // debug('calling ldap_servers_token_extract_attributes from validate, mapping='); debug($mapping['ldap_attr']);
532
          ldap_servers_token_extract_attributes($ldap_attribute_maps_in_token, $mapping['ldap_attr']);
533

    
534
          if ($mapping['direction'] == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) {
535
            $row_id = $map_index[$mapping['user_attr']];
536
            $to_drupal_user_mappings_exist = TRUE;
537
          //  if (!$is_drupal_user_prov_server) {
538
           //   $errors['mappings__'. $sid] =  t('Mapping rows exist for provisioning to drupal user, but server %sid is not enabled for provisioning
539
            //    to drupal users.', $tokens);
540
          //  }
541
          }
542
          if ($mapping['direction'] == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) {
543
            $row_id = $map_index[$mapping['ldap_attr']];
544
            $to_ldap_entries_mappings_exist = TRUE;
545
           // if (!$is_ldap_entry_prov_server) {
546
            //  $errors['mappings__'. $sid] =  t('Mapping rows exist for provisioning to ldap entries,
547
            //    but server %sid is not enabled for provisioning
548
             //   to ldap entries.', $tokens);
549
           // }
550

    
551
            if (count(array_keys($ldap_attribute_maps_in_token)) != 1) {
552
              $token_field_id = join('__', array('sm', 'user_tokens', $row_id));
553
              $errors[$token_field_id] =  t('When provisioning to ldap, ldap attribute column must be singular token such as [cn]. %ldap_attr is not.
554
                Do not use compound tokens such as "[displayName] [sn]" or literals such as "physics". Location: !row_descriptor', $tokens);
555
            }
556

    
557
          }
558
          $ldap_attr_field_id = join('__', array('sm', 'ldap_attr', $row_id));
559
          $user_attr_field_id = join('__', array('sm', 'user_attr', $row_id));
560
          $first_context_field_id = join('__', array('sm', 1, $row_id));
561
          $user_tokens_field_id = join('__', array('sm', 'user_tokens', $row_id));
562

    
563
          if (!$mapping['ldap_attr']) {
564
            $errors[$ldap_attr_field_id] =  t('No LDAP Attribute given in !row_descriptor', $tokens);
565
          }
566
          if ($mapping['user_attr'] == 'user_tokens' && !$mapping['user_tokens']) {
567
            $errors[$user_tokens_field_id] =  t('User tokens selected in !row_descriptor, but user tokens column empty.', $tokens);
568
          }
569

    
570
          if (isset($mapping['prov_events']) && count($mapping['prov_events']) == 0) {
571
            $warnings[$first_context_field_id] =  t('No synchronization events checked in !row_descriptor.
572
              This field will not be synchronized until some are checked.', $tokens);
573
          }
574
        }
575
      }
576
      if ($to_ldap_entries_mappings_exist && !isset($mappings['[dn]'])) {
577
        $errors['mappings__' . $synch_direction] =  t('Mapping rows exist for provisioning to ldap, but no ldap attribute is targetted for [dn].
578
          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');
579
      }
580
    }
581
    return array($errors, $warnings);
582
  }
583

    
584
  /**
585
   * populate object with data from form values
586
   *
587
   * @param array $values as $form_state['values'] from drupal form api
588
   * @param array $storage as $form_state['storage'] from drupal form api
589
   */
590
  protected function populateFromDrupalForm($values, $storage) {
591
    $this->drupalAcctProvisionServer = ($values['drupalAcctProvisionServer'] == 'none') ? 0 : $values['drupalAcctProvisionServer'];
592
    $this->ldapEntryProvisionServer = ($values['ldapEntryProvisionServer']  == 'none') ? 0 : $values['ldapEntryProvisionServer'];
593

    
594
    $this->drupalAcctProvisionTriggers = $values['drupalAcctProvisionTriggers'];
595
    $this->ldapEntryProvisionTriggers = $values['ldapEntryProvisionTriggers'];
596
    $this->orphanedDrupalAcctBehavior = $values['orphanedDrupalAcctBehavior'];
597
    $this->orphanedCheckQty = $values['orphanedCheckQty'];
598

    
599
    $this->manualAccountConflict = $values['manualAccountConflict'];
600
    $this->userConflictResolve  = ($values['userConflictResolve']) ? (int)$values['userConflictResolve'] : NULL;
601
    $this->acctCreation  = ($values['acctCreation']) ? (int)$values['acctCreation'] : NULL;
602
    $this->disableAdminPasswordField = $values['disableAdminPasswordField'];
603
   // $this->wsKey  = ($values['wsKey']) ? $values['wsKey'] : NULL;
604

    
605
   // $this->wsUserIps  = ($values['wsUserIps']) ? explode("\n", $values['wsUserIps']) : array();
606
  //  foreach ($this->wsUserIps as $i => $ip) {
607
  //    $this->wsUserIps[$i] = trim($ip);
608
  //  }
609
   // $this->wsEnabled  = ($values['wsEnabled']) ? (int)$values['wsEnabled'] : 0;
610

    
611
    $this->ldapUserSynchMappings = $this->synchMappingsFromForm($values, $storage);
612

    
613
  }
614

    
615

    
616

    
617
/**
618
 *  Extract synch mappings array from mapping table in admin form.
619
 *
620
 * @param array $values as $form_state['values'] from drupal form api
621
 * @param array $storage as $form_state['storage'] from drupal form api
622
 *
623
 * $values input names in form:
624
 *   1__sm__configurable__5,
625
 *   1__sm__remove__5,
626
 *   1__sm__ldap_attr__5,
627
 *   1__sm__convert__5,
628
 *   1__sm__direction__5,
629
 *   1__sm__user_attr__5,
630
 *   1__sm__user_tokens__5
631
 *   1__sm__1__5,
632
 *   1__sm__2__5,
633
    ...where
634
      -- first arg is direction, eg 1 or 2 LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER or LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY
635
      -- second arg is discarded ('sm')
636
      -- third part is field, e.g. user_attr
637
      -- fourth is the row in the configuration form, e.g. 5
638

639
   where additiond data is in $form['#storage'][<direction>]['synch_mapping_fields'][N]
640
    $form['#storage']['synch_mapping_fields'][<direction>][N] = array(
641
      'sid' => $sid,
642
      'action' => 'add',
643
    );
644
 */
645
  private function synchMappingsFromForm($values, $storage) {
646

    
647
    $mappings = array();
648
    foreach ($values as $field => $value) {
649

    
650
      $parts = explode('__', $field);
651
      // since synch mapping fields are in n-tuples, process entire n-tuple at once
652
      if (count($parts) != 4 || $parts[1] !== 'sm') {
653
        continue;
654
      }
655

    
656
      list($direction, $discard, $column_name, $i) = $parts;
657
      $action = $storage['synch_mapping_fields'][$direction][$i]['action'];
658

    
659
      $row_mappings = array();
660
      foreach (array('remove', 'configurable_to_drupal', 'configurable_to_ldap', 'convert', 'ldap_attr', 'user_attr', 'user_tokens') as $column_name) {
661
        $input_name = join('__', array($direction, 'sm', $column_name, $i));
662
        $row_mappings[$column_name] = isset($values[$input_name]) ? $values[$input_name] : NULL;
663
      }
664

    
665
      if ($row_mappings['remove']) {
666
        continue;
667
      }
668

    
669
      $key = ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) ? $row_mappings['user_attr'] : $row_mappings['ldap_attr'];
670
      if ($row_mappings['configurable_to_drupal'] && $row_mappings['ldap_attr'] && $row_mappings['user_attr']) {
671
        $mappings[$direction][$key] = array(
672
          'ldap_attr' => $row_mappings['ldap_attr'],
673
          'user_attr' => $row_mappings['user_attr'],
674
          'convert' => $row_mappings['convert'],
675
          'direction' => $direction,
676
          'user_tokens' => $row_mappings['user_tokens'],
677
          'config_module' => 'ldap_user',
678
          'prov_module' => 'ldap_user',
679
          'enabled' => 1,
680
          );
681

    
682
        $synchEvents = ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) ? $this->provisionsDrupalEvents : $this->provisionsLdapEvents;
683
        foreach ($synchEvents as $prov_event => $discard) {
684
          $input_name = join('__', array($direction, 'sm', $prov_event, $i));
685
          if (isset($values[$input_name]) && $values[$input_name]) {
686
            $mappings[$direction][$key]['prov_events'][] = $prov_event;
687
          }
688
        }
689
      }
690
    }
691

    
692
    return $mappings;
693
  }
694

    
695
  /**
696
   * method to respond to successfully validated form submit.
697
   *
698
   * @param array $values as $form_state['values'] from drupal form api
699
   * @param array $storage as $form_state['storage'] from drupal form api
700
   *
701
   * @return by reference to $form array
702
   */
703
  public function drupalFormSubmit($values, $storage) {
704

    
705
    $this->populateFromDrupalForm($values, $storage);
706

    
707
    try {
708
      $save_result = $this->save();
709
    }
710
    catch (Exception $e) {
711
      $this->errorName = 'Save Error';
712
      $this->errorMsg = t('Failed to save object.  Your form data was not saved.');
713
      $this->hasError = TRUE;
714
    }
715

    
716
  }
717

    
718
  /**
719
   * add existing mappings to ldap user provisioning mapping admin form table
720
   *
721
   * @param drupal form array $form
722
   * @param enum $direction LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER or LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY
723
   *
724
   * @return by reference to $form array
725
   */
726

    
727
  private function addServerMappingFields(&$form, $direction) {
728

    
729
    if ($direction == LDAP_USER_PROV_DIRECTION_NONE) {
730
      return;
731
    }
732

    
733
    $text = ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) ? 'target' : 'source';
734
    $user_attr_options = array('0' => t('Select') . ' ' . $text);
735

    
736
    if (!empty($this->synchMapping[$direction])) {
737
      foreach ($this->synchMapping[$direction] as $target_id => $mapping) {
738
        if (!isset($mapping['name']) || isset($mapping['exclude_from_mapping_ui']) && $mapping['exclude_from_mapping_ui']) {
739
          continue;
740
        }
741
        if (
742
          (isset($mapping['configurable_to_drupal']) && $mapping['configurable_to_drupal'] && $direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER)
743
          ||
744
          (isset($mapping['configurable_to_ldap']) && $mapping['configurable_to_ldap']  && $direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY)
745
          ) {
746
          $user_attr_options[$target_id] = substr($mapping['name'], 0, 25);
747
        }
748
      }
749
    }
750
    $user_attr_options['user_tokens'] = '-- user tokens --';
751

    
752
    $row = 0;
753

    
754
    // 1. non configurable mapping rows
755
    foreach ($this->synchMapping[$direction] as $target_id => $mapping) {
756
      if (isset($mapping['exclude_from_mapping_ui']) && $mapping['exclude_from_mapping_ui']) {
757
        continue;
758
      }
759
      if ( !$this->isMappingConfigurable($mapping, 'ldap_user') && ($mapping['direction'] == $direction || $mapping['direction'] == LDAP_USER_PROV_DIRECTION_ALL)) { // is configurable by ldap_user module (not direction to ldap_user)
760
        $this->addSynchFormRow($form, 'nonconfigurable', $direction, $mapping, $user_attr_options, $row);
761
        $row++;
762
      }
763
    }
764

    
765
    // 2. existing configurable mappings rows
766
    if (!empty($this->ldapUserSynchMappings[$direction])) {
767
      foreach ($this->ldapUserSynchMappings[$direction] as $target_attr_token => $mapping) {  // key could be ldap attribute name or user attribute name
768
        if (isset($mapping['enabled']) && $mapping['enabled'] && $this->isMappingConfigurable($this->synchMapping[$direction][$target_attr_token], 'ldap_user')) {
769
          $this->addSynchFormRow($form, 'update', $direction, $mapping, $user_attr_options, $row);
770
          $row++;
771
        }
772
      }
773
    }
774

    
775
    // 3. leave 4 rows for adding more mappings
776
    for ($i=0; $i<4; $i++) {
777
      $this->addSynchFormRow($form, 'add', $direction, NULL, $user_attr_options, $row);
778
      $row++;
779
    }
780

    
781
  }
782

    
783
  /**
784
   * add mapping form row to ldap user provisioning mapping admin form table
785
   *
786
   * @param drupal form array $form
787
   * @param string $action is 'add', 'update', or 'nonconfigurable'
788
   * @param enum $direction LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER or LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY
789
   * @param array $mapping is current setting for updates or nonconfigurable items
790
   * @param array $user_attr_options of drupal user target options
791
   * @param int $row is current row in table
792

793
   *
794
   * @return by reference to $form
795
   */
796
  private function addSynchFormRow(&$form, $action, $direction, $mapping, $user_attr_options, $row) {
797

    
798
    $id_prefix = $direction . '__';
799

    
800
    $id = $id_prefix . 'sm__remove__' . $row;
801
    $form[$id] = array(
802
      '#id' => $id,
803
      '#row' => $row,
804
      '#col' => 0,
805
      '#type' => 'checkbox',
806
      '#default_value' => NULL,
807
      '#disabled' => ($action == 'add' || $action == 'nonconfigurable'),
808
    );
809

    
810
    $id =  $id_prefix . 'sm__convert__' . $row;
811
    $form[$id] = array(
812
      '#id' => $id,
813
      '#row' => $row,
814
      '#col' => ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) ? 2 : 3,
815
      '#type' => 'checkbox',
816
      '#default_value' =>  isset($mapping['convert']) ? $mapping['convert'] : '',
817
      '#disabled' => ($action == 'nonconfigurable'),
818
      '#attributes' => array('class' => array('convert')),
819
    );
820

    
821
    $id =  $id_prefix . 'sm__ldap_attr__' . $row;
822
    $col = ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) ? 1 : 4;
823
    if ($action == 'nonconfigurable') {
824
      $form[$id] = array(
825
        '#id' => $id,
826
        '#row' => $row,
827
        '#col' => $col,
828
        '#type' => 'item',
829
        '#markup' => isset($mapping['source']) ? $mapping['source'] : '?',
830
        '#attributes' => array('class' => array('source')),
831
      );
832
    }
833
    else {
834
      $form[$id] = array(
835
        '#id' => $id,
836
        '#row' => $row,
837
        '#col' => $col,
838
        '#type' => 'textfield',
839
        '#default_value' => isset($mapping['ldap_attr']) ? $mapping['ldap_attr'] : '',
840
        '#size' => 20,
841
        '#maxlength' => 255,
842
        '#attributes' => array('class' => array('ldap-attr')),
843
      );
844
    }
845

    
846
    $user_attr_input_id =  $id_prefix . 'sm__user_attr__' . $row;
847
    $col = ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) ? 3 : 1;
848
    if ($action == 'nonconfigurable') {
849
      $form[$user_attr_input_id] = array(
850
        '#id' => $user_attr_input_id,
851
        '#row' => $row,
852
        '#col' => $col,
853
        '#type' => 'item',
854
        '#markup' => isset($mapping['name']) ? $mapping['name'] : '?',
855
      );
856
    }
857
    else {
858
      $form[$user_attr_input_id] = array(
859
        '#id' => $user_attr_input_id,
860
        '#row' => $row,
861
        '#col' => $col,
862
        '#type' => 'select',
863
        '#default_value' => isset($mapping['user_attr']) ? $mapping['user_attr'] : '',
864
        '#options' => $user_attr_options,
865
      );
866
    }
867

    
868
    if ($direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) {
869
      $id =  $id_prefix . 'sm__user_tokens__' . $row;
870
      $form[$id] = array(
871
        '#id' => $id,
872
        '#row' => $row,
873
        '#col' =>  2,
874
        '#type' => 'textfield',
875
        '#default_value' => isset($mapping['user_tokens']) ? $mapping['user_tokens'] : '',
876
        '#size' => 40,
877
        '#maxlength' => 255,
878
        '#disabled' => ($action == 'nonconfigurable'),
879
        '#states' => array(
880
          'visible' => array(   // action to take.
881
            ':input[name="' . $user_attr_input_id . '"]' => array('value' => 'user_tokens'),
882
          )
883
        ),
884
        '#attributes' => array('class' => array('tokens')),
885
      );
886
    }
887

    
888
    $form['#storage']['synch_mapping_fields'][$direction][$row] = array(
889
      'action' => $action,
890
      'direction' => $direction,
891
    );
892

    
893
    $id = $id_prefix . 'sm__configurable_to_drupal__' . $row;
894
    $form[$id] = array(
895
      '#id' => $id,
896
      '#type' => 'hidden',
897
      '#default_value' => ($action != 'nonconfigurable'),
898
    );
899

    
900

    
901
    $col = ($direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) ? 5 : 4;
902
    $synchEvents = ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) ? $this->provisionsDrupalEvents : $this->provisionsLdapEvents;
903

    
904
    foreach ($synchEvents as $prov_event => $prov_event_name) {
905
      $col++;
906
      $id =  $id_prefix . join('__', array('sm', $prov_event, $row));
907
      $form[$id] = array(
908
        '#id' => $id ,
909
        '#type' => 'checkbox',
910
        '#default_value' => isset($mapping['prov_events']) ? (int)(in_array($prov_event, $mapping['prov_events'])) : '',
911
        '#row' => $row,
912
        '#col' => $col,
913
        '#disabled' => (!$this->provisionEventConfigurable($prov_event, $mapping) || ($action == 'nonconfigurable')),
914
        '#attributes' => array('class' => array('synch-method')),
915
      );
916
    }
917
  }
918

    
919
  /**
920
   * Is a mapping configurable by a given module?
921
   *
922
   * @param array $mapping as mapping configuration for field, attribute, property, etc.
923
   * @param string $module machine name such as ldap_user
924
   *
925
   * @return boolean
926
   */
927
  private function isMappingConfigurable($mapping = NULL, $module = 'ldap_user') {
928
    $configurable = (
929
      (
930
        (!isset($mapping['configurable_to_drupal']) && !isset($mapping['configurable_to_ldap'])) ||
931
        (isset($mapping['configurable_to_drupal']) && $mapping['configurable_to_drupal']) ||
932
        (isset($mapping['configurable_to_ldap']) && $mapping['configurable_to_ldap'])
933
      )
934
      &&
935
      (
936
        !isset($mapping['config_module']) ||
937
        (isset($mapping['config_module']) && $mapping['config_module'] == $module)
938
      )
939
    );
940
    return $configurable;
941
  }
942

    
943

    
944
  /**
945
   * Is a particular synch method viable for a given mapping?
946
   * That is, Can it be enabled in the UI by admins?
947
   *
948
   * @param int $prov_event
949
   * @param array $mapping is array of mapping configuration.
950
   *
951
   * @return boolean
952
   */
953

    
954
  private function provisionEventConfigurable($prov_event, $mapping = NULL) {
955

    
956
    if ($mapping) {
957
      if ($prov_event == LDAP_USER_EVENT_CREATE_LDAP_ENTRY || $prov_event == LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY) {
958
        $configurable = (boolean)(!isset($mapping['configurable_to_ldap']) || $mapping['configurable_to_ldap']);
959
      }
960
      elseif ($prov_event == LDAP_USER_EVENT_CREATE_DRUPAL_USER || $prov_event == LDAP_USER_EVENT_SYNCH_TO_DRUPAL_USER) {
961
        $configurable = (boolean)(!isset($mapping['configurable_to_drupal']) || $mapping['configurable_to_drupal']);
962
      }
963
    }
964
    else {
965
      $configurable = TRUE;
966
    }
967

    
968
    return $configurable;
969
  }
970

    
971
  protected function setTranslatableProperties() {
972

    
973
    $values['drupalAcctProvisionServerDescription'] = t('Check ONE LDAP server configuration to use
974
      in provisioning Drupal users and their user fields.');
975
    $values['ldapEntryProvisionServerDescription'] = t('Check ONE LDAP server configuration to create ldap entries on.');
976

    
977
    $values['drupalAccountProvisionEventsDescription'] = t('Which user fields and properties are synched on create or synch is determined in the
978
      "Provisioning from LDAP to Drupal mappings" table below in the right two columns. If you are synching only from LDAP to Drupal, and not 
979
      retrieving the user password from LDAP into their Drupal account, a 20 character random password will be generated automatically for
980
      the user\'s Drupal account since Drupal requires a password for the "users" table. Check the watchdog at /admin/reports/dblog to
981
      confirm that a random password was generated when the user account was created.');
982

    
983
    $values['drupalAccountProvisionEventsOptions'] = array(
984
      LDAP_USER_DRUPAL_USER_PROV_ON_AUTHENTICATE => t('Create or Synch to Drupal user on successful authentication with LDAP
985
        credentials. (Requires LDAP Authentication module).'),
986
      LDAP_USER_DRUPAL_USER_PROV_ON_USER_UPDATE_CREATE => t('Create or Synch to Drupal user anytime a Drupal user account
987
        is created or updated. Requires a server with binding method of "Service Account Bind" or "Anonymous Bind".'),
988
      );
989

    
990
    $values['ldapEntryProvisionTriggersDescription'] = t('Which LDAP attributes are synched on create or synch is determined in the
991
      "Provisioning from Drupal to LDAP mappings" table below in the right two columns.');
992

    
993
    $values['ldapEntryProvisionTriggersOptions'] = array(
994
      LDAP_USER_LDAP_ENTRY_PROV_ON_USER_UPDATE_CREATE => t('Create or Synch to LDAP entry when a Drupal account is created or updated.
995
        Only applied to accounts with a status of approved.'),
996
      LDAP_USER_LDAP_ENTRY_PROV_ON_AUTHENTICATE => t('Create or Synch to LDAP entry when a user authenticates.'),
997
      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.'),
998
      LDAP_USER_DRUPAL_USER_PROV_ON_ALLOW_MANUAL_CREATE => t('Provide option on admin/people/create to create corresponding LDAP Entry.'),
999

    
1000
    );
1001

    
1002
    $values['orphanedDrupalAcctBehaviorDescription'] = '<ul>' .
1003
       '<li style="color: red">' . t('This is a new feature as of 11/7/2012!
1004
        It is highly recommended to use the "Perform no action,
1005
        but email list of orphaned accounts" for some time before using the
1006
        "Disable the account" options.') . '</li>' .
1007

    
1008
      '<li>' . t('These actions will only occur if the query to server is successful
1009
      and does not return a user entry.  If the ldap server is down or otherwise
1010
      cannot be connected to, no actions
1011
      will be performed.') . '</li>' .
1012

    
1013
      '<li>' .
1014
      t('When initially using this option, its best to simply check email and
1015
        delete the accounts by hand.  When you are happy with the
1016
      behavior, switch to one of the automated options.') . '</li>' .
1017

    
1018
      '</ul>';
1019

    
1020

    
1021
    $values['manualAccountConflictOptions'] =  array(
1022
      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.'),
1023
      LDAP_USER_MANUAL_ACCT_CONFLICT_LDAP_ASSOCIATE => t('Associate manually created Drupal accounts with related LDAP Account if one exists.'),
1024
      LDAP_USER_MANUAL_ACCT_CONFLICT_SHOW_OPTION_ON_FORM => t('Show option on user create form to determine how account conflict is resolved.'),
1025
    );
1026

    
1027
    /**
1028
    *  Drupal Account Provisioning and Synching
1029
    */
1030
    $values['userConflictResolveDescription'] = t('What should be done if a local Drupal or other external
1031
      user account already exists with the same login name.');
1032
    $values['userConflictOptions'] = array(
1033
      LDAP_USER_CONFLICT_LOG => t('Don\'t associate Drupal account with LDAP.  Require user to use Drupal password. Log the conflict'),
1034
      LDAP_USER_CONFLICT_RESOLVE => t('Associate Drupal account with the LDAP entry.  This option
1035
      is useful for creating accounts and assigning roles before an LDAP user authenticates.'),
1036
      );
1037

    
1038
    $values['acctCreationOptions'] = array(
1039
      LDAP_USER_ACCT_CREATION_LDAP_BEHAVIOR => t('Account creation settings at
1040
        /admin/config/people/accounts/settings do not affect "LDAP Associated" Drupal accounts.'),
1041
      LDAP_USER_ACCT_CREATION_USER_SETTINGS_FOR_LDAP => t('Account creation policy
1042
         at /admin/config/people/accounts/settings applies to both Drupal and LDAP Authenticated users.
1043
         "Visitors" option automatically creates and account when they successfully LDAP authenticate.
1044
         "Admin" and "Admin with approval" do not allow user to authenticate until the account is approved.'),
1045

    
1046
      );
1047

    
1048
      foreach ($values as $property => $default_value) {
1049
        $this->$property = $default_value;
1050
      }
1051
    }
1052

    
1053
}