class_attribute.inc 78.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php
/*
  This code is part of FusionDirectory (http://www.fusiondirectory.org/)
  Copyright (C) 2012  FusionDirectory

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/

/*! \brief This class allow to handle easily any kind of LDAP attribute
 *
 */
class Attribute
{
  /* \brief Name of this attribute in the LDAP */
  private $ldapName;
  /* \brief Label of this attribute in the form */
  private $label;
  /* \brief Description of this attribute */
  private $description;
  /* \brief Is this attribute mandatory */
  private $required;
  /* \brief Should this attribute be saved into the LDAP */
  private $inLdap = TRUE;
36
37
  /* \brief Should this attribute be unique
   * FALSE  -> no unicity check
38
   * one    -> unicity check in the same base -> broken right now because of object ous
39
40
41
42
   * sub    -> unicity check in the same subtree
   *  \__> this should not be used as it’s breaking reciprocity
   * whole  -> unicity check in the whole LDAP
   */
43
44
  private $unique = FALSE;

45
46
  /* \brief Prefix for the html id */
  protected $htmlid_prefix = '';
47
  /* \brief Should this attribute be shown */
48
49
50
51
52
  protected $visible = TRUE;
  /* \brief Name of the ACL to use, empty if we need our own */
  protected $acl;
  /* \brief Is this attribute disabled */
  protected $disabled = FALSE;
53
54
55
  /* \brief Should this attribute submit formular when changing value
   * If this is not a boolean it is a string containing a method name to call on the plugin when changing value */
  protected $submitForm = FALSE;
56
57
58
59
60
61
62
63
64
65
  /* \brief Value of this attribute */
  protected $value;
  /* \brief Value we read from POST */
  protected $postValue;
  /* \brief Default value of this attribute */
  protected $defaultValue;
  /* \brief Initial value of this attribute */
  protected $initialValue;
  /* \brief Reference to the plugin */
  protected $plugin;
66
  /* \brief Array of attributes to manage (prefix => value => attribute)
67
68
69
70
71
   * Prefix should be 'erase' or 'disable' */
  protected $managedAttributes = array();
  /* \brief Array of multiple values groups for managed attributes */
  protected $managedAttributesMultipleValues = array();

72
73
74
  /* \bried Array of booleans telling for each managing attributes if he's disabling us */
  protected $managingAttributesOrders = array();

75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
  /*! \brief The constructor of Attribute
   *
   *  \param string $label The label to show for this attribute
   *  \param string $description A more detailed description for the attribute
   *  \param string $ldapName The name of the attribute in the LDAP (If it's not in the ldap, still provide a unique name)
   *  \param boolean $required Is this attribute mandatory or not
   *  \param mixed defaultValue The default value for this attribute
   *  \param string acl The name of the acl for this attribute if he does not use its own. (Leave empty if he should use its own like most attributes do)
   */
  function __construct ($label, $description, $ldapName, $required = FALSE, $defaultValue = "", $acl = "")
  {
    $this->label        = $label;
    $this->description  = $description;
    $this->ldapName     = $ldapName;
    $this->required     = $required;
    $this->defaultValue = $defaultValue;
    $this->value        = $defaultValue;
    $this->postValue    = $this->value;
    $this->acl          = $acl;
    $this->plugin       = NULL;
  }

  /*! \brief Set the parent plugin for this attribute
   *
   *  \param simplePlugin &$plugin The parent plugin
   */
  function setParent (&$plugin)
  {
    $this->plugin = $plugin;
    $this->manageAttributes($this->getValue());
  }

  function setInLdap ($inLdap)
  {
    $this->inLdap = $inLdap;
  }

  function setVisible ($visible)
  {
    $this->visible = $visible;
  }

  function isVisible ()
  {
    return $this->visible;
  }

  function setUnique ($unique)
  {
124
    if ($unique === TRUE) {
125
      $this->unique = 'sub';
126
127
128
    } else {
      $this->unique = $unique;
    }
129
130
131
132
133
134
135
136
137
  }

  function isInLdap ()
  {
    return $this->inLdap;
  }

