FusionDirectory
 All Data Structures Files Functions Variables
class_Attribute.inc
Go to the documentation of this file.
1 <?php
2 /*
3  This code is part of FusionDirectory (http://www.fusiondirectory.org/)
4  Copyright (C) 2012-2016 FusionDirectory
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20 
29 class Attribute
30 {
31  /* \brief Name of this attribute in the LDAP */
32  private $ldapName;
33  /* \brief Label of this attribute in the form */
34  private $label;
35  /* \brief Description of this attribute */
36  private $description;
37  /* \brief Is this attribute mandatory */
38  private $required;
39  /* \brief Should this attribute be saved into the LDAP */
40  private $inLdap = TRUE;
41 
42  /* \brief Should this attribute be unique
43  * FALSE -> no unicity check
44  * one -> unicity check in the same base -> broken right now because of object ous
45  * sub -> unicity check in the same subtree
46  * \__> this should not be used as it’s breaking reciprocity
47  * whole -> unicity check in the whole LDAP
48  */
49  private $unique = FALSE;
50 
51  /* \brief Filter to use when checking unicity
52  * Most of the time this is NULL and filter is computed from plugin objectTypes and objectClasses */
53  private $uniqueFilter = NULL;
54 
55  /* \brief Prefix for the html id */
56  protected $htmlid_prefix = '';
57  /* \brief Should this attribute be shown */
58  protected $visible = TRUE;
59  /* \brief Name of the ACL to use, empty if we need our own */
60  protected $acl;
61  /* \brief Is this attribute disabled */
62  protected $disabled = FALSE;
63  /* \brief Should this attribute submit formular when changing value
64  * If this is not a boolean it is a string containing a method name to call on the plugin when changing value */
65  protected $submitForm = FALSE;
66  /* \brief Value of this attribute */
67  protected $value;
68  /* \brief Value we read from POST */
69  protected $postValue;
70  /* \brief Default value of this attribute */
71  protected $defaultValue;
72  /* \brief Initial value of this attribute */
73  protected $initialValue;
74  /* \brief Reference to the plugin */
75  protected $plugin;
76  /* \brief Array of attributes to manage (prefix => value => attribute)
77  * Prefix should be 'erase' or 'disable' */
78  protected $managedAttributes = array();
79  /* \brief Array of multiple values groups for managed attributes */
80  protected $managedAttributesMultipleValues = array();
81 
82  /* \bried Array of booleans telling for each managing attributes if he's disabling us */
83  protected $managingAttributesOrders = array();
84 
94  function __construct ($label, $description, $ldapName, $required = FALSE, $defaultValue = "", $acl = "")
95  {
96  $this->label = $label;
97  $this->description = $description;
98  $this->ldapName = $ldapName;
99  $this->required = $required;
100  $this->defaultValue = $defaultValue;
101  $this->value = $defaultValue;
102  $this->postValue = $this->value;
103  $this->acl = $acl;
104  $this->plugin = NULL;
105  }
106 
111  function setParent (&$plugin)
112  {
113  $this->plugin = $plugin;
114  $this->manageAttributes($this->getValue());
115  }
116 
117  function setInLdap ($inLdap)
118  {
119  $this->inLdap = $inLdap;
120  }
121 
122  function setVisible ($visible)
123  {
124  $this->visible = $visible;
125  }
126 
127  function isVisible ()
128  {
129  return $this->visible;
130  }
131 
132  function setUnique ($unique, $filter = NULL)
133  {
134  if ($unique === TRUE) {
135  $this->unique = 'one';
136  } else {
137  $this->unique = $unique;
138  }
139  $this->uniqueFilter = $filter;
140  }
141 
142  function getUnique ()
143  {
144  return $this->unique;
145  }
146 
147  function isInLdap ()
148  {
149  return $this->inLdap;
150  }
151 
152  function checkValue ($value)
153  {
154  /* Should throw InvalidValueException if needed */
155  }
156 
157  function setValue ($value)
158  {
159  $this->checkValue($value);
160  $old_value = $this->value;
161  $this->value = $value;
162  if (($this->submitForm != FALSE) && ($this->submitForm !== TRUE) && ($old_value != $value) && is_object($this->plugin)) {
163  $func = $this->submitForm;
164  $this->plugin->$func();
165  }
166  $this->manageAttributes($this->value);
167  }
168 
170  function setPostValue ($value)
171  {
172  if ($this->isVisible()) {
173  $this->postValue = $this->fixPostValue($value);
174  $this->manageAttributes($this->postValue);
175  }
176  }
177 
179  function fixPostValue ($value)
180  {
181  return $value;
182  }
183 
186  function resetToDefault ()
187  {
188  $this->setValue($this->defaultValue);
189  }
190 
191  function getValue ()
192  {
193  return $this->value;
194  }
195 
196  /* Return the value as an array of values to be displayed in a table columns */
197  function getArrayValue ()
198  {
199  return array($this->displayValue($this->getValue()));
200  }
201 
202  function getLdapName ()
203  {
204  return $this->ldapName;
205  }
206 
207  function getHtmlId ()
208  {
209  return $this->htmlid_prefix.preg_replace('/[\/\-,.#:;]/', '_', $this->getLdapName());
210  }
211 
212  /* html id to put in the "for" attribute of our "label" tag */
213  function getForHtmlId ()
214  {
215  return $this->getHtmlId();
216  }
217 
218  function getLabel ()
219  {
220  return $this->label;
221  }
222 
223  function getDescription ()
224  {
225  return $this->description;
226  }
227 
228  function getAcl ()
229  {
230  if (empty($this->acl)) {
231  return $this->getHtmlId();
232  } else {
233  return $this->acl;
234  }
235  }
236 
237  function setAcl ($acl)
238  {
239  $this->acl = $acl;
240  }
241 
242  function isRequired ()
243  {
244  return $this->required;
245  }
246 
247  function setRequired ($bool)
248  {
249  $this->required = $bool;
250  }
251 
252  protected function setLabel ($label)
253  {
254  $this->label = $label;
255  }
256 
257  protected function setDescription ($description)
258  {
259  $this->description = $description;
260  }
261 
262  function setDisabled ($disabled)
263  {
264  $this->disabled = $disabled;
265  }
266 
267  function isDisabled ()
268  {
269  return $this->disabled;
270  }
271 
272  function setManagingDisabled ($sender, $value)
273  {
274  $this->managingAttributesOrders[$sender] = $value;
275  $this->setDisabled(array_reduce($this->managingAttributesOrders,
276  function ($a, $b)
277  {
278  return $a || $b;
279  }
280  ));
281  }
282 
283  function setSubmitForm ($submitForm)
284  {
285  $this->submitForm = $submitForm;
286  }
287 
290  function loadValue ($attrs)
291  {
292  if ($this->inLdap) {
293  $this->loadAttrValue($attrs);
294  }
295  $this->initialValue = $this->getValue();
296  }
297 
300  protected function loadAttrValue ($attrs)
301  {
302  if (isset($attrs[$this->getLdapName()])) {
303  $this->setValue($this->inputValue($attrs[$this->getLdapName()][0]));
304  }
305  }
306 
307  function getInitialValue ()
308  {
309  return $this->initialValue;
310  }
311 
312  function setInitialValue ($value)
313  {
314  $this->initialValue = $value;
315  }
316 
317  function hasChanged ()
318  {
319  return ($this->getValue() !== $this->initialValue);
320  }
321 
322  function displayValue ($value)
323  {
324  return $value;
325  }
326 
331  function inputValue ($ldapValue)
332  {
333  return $ldapValue;
334  }
335 
336  function setDefaultValue ($value)
337  {
338  $this->defaultValue = $value;
339  }
340 
344  function setManagedAttributes ($mAttributes)
345  {
346  if (isset($mAttributes['multiplevalues'])) {
347  $this->managedAttributesMultipleValues = $mAttributes['multiplevalues'];
348  unset($mAttributes['multiplevalues']);
349  } else {
350  $this->managedAttributesMultipleValues = array();
351  }
352  $this->managedAttributes = $mAttributes;
353  $this->manageAttributes($this->getValue());
354  }
355 
356  protected function isValueManagingValue ($myvalue, $mavalue)
357  {
358  if (isset($this->managedAttributesMultipleValues[$mavalue])) {
359  return in_array($myvalue, $this->managedAttributesMultipleValues[$mavalue]);
360  } else {
361  return ($myvalue == $mavalue);
362  }
363  }
364 
365  function manageAttributes ($myvalue)
366  {
367  if ($this->plugin === NULL) {
368  return FALSE;
369  }
370  foreach ($this->managedAttributes as $array) {
371  foreach ($array as $value => $attributes) {
372  foreach ($attributes as $attribute) {
373  $disabled = $this->isValueManagingValue($myvalue, $value);
374  $this->plugin->attributesAccess[$attribute]->setManagingDisabled($this->getLdapName(), $disabled);
375  }
376  }
377  }
378  return TRUE;
379  }
380 
383  function loadPostValue ()
384  {
385  if ($this->isVisible()) {
386  $this->postValue = $this->value;
387  if (isset($_POST[$this->getHtmlId()])) {
388  $this->setPostValue($_POST[$this->getHtmlId()]);
389  }
390  }
391  }
392 
395  function applyPostValue ()
396  {
397  if (!$this->disabled && $this->isVisible()) {
398  $this->setValue($this->postValue);
399  }
400  }
401 
404  function computeLdapValue ()
405  {
406  return $this->getValue();
407  }
408 
411  function fillLdapValue (&$attrs)
412  {
413  if ($this->inLdap) {
414  $value = $this->computeLdapValue();
415  if ($value !== '') {
416  $attrs[$this->getLdapName()] = $value;
417  } else {
418  $attrs[$this->getLdapName()] = array();
419  }
420  }
421  }
422 
425  function fillLdapValueHook (&$attrs)
426  {
427  foreach ($this->managedAttributes as $prefix => $array) {
428  if ($prefix != 'erase') {
429  continue;
430  }
431  foreach ($array as $value => $attributes) {
432  $myvalue = $this->getValue();
433  $erase = $this->isValueManagingValue($myvalue, $value);
434  if (!$erase) {
435  continue;
436  }
437  foreach ($attributes as $attribute) {
438  $attrs[$attribute] = array();
439  }
440  }
441  }
442  }
443 
446  function check ()
447  {
448  global $config;
449  $value = $this->getValue();
450  if ($this->isRequired() && !$this->disabled && (($value === "") || ($value === array()))) {
451  return msgPool::required($this->getLabel());
452  } elseif (($this->unique !== FALSE) && !$this->disabled) {
453  $value = $this->computeLdapValue();
454  if (($value === "") || ($value === array())) {
455  return;
456  }
457  $ldap = $config->get_ldap_link();
458  $base = $config->current['BASE'];
459  if ($this->unique !== 'whole') {
460  if (isset($this->plugin->base) && !empty($this->plugin->base)) {
461  $base = $this->plugin->base;
462  } elseif (isset($this->plugin->dn) && !empty($this->plugin->dn) && ($this->plugin->dn != 'new')) {
463  $base = dn2base($this->plugin->dn);
464  }
465  }
466  $ldap->cd($base);
467  if (is_array($value)) {
468  $filter = '(|('.$this->getLdapName().'='.join(')('.$this->getLdapName().'=', array_map('ldap_escape_f', $value)).'))';
469  } else {
470  $filter = '('.$this->getLdapName().'='.ldap_escape_f($value).')';
471  }
472  $infos = pluglist::pluginInfos(get_class($this->plugin));
473  if ($this->uniqueFilter === NULL) {
474  $filters = array_map(
475  function ($key, $ot)
476  {
477  if (!is_numeric($key)) {
478  $ot = $key;
479  }
480  try {
481  $oinfos = objects::infos($ot);
482  return $oinfos['filter'];
483  } catch (NonExistingObjectTypeException $e) {
484  return '';
485  }
486  },
487  array_keys($infos['plObjectType']),
488  array_values($infos['plObjectType'])
489  );
490  $pluginFilter = $this->plugin->getObjectClassFilter();
491  if (!empty($pluginFilter)) {
492  $filters[] = $pluginFilter;
493  }
494  } else {
495  $filters = array($this->uniqueFilter);
496  }
497  $filter = '(&'.$filter.implode($filters).')';
498  $ldap->search($filter, array($this->getLdapName()));
499  $branches = array_filter(
500  array_map(
501  function ($key, $ot)
502  {
503  if (!is_numeric($key)) {
504  $ot = $key;
505  }
506  try {
507  $oinfos = objects::infos($ot);
508  return $oinfos['ou'];
509  } catch (NonExistingObjectTypeException $e) {
510  return FALSE;
511  }
512  },
513  array_keys($infos['plObjectType']),
514  array_values($infos['plObjectType'])
515  ),
516  function ($ou)
517  {
518  return ($ou !== FALSE);
519  }
520  );
521  while ($attrs = $ldap->fetch()) {
522  if ($attrs['dn'] != $this->plugin->dn) {
523  $dn_base = preg_replace('/^[^,]+,/', '', $attrs['dn']);
524  $found = FALSE;
525  if ($this->unique === 'one') {
526  /* Check that this entry is in a concerned branch */
527  foreach ($branches as $branch) {
528  if ($branch.$base == $dn_base) {
529  $dn_base = preg_replace('/^'.preg_quote($branch, '/').'/', '', $dn_base);
530  $found = TRUE;
531  break;
532  }
533  }
534  } elseif ($this->uniqueFilter === NULL) { /* whole (or sub) */
535  /* Check that this entry is in a concerned branch */
536  foreach ($branches as $branch) {
537  if (preg_match('/^'.preg_quote($branch, '/').'/', $dn_base)) {
538  $dn_base = preg_replace('/^'.preg_quote($branch, '/').'/', '', $dn_base);
539  $found = TRUE;
540  break;
541  }
542  }
543  if (!in_array($dn_base, $config->departments)) {
544  continue;
545  }
546  } else {
547  $found = TRUE;
548  }
549  if (!$found) {
550  continue;
551  }
552 
553  return msgPool::duplicated($this->getLabel(), $attrs['dn']);
554  }
555  }
556  }
557  }
558 
565  function renderAttribute(&$attributes, $readOnly)
566  {
567  if ($this->visible) {
568  if ($readOnly) {
569  $input = '{literal}'.htmlentities($this->getValue(), ENT_COMPAT, 'UTF-8').'{/literal}';
570  } elseif (is_object($this->plugin) && $this->plugin->is_template) {
571  $input = $this->renderTemplateInput();
572  } else {
573  $input = $this->renderFormInput();
574  }
575  $attributes[$this->getLdapName()] = array(
576  'htmlid' => $this->getForHtmlId(),
577  'label' => '{literal}'.$this->getLabel().'{/literal}'.($this->isRequired() ? '{$must}' : ''),
578  'description' => ($this->isRequired() ? sprintf(_("%s (required)"), $this->getDescription()) : $this->getDescription()),
579  'input' => $input,
580  );
581  }
582  }
583 
588  function serializeAttribute(&$attributes, $form = TRUE)
589  {
590  if (!$form || $this->visible) {
591  $class = get_class($this);
592  while ($class != 'Attribute') {
593  $type[] = $class;
594  $class = get_parent_class($class);
595  }
596  /* Avoid empty array */
597  $type[] = 'Attribute';
598  $infos = array(
599  'htmlid' => $this->getHtmlId(),
600  'label' => $this->getLabel(),
601  'required' => $this->isRequired(),
602  'disabled' => $this->disabled,
603  'description' => $this->getDescription(),
604  'value' => $this->getValue(),
605  'default' => $this->defaultValue,
606  'type' => $type,
607  );
608  if (!$form) {
609  $infos['inldap'] = $this->isInLdap();
610  $infos['visible'] = $this->visible;
611  $infos['htmlids'] = $this->htmlIds();
612  }
613  $attributes[$this->getLdapName()] = $infos;
614  }
615  }
616 
621  function deserializeValue($values)
622  {
623  if (isset($values[$this->getLdapName()])) {
624  $this->setValue($values[$this->getLdapName()]);
625  }
626  }
627 
632  function renderAcl($display)
633  {
634  return '{render aclName="'.$this->getAcl().'" acl=$'.$this->getAcl()."ACL}\n$display\n{/render}";
635  }
636 
639  function getAclInfo ()
640  {
641  if (empty($this->acl)) {
642  return array(
643  'name' => $this->getHtmlId(),
644  'desc' => $this->getDescription()
645  );
646  } else {
647  /* If acl is not empty, we use an acl that is not ours, we have no acl to create */
648  return FALSE;
649  }
650  }
651 
652  protected function changeStateJS ()
653  {
654  return join(array_map(
655  function ($id) {
656  return 'changeState('.json_encode($id).');';
657  },
658  $this->htmlIds()
659  ));
660  }
661 
662  public function htmlIds()
663  {
664  return array($this->getHtmlId());
665  }
666 
667  protected function managedAttributesJS ()
668  {
669  $js = '';
670  $id = $this->getHtmlId();
671  foreach ($this->managedAttributes as $array) {
672  foreach ($array as $value => $attributes) {
673  if (isset($this->managedAttributesMultipleValues[$value])) {
674  $js .= 'disableAttributes = inArray(document.getElementById('.json_encode($id).').value,'.json_encode($this->managedAttributesMultipleValues[$value]).');';
675  } else {
676  $js .= 'disableAttributes = (document.getElementById('.json_encode($id).').value == '.json_encode($value).');'."\n";
677  }
678  foreach ($attributes as $attribute) {
679  foreach ($this->plugin->attributesAccess[$attribute]->htmlIds() as $htmlId) {
680  $js .= 'if (document.getElementById('.json_encode($htmlId).')) { document.getElementById('.json_encode($htmlId).').disabled = disableAttributes; }'."\n";
681  }
682  }
683  }
684  }
685  return $js;
686  }
687 
688  function renderTemplateInput ()
689  {
690  return $this->renderFormInput();
691  }
692 
693  function foreignKeyUpdate($oldvalue, $newvalue, $source)
694  {
695  if ($source['MODE'] == 'move') {
696  if ($this->getValue() == $oldvalue) {
697  $this->setValue($newvalue);
698  }
699  }
700  }
701 
702  function foreignKeyCheck($value, $source)
703  {
704  return ($this->getValue() == $value);
705  }
706 
707  protected function renderInputField($type, $name, $attributes = array())
708  {
709  $input = '<input type="'.$type.'" '.
710  'name="'.$name.'" id="'.$name.'"'.
711  ($this->disabled ? ' disabled="disabled"' : '');
712  foreach ($attributes as $label => $value) {
713  $input .= ' '.$label.'="'.$value.'"';
714  }
715  $input .= '/>';
716  return $input;
717  }
718 }
719 
721 {
731  function __construct ($ldapName, $required = FALSE, $defaultValue = "", $acl = "", $label = NULL, $description = "hidden")
732  {
733  if ($label === NULL) {
734  $label = $ldapName;
735  }
736  parent::__construct($label, $description, $ldapName, $required, $defaultValue, $acl);
737  $this->setVisible(FALSE);
738  }
739 }
740 
742 {
743  protected function loadAttrValue ($attrs)
744  {
745  if (isset($attrs[$this->getLdapName()]['count'])) {
746  $this->value = array();
747  for ($i = 0; $i < $attrs[$this->getLdapName()]['count']; $i++) {
748  $this->value[] = $attrs[$this->getLdapName()][$i];
749  }
750  } else {
751  $this->resetToDefault();
752  }
753  }
754 }
755 
756 /* Dummy attribute class in order to give stats information to the template */
758 {
759  function __construct ($ldapName)
760  {
761  parent::__construct("Fake one", "", $ldapName, FALSE, "", "noacl");
762  $this->setInLdap(FALSE);
763  }
764 
765  function renderAttribute(&$attributes, $readOnly)
766  {
767  $attributes[$this->getLdapName()] = $this->getValue();
768  }
769 }
770 
777 {
778  protected $allowHTML = FALSE;
779  protected $allowSmarty = FALSE;
780 
781  function renderFormInput ()
782  {
783  if ($this->allowHTML) {
784  $value = $this->getValue();
785  } else {
786  $value = htmlentities($this->getValue(), ENT_COMPAT, 'UTF-8');
787  }
788  if ($this->allowSmarty) {
789  return $value;
790  } else {
791  return '{literal}'.$value.'{/literal}';
792  }
793  }
794 
795  function setAllowHTML ($allowHTML)
796  {
797  $this->allowHTML = $allowHTML;
798  }
799 
800  function setAllowSmarty ($allowSmarty)
801  {
802  $this->allowSmarty = $allowSmarty;
803  }
804 }
805 
811 {
812  function fillLdapValue (&$attrs)
813  {
814  }
815 }
816 
822 {
823  protected function loadAttrValue ($attrs)
824  {
825  if (isset($attrs[$this->getLdapName()]['count'])) {
826  $this->value = array();
827  for ($i = 0; $i < $attrs[$this->getLdapName()]['count']; $i++) {
828  $this->value[] = $attrs[$this->getLdapName()][$i];
829  }
830  } else {
831  $this->resetToDefault();
832  }
833  }
834 
835  function renderFormInput ()
836  {
837  $value = $this->getValue();
838  if (is_array($value)) {
839  $value = join(', ', $value);
840  }
841  return '{literal}'.htmlentities($value, ENT_COMPAT, 'UTF-8').'{/literal}';
842  }
843 }
844 
850 {
851  function __construct ($label, $description, $ldapName, $required = FALSE, $defaultValue = "", $acl = "")
852  {
853  parent::__construct ($label, $description, $ldapName, $required, $defaultValue, $acl);
854  $this->setInLdap(FALSE);
855  }
856 }
857 ?>
setManagedAttributes($mAttributes)
Set a list of attributes that are managed by this attributes. See FusionDirectory wiki for detailed d...
renderAcl($display)
Add ACL information around display.
fillLdapValueHook(&$attrs)
Post-modify the attrs array if needed (used for erasing managed attributes)
This class allow to display an attribute.
setPostValue($value)
Set the postValue.
getAclInfo()
Get ACL information about the ACL we need to create.
applyPostValue()
Apply this attribute postValue in value if this attribute is enabled.
computeLdapValue()
Computes LDAP value.
This class allow to handle easily any kind of LDAP attribute.
fillLdapValue(&$attrs)
Fill LDAP value in the attrs array.
static required($name)
Display error about required field empty.
renderAttribute(&$attributes, $readOnly)
Render this attribute form input(s)
inputValue($ldapValue)
Return the ldap value in the correct intern format value.
check()
Check the correctness of this attribute.
loadValue($attrs)
If in LDAP, loads this attribute value from the attrs array.
dn2base($dn, $ou=NULL)
Return the base of a given DN.
Definition: functions.inc:1314
static duplicated($name, $dn=NULL)
Display error about existing entry in the system.
This class contains all the function needed to manage acl.
Definition: class_acl.inc:30
deserializeValue($values)
Apply value from RPC requests.
This class allow to display an attribute.
This class allow to display a text in front of an attribute.
fixPostValue($value)
In case a treatment is needed on POST content.
loadPostValue()
Update this attributes postValue depending of the $_POST values.
setParent(&$plugin)
Set the parent plugin for this attribute.
resetToDefault()
Reset this attribute to its default value.
__construct($ldapName, $required=FALSE, $defaultValue="", $acl="", $label=NULL, $description="hidden")
The constructor of HiddenAttribute.
This class allow to display an attribute.
loadAttrValue($attrs)
Loads this attribute value from the attrs array.
serializeAttribute(&$attributes, $form=TRUE)
Serialize this attribute for RPC requests.
__construct($label, $description, $ldapName, $required=FALSE, $defaultValue="", $acl="")
The constructor of Attribute.