Ubiquity 2.5.2
php rapid development framework
Loading...
Searching...
No Matches
FormModelViewerTrait.php
Go to the documentation of this file.
1<?php
2
4
5use Ajax\php\ubiquity\utils\DataFormHelper;
6use Ajax\semantic\html\collections\form\HtmlFormCheckbox;
7use Ajax\semantic\html\collections\form\HtmlFormField;
8use Ajax\semantic\html\collections\form\HtmlFormInput;
9use Ajax\semantic\html\elements\HtmlButton;
10use Ajax\semantic\html\elements\HtmlIconGroups;
11use Ajax\semantic\widgets\dataform\DataForm;
12use Ajax\semantic\widgets\datatable\DataTable;
13use Ajax\service\JArray;
19
31
32 abstract public function getDataTableId();
33
34 protected function relationMembersInForm($form, $instance, $className, $fields, $relations, &$fieldTypes) {
35 foreach ($relations as $field => $member) {
36 if (\array_search($field, $fields) !== false) {
37 unset($fieldTypes[$field]);
38 if (OrmUtils::getAnnotationInfoMember($className, '#manyToOne', $member) !== false) {
39 $this->manyToOneFormField($form, $member, $className, $instance);
40 } elseif (($annot = OrmUtils::getAnnotationInfoMember($className, '#oneToMany', $member)) !== false) {
41 $fkClass = $annot['className'];
42 if (OrmUtils::isManyToMany($fkClass)) {
43 $this->oneToManyFormFieldDt($form, $member, $instance, $annot);
44 } else {
45 $this->oneToManyFormField($form, $member, $instance, $annot);
46 }
47 } elseif (($annot = OrmUtils::getAnnotationInfoMember($className, '#manyToMany', $member)) !== false) {
48 $this->manyToManyFormField($form, $member, $instance, $annot);
49 }
50 }
51 }
52 }
53
54 protected function manyToOneFormField($form, $member, $className, $instance) {
55 $joinColumn = OrmUtils::getAnnotationInfoMember($className, '#joinColumn', $member);
56 if ($joinColumn) {
57 $fkObject = Reflexion::getMemberValue($instance, $member);
58 $fkClass = $joinColumn ['className'];
59 if ($fkObject === null) {
60 $fkObject = new $fkClass ();
61 }
62 $fkId = OrmUtils::getFirstKey($fkClass);
63
64 $fkIdGetter = 'get' . \ucfirst($fkId);
65 if (\method_exists($fkObject, '__toString') && \method_exists($fkObject, $fkIdGetter)) {
66 $fkField = $joinColumn ['name'];
67 $fkValue = OrmUtils::getFirstKeyValue($fkObject);
68 if (!Reflexion::setMemberValue($instance, $fkField, $fkValue)) {
69 $instance->{$fkField} = OrmUtils::getFirstKeyValue($fkObject);
70 }
71 $attr = [];
72 if (OrmUtils::isNullable($className, $member)) {
73 $attr = ['jsCallback' => function ($elm) {
74 $elm->getField()->setClearable(true);
75 }];
76 } else {
77 $attr = ['jsCallback' => function ($elm) {
78 $elm->addRules(['empty']);
79 }];
80 }
81 $form->fieldAsDropDown($fkField, JArray::modelArray($this->controller->_getAdminData()->getManyToOneDatas($fkClass, $instance, $member), $fkIdGetter, '__toString'), false, $attr);
82 $form->setCaption($fkField, \ucfirst($member));
83 }
84 }
85 }
86
87 protected function oneToManyFormField(DataForm $form, $member, $instance, $annot) {
88 $newField = $member . 'Ids';
89 $fkClass = $annot ['className'];
90 $fkId = OrmUtils::getFirstKey($fkClass);
91 $fkIdGetter = 'get' . \ucfirst($fkId);
92 $fkInstances = Reflexion::getMemberValue($instance, $member);//DAO::getOneToMany ( $instance, $member );
93 $ids = \array_map(function ($elm) use ($fkIdGetter) {
94 return $elm->{$fkIdGetter} ();
95 }, $fkInstances);
96 $instance->{$newField} = \implode(",", $ids);
97 $form->fieldAsDropDown($newField, JArray::modelArray($this->controller->_getAdminData()->getOneToManyDatas($fkClass, $instance, $member), $fkIdGetter, "__toString"), true);
98 $form->setCaption($newField, \ucfirst($member));
99 }
100
101 protected function oneToManyFormFieldDt(DataForm $form, $member, $instance, $annot) {
102 $newField = $member . 'Ids';
103 $fkClass = $annot ['className'];
104 $fkv = OrmUtils::getFirstKeyValue($instance);
105 if ($fkv != null) {
106 $fkInstances = DAO::getOneToMany($instance, $member);
107 }
108 $fields = OrmUtils::getManyToManyFieldsDt(\get_class($instance), $fkClass);
109 $fkInstances[] = new $fkClass();
110 $relFields = OrmUtils::getFieldsInRelations_($fkClass);
111 $form->fieldAsDataTable($newField, $fkClass, $fkInstances, $fields, ['jsCallback' => function (DataTable $dt) use ($fkClass, $relFields, $fields, $newField) {
112 $this->dtManyField($dt, $fkClass, $relFields, $fields);
113 $id = $dt->getIdentifier();
114 $removeSelected = 'function updateCmb(){let cmb=$("#' . $id . ' tbody tr:last-child div.dropdown");cmb.find("a[data-value]").removeClass("disabled");$("#' . $id . ' tbody tr div.dropdown input").each(function(){if($(this).val()) cmb.find("[data-value="+$(this).val()+"]").addClass("disabled");});}';
115 $this->jquery->execAtLast($removeSelected . 'updateCmb();$("#' . $id . ' tbody tr:last-child .dropdown").removeClass("disabled");$("#' . $id . ' tbody tr:last-child").find("input._status").val("added");');
116 $deleteJS = $this->jquery->execJSFromFile('@framework/js/delete', [], false);
117 $this->jquery->click('._delete', '$("[name=' . $newField . ']").val("updated");' . $deleteJS, true, false, false, "#$id");
118 $this->jquery->change('tr:last-child input', $this->jquery->execJSFromFile('@framework/js/change', compact('id'), false), false, false, "#$id");
119 $this->jquery->change('tr .dropdown input', 'updateCmb();', false, false, "#$id");
120 $this->jquery->change('tr input', '$("[name=' . $newField . ']").val("updated");if($(this).closest("tr").find("input._status").val()!=="added"){$(this).closest("tr").find("input._status").val("updated");}', false, false, "#$id");
121
122 }]);
123 $form->setCaption($newField, \ucfirst($member));
124 }
125
126 protected function dtManyField(DataTable $dt, $className, array $relations, array $fields) {
127 foreach ($relations as $field => $member) {
128 if (\array_search($field, $fields) !== false) {
129 if (OrmUtils::getAnnotationInfoMember($className, "#manyToOne", $member) !== false) {
130 $this->dtManyFieldCmb($dt, $member, $className);
131 }
132 }
133 }
134 }
135
136 protected function dtManyFieldCmb($dt, $member, $className) {
137 $joinColumn = OrmUtils::getAnnotationInfoMember($className, "#joinColumn", $member);
138 if ($joinColumn) {
139 $fkClass = $joinColumn ['className'];
140 $fkId = OrmUtils::getFirstKey($fkClass);
141
142 $fkIdGetter = 'get' . \ucfirst($fkId);
143 $fkField = $joinColumn ['name'];
144
145 $attr = [];
146 if (OrmUtils::isNullable($className, $member)) {
147 $attr = ['jsCallback' => function ($elm) {
148 $f = $elm->getField();
149 $f->setClearable(true);
150 $f->addClass('disabled');
151 }];
152 } else {
153 $attr = ['jsCallback' => function ($elm) {
154 $elm->getField()->addClass('disabled');
155 }];
156 }
157 $dt->fieldAsDropDown($fkField, JArray::modelArray($this->controller->_getAdminData()->getManyToOneDatas($fkClass, null, $member), $fkIdGetter, '__toString'), false, $attr);
158 }
159 }
160
161 protected function manyToManyFormField(DataForm $form, $member, $instance, $annot) {
162 $newField = $member . 'Ids';
163 $fkClass = $annot ['targetEntity'];
164 $fkId = OrmUtils::getFirstKey($fkClass);
165 $fkIdGetter = 'get' . \ucfirst($fkId);
166 $fkInstances = Reflexion::getMemberValue($instance, $member);//DAO::getManyToMany ( $instance, $member );
167 $ids = \array_map(function ($elm) use ($fkIdGetter) {
168 return $elm->{$fkIdGetter} ();
169 }, $fkInstances);
170 $instance->{$newField} = \implode(',', $ids);
171 $form->fieldAsDropDown($newField, JArray::modelArray($this->controller->_getAdminData()->getManyToManyDatas($fkClass, $instance, $member), $fkIdGetter, '__toString'), true, ['jsCallback' => function ($elm) {
172 $elm->getField()->asSearch();
173 }]);
174 $form->setCaption($newField, \ucfirst($member));
175 }
176
181 public function getEditMemberParams() {
182 return $this->defaultEditMemberParams();
183 }
184
190 protected function getEditMemberParams_($part) {
191 $params = $this->getEditMemberParams();
192 if ($params && isset ($params [$part])) {
193 return $params [$part];
194 }
195 }
196
201 protected function defaultEditMemberParams() {
202 return ['dataTable' => EditMemberParams::dataTable('#' . $this->getDataTableId()), 'dataElement' => EditMemberParams::dataElement()];
203 }
204
213 public function getForm($identifier, $instance, $updateUrl = 'updateModel') {
214 $hasMessage = $this->formHasMessage();
215 $form = $this->jquery->semantic()->dataForm($identifier, $instance);
216 $form->setLibraryId('frmEdit');
217 $className = \get_class($instance);
218 $fields = \array_unique($this->controller->_getAdminData()->getFormFieldNames($className, $instance));
219 $relFields = OrmUtils::getFieldsInRelations_($className);
220
221 $this->setFormFields_($fields, $relFields);
222 if ($hasMessage) {
223 \array_unshift($fields, '_message');
224 }
225 $form->setFields($fields);
226 $fieldTypes = OrmUtils::getFieldTypes($className);
227 $attrs = ValidatorsManager::getUIConstraints($instance);
228
229 $this->relationMembersInForm($form, $instance, $className, $fields, $relFields, $fieldTypes);
230 OrmUtils::setFieldToMemberNames($fields, $relFields);
231 $form->setCaptions($this->getFormCaptions($fields, $className, $instance));
232 if ($hasMessage) {
233 $message = $this->getFormTitle($form, $instance);
234 $form->setCaption('_message', $message ['subMessage']);
235 $form->fieldAsMessage('_message', ['icon' => $message ['icon']]);
236 $instance->_message = $message ['message'];
237 }
238
239 $this->setFormFieldsComponent($form, $fieldTypes, $attrs);
240 $form->setSubmitParams($this->controller->_getBaseRoute() . '/' . $updateUrl, '#frm-add-update');
241 $form->onGenerateField([$this, 'onGenerateFormField']);
242 return $form;
243 }
244
256 public function getMemberForm($identifier, $instance, $member, $td, $part, $updateUrl = '_updateMember') {
257 $editMemberParams = $this->getEditMemberParams_($part);
258
259 $form = $this->jquery->semantic()->dataForm($identifier, $instance);
260 $form->on("dblclick", "", true, true);
261 $form->setProperty("onsubmit", "return false;");
262 $form->setProperty('style', 'margin:0;');
263 $form->addClass("_memberForm");
264 $className = \get_class($instance);
265 $fields = ["id", $member];
266 $relFields = OrmUtils::getFieldsInRelations_($className);
267 $hasRelations = $this->setFormFields_($fields, $relFields);
268 $form->setFields($fields);
269 $fieldTypes = OrmUtils::getFieldTypes($className);
270 $form->fieldAsHidden(0);
271 $attrs = ValidatorsManager::getUIConstraints($instance);
272 $this->setMemberFormFieldsComponent($form, $fieldTypes, $attrs);
273 if ($hasRelations) {
274 $this->relationMembersInForm($form, $instance, $className, $fields, $relFields, $fieldTypes);
275 }
276 $form->setCaptions(["", ""]);
277 $form->onGenerateField(function (HtmlFormField $f, $nb) use ($identifier, $editMemberParams) {
278 if ($nb == 1) {
279 $f->setSize("mini");
280 if ($editMemberParams->getHasButtons()) {
281 $btO = HtmlButton::icon("btO", "check")->addClass("green mini compact")->onClick("\$('#" . $identifier . "').trigger('validate');", true, true);
282 $btC = HtmlButton::icon("btC", "close")->addClass("mini compact")->onClick("\$('#" . $identifier . "').trigger('endEdit');");
283 $f->wrap("<div class='inline fields' style='margin:0;'>", [$btO, $btC, "</div>"]);
284 if (!$editMemberParams->getHasPopup()) {
285 if (!($f instanceof HtmlFormCheckbox)) {
286 $f->setWidth(16)->setProperty("style", "padding-left:0;");
287 }
288 }
289 }
290 $f->on("keydown", "if(event.keyCode===27) {\$('#" . $identifier . "').trigger('endEdit');}");
291 $f->onClick("return false;", true, true);
292 } else {
293 $f->setProperty("style", "display: none;");
294 }
295 });
296 $form->setSubmitParams($this->controller->_getBaseRoute() . "/$updateUrl/" . $member . "/" . $editMemberParams->getUpdateCallback(), "#" . $td, ["attr" => "", "hasLoader" => false, "jsCallback" => "$(self).remove();", "jqueryDone" => "html"]);
297 if ($editMemberParams->getHasPopup()) {
298 $endEdit = "\$('#" . $identifier . "').html();\$('.popup').hide();\$('#" . $td . "').popup('destroy');";
299 $validate = $endEdit;
300 } else {
301 $endEdit = "let td=\$('#" . $td . "');td.html(td.data('originalText'));";
302 $validate = "";
303 }
304 $form->on("endEdit", $endEdit);
305 $form->on("validate", "\$('#" . $identifier . "').form('submit');" . $validate);
306 $this->jquery->execAtLast("$('form').find('input[type=text],textarea,select').filter(':visible:first').focus();");
307 return $form;
308 }
309
310 private function setFormFields_(&$fields, $relFields) {
311 $hasRelations = false;
312 $relFields = \array_flip($relFields);
313 foreach ($fields as $index => $field) {
314 if (isset ($relFields [$field])) {
315 $fields [$index] = $relFields [$field];
316 $hasRelations = true;
317 }
318 }
319 return $hasRelations;
320 }
321
329 protected function getFormTitle($form, $instance) {
330 $type = ($instance->_new) ? 'new' : 'edit';
331 $messageInfos = ['new' => ['icon' => HtmlIconGroups::corner('table ' . $this->style, 'plus ' . $this->style, 'big'), 'subMessage' => '&nbsp;New object creation'], 'edit' => ['icon' => HtmlIconGroups::corner('table ' . $this->style, 'edit ' . $this->style, 'big'), 'subMessage' => '&nbsp;Editing an existing object']];
332 $message = $messageInfos [$type];
333 $message ['message'] = '&nbsp;' . \get_class($instance);
334 return $message;
335 }
336
344 public function setFormFieldsComponent(DataForm $form, $fieldTypes, $attributes = []) {
345 DataFormHelper::addDefaultUIConstraints($form, $fieldTypes, $attributes);
346 }
347
355 public function setMemberFormFieldsComponent(DataForm $form, $fieldTypes, $attributes = []) {
356 DataFormHelper::addDefaultUIConstraints($form, $fieldTypes, $attributes);
357 }
358
364 public function onGenerateFormField($field, $nb, $name) {
365 if ($field instanceof HtmlFormInput) {
366 if ($field->getDataField()->getProperty('type') == "datetime-local") {
367 $v = $field->getDataField()->getProperty('value');
368 if ($v != null) {
369 $field->getDataField()->setValue(date("Y-m-d\TH:i:s", \strtotime($v)));
370 }
371 }
372 }
373 return;
374 }
375
383 public function isModal($objects, $model) {
384 return \count($objects) > 5;
385 }
386
393 public function getFormCaptions($captions, $className, $instance) {
394 return \array_map('ucfirst', $captions);
395 }
396
402 public function getFormModalTitle(object $instance): string {
403 return \get_class($instance);
404 }
405
410 public function formHasMessage(): bool {
411 return true;
412 }
413
419 public function onFormModalButtons(HtmlButton $btOkay, HtmlButton $btCancel): void {
420 $btOkay->setValue("Validate modifications");
421 }
422}
423
For using in a CRUDController ModelViewer with getEditMemberParams method.
isModal($objects, $model)
Condition to determine if the edit or add form is modal for $model objects.
relationMembersInForm($form, $instance, $className, $fields, $relations, &$fieldTypes)
onFormModalButtons(HtmlButton $btOkay, HtmlButton $btCancel)
Hook for changing the edit/new modal buttons.
setMemberFormFieldsComponent(DataForm $form, $fieldTypes, $attributes=[])
Sets the components for each field.
setFormFieldsComponent(DataForm $form, $fieldTypes, $attributes=[])
Sets the components for each field.
formHasMessage()
If true, display a message for editing or updating (default true).
onGenerateFormField($field, $nb, $name)
For doing something when $field is generated in form.
getFormTitle($form, $instance)
Returns an associative array defining form message title with keys "icon","message",...
getFormCaptions($captions, $className, $instance)
Returns the captions for form fields.
manyToManyFormField(DataForm $form, $member, $instance, $annot)
oneToManyFormField(DataForm $form, $member, $instance, $annot)
dtManyField(DataTable $dt, $className, array $relations, array $fields)
oneToManyFormFieldDt(DataForm $form, $member, $instance, $annot)
getForm($identifier, $instance, $updateUrl='updateModel')
Returns the form for adding or modifying an object.
getMemberForm($identifier, $instance, $member, $td, $part, $updateUrl='_updateMember')
Returns a form for member editing.
Gateway class between database and object model.
Definition DAO.php:33
Object/relational mapping utilities.
Definition OrmUtils.php:17
Reflection utilities in dev environment only.
Definition Reflexion.php:17