  function setValue ($value)
  {
138
139
140
141
142
143
    $old_value    = $this->value;
    $this->value  = $value;
    if (($this->submitForm != FALSE) && ($this->submitForm !== TRUE) && ($old_value != $value) && is_object($this->plugin)) {
      $func = $this->submitForm;
      $this->plugin->$func();
    }
144
145
146
147
148
    $this->manageAttributes($this->value);
  }

  function setPostValue ($value)
  {
149
150
151
152
    if ($this->isVisible()) {
      $this->postValue = $value;
      $this->manageAttributes($this->postValue);
    }
153
154
155
156
157
158
159
160
161
162
163
164
165
166
  }

  /*! \brief Reset this attribute to its default value
   */
  function resetToDefault ()
  {
    $this->setValue($this->defaultValue);
  }

  function getValue ()
  {
    return $this->value;
  }

167
  /* Return the value as an array of values to be displayed in a table columns */
168
169
  function getArrayValue ()
  {
170
    return array($this->displayValue($this->getValue()));
171
172
173
174
175
176
177
178
179
  }

  function getLdapName ()
  {
    return $this->ldapName;
  }

  function getHtmlId ()
  {
180
    return $this->htmlid_prefix.preg_replace('/[\/\-,.#:;]/', '_', $this->getLdapName());
181
182
  }

Côme Bernigaud's avatar
Côme Bernigaud committed
183
184
185
186
187
188
  /* html id to put in the "for" attribute of our "label" tag */
  function getForHtmlId ()
  {
    return $this->getHtmlId();
  }

189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
  function getLabel ()
  {
    return $this->label;
  }

  function getDescription ()
  {
    return $this->description;
  }

  function getAcl ()
  {
    if (empty($this->acl)) {
      return $this->getHtmlId();
    } else {
      return $this->acl;
    }
  }

  function setAcl ($acl)
  {
    $this->acl = $acl;
  }

  function isRequired ()
  {
    return $this->required;
  }

  protected function setRequired ($bool)
  {
    $this->required = $bool;
  }

  protected function setLabel ($label)
  {
    $this->label = $label;
  }

  protected function setDescription ($description)
  {
    $this->description = $description;
  }

  function setDisabled ($disabled)
  {
    $this->disabled = $disabled;
  }

238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
  function setManagingDisabled ($sender, $value)
  {
    $this->managingAttributesOrders[$sender] = $value;
    $this->setDisabled(array_reduce($this->managingAttributesOrders,
      function ($a, $b)
      {
        return $a || $b;
      }
    ));
  }

  function setSubmitForm ($submitForm)
  {
    $this->submitForm = $submitForm;
  }

254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
  /*! \brief If in LDAP, loads this attribute value from the attrs array
   */
  function loadValue ($attrs)
  {
    if ($this->inLdap) {
      $this->loadAttrValue($attrs);
    }
    $this->initialValue = $this->getValue();
  }

  /*! \brief Loads this attribute value from the attrs array
   */
  protected function loadAttrValue ($attrs)
  {
    if (isset($attrs[$this->getLdapName()])) {
      $this->setValue($this->inputValue($attrs[$this->getLdapName()][0]));
    }
  }

  function getInitialValue ()
  {
    return $this->initialValue;
  }

278
279
280
281
282
  function setInitialValue ($value)
  {
    $this->initialValue = $value;
  }

283
284
285
286
287
288
289
290
291
292
  function hasChanged ()
  {
    return ($this->getValue() !== $this->initialValue);
  }

  function displayValue ($value)
  {
    return $value;
  }

293
294
295
296
297
  /*! \brief Return the ldap value in the correct intern format value
   *
   *  \param $ldapValue The value as found in the LDAP
   */
  function inputValue ($ldapValue)
298
  {
299
    return $ldapValue;
300
301
302
303
  }

  function setDefaultValue ($value)
  {
304
    $this->defaultValue = $value;
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
  }

