Passed
Push — master ( d7f029...202469 )
by Jean-Christophe
15:08
created

FormModelViewerTrait::getEditMemberParams_()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3.072

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 6
ccs 4
cts 5
cp 0.8
rs 10
c 0
b 0
f 0
cc 3
nc 2
nop 1
crap 3.072
1
<?php
2
3
namespace Ubiquity\controllers\crud\viewers\traits;
4
5
use Ajax\semantic\html\collections\form\HtmlFormField;
6
use Ajax\semantic\html\collections\form\HtmlFormInput;
7
use Ajax\semantic\html\elements\HtmlButton;
8
use Ajax\semantic\html\elements\HtmlIconGroups;
9
use Ajax\semantic\widgets\dataform\DataForm;
10
use Ajax\service\JArray;
11
use Ubiquity\controllers\crud\EditMemberParams;
12
use Ubiquity\orm\DAO;
13
use Ubiquity\orm\OrmUtils;
14
use Ubiquity\orm\parser\Reflexion;
15
16
/**
17
 * Associated with a CRUDController class (part of ModelViewer)
18
 * Responsible of the display of the form
19
 * Ubiquity\controllers\crud\viewers\traits$FormModelViewerTrait
20
 * This class is part of Ubiquity
21
 *
22
 * @author jcheron <[email protected]>
23
 * @version 1.0.2
24
 * @property \Ajax\JsUtils $jquery
25
 */
