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  $value = $this->getValue();
570  if (is_array($value)) {
571  $input = '{literal}'.implode('<br/>', array_map(
572  function ($v)
573  {
574  return htmlentities($v, ENT_COMPAT, 'UTF-8');
575  },
576  $value
577  )).'{/literal}';
578  } else {
579  $input = '{literal}'.htmlentities($value, ENT_COMPAT, 'UTF-8').'{/literal}';
580  }
581  } elseif (is_object($this->plugin) && $this->plugin->is_template) {
582  $input = $this->renderTemplateInput();
583  } else {
584  $input = $this->renderFormInput();
585  }
586  $attributes[$this->getLdapName()] = array(
587  'htmlid' => $this->getForHtmlId(),
588  'label' => '{literal}'.$this->getLabel().'{/literal}'.($this->isRequired() ? '{$must}' : ''),
589  'description' => ($this->isRequired() ? sprintf(_("%s (required)"), $this->getDescription()) : $this->getDescription()),
590  'input' => $input,
591  );
592  }
593  }
594 
599  function serializeAttribute(&$attributes, $form = TRUE)
600  {
601  if (!$form || $this->visible) {
602  $class = get_class($this);
603  while ($class != 'Attribute') {
604  $type[] = $class;
605  $class = get_parent_class($class);
606  }
607  /* Avoid empty array */
608  $type[] = 'Attribute';
609  $infos = array(
610  'htmlid' => $this->getHtmlId(),
611  'label' => $this->getLabel(),
612  'required' => $this->isRequired(),
613  'disabled' => $this->disabled,
614  'description' => $this->getDescription(),
615  'value' => $this->getValue(),
616  'default' => $this->defaultValue,
617  'type' => $type,
618  );
619  if (!$form) {
620  $infos['inldap'] = $this->isInLdap();
621  $infos['visible'] = $this->visible;
622  $infos['htmlids'] = $this->htmlIds();
623  }
624  $attributes[$this->getLdapName()] = $infos;
625  }
626  }
627 
632  function deserializeValue($values)
633  {
634  if (isset($values[$this->getLdapName()])) {
635  $this->setValue($values[$this->getLdapName()]);
636  }
637  }
638 
643  function renderAcl($display)
644  {
645  return '{render aclName="'.$this->getAcl().'" acl=$'.$this->getAcl()."ACL}\n$display\n{/render}";
646  }
647 
650  function getAclInfo ()
651  {
652  if (empty($this->acl)) {
653  return array(
654  'name' => $this->getHtmlId(),
655  'desc' => $this->getDescription()
656  );
657  } else {
658  /* If acl is not empty, we use an acl that is not ours, we have no acl to create */
659  return FALSE;
660  }
661  }
662 
663  protected function changeStateJS ()
664  {
665  return join(array_map(
666  function ($id) {
667  return 'changeState('.json_encode($id).');';
668  },
669  $this->htmlIds()
670  ));
671  }
672 
673  public function htmlIds()
674  {
675  return array($this->getHtmlId());
676  }
677 
678  protected function managedAttributesJS ()
679  {
680  $js = '';
681  $id = $this->getHtmlId();
682  foreach ($this->managedAttributes as $array) {
683  foreach ($array as $value => $attributes) {
684  if (isset($this->managedAttributesMultipleValues[$value])) {
685  $js .= 'disableAttributes = inArray(document.getElementById('.json_encode($id).').value,'.json_encode($this->managedAttributesMultipleValues[$value]).');';
686  } else {
687  $js .= 'disableAttributes = (document.getElementById('.json_encode($id).').value == '.json_encode($value).');'."\n";
688  }
689  foreach ($attributes as $attribute) {
690  foreach ($this->plugin->attributesAccess[$attribute]->htmlIds() as $htmlId) {
691  $js .= 'if (document.getElementById('.json_encode($htmlId).')) { document.getElementById('.json_encode($htmlId).').disabled = disableAttributes; }'."\n";
692  }
693  }
694  }
695  }
696  return $js;
697  }
698 
699  function renderTemplateInput ()
700  {
701  return $this->renderFormInput();
702  }
703 
704  function foreignKeyUpdate($oldvalue, $newvalue, $source)
705  {
706  if ($source['MODE'] == 'move') {
707  if ($this->getValue() == $oldvalue) {
708  $this->setValue($newvalue);
709  }
710  }
711  }
712 
713  function foreignKeyCheck($value, $source)
714  {
715  return ($this->getValue() == $value);
716  }
717 
718  protected function renderInputField($type, $name, $attributes = array())
719  {
720  $input = '<input type="'.$type.'" '.
721  'name="'.$name.'" id="'.$name.'"'.
722  ($this->disabled ? ' disabled="disabled"' : '');
723  foreach ($attributes as $label => $value) {
724  $input .= ' '.$label.'="'.$value.'"';
725  }
726  $input .= '/>';
727  return $input;
728  }
729 }
730 
732 {
742  function __construct ($ldapName, $required = FALSE, $defaultValue = "", $acl = "", $label = NULL, $description = "hidden")
743  {
744  if ($label === NULL) {
745  $label = $ldapName;
746  }
747  parent::__construct($label, $description, $ldapName, $required, $defaultValue, $acl);
748  $this->setVisible(FALSE);
749  }
750 }
751 
753 {
754  protected function loadAttrValue ($attrs)
755  {
756  if (isset($attrs[$this->getLdapName()]['count'])) {
757  $this->value = array();
758  for ($i = 0; $i < $attrs[$this->getLdapName()]['count']; $i++) {
759  $this->value[] = $attrs[$this->getLdapName()][$i];
760  }
761  } else {
762  $this->resetToDefault();
763  }
764  }
765 }
766 
767 /* Dummy attribute class in order to give stats information to the template */
769 {
770  function __construct ($ldapName)
771  {
772  parent::__construct("Fake one", "", $ldapName, FALSE, "", "noacl");
773  $this->setInLdap(FALSE);
774  }
775 
776  function renderAttribute(&$attributes, $readOnly)
777  {
778  $attributes[$this->getLdapName()] = $this->getValue();
779  }
780 }
781 
788 {
789  protected $allowHTML = FALSE;
790  protected $allowSmarty = FALSE;
791 
792  function renderFormInput ()
793  {
794  if ($this->allowHTML) {
795  $value = $this->getValue();
796  } else {
797  $value = htmlentities($this->getValue(), ENT_COMPAT, 'UTF-8');
798  }
799  if ($this->allowSmarty) {
800  return $value;
801  } else {
802  return '{literal}'.$value.'{/literal}';
803  }
804  }
805 
806  function setAllowHTML ($allowHTML)
807  {
808  $this->allowHTML = $allowHTML;
809  }
810 
811  function setAllowSmarty ($allowSmarty)
812  {
813  $this->allowSmarty = $allowSmarty;
814  }
815 }
816 
822 {
823  function fillLdapValue (&$attrs)
824  {
825  }
826 }
827 
833 {
834  protected function loadAttrValue ($attrs)
835  {
836  if (isset($attrs[$this->getLdapName()]['count'])) {
837  $this->value = array();
838  for ($i = 0; $i < $attrs[$this->getLdapName()]['count']; $i++) {
839  $this->value[] = $attrs[$this->getLdapName()][$i];
840  }
841  } else {
842  $this->resetToDefault();
843  }
844  }
845 
846  function renderFormInput ()
847  {
848  $value = $this->getValue();
849  if (is_array($value)) {
850  $value = join(', ', $value);
851  }
852  return '{literal}'.htmlentities($value, ENT_COMPAT, 'UTF-8').'{/literal}';
853  }
854 }
855 
861 {
862  function __construct ($label, $description, $ldapName, $required = FALSE, $defaultValue = "", $acl = "")
863  {
864  parent::__construct ($label, $description, $ldapName, $required, $defaultValue, $acl);
865  $this->setInLdap(FALSE);
866  }
867 }
868 ?>
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:1295
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.