  /*! \brief Set a list of attributes that are managed by this attributes.
   * See FusionDirectory wiki for detailed documentation
   */
  function setManagedAttributes ($mAttributes)
  {
    if (isset($mAttributes['multiplevalues'])) {
      $this->managedAttributesMultipleValues = $mAttributes['multiplevalues'];
      unset($mAttributes['multiplevalues']);
    } else {
      $this->managedAttributesMultipleValues = array();
    }
    $this->managedAttributes = $mAttributes;
    $this->manageAttributes($this->getValue());
  }

  protected function isValueManagingValue ($myvalue, $mavalue)
  {
    if (isset($this->managedAttributesMultipleValues[$mavalue])) {
      return in_array($myvalue, $this->managedAttributesMultipleValues[$mavalue]);
    } else {
      return ($myvalue == $mavalue);
    }
  }

  function manageAttributes ($myvalue)
  {
    if ($this->plugin === NULL) {
      return FALSE;
    }
336
    foreach ($this->managedAttributes as $array) {
337
338
339
340
      foreach ($array as $value => $attributes) {
        foreach ($attributes as $attribute) {
          $disabled = $this->isValueManagingValue($myvalue, $value);
          $this->plugin->attributesAccess[$attribute]->setManagingDisabled($this->getLdapName(), $disabled);
341
342
343
344
345
346
347
348
349
350
        }
      }
    }
    return TRUE;
  }

  /*! \brief Update this attributes postValue depending of the $_POST values
   */
  function loadPostValue ()
  {
351
352
353
354
355
    if ($this->isVisible()) {
      $this->postValue = $this->value;
      if (isset($_POST[$this->getHtmlId()])) {
        $this->setPostValue($_POST[$this->getHtmlId()]);
      }
356
357
358
359
360
361
362
    }
  }

  /*! \brief Apply this attribute postValue in value if this attribute is enabled
   */
  function applyPostValue ()
  {
363
    if (!$this->disabled && $this->isVisible()) {
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
      $this->setValue($this->postValue);
    }
  }

  /*! \brief Computes LDAP value
   */
  function computeLdapValue ()
  {
    return $this->getValue();
  }

  /*! \brief Fill LDAP value in the attrs array
   */
  function fillLdapValue (&$attrs)
  {
    if ($this->inLdap) {
      $value = $this->computeLdapValue();
381
      if ($value !== '') {
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
        $attrs[$this->getLdapName()] = $value;
      } else {
        $attrs[$this->getLdapName()] = array();
      }
    }
  }

  /*! \brief Post-modify the attrs array if needed (used for erasing managed attributes)
   */
  function fillLdapValueHook (&$attrs)
  {
    foreach ($this->managedAttributes as $prefix => $array) {
      if ($prefix != 'erase') {
        continue;
      }
397
      foreach ($array as $value => $attributes) {
398
399
400
401
402
        $myvalue = $this->getValue();
        $erase = $this->isValueManagingValue($myvalue, $value);
        if (!$erase) {
          continue;
        }
403
404
        foreach ($attributes as $attribute) {
          $attrs[$attribute] = array();
405
406
407
408
409
410
411
412
413
        }
      }
    }
  }

  /*! \brief Check the correctness of this attribute
   */
  function check ()
  {
414
415
    $value = $this->getValue();
    if ($this->isRequired() && !$this->disabled && (($value === "") || ($value === array()))) {
416
      return msgPool::required($this->getLabel());
417
    } elseif (($this->unique !== FALSE) && !$this->disabled) {
418
419
420
421
      $value = $this->computeLdapValue();
      if (($value === "") || ($value === array())) {
        return;
      }
422
      $ldap = $this->plugin->config->get_ldap_link();
423
      if ($this->unique === 'whole') {
424
        $ldap->cd($this->plugin->config->current['BASE']);
425
      } else {
426
427
        if (isset($this->plugin->base) && !empty($this->plugin->base)) {
          $base = $this->plugin->base;
428
        } elseif (isset($this->plugin->dn) && !empty($this->plugin->dn) && ($this->plugin->dn != 'new')) {
429
          $base = dn2base($this->plugin->dn);
430
431
        } else {
          $base = $this->plugin->config->current['BASE'];
432
433
        }
        $ldap->cd($base);
434
435
      }
      $filter = "(".$this->getLdapName()."=".$value.")";
436
437
438
439
      $pluginFilter = $this->plugin->getObjectClassFilter();
      if (!empty($pluginFilter)) {
        $filter = "(&$pluginFilter$filter)";
      }
440
441
      if ($this->unique === 'one') {
        $ldap->ls($filter, "", array($this->getLdapName()));
442
443
444
      } else {
        $ldap->search($filter, array($this->getLdapName()));
      }
445
446
447
448
449
450
451
452
453
      while ($attrs = $ldap->fetch()) {
        if ($attrs['dn'] != $this->plugin->dn) {
          return msgPool::duplicated($this->getLabel());
        }
      }
    }
  }

