id = $id; $this->action = $action; $this->method = $method; $this->locales = $locales; } /** * Add a form field * * @param Field $field * @param array $position [ * * @option string One of FIELD_POSITION_BEFORE or FIELD_POSITION_AFTER * @option string The field to position it before or after * ] */ public function addField($field, $position = []): static { if (empty($position)) { $this->fields[] = $field; } else { $this->fields = $this->addToPosition($position[1], $this->fields, $field, $position[0]); } return $this; } /** * Remove a form field * * @param string $fieldName */ public function removeField($fieldName): static { $this->fields = array_values(array_filter($this->fields, function ($field) use ($fieldName) { return $field->name !== $fieldName; })); return $this; } /** * Get a form field * * @param string $fieldName * * @return ?Field */ public function getField($fieldName) { foreach ($this->fields as $field) { if ($field->name === $fieldName) { return $field; } } return null; } /** * Add a form group * * @param array $args [ * * @option id string Required A unique ID for this form group * @option label string A label to identify this group of fields. Will become the fieldset's * @option description string A description of this group of fields. * ] * * @param array $position [ * * @option string One of FIELD_POSITION_BEFORE or FIELD_POSITION_AFTER * @option string The group to position it before or after * ] */ public function addGroup($args, $position = []): static { if (empty($args['id'])) { throw new Exception('Tried to add a form group without an id.'); } if (empty($position)) { $this->groups[] = $args; } else { $this->groups = $this->addToPosition($position[1], $this->groups, $args, $position[0]); } return $this; } /** * Remove a form group * * @param string $groupId */ public function removeGroup($groupId): static { $this->groups = array_filter($this->groups, function ($group) use ($groupId) { return $group['id'] !== $groupId; }); $this->fields = array_filter($this->fields, function ($field) use ($groupId) { return $field['groupId'] !== $groupId; }); return $this; } /** * Add a form page * * @param array $args [ * * @option id string Required A unique ID for this form page * @option label string The name of the page to identify it in the page list * @option submitButton array Required Assoc array defining submission/next button params. Supports any param of the Button component in the UI Library. * @option previousButton array Assoc array defining button params to go back to the previous page. Supports any param of the Button component in the UI Library. * ] * * @param array $position [ * * @option string One of FIELD_POSITION_BEFORE or FIELD_POSITION_AFTER * @option string The page to position it before or after * ] */ public function addPage($args, $position = []): static { if (empty($args['id'])) { fatalError('Tried to add a form page without an id.'); } if (empty($position)) { $this->pages[] = $args; } else { $this->pages = $this->addToPosition($position[1], $this->pages, $args, $position[0]); } return $this; } /** * Remove a form page * * @param string $pageId */ public function removePage($pageId): static { $this->pages = array_filter($this->pages, function ($page) use ($pageId) { return $page['id'] !== $pageId; }); foreach ($this->groups as $group) { if ($group['pageId'] === $pageId) { $this->removeGroup($group['id']); } } return $this; } /** * Add an field, group or page to a specific position in its array * * @param string $id The id of the item to position before or after * @param array $list The list of fields, groups or pages * @param mixed $item The item to insert * @param string $position FIELD_POSITION_BEFORE or FIELD_POSITION_AFTER * * @return array */ public function addToPosition($id, $list, $item, $position) { $index = count($list); foreach ($list as $key => $val) { if (($val instanceof \PKP\components\forms\Field && $id === $val->name) || (!$val instanceof \PKP\components\forms\Field && $id === $val['id'])) { $index = $key; break; } } if (!$index && $position === FIELD_POSITION_BEFORE) { array_unshift($list, $item); return $list; } $slice = $position === FIELD_POSITION_BEFORE ? $index : $index + 1; return array_merge( array_slice($list, 0, $slice), [$item], array_slice($list, $slice) ); } /** * Add a hidden field to this form */ public function addHiddenField(string $name, $value) { $this->hiddenFields[$name] = $value; } /** * Retrieve the configuration data to be used when initializing this * handler on the frontend * * @return array Configuration data */ public function getConfig() { if (empty($this->id) || empty($this->action) || ($this->action !== self::ACTION_EMIT && empty($this->method))) { throw new Exception('FormComponent::getConfig() was called but one or more required property is missing: id, method, action.'); } Hook::run('Form::config::before', [$this]); // Add a default page/group if none exist if (!$this->groups) { $this->addGroup(['id' => 'default']); $this->fields = array_map(function ($field) { $field->groupId = 'default'; return $field; }, $this->fields); } if (!$this->pages) { $this->addPage(['id' => 'default', 'submitButton' => ['label' => __('common.save')]]); $this->groups = array_map(function ($group) { $group['pageId'] = 'default'; return $group; }, $this->groups); } $fieldsConfig = array_map([$this, 'getFieldConfig'], $this->fields); $visibleLocales = [Locale::getLocale()]; if (Locale::getLocale() !== Locale::getPrimaryLocale()) { array_unshift($visibleLocales, Locale::getPrimaryLocale()); } $config = [ 'id' => $this->id, 'method' => $this->method, 'action' => $this->action, 'fields' => $fieldsConfig, 'groups' => $this->groups, 'hiddenFields' => (object) $this->hiddenFields, 'pages' => $this->pages, 'primaryLocale' => Locale::getPrimaryLocale(), 'visibleLocales' => $visibleLocales, 'supportedFormLocales' => array_values($this->locales), // See #5690 'errors' => (object) [], ]; Hook::call('Form::config::after', [&$config, $this]); return $config; } /** * Compile a configuration array for a single field * * @param Field $field * * @return array */ public function getFieldConfig($field) { $config = $field->getConfig(); // Add a value property if the field does not include one if (!array_key_exists('value', $config)) { $config['value'] = $field->isMultilingual ? [] : $field->getEmptyValue(); } if ($field->isMultilingual) { if (is_null($config['value'])) { $config['value'] = []; } foreach ($this->locales as $locale) { if (!array_key_exists($locale['key'], $config['value'])) { $config['value'][$locale['key']] = $field->getEmptyValue(); } } } return $config; } }