27 protected $valueUnicity = TRUE;
28 protected $editingValue = FALSE;
29 protected $linearRendering = TRUE;
41 $attribute->getLabel(), $attribute->getDescription(),
42 $attribute->getLdapName(), $attribute->isRequired(),
45 $this->attribute = $attribute;
46 $this->attribute->setRequired(TRUE);
47 $this->attribute->setIsSubAttribute(TRUE);
48 $this->valueUnicity = $valueUnicity;
51 protected function getValueCount ()
53 return count($this->getValue());
56 function setIsSubAttribute (
bool $bool)
58 parent::setIsSubAttribute($bool);
59 $this->attribute->setIsSubAttribute($this->isSubAttribute);
62 function setManagedAttributes (array $dontcare)
64 trigger_error(
'method setManagedAttributes is not supported for SetAttributes');
67 function setLinearRendering (
bool $bool)
69 $this->linearRendering = $bool;
72 protected function loadAttrValue (array $attrs)
74 if (isset($attrs[$this->getLdapName()][
'count'])) {
76 for ($i = 0; $i < $attrs[$this->getLdapName()][
'count']; $i++) {
77 $this->value[] = $attrs[$this->getLdapName()][$i];
83 function getAcl ():
string 85 if ($this->attribute === FALSE) {
86 return parent::getAcl();
88 return $this->attribute->getAcl();
91 function getAclInfo ()
93 if ($this->attribute === FALSE) {
94 return parent::getAclInfo();
96 return $this->attribute->getAclInfo();
99 function setAcl (
string $acl)
101 if ($this->attribute === FALSE) {
102 return parent::setAcl($acl);
104 $this->attribute->setAcl($acl);
107 function addPostValue ($value)
112 if ($this->valueUnicity && in_array($value, $this->postValue, TRUE)) {
115 $this->postValue[] = $value;
119 function delPostValue ($key)
121 unset($this->postValue[$key]);
124 function loadPostValue ()
126 $this->editingValue = FALSE;
127 $id = $this->getHtmlId();
128 if ($this->isVisible()) {
129 $this->postValue = $this->value;
130 if (isset($_POST[
"add".$id])) {
131 if ($this->attribute !== FALSE) {
132 $this->attribute->loadPostValue();
133 $this->attribute->applyPostValue();
134 $this->addPostValue($this->attribute->getValue());
136 } elseif (isset($_POST[
"del".$id]) && isset($_POST[
"row".$id])) {
137 foreach ($_POST[
"row".$id] as $key) {
138 $this->delPostValue($key);
140 } elseif ($this->attribute !== FALSE) {
141 $this->attribute->loadPostValue();
142 $this->attribute->applyPostValue();
143 $this->editingValue = $this->attribute->getValue();
150 $error = parent::check();
151 if (!empty($error) || ($this->attribute === FALSE)) {
154 $values = $this->getValue();
155 if (!is_array($values)) {
161 foreach ($values as $value) {
162 $this->attribute->setValue($value);
163 $error = $this->attribute->check();
164 if (!empty($error)) {
171 function renderFormInput ():
string 173 $display = $this->renderOnlyFormInput();
174 $attr_display = $this->renderAttributeInput(FALSE);
175 $buttons = $this->renderButtons();
176 return $this->
renderAcl($display).$attr_display.$this->renderAcl($buttons);
179 function renderTemplateInput ():
string 181 $display = $this->renderOnlyFormInput();
182 $attr_display = $this->renderAttributeInput(TRUE);
183 $buttons = $this->renderButtons();
184 return $this->
renderAcl($display).$attr_display.$this->renderAcl($buttons);
187 function renderOnlyFormInput ():
string 189 if (($this->size < 15) && ($this->size < $this->getValueCount())) {
190 $this->size = min(15, $this->getValueCount());
192 $id = $this->getHtmlId();
194 $smarty->assign($id.
'_values', $this->getDisplayValues());
195 $display =
'<select multiple="multiple" name="row'.$id.
'[]" id="row'.$id.
'" size="'.$this->size.
'"'.
196 ($this->disabled ?
' disabled="disabled"' :
'').
198 $display .=
'{html_options options=$'.$id.
'_values}';
199 $display .=
'</select><br/>'.
"\n";
203 function getDisplayValues ()
205 if ($this->attribute === FALSE) {
206 return $this->getValue();
208 $attribute = $this->attribute;
210 function ($value) use ($attribute)
212 return $attribute->displayValue($value);
218 function handleEditingValue ()
220 if ($this->editingValue === FALSE) {
221 $this->attribute->resetToDefault();
223 $this->attribute->setValue($this->editingValue);
227 function renderAttributeInput ($template = FALSE)
229 if ($this->attribute === FALSE) {
232 $this->handleEditingValue();
233 if ($this->valueUnicity && ($this->attribute instanceOf
SelectAttribute)) {
234 $this->attribute->setHiddenChoices($this->getValue());
237 return $this->attribute->renderTemplateInput();
239 return $this->attribute->renderFormInput();
243 function renderAttribute (array &$attributes,
bool $readOnly,
bool $readable,
bool $writable)
245 if ($this->attribute === FALSE) {
246 return parent::renderAttribute($attributes, $readOnly, $readable, $writable);
248 if ($this->visible) {
249 $this->attribute->setDisabled($this->disabled);
250 if ($this->linearRendering || $readOnly) {
251 parent::renderAttribute($attributes, $readOnly, $readable, $writable);
253 if ($this->valueUnicity && ($this->attribute instanceOf
SelectAttribute)) {
254 $this->attribute->setHiddenChoices($this->getValue());
256 $attributes[$this->getLdapName()] = [
257 'htmlid' => $this->getForHtmlId(),
258 'label' =>
'{literal}'.htmlescape($this->getLabel()).
'{/literal}',
259 'description' => ($this->isRequired() ? sprintf(_(
"%s (required)"), $this->getDescription()) : $this->getDescription()),
260 'input' => $this->
renderAcl($this->renderOnlyFormInput()),
261 'subattribute' => $this->isSubAttribute,
262 'required' => $this->isRequired(),
263 'readable' => $readable,
264 'writable' => $writable,
266 $this->handleEditingValue();
267 $this->attribute->renderAttribute($attributes, $readOnly, $readable, $writable);
268 $attributes[$this->getLdapName().
'_buttons'] = [
269 'htmlid' =>
'add'.$this->getHtmlId(),
272 'input' => $this->
renderAcl($this->renderButtons()),
273 'subattribute' => TRUE,
275 'readable' => $readable,
276 'writable' => $writable,
282 function serializeAttribute (array &$attributes,
bool $form = TRUE)
284 parent::serializeAttribute($attributes, $form);
285 if ($this->attribute === FALSE) {
292 $this->attribute->setDisabled($this->disabled);
293 $this->attribute->serializeAttribute($subattributes, $form);
294 $attributes[$this->getLdapName()][
'attributes'] = $subattributes;
295 $attributes[$this->getLdapName()][
'attributes_order'] = array_keys($subattributes);
299 function getForHtmlId ():
string 302 if (is_object($this->attribute)) {
303 return $this->attribute->getForHtmlId();
309 function renderButtons ()
311 $id = $this->getHtmlId();
312 $buttons = $this->renderInputField(
316 'formnovalidate' =>
'formnovalidate',
317 'class' =>
'subattribute',
320 $buttons .= $this->renderInputField(
324 'formnovalidate' =>
'formnovalidate',
325 'class' =>
'subattribute',
331 function computeLdapValue ()
334 return array_values($this->getValue());
337 protected function sortValues ()
342 public function htmlIds (): array
344 $id = $this->getHtmlId();
345 return array_merge([
'add'.$id,
'del'.$id,
'row'.$id], $this->attribute->htmlIds());
354 parent::setParent($plugin);
355 if ($this->attribute !== FALSE) {
356 $this->attribute->setParent($plugin);
360 function getArrayValues ()
363 foreach ($this->getValue() as $value) {
364 $this->attribute->setValue($value);
366 foreach ($this->attribute->getArrayValue() as $val) {
374 function foreignKeyUpdate ($oldvalue, $newvalue, array $source)
376 foreach ($this->value as $key => &$value) {
377 if (($source[
'FIELD'] ==
'dn') && ($source[
'MODE'] ==
'move')) {
378 if ($newvalue === NULL) {
379 if (preg_match(
'/'.preg_quote($oldvalue,
'/').
'$/', $value)) {
380 unset($this->value[$key]);
383 $value = preg_replace(
'/'.preg_quote($oldvalue,
'/').
'$/', $newvalue, $value);
385 } elseif ($value == $oldvalue) {
386 if ($newvalue === NULL) {
387 unset($this->value[$key]);
388 } elseif ($source[
'MODE'] ==
'copy') {
389 $this->value[] = $newvalue;
390 } elseif ($source[
'MODE'] ==
'move') {
398 function foreignKeyCheck ($value, array $source):
bool 400 return in_array($value, $this->getValue());
403 function setSize ($size)
408 function checkValue ($value)
410 if (!is_array($value)) {
411 throw new InvalidValueException(sprintf(_(
'SetAttribute "%s" was set to a non-compatible value'), $this->getLabel()));
422 protected $edit_enabled;
423 protected $headers = FALSE;
432 function __construct ($attribute, $order = TRUE, $values = [], $edit_enabled = FALSE)
434 parent::__construct($attribute, $values);
435 $this->order = $order;
436 $this->edit_enabled = $edit_enabled;
439 function setHeaders ($h)
444 function readValue ($value)
447 return preg_split(
'/:/', $value, 2);
453 function writeValue ($key, $value)
456 return $key.
":".$value;
462 function computeLdapValue ()
466 foreach ($this->getValue() as $key => $value) {
467 $ldapValue[] = $this->writeValue($key, $value);
472 protected function sortValues ()
479 protected function loadAttrValue (array $attrs)
481 if (isset($attrs[$this->getLdapName()][
"count"])) {
483 for ($i = 0; $i < $attrs[$this->getLdapName()][
"count"]; $i++) {
484 $value = $this->readValue($attrs[$this->getLdapName()][$i]);
485 if (is_array($value)) {
486 $this->value[$value[0]] = $value[1];
488 $this->value[] = $value;
494 $this->reIndexValues();
500 function renderOnlyFormInput ():
string 502 if (($this->size < 15) && ($this->size < $this->getValueCount())) {
503 $this->size = min(15, $this->getValueCount());
505 $id = $this->getHtmlId();
508 $height = ($this->size * 26) + 6;
509 if ($this->headers) {
512 $div->setHeight($height);
513 $div->setHeaders($this->headers);
514 foreach ($this->getValue() as $key => $value) {
516 foreach ($this->getAttributeArrayValue($key, $value) as $field) {
517 if (is_array($field)) {
520 $fields[] = [
'string' => $field];
523 if (empty($fields)) {
527 list ($img, $nbicons) = $this->genRowIcons($key, $value);
529 $fields[] = [
'html' => $img,
'attach' =>
'style="border:0px;width:'.($nbicons * 20).
'px;"'];
531 $div->addEntry($fields);
533 $smarty->assign(
"div_$id", $div->drawList());
534 return '{$div_'.$id.
'}'.
"\n";
537 protected function genRowIcons ($key, $value)
539 $id = $this->getHtmlId();
547 $img .= $this->renderInputField(
548 'image', $id.
'_up_'.$key,
550 'src' =>
'geticon.php?context=actions&icon=view-sort-descending&size=16',
551 'title' => _(
'Sort up'),
552 'alt' => _(
'Sort up'),
554 'formnovalidate' =>
'formnovalidate',
559 $img .=
'<img src="images/empty.png" alt="" style="width:16px;"/>';
561 if (($key + 1) < $this->getValueCount()) {
562 $img .= $this->renderInputField(
563 'image', $id.
'_down_'.$key,
565 'src' =>
'geticon.php?context=actions&icon=view-sort-ascending&size=16',
566 'title' => _(
'Sort down'),
567 'alt' => _(
'Sort down'),
569 'formnovalidate' =>
'formnovalidate',
574 $img .=
'<img src="images/empty.png" alt="" style="width:16px;"/>';
577 if ($this->edit_enabled) {
579 $img .= $this->renderInputField(
580 'image', $id.
'_edit_'.$key,
582 'src' =>
'geticon.php?context=actions&icon=document-edit&size=16',
583 'title' => _(
'Edit'),
586 'formnovalidate' =>
'formnovalidate',
591 $img .= $this->renderInputField(
592 'image', $id.
'_del_'.$key,
594 'src' =>
'geticon.php?context=actions&icon=edit-delete&size=16',
595 'title' => _(
'Delete'),
596 'alt' => _(
'Delete'),
598 'formnovalidate' =>
'formnovalidate',
603 return [$img, $nbicons];
606 protected function getAttributeArrayValue ($key, $value)
608 $this->attribute->setValue($value);
609 return $this->attribute->getArrayValue();
612 protected function reIndexValues ()
614 $this->value = array_values($this->value);
617 function loadPostValue ()
619 $this->editingValue = FALSE;
620 if ($this->isVisible()) {
621 $this->postValue = $this->value;
622 $id = $this->getHtmlId();
623 foreach (array_keys($_POST) as $name) {
624 if ($this->handlePostValueActions($id, $name)) {
628 $this->handleAddAndEditValue();
632 protected function handlePostValueActions ($id, $postValue)
635 if (preg_match(
'/^'.$id.
'_up_/', $postValue)) {
636 $key = preg_replace(
'/^'.$id.
'_up_/',
'', $postValue);
637 $key = (int)preg_replace(
'/_[xy]$/',
'', $key);
639 $tmp = $this->postValue[$key];
640 $this->postValue[$key] = $this->postValue[$key - 1];
641 $this->postValue[$key - 1] = $tmp;
644 if (preg_match(
'/^'.$id.
'_down_/', $postValue)) {
645 $key = preg_replace(
'/^'.$id.
'_down_/',
'', $postValue);
646 $key = (int)preg_replace(
'/_[xy]$/',
'', $key);
648 $tmp = $this->postValue[$key];
649 $this->postValue[$key] = $this->postValue[$key + 1];
650 $this->postValue[$key + 1] = $tmp;
654 if ($this->edit_enabled && preg_match(
'/^'.$id.
'_edit_/', $postValue)) {
655 $key = preg_replace(
'/^'.$id.
'_edit_/',
'', $postValue);
656 $key = preg_replace(
'/_[xy]$/',
'', $key);
657 $this->handleEdit($key);
660 if (preg_match(
'/^'.$id.
'_del_/', $postValue)) {
661 $key = preg_replace(
'/^'.$id.
'_del_/',
'', $postValue);
662 $key = preg_replace(
'/_[xy]$/',
'', $key);
663 $this->delPostValue($key);
669 protected function handleAddAndEditValue ()
671 $id = $this->getHtmlId();
672 if ($this->attribute === FALSE) {
675 if (isset($_POST[
"add$id"])) {
676 $this->attribute->loadPostValue();
677 $this->attribute->applyPostValue();
678 if ($error = $this->attribute->check()) {
679 if (is_string($error)) {
684 $this->addPostValue($this->attribute->getValue());
686 } elseif ($this->editingValue === FALSE) {
687 $this->attribute->loadPostValue();
688 $this->attribute->applyPostValue();
689 $this->editingValue = $this->attribute->getValue();
693 protected function handleEdit ($key)
695 $this->editingValue = $this->value[$key];
696 $this->delPostValue($key);
697 $this->plugin->focusedField = $this->getHtmlId();
702 parent::applyPostValue();
704 $this->reIndexValues();
708 public function htmlIds (): array
710 $id = $this->getHtmlId();
712 if ($this->attribute !== FALSE) {
713 $ids = array_merge($ids, $this->attribute->htmlIds());
715 $nb_values = $this->getValueCount();
716 for ($i = 0; $i < $nb_values; ++$i) {
719 $ids[] = $id.
'_up_'.$i;
721 if (($i + 1) < $nb_values) {
722 $ids[] = $id.
'_down_'.$i;
725 $ids[] = $id.
'_del_'.$i;
730 function renderButtons ()
732 $id = $this->getHtmlId();
733 $buttons = $this->renderInputField(
737 'formnovalidate' =>
'formnovalidate',
738 'class' =>
'subattribute',
750 protected $objectClass;
751 protected $objectClasses;
753 function __construct ($label, $description, $ldapName, $objectClass, $attributes, $order = FALSE, $values = [], $edit_enabled = FALSE, $acl =
"")
755 $attributes_keys = [];
756 foreach ($attributes as $attribute) {
757 $attributes_keys[$attribute->getLdapName()] = $attribute;
758 $attributes_keys[$attribute->getLdapName()]->htmlid_prefix = $ldapName.
'_';
761 $description, $ldapName,
766 parent::__construct($composite, $order, $values, $edit_enabled);
767 if (is_array($objectClass)) {
768 $this->objectClass = $objectClass[0];
769 $this->objectClasses = $objectClass;
771 $this->objectClass = $objectClass;
772 $this->objectClasses = [$objectClass];
776 protected function loadAttrValue (array $attrs)
780 if (isset($attrs[
'dn'])) {
781 $ldap = $config->get_ldap_link();
782 $ldap->cd($attrs[
'dn']);
783 $ldap->search(
'objectClass='.$this->objectClass, [
'*'],
'one');
785 while ($subattrs = $ldap->fetch(TRUE)) {
786 $this->attribute->resetToDefault();
787 foreach ($this->attribute->attributes as &$attribute) {
788 $attribute->loadAttrValue($subattrs);
791 $this->value[] = $this->attribute->getValue();
803 function postLdapSave ($ldap)
806 $ldap->cd($this->plugin->dn);
807 $ldap->search(
'objectClass='.$this->objectClass, [
'dn'],
'one');
809 while ($attrs = $ldap->fetch()) {
810 $delete[] = $attrs[
'dn'];
812 foreach ($delete as $dn) {
816 foreach ($this->value as $val) {
817 $attrs = [
'objectClass' => $this->objectClasses];
818 $this->attribute->setValue($val);
819 foreach ($this->attribute->attributes as &$attribute) {
820 $attribute->fillLdapValue($attrs);
823 $dn = $this->compute_attribute_dn();
825 foreach (array_keys($attrs) as $index) {
826 if (is_array($attrs[$index]) && (count($attrs[$index]) == 0)) {
827 unset($attrs[$index]);
831 if (!$ldap->success()) {
838 function compute_attribute_dn ()
841 reset($this->attribute->attributes);
842 $firstAttribute = key($this->attribute->attributes);
843 return $firstAttribute.
'='.$this->attribute->attributes[$firstAttribute]->computeLdapValue().
','.$this->plugin->dn;
This class allow to handle easily a Select LDAP attribute with a set of choices.
fillLdapValue(array &$attrs)
Fill LDAP value in the attrs array.
Exception class which can be thrown if an attribute is set to a value with a non-compatible type...
static delButton($escape=TRUE)
Text for an delete button.
setParent(&$plugin)
Set the parent plugin for this attribute.
static addButton($escape=TRUE)
Text for an add button.
This class allow to handle easily a composite attribute.
__construct(\FusionDirectory\Core\SimplePlugin\Attribute $attribute, array $values=[], bool $valueUnicity=TRUE)
The constructor of SetAttribute.
& get_smarty()
Get global smarty object.
Error returned by an LDAP operation called from SimplePlugin.
static invalidValue(string $error)
Format error message for invalid value.
Error returned by check method of SimplePlugin.
applyPostValue()
Apply this attribute postValue in value if this attribute is enabled.
This class allow to handle easily a multi-valuated attribute.
renderAcl(string $display)
Add ACL information around display.
An OrderedArrayAttribute which stores its values in LDAP subnodes.
__construct($attribute, $order=TRUE, $values=[], $edit_enabled=FALSE)
The constructor of OrderedArrayAttribute.
This class contains all the functions to manage select box.
Multivalued attribute displayed as a columned table. May allow ordering and/or editing.
This class allow to handle easily any kind of LDAP attribute.