  /*! \brief Render this attribute form input(s)
454
455
456
457
   *
   *  \param array& attributes the attributes array
   *
   *  \param bool readOnly should we show text or input
458
   */
459
  function renderAttribute(&$attributes, $readOnly)
460
461
  {
    if ($this->visible) {
462
      if ($readOnly) {
463
        $input = '{literal}'.htmlentities($this->getValue(), ENT_COMPAT, 'UTF-8').'{/literal}';
464
465
      } elseif (is_object($this->plugin) && $this->plugin->is_template) {
        $input = $this->renderTemplateInput();
466
467
468
      } else {
        $input = $this->renderFormInput();
      }
469
      $attributes[$this->getLdapName()] = array(
Côme Bernigaud's avatar
Côme Bernigaud committed
470
        'htmlid'      => $this->getForHtmlId(),
471
472
        'label'       => '{literal}'.$this->getLabel().'{/literal}'.($this->isRequired()?'{$must}':''),
        'description' => ($this->isRequired()?sprintf(_("%s (required)"), $this->getDescription()):$this->getDescription()),
473
        'input'       => $input,
474
475
476
477
      );
    }
  }

478
479
480
481
482
483
484
  /*! \brief Serialize this attribute for RPC requests
   *
   *  \param array& attributes the attributes array
   */
  function serializeAttribute(&$attributes)
  {
    if ($this->visible) {
485
486
487
488
489
490
      $class = get_class($this);
      while ($class != 'Attribute') {
        $type[] = $class;
        $class  = get_parent_class($class);
      }
      $type[] = 'Attribute'; // To avoid empty array
491
      $attributes[$this->getLdapName()] = array(
492
        'id'          => $this->getHtmlId(),
493
494
495
496
497
        'label'       => $this->getLabel(),
        'required'    => $this->isRequired(),
        'disabled'    => $this->disabled,
        'description' => $this->getDescription(),
        'value'       => $this->getValue(),
498
        'type'        => $type,
499
500
501
502
      );
    }
  }

503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
  /*! \brief Add ACL information around display
   *
   *  \param string $display the display information to pass through ACL
   */
  function renderAcl($display)
  {
    return '{render acl=$'.$this->getAcl()."ACL}\n$display\n{/render}";
  }

  /*! \brief Get ACL information about the ACL we need to create
   */
  function getAclInfo ()
  {
    if (empty($this->acl)) { // If acl is not empty, we use an acl that is not ours, we have no acl to create
      return array(
        'name' => $this->getHtmlId(),
        'desc' => $this->getDescription()
      );
    } else {
      return FALSE;
    }
  }

  protected function changeStateJS ()
  {
    return join(array_map(
      function ($id) {
        return 'changeState('.json_encode($id).');';
      },
      $this->htmlIds()
    ));
  }

  protected function htmlIds()
  {
    return array($this->getHtmlId());
  }

  protected function managedAttributesJS ()
  {
    $js = '';
    $id = $this->getHtmlId();
545
    foreach ($this->managedAttributes as $array) {
546
      foreach ($array as $value => $attributes) {
547
548
549
550
551
        if (isset($this->managedAttributesMultipleValues[$value])) {
          $js .= 'disableAttributes = inArray(document.getElementById('.json_encode($id).').value,'.json_encode($this->managedAttributesMultipleValues[$value]).');';
        } else {
          $js .= 'disableAttributes = (document.getElementById('.json_encode($id).').value == '.json_encode($value).');'."\n";
        }
552
553
554
        foreach ($attributes as $attribute) {
          foreach ($this->plugin->attributesAccess[$attribute]->htmlIds() as $htmlId) {
            $js .= 'document.getElementById('.json_encode($htmlId).').disabled = disableAttributes;'."\n";
555
556
557
558
559
560
          }
        }
      }
    }
    return $js;
  }
561
562
563
564
565
566
567
568

