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