Passed
Push — master ( b68a78...d29a76 )
by Jean-Christophe
16:10 queued 03:52
created

ModelViewer::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 3
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Ubiquity\controllers\crud\viewers;
4
5
use Ajax\semantic\html\elements\HtmlButton;
6
use Ajax\semantic\html\elements\HtmlHeader;
7
use Ajax\semantic\html\elements\HtmlLabel;
8
use Ajax\semantic\widgets\datatable\DataTable;
9
use Ajax\semantic\widgets\datatable\PositionInTable;
10
use Ubiquity\controllers\crud\CRUDHelper;
11
use Ubiquity\controllers\crud\interfaces\HasModelViewerInterface;
12
use Ubiquity\controllers\crud\viewers\traits\FormModelViewerTrait;
13
use Ubiquity\orm\OrmUtils;
14
use Ubiquity\utils\base\UString;
15
16
/**
17
 * Associated with a CRUDController class
18
 * Responsible of the display
19
 *
20
 * @author jc
21
 * @version 1.0.3
22
 *
23
 */
24
class ModelViewer {
25
	use FormModelViewerTrait;
26
	/**
27
	 *
28
	 * @var \Ajax\JsUtils
29
	 */
30
	private $jquery;
31
32
	/**
33
	 *
34
	 * @var HasModelViewerInterface
35
	 */
36
	protected $controller;
37
38 7
	public function __construct(HasModelViewerInterface $controller) {
39 7
		$this->jquery = $controller->jquery;
40 7
		$this->controller = $controller;
41 7
	}
42
43
	/**
44
	 * Returns a DataElement object for displaying the instance
45
	 * Used in the display method of the CrudController
46
	 * in display route
47
	 *
48
	 * @param object $instance
49
	 * @param string $model The model class name (long name)
50
	 * @param boolean $modal
51
	 * @return \Ajax\semantic\widgets\dataelement\DataElement
52
	 */
53 2
	public function getModelDataElement($instance, $model, $modal) {
54 2
		$semantic = $this->jquery->semantic ();
55 2
		$fields = $this->controller->_getAdminData ()->getElementFieldNames ( $model );
56
57 2
		$dataElement = $semantic->dataElement ( "de", $instance );
58 2
		$pk = OrmUtils::getFirstKeyValue ( $instance );
59
		$dataElement->getInstanceViewer ()->setIdentifierFunction ( function () use ($pk) {
60 2
			return $pk;
61 2
		} );
62 2
		$dataElement->setFields ( $fields );
63 2
		$dataElement->setCaptions ( $this->getElementCaptions ( $fields, $model, $instance ) );
64
65 2
		$fkInstances = CRUDHelper::getFKIntances ( $instance, $model );
66 2
		foreach ( $fkInstances as $member => $fkInstanceArray ) {
67 2
			if (array_search ( $member, $fields ) !== false) {
68
				$dataElement->setValueFunction ( $member, function () use ($fkInstanceArray, $member) {
69 2
					return $this->getFkMemberElement ( $member, $fkInstanceArray ["objectFK"], $fkInstanceArray ["fkClass"], $fkInstanceArray ["fkTable"] );
70 2
				} );
71
			}
72
		}
73 2
		$this->addEditMemberFonctionality ( "dataElement" );
74 2
		return $dataElement;
75
	}
76
77
	/**
78
	 * Returns the captions for DataElement fields
79
	 * in display route
80
	 *
81
	 * @param array $captions
82
	 * @param string $className
83
	 */
84 2
	public function getElementCaptions($captions, $className, $instance) {
85 2
		return array_map ( 'ucfirst', $captions );
86
	}
87
88
	/**
89
	 * Returns the dataTable responsible for displaying instances of the model
90
	 *
91
	 * @param array $instances objects to display
92
	 * @param string $model model class name (long name)
93
	 * @return DataTable
94
	 */
95 7
	public function getModelDataTable($instances, $model, $totalCount, $page = 1) {
96 7
		$adminRoute = $this->controller->_getBaseRoute ();
97 7
		$files = $this->controller->_getFiles ();
98 7
		$dataTable = $this->getDataTableInstance ( $instances, $model, $totalCount, $page );
99 7
		$attributes = $this->controller->_getAdminData ()->getFieldNames ( $model );
100 7
		$this->setDataTableAttributes ( $dataTable, $attributes, $model, $instances );
101 7
		$dataTable->setCaptions ( $this->getCaptions ( $attributes, $model ) );
102
103 7
		$dataTable->addClass ( 'small very compact' );
104 7
		$lbl = new HtmlLabel ( 'search-query', "<span id='search-query-content'></span>" );
105 7
		$icon = $lbl->addIcon ( 'delete', false );
106 7
		$lbl->wrap ( "<span>", "</span>" );
107 7
		$lbl->setProperty ( "style", "display: none;" );
108 7
		$icon->getOnClick ( $adminRoute . $files->getRouteRefreshTable (), '#'.$this->getDataTableId(), [ "jqueryDone" => "replaceWith","hasLoader" => "internal" ] );
109
110 7
		$dataTable->addItemInToolbar ( $lbl );
111 7
		$dataTable->addSearchInToolbar ();
112 7
		$dataTable->setToolbarPosition ( PositionInTable::FOOTER );
113 7
		$dataTable->getToolbar ()->setSecondary ();
114 7
		return $dataTable;
115
	}
116
117 7
	public function setDataTableAttributes(DataTable $dataTable, $attributes, $model, $instances, $selector = null) {
118 7
		$modal = ($this->isModal ( $instances, $model ) ? 'modal' : 'no');
119
120 7
		$adminRoute = $this->controller->_getBaseRoute ();
121 7
		$files = $this->controller->_getFiles ();
122 7
		$dataTable->setButtons ( $this->getDataTableRowButtons () );
123 7
		$dataTable->setFields ( $attributes );
124 7
		if (\array_search ( 'password', $attributes ) !== false) {
125
			$dataTable->setValueFunction ( 'password', function ($v) {
126 1
				return UString::mask ( $v );
127 1
			} );
128
		}
129 7
		$dataTable->setIdentifierFunction ( CRUDHelper::getIdentifierFunction ( $model ) );
130
131 7
		if (! isset ( $selector )) {
132 7
			if (\count ( $instances ) > 0 && $this->showDetailsOnDataTableClick ()) {
133 7
				$dataTable->getOnRow ( "click", $adminRoute . $files->getRouteDetails (), "#table-details", [ "selector" => $selector,"attr" => "data-ajax","hasLoader" => false,"jsCondition" => "!event.detail || event.detail==1","jsCallback" => "return false;" ] );
134 7
				$dataTable->setActiveRowSelector ( "active" );
135
			}
136
137 7
			$dataTable->setUrls ( [ "refresh" => $adminRoute . $files->getRouteRefresh (),"delete" => $adminRoute . $files->getRouteDelete (),"edit" => $adminRoute . $files->getRouteEdit () . "/" . $modal,"display" => $adminRoute . $files->getRouteDisplay () . "/" . $modal ] );
138 7
			$dataTable->setTargetSelector ( [ "delete" => "#table-messages","edit" => "#frm-add-update","display" => "#table-details" ] );
139 7
			$this->addEditMemberFonctionality ( "dataTable" );
140
		}
141 7
		$this->addAllButtons ( $dataTable, $attributes );
142 7
	}
143
144 7
	public function addEditMemberFonctionality($part) {
145 7
		if (($editMemberParams = $this->getEditMemberParams ()) !== false) {
146 7
			if (isset ( $editMemberParams [$part] )) {
147 7
				$params = $editMemberParams [$part];
148 7
				$params->compile ( $this->controller->_getBaseRoute (), $this->jquery, $part );
149
			}
150
		}
151 7
	}
152
153
	/**
154
	 *
155
	 * @param string $model The model class name (long name)
156
	 * @param number $totalCount The total count of objects
157
	 * @return void|number default : 6
158
	 */
159 7
	public function recordsPerPage($model, $totalCount = 0) {
160 7
		if ($totalCount > 6)
161 2
			return 6;
162 5
		return;
163
	}
164
165
	/**
166
	 * Returns the fields on which a grouping is performed
167
	 */
168 3
	public function getGroupByFields() {
169 3
		return;
170
	}
171
172
	/**
173
	 * Returns the dataTable instance for dispaying a list of object
174
	 *
175
	 * @param array $instances
176
	 * @param string $model
177
	 * @param number $totalCount
178
	 * @param number $page
179
	 * @return DataTable
180
	 */
181 7
	protected function getDataTableInstance($instances, $model, $totalCount, $page = 1): DataTable {
182 7
		$dtId=$this->getDataTableId();
183 7
		$semantic = $this->jquery->semantic ();
184 7
		$recordsPerPage = $this->recordsPerPage ( $model, $totalCount );
185 7
		if (is_numeric ( $recordsPerPage )) {
186 2
			$grpByFields = $this->getGroupByFields ();
187 2
			if (is_array ( $grpByFields )) {
188
				$dataTable = $semantic->dataTable ( $dtId, $model, $instances );
189
				$dataTable->setGroupByFields ( $grpByFields );
190
			} else {
191 2
				$dataTable = $semantic->jsonDataTable ( $dtId, $model, $instances );
192
			}
193 2
			$dataTable->paginate ( $page, $totalCount, $recordsPerPage, 5 );
194 2
			$dataTable->onActiveRowChange ( '$("#table-details").html("");' );
195 2
			$dataTable->onSearchTerminate ( '$("#search-query-content").html(data);$("#search-query").show();$("#table-details").html("");' );
196
		} else {
197 5
			$dataTable = $semantic->dataTable ( $dtId, $model, $instances );
198
		}
199 7
		$dataTable->setLibraryId('lv');
200 7
		return $dataTable;
201
	}
202
203
	/**
204
	 * Returns an array of buttons ["display","edit","delete"] to display for each row in dataTable
205
	 *
206
	 * @return string[]
207
	 */
208 2
	protected function getDataTableRowButtons() {
209 2
		return [ 'edit','delete' ];
210
	}
211
212 7
	public function addAllButtons(DataTable $dataTable, $attributes) {
213 7
		$transition=$this->getTransition();
214
		$dataTable->onPreCompile ( function () use (&$dataTable) {
215 7
			$dataTable->getHtmlComponent ()->colRightFromRight ( 0 );
216 7
		} );
217
		$dataTable->addAllButtons ( false, [ 'ajaxTransition' => $transition ], function ($bt) {
218 5
			$bt->addClass ( 'circular' );
219 5
			$this->onDataTableRowButton ( $bt );
220
		}, function ($bt) {
221 7
			$bt->addClass ( 'circular' );
222 7
			$this->onDataTableRowButton ( $bt );
223
		}, function ($bt) {
224 7
			$bt->addClass ( 'circular' );
225 7
			$this->onDataTableRowButton ( $bt );
226 7
		} );
227 7
		$dataTable->setDisplayBehavior ( [ 'jsCallback' => '$("#dataTable").hide();','ajaxTransition' => $transition] );
228 7
	}
229
230
	/**
231
	 * The default transition for display, edit and delete behaviors
232
	 * @return string
233
	 */
234 7
	public function getTransition(){
235 7
		return 'fade';
236
	}
237
238 7
	public function getDataTableId(){
239 7
		return 'lv';
240
	}
241
242
	/**
243
	 * To override for modifying the dataTable row buttons
244
	 *
245
	 * @param HtmlButton $bt
246
	 */
247 7
	public function onDataTableRowButton(HtmlButton $bt) {
248 7
	}
249
250
	/**
251
	 * To override for modifying the showConfMessage dialog buttons
252
	 *
253
	 * @param HtmlButton $confirmBtn The confirmation button
254
	 * @param HtmlButton $cancelBtn The cancellation button
255
	 */
256 3
	public function onConfirmButtons(HtmlButton $confirmBtn, HtmlButton $cancelBtn) {
257 3
	}
258
259
	/**
260
	 * Returns the captions for list fields in showTable action
261
	 *
262
	 * @param array $captions
263
	 * @param string $className
264
	 */
265 7
	public function getCaptions($captions, $className) {
266 7
		return \array_map ( 'ucfirst', $captions );
267
	}
268
269
	/**
270
	 * Returns the header for a single foreign object (element is an instance, issue from ManyToOne), (from DataTable)
271
	 *
272
	 * @param string $member
273
	 * @param string $className
274
	 * @param object $object
275
	 * @return HtmlHeader
276
	 */
277
	public function getFkHeaderElementDetails($member, $className, $object) {
278
		return new HtmlHeader ( '', 4, $member, 'content' );
279
	}
280
281
	/**
282
	 * Returns the header for a list of foreign objects (issue from oneToMany or ManyToMany), (from DataTable)
283
	 *
284
	 * @param string $member
285
	 * @param string $className
286
	 * @param array $list
287
	 * @return HtmlHeader
288
	 */
289 1
	public function getFkHeaderListDetails($member, $className, $list) {
290 1
		return new HtmlHeader ( '', 4, $member . ' (' . \count ( $list ) . ')', 'content' );
291
	}
292
293
	/**
294
	 * Returns a component for displaying a single foreign object (manyToOne relation), (from DataTable)
295
	 *
296
	 * @param string $member
297
	 * @param string $className
298
	 * @param object $object
299
	 * @return \Ajax\common\html\BaseHtml
300
	 */
301
	public function getFkElementDetails($member, $className, $object) {
302
		return $this->jquery->semantic ()->htmlLabel ( 'element-' . $className . '.' . $member, $object . '' );
303
	}
304
305
	/**
306
	 * Returns a list component for displaying a collection of foreign objects (*ToMany relations), (from DataTable)
307
	 *
308
	 * @param string $member
309
	 * @param string $className
310
	 * @param array|\Traversable $list
311
	 * @return \Ajax\common\html\HtmlCollection
312
	 */
313 1
	public function getFkListDetails($member, $className, $list) {
314 1
		$element = $this->jquery->semantic ()->htmlList ( 'list-' . $className . '.' . $member );
315 1
		$element->setMaxVisible ( 15 );
316
317 1
		return $element->addClass ( 'animated divided celled' );
318
	}
319
320
	/**
321
	 * Returns a component for displaying a foreign object (from DataTable)
322
	 *
323
	 * @param string $memberFK
324
	 * @param mixed $objectFK
325
	 * @param string $fkClass
326
	 * @param string $fkTable
327
	 * @return \Ajax\semantic\html\elements\HtmlHeader[]|\Ajax\common\html\BaseHtml[]|NULL
328
	 */
329 1
	public function getFkMemberElementDetails($memberFK, $objectFK, $fkClass, $fkTable) {
330 1
		$_fkClass = str_replace ( "\\", ".", $fkClass );
331 1
		$header = new HtmlHeader ( "", 4, $memberFK, "content" );
332 1
		if (is_array ( $objectFK ) || $objectFK instanceof \Traversable) {
333 1
			$header = $this->getFkHeaderListDetails ( $memberFK, $fkClass, $objectFK );
334 1
			$element = $this->getFkListDetails ( $memberFK, $fkClass, $objectFK );
335 1
			foreach ( $objectFK as $oItem ) {
336 1
				if (method_exists ( $oItem, "__toString" )) {
337 1
					$id = (CRUDHelper::getIdentifierFunction ( $fkClass )) ( 0, $oItem );
338 1
					$item = $element->addItem ( $oItem . "" );
339 1
					$item->setProperty ( "data-ajax", $_fkClass . "||" . $id );
340 1
					$item->addClass ( "showTable" );
341 1
					$this->onDisplayFkElementListDetails ( $item, $memberFK, $fkClass, $oItem );
342
				}
343
			}
344
		} else {
345
			if (method_exists ( $objectFK, "__toString" )) {
346
				$header = $this->getFkHeaderElementDetails ( $memberFK, $fkClass, $objectFK );
347
				$id = (CRUDHelper::getIdentifierFunction ( $fkClass )) ( 0, $objectFK );
348
				$element = $this->getFkElementDetails ( $memberFK, $fkClass, $objectFK );
349
				$element->setProperty ( "data-ajax", $_fkClass . "||" . $id )->addClass ( "showTable" );
350
			}
351
		}
352 1
		if (isset ( $element )) {
353 1
			return [ $header,$element ];
354
		}
355
		return null;
356
	}
357
358
	/**
359
	 * To modify for displaying an element in a list component of foreign objects (from DataTable)
360
	 *
361
	 * @param \Ajax\common\html\HtmlDoubleElement $element
362
	 * @param string $member
363
	 * @param string $className
364
	 * @param object $object
365
	 */
366 1
	public function onDisplayFkElementListDetails($element, $member, $className, $object) {
367 1
	}
368
369
	/**
370
	 * Returns a component for displaying a foreign object (from DataElement)
371
	 *
372
	 * @param string $memberFK
373
	 * @param mixed $objectFK
374
	 * @param string $fkClass
375
	 * @param string $fkTable
376
	 * @return string|NULL
377
	 */
378 2
	public function getFkMemberElement($memberFK, $objectFK, $fkClass, $fkTable) {
379 2
		$element = "";
380 2
		$_fkClass = str_replace ( "\\", ".", $fkClass );
381 2
		if (is_array ( $objectFK ) || $objectFK instanceof \Traversable) {
382 2
			$element = $this->getFkList ( $memberFK, $objectFK );
383 2
			foreach ( $objectFK as $oItem ) {
384 2
				if (\method_exists ( $oItem, '__toString' )) {
385 2
					$id = (CRUDHelper::getIdentifierFunction ( $fkClass )) ( 0, $oItem );
386 2
					$item = $element->addItem ( $oItem . '' );
387 2
					$item->setProperty ( 'data-ajax', $_fkClass . '||' . $id );
388 2
					$item->addClass ( 'showTable' );
389 2
					$this->displayFkElementList ( $item, $memberFK, $fkClass, $oItem );
390
				}
391
			}
392
		} else {
393
			if (method_exists ( $objectFK, '__toString' )) {
394
				$id = (CRUDHelper::getIdentifierFunction ( $fkClass )) ( 0, $objectFK );
395
				$element = $this->getFkElement ( $memberFK, $fkClass, $objectFK );
396
				$element->setProperty ( 'data-ajax', $_fkClass . '||' . $id )->addClass ( 'showTable' );
397
			}
398
		}
399 2
		return $element;
400
	}
401
402
	/**
403
	 * Returns a list component for displaying a collection of foreign objects (*ToMany relations), (from DataElement)
404
	 *
405
	 * @param string $member
406
	 * @param string $className
407
	 * @param array|\Traversable $list
408
	 * @return \Ajax\common\html\HtmlCollection
409
	 */
410 2
	public function getFkList($member, $list) {
411 2
		$element = $this->jquery->semantic ()->htmlList ( 'list-' . $member );
412 2
		$element->setMaxVisible ( 10 );
413 2
		return $element->addClass ( 'animated' );
414
	}
415
416
	/**
417
	 * To modify for displaying an element in a list component of foreign objects, (from DataElement)
418
	 *
419
	 * @param \Ajax\common\html\HtmlDoubleElement $element
420
	 * @param string $member
421
	 * @param string $className
422
	 * @param object $object
423
	 */
424 2
	public function displayFkElementList($element, $member, $className, $object) {
425 2
	}
426
427
	/**
428
	 * Returns a component for displaying a single foreign object (manyToOne relation), (from DataElement)
429
	 *
430
	 * @param string $member
431
	 * @param string $className
432
	 * @param object $object
433
	 * @return \Ajax\common\html\BaseHtml
434
	 */
435
	public function getFkElement($member, $className, $object) {
436
		return $this->jquery->semantic ()->htmlLabel ( 'element-' . $className . '.' . $member, $object . '' );
437
	}
438
439
	/**
440
	 * To override to make sure that the detail of a clicked object is displayed or not
441
	 *
442
	 * @return boolean Return true if you want to see details
443
	 */
444 7
	public function showDetailsOnDataTableClick() {
445 7
		return true;
446
	}
447
}
448
449