  function renderTemplateInput ()
  {
    return $this->renderFormInput();
  }

  function foreignKeyUpdate($oldvalue, $newvalue, $source)
  {
569
570
571
572
    if ($source['MODE'] == 'move') {
      if ($this->getValue() == $oldvalue) {
        $this->setValue($newvalue);
      }
573
574
    }
  }
575
576
577
578
579

  function foreignKeyCheck($value, $source)
  {
    return ($this->getValue() == $value);
  }
580
581
582
583
584
585
586

  protected function renderInputField($type, $name, $attributes = array())
  {
    $input  = '<input type="'.$type.'" '.
              'name="'.$name.'" id="'.$name.'"'.
              ($this->disabled? ' disabled="disabled"':'');
    foreach ($attributes as $label => $value) {
587
      $input .= ' '.$label.'="'.$value.'"';
588
589
590
591
    }
    $input .= '/>';
    return $input;
  }
592
593
594
595
596
597
598
}

/*! \brief This class allow to handle easily a Boolean LDAP attribute
 *
 */
class BooleanAttribute extends Attribute
{
599
600
  public $trueValue;
  public $falseValue;
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619

  /*! \brief The constructor of BooleanAttribute
   *
   *  \param string $label The label to show for this attribute
   *  \param string $description A more detailed description for the attribute
   *  \param string $ldapName The name of the attribute in the LDAP (If it's not in the ldap, still provide a unique name)
   *  \param boolean $required Is this attribute mandatory or not
   *  \param mixed $defaultValue The default value for this attribute
   *  \param string $acl The name of the acl for this attribute if he does not use its own. (Leave empty if he should use its own like most attributes do)
   *  \param mixed $trueValue The value to store in LDAP when this boolean is TRUE. (For weird schemas that uses string or integer to store a boolean)
   *  \param mixed $falseValue The value to store in LDAP when this boolean is FALSE. (For weird schemas that uses string or integer to store a boolean)
   */
  function __construct ($label, $description, $ldapName, $required = FALSE, $defaultValue = FALSE, $acl = "", $trueValue = "TRUE", $falseValue = "FALSE")
  {
    parent::__construct($label, $description, $ldapName, $required, $defaultValue, $acl);
    $this->trueValue  = $trueValue;
    $this->falseValue = $falseValue;
  }

620
  function inputValue ($value)
621
  {
622
    return ($value == $this->trueValue);
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
  }

  function loadPostValue ()
  {
    if ($this->isVisible()) {
      $this->setPostValue(isset($_POST[$this->getHtmlId()]));
    }
  }

  function computeLdapValue ()
  {
    return ($this->value?$this->trueValue:$this->falseValue);
  }

  function renderFormInput ()
  {
    $id = $this->getHtmlId();
640
    $attributes = ($this->value?array('checked' => 'checked'): array());
641
642
    if ($this->submitForm) {
      $js       = 'document.mainform.submit();';
643
      $attributes['onChange'] = 'javascript:'.htmlentities($js, ENT_COMPAT, 'UTF-8');
644
    } elseif (!empty($this->managedAttributes)) {
645
      $js       = $this->managedAttributesJS();
646
      $attributes['onChange'] = 'javascript:'.htmlentities($js, ENT_COMPAT, 'UTF-8');
647
    }
648
    $display  = $this->renderInputField('checkbox', $id, $attributes);
649
650
651
652
653
654
655
    return $this->renderAcl($display);
  }