26
trait FormModelViewerTrait {
27
28 3
	protected function relationMembersInForm($form, $instance, $className, $fields, $relations) {
29 3
		foreach ( $relations as $field => $member ) {
30 3
			if (array_search ( $field, $fields ) !== false) {
31 1
				if (OrmUtils::getAnnotationInfoMember ( $className, "#manyToOne", $member ) !== false) {
32 1
					$this->manyToOneFormField ( $form, $member, $className, $instance );
33
				} elseif (($annot = OrmUtils::getAnnotationInfoMember ( $className, "#oneToMany", $member )) !== false) {
34
					$this->oneToManyFormField ( $form, $member, $instance, $annot );
35
				} elseif (($annot = OrmUtils::getAnnotationInfoMember ( $className, "#manyToMany", $member )) !== false) {
36
					$this->manyToManyFormField ( $form, $member, $instance, $annot );
37
				}
38
			}
39
		}
40 3
	}
41
42 1
	protected function manyToOneFormField(DataForm $form, $member, $className, $instance) {
43 1
		$joinColumn = OrmUtils::getAnnotationInfoMember ( $className, "#joinColumn", $member );
44 1
		if ($joinColumn) {
45 1
			$fkObject = Reflexion::getMemberValue ( $instance, $member );
46 1
			$fkClass = $joinColumn ["className"];
47 1
			if ($fkObject === null) {
48
				$fkObject = new $fkClass ();
49
			}
50 1
			$fkId = OrmUtils::getFirstKey ( $fkClass );
51 1
			$fkIdGetter = "get" . \ucfirst ( $fkId );
52 1
			if (\method_exists ( $fkObject, "__toString" ) && \method_exists ( $fkObject, $fkIdGetter )) {
53 1
				$fkField = $joinColumn ["name"];
54 1
				$fkValue = OrmUtils::getFirstKeyValue ( $fkObject );
55 1
				if (! Reflexion::setMemberValue ( $instance, $fkField, $fkValue )) {
56 1
					$instance->{$fkField} = OrmUtils::getFirstKeyValue ( $fkObject );
57
				}
58 1
				$form->fieldAsDropDown ( $fkField, JArray::modelArray ( $this->controller->_getAdminData ()->getManyToOneDatas ( $fkClass, $instance, $member ), $fkIdGetter, "__toString" ) );
59 1
				$form->setCaption ( $fkField, \ucfirst ( $member ) );
60
			}
61
		}
62 1
	}
63
64
	protected function oneToManyFormField(DataForm $form, $member, $instance, $annot) {
65
		$newField = $member . "Ids";
66
		$fkClass = $annot ["className"];
67
		$fkId = OrmUtils::getFirstKey ( $fkClass );
68
		$fkIdGetter = "get" . \ucfirst ( $fkId );
69
		$fkInstances = DAO::getOneToMany ( $instance, $member );
70
		$ids = \array_map ( function ($elm) use ($fkIdGetter) {
71
			return $elm->{$fkIdGetter} ();
72
		}, $fkInstances );
73
		$instance->{$newField} = \implode ( ",", $ids );
74
		$form->fieldAsDropDown ( $newField, JArray::modelArray ( $this->controller->_getAdminData ()->getOneToManyDatas ( $fkClass, $instance, $member ), $fkIdGetter, "__toString" ), true );
75
		$form->setCaption ( $newField, \ucfirst ( $member ) );
76
	}
77
78
	protected function manyToManyFormField(DataForm $form, $member, $instance, $annot) {
79
		$newField = $member . "Ids";
80
		$fkClass = $annot ["targetEntity"];
81
		$fkId = OrmUtils::getFirstKey ( $fkClass );
82
		$fkIdGetter = "get" . \ucfirst ( $fkId );
83
		$fkInstances = DAO::getManyToMany ( $instance, $member );
84
		$ids = \array_map ( function ($elm) use ($fkIdGetter) {
85
			return $elm->{$fkIdGetter} ();
86
		}, $fkInstances );
87
		$instance->{$newField} = \implode ( ",", $ids );
88
		$form->fieldAsDropDown ( $newField, JArray::modelArray ( $this->controller->_getAdminData ()->getManyToManyDatas ( $fkClass, $instance, $member ), $fkIdGetter, "__toString" ), true, [ "jsCallback" => function ($elm) {
89
			$elm->getField ()->asSearch ();
90
		} ] );
91
		$form->setCaption ( $newField, \ucfirst ( $member ) );
92
	}
93
94
	/**
95
	 *
96
	 * @return \Ubiquity\controllers\crud\EditMemberParams[]
97
	 */
98 7
	public function getEditMemberParams() {
99 7
		return $this->defaultEditMemberParams ();
100
	}
101
102
	/**
103
	 *
104
	 * @param string $part
105
	 * @return \Ubiquity\controllers\crud\EditMemberParams
106
	 */
107 2
	protected function getEditMemberParams_($part) {
108 2
		$params = $this->getEditMemberParams ();
109 2
		if ($params && isset ( $params [$part] )) {
110 2
			return $params [$part];
111
		}
112
		return new EditMemberParams ();
113
	}
114
115
	/**
116
	 *
117
	 * @return \Ubiquity\controllers\crud\EditMemberParams[]
118
	 */
119 7
	protected function defaultEditMemberParams() {
120 7
		return [ "dataTable" => EditMemberParams::dataTable (),"dataElement" => EditMemberParams::dataElement () ];
121
	}
122
123
	/**
124
	 * Returns the form for adding or modifying an object
125
	 *
126
	 * @param string $identifier
127
	 * @param object $instance the object to add or modify
128
	 * @param ?string $updateUrl
129
	 * @return \Ajax\semantic\widgets\dataform\DataForm
130
	 */
131 3
	public function getForm($identifier, $instance, $updateUrl = 'updateModel') {
132 3
		$form = $this->jquery->semantic ()->dataForm ( $identifier, $instance );
133 3
		$form->setLibraryId ( "frmEdit" );
134 3
		$className = \get_class ( $instance );
135 3
		$fields = array_unique ( $this->controller->_getAdminData ()->getFormFieldNames ( $className, $instance ) );
136 3
		$relFields = OrmUtils::getFieldsInRelations_ ( $className );
137
138 3
		$this->setFormFields_ ( $fields, $relFields );
139 3
		array_unshift ( $fields, "_message" );
140 3
		$form->setFields ( $fields );
141
142 3
		$fieldTypes = OrmUtils::getFieldTypes ( $className );
143 3
		$this->setFormFieldsComponent ( $form, $fieldTypes );
144 3
		$this->relationMembersInForm ( $form, $instance, $className, $fields, $relFields );
145 3
		OrmUtils::setFieldToMemberNames ( $fields, $relFields );
146 3
		$form->setCaptions ( $this->getFormCaptions ( $fields, $className, $instance ) );
147 3
		$message = $this->getFormTitle ( $form, $instance );
148 3
		$form->setCaption ( "_message", $message ["subMessage"] );
149 3
		$form->fieldAsMessage ( "_message", [ "icon" => $message ["icon"] ] );
150 3
		$instance->_message = $message ["message"];
151 3
		$form->setSubmitParams ( $this->controller->_getBaseRoute () . "/" . $updateUrl, "#frm-add-update" );
152 3
		$form->onGenerateField ( [ $this,'onGenerateFormField' ] );
153 3
		return $form;
154
	}
155
156
	/**
157
	 * Returns a form for member editing
158
	 *
159
	 * @param string $identifier
160
	 * @param object $instance
161
	 * @param string $member
162
	 * @param string $td
163
	 * @param string $part
164
	 * @param ?string $updateUrl
165
	 * @return \Ajax\semantic\widgets\dataform\DataForm
166
	 */
167 2
	public function getMemberForm($identifier, $instance, $member, $td, $part, $updateUrl = '_updateMember') {
168 2
		$editMemberParams = $this->getEditMemberParams_ ( $part );
169
170 2
		$form = $this->jquery->semantic ()->dataForm ( $identifier, $instance );
171 2
		$form->on ( "dblclick", "", true, true );
172 2
		$form->setProperty ( "onsubmit", "return false;" );
173 2
		$form->addClass ( "_memberForm" );
174 2
		$className = \get_class ( $instance );
175 2
		$fields = [ "id",$member ];
176 2
		$relFields = OrmUtils::getFieldsInRelations_ ( $className );
177 2
		$hasRelations = $this->setFormFields_ ( $fields, $relFields );
178 2
		$form->setFields ( $fields );
179 2
		$fieldTypes = OrmUtils::getFieldTypes ( $className );
180 2
		$form->fieldAsHidden ( 0 );
181 2
		$this->setMemberFormFieldsComponent ( $form, $fieldTypes );
182 2
		if ($hasRelations) {
183
			$this->relationMembersInForm ( $form, $instance, $className, $fields, $relFields );
184
		}
185 2
		$form->setCaptions ( [ "","" ] );
186
		$form->onGenerateField ( function (HtmlFormField $f, $nb) use ($identifier, $editMemberParams) {
187 2
			if ($nb == 1) {
188 2
				$f->setSize ( "mini" );
189 2
				if ($editMemberParams->getHasButtons ()) {
190 2
					$btO = HtmlButton::icon ( "btO", "check" )->addClass ( "green mini compact" )->onClick ( "\$('#" . $identifier . "').trigger('validate');", true, true );
191 2
					$btC = HtmlButton::icon ( "btC", "close" )->addClass ( "mini compact" )->onClick ( "\$('#" . $identifier . "').trigger('endEdit');" );
192 2
					$f->wrap ( "<div class='fields' style='margin:0;'>", [ $btO,$btC,"</div>" ] );
193 2
					if (! $editMemberParams->getHasPopup ()) {
194 1
						$f->setWidth ( 16 )->setProperty ( "style", "padding-left:0;" );
195
					}
196
				}
197 2
				$f->on ( "keydown", "if(event.keyCode===27) {\$('#" . $identifier . "').trigger('endEdit');}" );
198 2
				$f->onClick ( "return false;", true, true );
199
			} else {
200 2
				$f->setProperty ( "style", "display: none;" );
201
			}
202 2
		} );
203 2
		$form->setSubmitParams ( $this->controller->_getBaseRoute () . "/$updateUrl/" . $member . "/" . $editMemberParams->getUpdateCallback (), "#" . $td, [ "attr" => "","hasLoader" => false,"jsCallback" => "$(self).remove();","jqueryDone" => "html" ] );
204 2
		if ($editMemberParams->getHasPopup ()) {
205 1
			$endEdit = "\$('#" . $identifier . "').html();\$('.popup').hide();\$('#" . $td . "').popup('destroy');";
206 1
			$validate = $endEdit;
207
		} else {
208 1
			$endEdit = "let td=\$('#" . $td . "');td.html(td.data('originalText'));";
209 1
			$validate = "";
210
		}
211 2
		$form->on ( "endEdit", $endEdit );
212 2
		$form->on ( "validate", "\$('#" . $identifier . "').form('submit');" . $validate );
213 2
		$this->jquery->execAtLast ( "$('form').find('input[type=text],textarea,select').filter(':visible:first').focus();" );
214 2
		return $form;
215
	}
216
217 4
	private function setFormFields_(&$fields, $relFields) {
218 4
		$hasRelations = false;
219 4
		$relFields = array_flip ( $relFields );
220 4
		foreach ( $fields as $index => $field ) {
221 4
			if (isset ( $relFields [$field] )) {
222
				$fields [$index] = $relFields [$field];
223
				$hasRelations = true;
224
			}
225
		}
226 4
		return $hasRelations;
227
	}
228
229
	/**
230
	 * Returns an associative array defining form message title with keys "icon","message","subMessage"
231
	 *
232
	 * @param DataForm $form
233
	 * @param object $instance
234
	 * @return array the message title
235
	 */
236 3
	protected function getFormTitle($form, $instance) {
237 3
		$type = ($instance->_new) ? "new" : "edit";
238 3
		$messageInfos = [ "new" => [ "icon" => HtmlIconGroups::corner ( "table", "plus", "big" ),"subMessage" => "New object creation" ],"edit" => [ "icon" => HtmlIconGroups::corner ( "table", "edit", "big" ),"subMessage" => "Editing an existing object" ] ];
239 3
		$message = $messageInfos [$type];
240 3
		$message ["message"] = \get_class ( $instance );
241 3
		return $message;
242
	}
243
244
	/**
245
	 * Sets the components for each field
246
	 *
247
	 * @param DataForm $form
248
	 * @param array $fieldTypes associative array of field names (keys) and types (values)
249
	 */
250 3
	public function setFormFieldsComponent(DataForm $form, $fieldTypes) {
251 3
		$this->setFormFieldsComponent_ ( $form, $fieldTypes );
252 3
	}
253
254
	/**
255
	 * Sets the components for each field
256
	 *
257
	 * @param DataForm $form
258
	 * @param array $fieldTypes associative array of field names (keys) and types (values)
259
	 */
260 2
	public function setMemberFormFieldsComponent(DataForm $form, $fieldTypes) {
261 2
		$this->setFormFieldsComponent_ ( $form, $fieldTypes );
262 2
	}
263
264 4
	protected function setFormFieldsComponent_(DataForm $form, $fieldTypes) {
265 4
		foreach ( $fieldTypes as $property => $type ) {
266 4
			switch ($property) {
267 4
				case "password" :
268
					$form->fieldAsInput ( $property, [ "inputType" => "password" ] );
269
					$form->setValidationParams ( [ "inline" => true ] );
270
					break;
271 4
				case "email" :
272 4
				case "mail" :
273
					$form->fieldAsInput ( $property, [ "inputType" => "email","rules" => [ [ "email" ] ] ] );
274
					break;
275
			}
276
277 4
			switch ($type) {
278 4
				case "tinyint(1)" :
279
					$form->fieldAsCheckbox ( $property );
280
					break;
281 4
				case "int" :
282 4
				case "integer" :
283
					$form->fieldAsInput ( $property, [ "inputType" => "number" ] );
284
					break;
285 4
				case "date" :
286
					$form->fieldAsInput ( $property, [ "inputType" => "date" ] );
287
					break;
288 4
				case "datetime" :
289 1
					$form->fieldAsInput ( $property, [ "inputType" => "datetime-local" ] );
290 1
					break;
291
			}
292
		}
293 4
	}
294
295
	/**
296
	 * For doing something when $field is generated in form
297
	 *
298
	 * @param mixed $field
299
	 */
300 3
	public function onGenerateFormField($field, $nb) {
301 3
		if ($field instanceof HtmlFormInput) {
302 3
			if ($field->getDataField ()->getProperty ( 'type' ) == "datetime-local") {
303 1
				$v = $field->getDataField ()->getProperty ( 'value' );
304 1
				$field->getDataField ()->setValue ( date ( "Y-m-d\TH:i:s", strtotime ( $v ) ) );
305
			}
306
		}
307 3
		return;
308
	}
309
310
	/**
311
	 * Condition to determine if the edit or add form is modal for $model objects
312
	 *
313
	 * @param array $objects
314
	 * @param string $model
315
	 * @return boolean
316
	 */
317 7
	public function isModal($objects, $model) {
318 7
		return \count ( $objects ) > 5;
319
	}
320
321
	/**
322
	 * Returns the captions for form fields
323
	 *
324
	 * @param array $captions
325
	 * @param string $className
326
	 */
327 3
	public function getFormCaptions($captions, $className, $instance) {
328 3
		return \array_map ( "ucfirst", $captions );
329
	}
330
}
331
332