xref: /plugin/combo/ComboStrap/Meta/Form/FormMeta.php (revision 04fd306c7c155fa133ebb3669986875d65988276)
1*04fd306cSNickeau<?php
2*04fd306cSNickeau
3*04fd306cSNickeau
4*04fd306cSNickeaunamespace ComboStrap\Meta\Form;
5*04fd306cSNickeau
6*04fd306cSNickeau
7*04fd306cSNickeauuse ComboStrap\DataType;
8*04fd306cSNickeauuse ComboStrap\ExceptionRuntime;
9*04fd306cSNickeauuse ComboStrap\Meta\Form\FormMetaField;
10*04fd306cSNickeauuse ComboStrap\Meta\Form\FormMetaTab;
11*04fd306cSNickeauuse ComboStrap\Html;
12*04fd306cSNickeauuse ComboStrap\LogUtility;
13*04fd306cSNickeauuse ComboStrap\Meta\Api\Metadata;
14*04fd306cSNickeauuse ComboStrap\Meta\Api\MetadataStore;
15*04fd306cSNickeau
16*04fd306cSNickeau/**
17*04fd306cSNickeau * Class FormMeta
18*04fd306cSNickeau * @package ComboStrap
19*04fd306cSNickeau *
20*04fd306cSNickeau * Represents form metadata sends via an ajax request
21*04fd306cSNickeau *
22*04fd306cSNickeau * It makes sure that the data send
23*04fd306cSNickeau * is coherent
24*04fd306cSNickeau */
25*04fd306cSNickeauclass FormMeta
26*04fd306cSNickeau{
27*04fd306cSNickeau
28*04fd306cSNickeau    const FORM_TYPES = [self::FORM_NAV_TABS_TYPE, self::FORM_LIST_GROUP_TYPE];
29*04fd306cSNickeau    const FORM_NAV_TABS_TYPE = "nav-tabs";
30*04fd306cSNickeau    const FORM_LIST_GROUP_TYPE = "list-group";
31*04fd306cSNickeau    const FIELDS_ATTRIBUTE = "fields";
32*04fd306cSNickeau    const TABS_ATTRIBUTE = "tabs";
33*04fd306cSNickeau
34*04fd306cSNickeau    private $name;
35*04fd306cSNickeau
36*04fd306cSNickeau    /**
37*04fd306cSNickeau     * @var FormMetaField[]
38*04fd306cSNickeau     */
39*04fd306cSNickeau    private $fields;
40*04fd306cSNickeau    /**
41*04fd306cSNickeau     * @var FormMetaTab[]|string[]
42*04fd306cSNickeau     */
43*04fd306cSNickeau    private $tabs;
44*04fd306cSNickeau    /**
45*04fd306cSNickeau     * @var string
46*04fd306cSNickeau     */
47*04fd306cSNickeau    private $type;
48*04fd306cSNickeau
49*04fd306cSNickeau    /**
50*04fd306cSNickeau     * @throws ExceptionRuntime
51*04fd306cSNickeau     */
52*04fd306cSNickeau    public function __construct($name)
53*04fd306cSNickeau    {
54*04fd306cSNickeau        Html::validNameGuard($name);
55*04fd306cSNickeau        $this->name = $name;
56*04fd306cSNickeau    }
57*04fd306cSNickeau
58*04fd306cSNickeau
59*04fd306cSNickeau    public static function create($name): FormMeta
60*04fd306cSNickeau    {
61*04fd306cSNickeau        return new FormMeta($name);
62*04fd306cSNickeau    }
63*04fd306cSNickeau
64*04fd306cSNickeau    public function addField(FormMetaField $formField): FormMeta
65*04fd306cSNickeau    {
66*04fd306cSNickeau        $this->fields[] = $formField;
67*04fd306cSNickeau        $tab = $formField->getTab();
68*04fd306cSNickeau        if (!empty($tab) && !isset($this->tabs[$tab])) {
69*04fd306cSNickeau            $this->tabs[$tab] = $tab;
70*04fd306cSNickeau        }
71*04fd306cSNickeau        return $this;
72*04fd306cSNickeau    }
73*04fd306cSNickeau
74*04fd306cSNickeau    public function addTab(FormMetaTab $tab): FormMeta
75*04fd306cSNickeau    {
76*04fd306cSNickeau        $this->tabs[$tab->getName()] = $tab;
77*04fd306cSNickeau        return $this;
78*04fd306cSNickeau    }
79*04fd306cSNickeau
80*04fd306cSNickeau    public function toAssociativeArray(): array
81*04fd306cSNickeau    {
82*04fd306cSNickeau
83*04fd306cSNickeau        $fieldsArray = [];
84*04fd306cSNickeau        foreach ($this->fields as $element) {
85*04fd306cSNickeau            /**
86*04fd306cSNickeau             * The order is kept even if we add a key
87*04fd306cSNickeau             */
88*04fd306cSNickeau            $fieldsArray[$element->getName()] = $element->toAssociativeArray();
89*04fd306cSNickeau        }
90*04fd306cSNickeau        $tabs = [];
91*04fd306cSNickeau        foreach ($this->tabs as $element) {
92*04fd306cSNickeau            if (!($element instanceof FormMetaTab)) {
93*04fd306cSNickeau                $tab = FormMetaTab::create($element);
94*04fd306cSNickeau            } else {
95*04fd306cSNickeau                $tab = $element;
96*04fd306cSNickeau            }
97*04fd306cSNickeau            /**
98*04fd306cSNickeau             * The order is kept even if we add a key
99*04fd306cSNickeau             */
100*04fd306cSNickeau            $tabs[$tab->getName()] = $tab->toAssociativeArray();
101*04fd306cSNickeau        }
102*04fd306cSNickeau        return [
103*04fd306cSNickeau            self::FIELDS_ATTRIBUTE => $fieldsArray,
104*04fd306cSNickeau            self::TABS_ATTRIBUTE => $tabs
105*04fd306cSNickeau        ];
106*04fd306cSNickeau    }
107*04fd306cSNickeau
108*04fd306cSNickeau    /**
109*04fd306cSNickeau     * ie nav-tabs versus list-group:
110*04fd306cSNickeau     * https://getbootstrap.com/docs/5.0/components/list-group/#javascript-behavior
111*04fd306cSNickeau     *
112*04fd306cSNickeau     * @param string $type
113*04fd306cSNickeau     * @return FormMeta
114*04fd306cSNickeau     */
115*04fd306cSNickeau    public function setType(string $type): FormMeta
116*04fd306cSNickeau    {
117*04fd306cSNickeau        if (!in_array($type, self::FORM_TYPES)) {
118*04fd306cSNickeau            LogUtility::msg("The form type ($type) is unknown");
119*04fd306cSNickeau            return $this;
120*04fd306cSNickeau        }
121*04fd306cSNickeau        $this->type = $type;
122*04fd306cSNickeau        return $this;
123*04fd306cSNickeau    }
124*04fd306cSNickeau
125*04fd306cSNickeau    /**
126*04fd306cSNickeau     * The data as if it was send by a HTML form to the
127*04fd306cSNickeau     * post endpoint
128*04fd306cSNickeau     *
129*04fd306cSNickeau     * It transforms the fields to an associative array
130*04fd306cSNickeau     * that should be send with a post request
131*04fd306cSNickeau     *
132*04fd306cSNickeau     * ie Equivalent to the javascript api formdata output
133*04fd306cSNickeau     * (Used in test to simulate a post)
134*04fd306cSNickeau     *
135*04fd306cSNickeau     * TODO: Not sure but with the {@link MetadataStore}, this should move to the class
136*04fd306cSNickeau     *   where the target/read store is a {@link MetadataFormDataStore} ?
137*04fd306cSNickeau     */
138*04fd306cSNickeau    public function toFormData(): array
139*04fd306cSNickeau    {
140*04fd306cSNickeau        $data = [];
141*04fd306cSNickeau        $this->toFormDataRecurse($data, $this->fields);
142*04fd306cSNickeau        return $data;
143*04fd306cSNickeau    }
144*04fd306cSNickeau
145*04fd306cSNickeau    /**
146*04fd306cSNickeau     * @param $data
147*04fd306cSNickeau     * @param FormMetaField[] $fields
148*04fd306cSNickeau     */
149*04fd306cSNickeau    private function toFormDataRecurse(&$data, array $fields)
150*04fd306cSNickeau    {
151*04fd306cSNickeau
152*04fd306cSNickeau        foreach ($fields as $field) {
153*04fd306cSNickeau
154*04fd306cSNickeau            if ($field->isMutable()) {
155*04fd306cSNickeau
156*04fd306cSNickeau                $value = $field->getValue();
157*04fd306cSNickeau                if ($field->getType() === DataType::BOOLEAN_TYPE_VALUE) {
158*04fd306cSNickeau                    if ($value === $field->getDefaultValue() || $value === null) {
159*04fd306cSNickeau                        continue;
160*04fd306cSNickeau                    }
161*04fd306cSNickeau                }
162*04fd306cSNickeau                if ($value === null) {
163*04fd306cSNickeau                    // A form would return empty string
164*04fd306cSNickeau                    $value = "";
165*04fd306cSNickeau                }
166*04fd306cSNickeau                if (is_array($value)) {
167*04fd306cSNickeau                    $temp = [];
168*04fd306cSNickeau                    foreach ($value as $subValue) {
169*04fd306cSNickeau                        if ($subValue === null) {
170*04fd306cSNickeau                            $temp[] = "";
171*04fd306cSNickeau                        } else {
172*04fd306cSNickeau                            if (is_array($subValue) && $field->isMultiple()) {
173*04fd306cSNickeau                                $temp[] = implode(",", $subValue);
174*04fd306cSNickeau                            } else {
175*04fd306cSNickeau                                $temp[] = $subValue;
176*04fd306cSNickeau                            }
177*04fd306cSNickeau                        }
178*04fd306cSNickeau                    }
179*04fd306cSNickeau                    $value = $temp;
180*04fd306cSNickeau                }
181*04fd306cSNickeau                $data[$field->getName()] = $value;
182*04fd306cSNickeau
183*04fd306cSNickeau            }
184*04fd306cSNickeau            $formMetaChildren = $field->getChildren();
185*04fd306cSNickeau            if ($formMetaChildren != null) {
186*04fd306cSNickeau                $this->toFormDataRecurse($data, $formMetaChildren);
187*04fd306cSNickeau            }
188*04fd306cSNickeau        }
189*04fd306cSNickeau
190*04fd306cSNickeau    }
191*04fd306cSNickeau
192*04fd306cSNickeau    /**
193*04fd306cSNickeau     * @param Metadata $metadata
194*04fd306cSNickeau     * @return FormMeta
195*04fd306cSNickeau     */
196*04fd306cSNickeau    public function addFormFieldFromMetadata(Metadata $metadata): FormMeta
197*04fd306cSNickeau    {
198*04fd306cSNickeau        $field = FormMetaField::createFromMetadata($metadata);
199*04fd306cSNickeau        $this->addField($field);
200*04fd306cSNickeau        return $this;
201*04fd306cSNickeau    }
202*04fd306cSNickeau
203*04fd306cSNickeau
204*04fd306cSNickeau}
205