  protected function managedAttributesJS ()
  {
    $js = '';
    $id = $this->getHtmlId();
656
    foreach ($this->managedAttributes as $array) {
657
      foreach ($array as $value => $attributes) {
658
659
660
661
662
        if (isset($this->managedAttributesMultipleValues[$value])) {
          trigger_error('Multiple values are not available for boolean attributes');
        } else {
          $js .= 'disableAttributes = (document.getElementById('.json_encode($id).').checked == '.($value?'true':'false').');'."\n";
        }
663
664
665
        foreach ($attributes as $attribute) {
          foreach ($this->plugin->attributesAccess[$attribute]->htmlIds() as $htmlId) {
            $js .= 'document.getElementById('.json_encode($htmlId).').disabled = disableAttributes;'."\n";
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
          }
        }
      }
    }
    return $js;
  }
}

/*! \brief This class allow to handle easily a Boolean LDAP attribute that triggers a set of objectclasses
 *
 */
class ObjectClassBooleanAttribute extends BooleanAttribute
{
  private $objectclasses;


  /*! \brief The constructor of ObjectClassBooleanAttribute
   *
   *  \param string $label The label to show for this attribute
   *  \param string $description A more detailed description for the attribute
   *  \param string $ldapName The name of the attribute in the LDAP (If it's not in the ldap, still provide a unique name)
   *  \param boolean $required Is this attribute mandatory or not
   *  \param mixed $objectclasses objectClass or array of objectClasses that this boolean should add/remove depending on its state
   *  \param mixed $defaultValue The default value for this attribute
   *  \param string $acl The name of the acl for this attribute if he does not use its own. (Leave empty if he should use its own like most attributes do)
   */
  function __construct ($label, $description, $ldapName, $required, $objectclasses, $defaultValue = FALSE, $acl = "")
  {
    if (is_array($objectclasses)) {
      $this->objectclasses = $objectclasses;
    } else {
      $this->objectclasses = array($objectclasses);
    }
    parent::__construct($label, $description, $ldapName, $required, $defaultValue, $acl);
    $this->setInLdap(FALSE);
  }

  function loadValue ($attrs)
  {
    if (isset($attrs['objectClass'])) {
      $missing_oc = array_udiff($this->objectclasses, $attrs['objectClass'], 'strcasecmp');
      $this->setValue(empty($missing_oc));
    } else {
      $this->resetToDefault();
    }
    $this->initialValue = $this->value;
  }

  function fillLdapValue (&$attrs)
  {
    if ($this->getValue()) {
      $attrs['objectClass'] = array_merge_unique($this->objectclasses, $attrs['objectClass']);
    } else {
      $attrs['objectClass'] = array_remove_entries($this->objectclasses, $attrs['objectClass']);
    }
  }
}

/*! \brief This class allow to handle easily a String LDAP attribute
 *
 */
class StringAttribute extends Attribute
{
  private $pattern;
  protected $example;

  /*! \brief The constructor of StringAttribute
   *
   *  \param string $label The label to show for this attribute
   *  \param string $description A more detailed description for the attribute
   *  \param string $ldapName The name of the attribute in the LDAP (If it's not in the ldap, still provide a unique name)
   *  \param boolean $required Is this attribute mandatory or not
   *  \param mixed $defaultValue The default value for this attribute
   *  \param string $acl The name of the acl for this attribute if he does not use its own. (Leave empty if he should use its own like most attributes do)
   *  \param string $regexp A regular expression that should be matched by the value of this attribute in order for it to be considered valid. Will be used as a PHP regexp and as an html5 input pattern.
   */
  function __construct ($label, $description, $ldapName, $required = FALSE, $defaultValue = "", $acl = "", $regexp = "", $example = NULL)
  {
    parent::__construct($label, $description, $ldapName, $required, $defaultValue, $acl);
    $this->pattern = $regexp;
    $this->example = ($example === NULL?$defaultValue:$example);
  }

  function setExample ($example)
  {
    $this->example = $example;
  }

