init($args); // find the column try { $this->column = $this->findColumn($this->opt['label']); } catch (StructException $e) { msg(hsc($e->getMessage()), -1); } $this->standardArgs($args); } /** * Sets the value and validates it * * @param mixed $value * @return bool value was set successfully validated */ protected function setVal($value) { if (!$this->column) { $value = ''; //don't validate placeholders here } elseif ($this->replace($value) == $value) { $validator = new ValueValidator(); $this->error = !$validator->validateValue($this->column, $value); if ($this->error) { foreach ($validator->getErrors() as $error) { msg(hsc($error), -1); } } } if ($value === [] || $value === '') { if (!isset($this->opt['optional'])) { $this->error = true; if ($this->column) { $label = $this->column->getTranslatedLabel(); } else { $label = $this->opt['label']; } msg(sprintf($this->getLang('e_required'), hsc($label)), -1); } } $this->opt['value'] = $value; return !$this->error; } /** * Creates the HTML for the field * * @param array $params * @param Doku_Form $form * @param int $formid */ public function renderfield($params, Doku_Form $form, $formid) { if (!$this->column) return; // this is what parent does $this->_handlePreload(); if (!$form->_infieldset) { $form->startFieldset(''); } if ($this->error) { $params['class'] = 'bureaucracy_error'; } // output the field $value = $this->createValue(); $field = $this->makeField($value, $params['name']); $form->addElement($field); } /** * Adds replacement for type user to the parent method * * @return array|mixed|string */ public function getReplacementValue() { $value = $this->getParam('value'); if (is_array($value)) { return [$this, 'replacementMultiValueCallback']; } if (!empty($value) && $this->column->getType() instanceof User) { return userlink($value, true); } return parent::getReplacementValue(); } /** * Adds handling of type user to the parent method * * @param $matches * @return string */ public function replacementMultiValueCallback($matches) { $value = $this->opt['value']; //default value if (is_null($value) || $value === false) { if (isset($matches['default']) && $matches['default'] != '') { return $matches['default']; } return $matches[0]; } if (!empty($value) && $this->column->getType() instanceof User) { $value = array_map(static fn($user) => userlink($user, true), $value); } //check if matched string containts a pair of brackets $delimiter = preg_match('/\(.*\)/s', $matches[0]) ? $matches['delimiter'] : ', '; return implode($delimiter, $value); } /** * Returns a Value object for the current column. * Special handling for Page and Lookup literal form values. * * @return Value */ protected function createValue() { // input value or appropriately initialized empty value $preparedValue = $this->opt['value'] ?? ($this->column->isMulti() ? [] : ''); // page fields might need to be JSON encoded depending on usetitles config if ( $this->column->getType() instanceof Page && $this->column->getType()->getConfig()['usetitles'] ) { if ($this->column->isMulti()) { $preparedValue = array_map( static fn($val) => json_encode([$val, null], JSON_THROW_ON_ERROR), $preparedValue ); } else { $preparedValue = json_encode([$preparedValue, null], JSON_THROW_ON_ERROR); } } $value = new Value($this->column, $preparedValue); // no way to pass $israw parameter to constructor, so re-set the Lookup value if ($this->column->getType() instanceof Lookup) { $value->setValue($preparedValue, true); } return $value; } /** * Create the input field * * @param Value $field * @param String $name field's name * @return string */ protected function makeField(Value $field, $name) { $trans = hsc($field->getColumn()->getTranslatedLabel()); $hint = hsc($field->getColumn()->getTranslatedHint()); $class = $hint ? 'hashint' : ''; $lclass = $this->error ? 'bureaucracy_error' : ''; $colname = $field->getColumn()->getFullQualifiedLabel(); $required = empty($this->opt['optional']) ? ' *' : ''; $id = uniqid('struct__', true); $input = $field->getValueEditor($name, $id); $html = '