  function renderFormInput ()
  {
    $id = $this->getHtmlId();
757
758
759
    $attributes = array(
      'value' => '{literal}'.htmlentities($this->getValue(), ENT_COMPAT, 'UTF-8').'{/literal}'
    );
760
761
    if (!empty($this->managedAttributes)) {
      $js       = $this->managedAttributesJS();
762
      $attributes['onChange'] = 'javascript:'.htmlentities($js, ENT_COMPAT, 'UTF-8');
763
    }
764
    $display  = $this->renderInputField('text', $id, $attributes);
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
    return $this->renderAcl($display);
  }

  function check ()
  {
    $error = parent::check();
    if (!empty($error)) {
      return $error;
    } else {
      if ($this->value !== "") {
        return $this->validate();
      }
    }
  }

  function validate ()
  {
    if (($this->pattern !== "") && !preg_match($this->pattern, $this->value)) {
      return msgPool::invalid($this->getLabel(), $this->value, $this->pattern, htmlentities($this->example));
    }
  }
}

788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
class HiddenAttribute extends Attribute
{
  /*! \brief The constructor of HiddenAttribute
   *
   *  \param string $label The label to show for this attribute
   *  \param string $description A more detailed description for the attribute
   *  \param string $ldapName The name of the attribute in the LDAP (If it's not in the ldap, still provide a unique name)
   *  \param boolean $required Is this attribute mandatory or not
   *  \param mixed $defaultValue The default value for this attribute
   *  \param string $acl The name of the acl for this attribute if he does not use its own. (Leave empty if he should use its own like most attributes do)
   */
  function __construct ($ldapName, $required = FALSE, $defaultValue = "", $acl = "", $label = NULL, $description = "hidden")
  {
    if ($label === NULL) {
      $label = $ldapName;
    }
    parent::__construct($label, $description, $ldapName, $required, $defaultValue, $acl);
    $this->setVisible(FALSE);
  }
}

809
810
811
/* Dummy attribute class in order to give stats information to the template */
class FakeAttribute extends Attribute
{
812
  function __construct ($ldapName)
813
  {
814
    parent::__construct("Fake one", "", $ldapName, FALSE, "", "noacl");
815
816
817
818
819
820
821
822
823
    $this->setInLdap(FALSE);
  }

  function renderAttribute(&$attributes, $readOnly)
  {
    $attributes[$this->getLdapName()] = $this->getValue();
  }
}

824
825
826
827
828
829
830
831
832
833
834
835
/*! \brief This class allow to display an attribute.
 *
 * It can be used to display an attribute value the user is never allowed to modify.
 */
class DisplayLDAPAttribute extends Attribute
{
  function renderFormInput ()
  {
    return $this->getValue();
  }
}

836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
/*! \brief This class allow to display an attribute.
 *
 * It can be used to display an attribute value the user is never allowed to modify.
 */
class DisplayLDAPArrayAttribute extends Attribute
{
  protected function loadAttrValue ($attrs)
  {
    if (isset($attrs[$this->getLdapName()]['count'])) {
      $this->value = array();
      for ($i = 0; $i < $attrs[$this->getLdapName()]['count']; $i++) {
        $this->value[] = $attrs[$this->getLdapName()][$i];
      }
    } else {
      $this->resetToDefault();
    }
  }

  function renderFormInput ()
  {
    return join(', ', $this->getValue());
  }
}

Côme Bernigaud's avatar
Côme Bernigaud committed
860
861
862
863
/*! \brief This class allow to display a text in front of an attribute.
 *
 * For instance, it can be used to display a link.
 */
864
class DisplayAttribute extends DisplayLDAPAttribute
Côme Bernigaud's avatar
Côme Bernigaud committed
865
866
867
868
869
870
871
872
{
  function __construct ($label, $description, $ldapName, $required = FALSE, $defaultValue = "", $acl = "")
  {
    parent::__construct ($label, $description, $ldapName, $required, $defaultValue, $acl);
    $this->setInLdap(FALSE);
  }
}

873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
/*! \brief This class allow to handle easily a String LDAP attribute that appears as a text area
 *
 */
class TextAreaAttribute extends StringAttribute
{
  function renderFormInput ()
  {
    $id = $this->getHtmlId();
    $display  = '<textarea name="'.$id.'" id="'.$id.'"'.
                ($this->disabled? 'disabled="disabled"':'').'>'.
                '{literal}'.htmlentities($this->getValue(), ENT_COMPAT, 'UTF-8').'{/literal}</textarea>';
    return $this->renderAcl($display);
  }
}

/*! \brief This class allow to handle easily a String LDAP attribute that contains a password
 *
 */
class PasswordAttribute extends StringAttribute
{
  function renderFormInput ()
  {
    $id = $this->getHtmlId();
896
897
898
899
900
901
    $display  = $this->renderInputField(
      'password', $id,
      array(
        'value' => '{literal}'.htmlentities($this->getValue(), ENT_COMPAT, 'UTF-8').'{/literal}'
      )
    );
902
903
    return $this->renderAcl($display);
  }
904
905
906
907
908

  function renderTemplateInput ()
  {
    return parent::renderFormInput();
  }
909
910
911
912
913
914
915
916
}

/*! \brief This class allow to handle easily a Select LDAP attribute with a set of choices
 *
 */
class SelectAttribute extends Attribute
{
  protected $choices;
917
918
  protected $outputs  = NULL;
  protected $size     = 1;
919
920
921
922
923
924
925
926
927
928
929
930

  /*! \brief The constructor of SelectAttribute
   *
   *  \param string $label The label to show for this attribute
   *  \param string $description A more detailed description for the attribute
   *  \param string $ldapName The name of the attribute in the LDAP (If it's not in the ldap, still provide a unique name)
   *  \param boolean $required Is this attribute mandatory or not
   *  \param array $choices The choices this select should offer. Pass array("") if you're gonna fill it later with setChoices
   *  \param mixed $defaultValue The default value for this attribute
   *  \param array $outputs The label corresponding to the choices, leave to NULL if you want to display the choices themselves
   *  \param string $acl The name of the acl for this attribute if he does not use its own. (Leave empty if he should use its own like most attributes do)
   */
931
  function __construct ($label, $description, $ldapName, $required = FALSE, $choices = array(), $defaultValue = "", $outputs = NULL, $acl = "")
932
  {
933
934
935
    if (!in_array($defaultValue, $choices) && isset($choices[0])) {
      $defaultValue = $choices[0];
    }
936
937
938
939
940
941
942
943
    parent::__construct($label, $description, $ldapName, $required, $defaultValue, $acl);
    $this->setChoices($choices, $outputs);
  }

  function setChoices ($choices, $outputs = NULL)
  {
    $this->outputs = NULL;
    if (!$this->isRequired() && !in_array("", $choices)) {
944
      array_unshift($choices, "");
945
      if (is_array($outputs)) {
946
        array_unshift($outputs, _("None"));
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
      }
    }
    $this->choices = $choices;
    if (!in_array($this->defaultValue, $this->choices) && isset($this->choices[0])) {
      $this->defaultValue = $this->choices[0];
    }
    if (is_array($outputs)) {
      $this->setDisplayChoices($outputs);
    }
    if (!in_array($this->value, $this->choices)) {
      $this->resetToDefault();
    }
  }

  function setDisplayChoices ($values)
  {
    $this->outputs = array();
    $i = 0;
    foreach ($this->choices as $choice) {
      $this->outputs[$choice] = $values[$i++];
    }
  }

  protected function setRequired ($bool)
  {
    parent::setRequired($bool);
    $key = array_search("", $this->choices);
    if ($this->isRequired() && ($key !== FALSE)) {
      unset($this->choices[$key]);
976
      unset($this->outputs[""]);
977
978
979
980
981
982
983
984
985
986
987
    } elseif (!$this->isRequired() && !in_array("", $this->choices)) {
      $this->choices[] = "";
      if (!isset($this->output[""])) {
        $this->output[""] = _("None");
      }
    }
  }

  function displayValue ($value)
  {
    if ($this->outputs !== NULL) {
988
989
990
991
992
993
      if (isset($this->outputs[$value])) {
        return $this->outputs[$value];
      } else {
        trigger_error("No display value set for '$value' in ".$this->getLabel());
        return $value;
      }
994
995
996
997
998
999
1000
    } else {
      return $value;
    }
  }

  function check ()
  {