Passed
Pull Request — master (#201)
by Jean-Christophe
26:40
created

CRUDController::refreshAsJson()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 4
c 0
b 0
f 0
dl 0
loc 5
ccs 0
cts 5
cp 0
rs 10
cc 1
nc 1
nop 1
crap 2
1
<?php
2
3
namespace Ubiquity\controllers\crud;
4
5
use Ubiquity\orm\DAO;
6
use Ubiquity\controllers\ControllerBase;
7
use Ubiquity\controllers\crud\interfaces\HasModelViewerInterface;
8
use Ubiquity\controllers\semantic\MessagesTrait;
9
use Ubiquity\utils\http\URequest;
10
use Ubiquity\utils\http\UResponse;
11
use Ubiquity\orm\OrmUtils;
12
use Ubiquity\utils\base\UString;
13
use Ajax\semantic\html\collections\HtmlMessage;
14
use Ajax\common\html\HtmlContentOnly;
15
use Ubiquity\controllers\semantic\InsertJqueryTrait;
16
use Ajax\semantic\widgets\datatable\DataTable;
17
18
/**
19
 * Ubiquity\controllers\crud$CRUDController
20
 * This class is part of Ubiquity
21
 *
22
 * @author jc
23
 * @version 1.0.3
24
 *
25
 */
26
abstract class CRUDController extends ControllerBase implements HasModelViewerInterface {
27
	use MessagesTrait,CRUDControllerUtilitiesTrait,InsertJqueryTrait;
28
	protected $model;
29
	protected $activePage=1;
30
	protected $style;
31
	
32 7
	public function __construct() {
33 7
		parent::__construct ();
34 7
		DAO::$transformerOp = 'toView';
35 7
		$this->style = '';
36 7
		$this->_insertJquerySemantic ();
37
	}
38
	
39
	/**
40
	 * Return a JSON representation of $instances for the JsonDataTable component
41
	 * @param array $instances
42
	 * @return string
43
	 */
44
	protected function refreshAsJson($instances){
45
		$objects = \array_map ( function ($o) {
46
			return $o->_rest;
47
		}, $instances );
48
			return \json_encode(\array_values ( $objects ));
49
	}
50
	
51 2
	public function _setStyle($elm) {
52 2
		if ($this->style === 'inverted') {
53
			$elm->setInverted ( true );
54
			if ($elm instanceof DataTable) {
55
				$elm->setActiveRowSelector ( 'black' );
56
			}
57
		}
58
	}
59
	
60
	/**
61
	 * Default page : list all objects
62
	 * Uses modelViewer.isModal, modelViewer.getModelDataTable
63
	 * Uses CRUDFiles.getViewIndex template (default : @framework/crud/index.html)
64
	 * Triggers the events onDisplayElements,beforeLoadView
65
	 */
66 7
	public function index() {
67 7
		$objects = $this->getInstances ( $totalCount ,$this->activePage);
68 7
		$modal = ($this->_getModelViewer ()->isModal ( $objects, $this->model )) ? "modal" : "no";
69 7
		$dt = $this->_getModelViewer ()->getModelDataTable ( $objects, $this->model, $totalCount ,$this->activePage);
70 7
		$this->jquery->getOnClick ( '#btAddNew', $this->_getBaseRoute () . '/newModel/' . $modal, '#frm-add-update', [ 'hasLoader' => 'internal' ] );
71 7
		$this->_getEvents ()->onDisplayElements ( $dt, $objects, false );
72 7
		$this->crudLoadView ( $this->_getFiles ()->getViewIndex (), [ 'classname' => $this->model,'messages' => $this->jquery->semantic ()->matchHtmlComponents ( function ($compo) {
73 7
			return $compo instanceof HtmlMessage;
74 7
		} ) ] );
75
	}
76
77
	/**
78
	 * @param $member
79
	 * @param boolean $callback
80
	 * @throws \Exception
81
	 *
82
	 * @post
83
	 */
84
	#[\Ubiquity\attributes\items\router\Post]
85 2
	public function updateMember($member, $callback = false) {
86 2
		$instance = $_SESSION ['instance'] ?? null;
87 2
		if (isset ( $instance )) {
88 2
			$this->_getEvents ()->onBeforeUpdateRequest ( $_POST, false );
89 2
			$updated = CRUDHelper::update ( $instance, $_POST, true, true, function ($inst) {
90 2
				$this->_getEvents ()->onBeforeUpdate ( $inst, false );
91 2
			} );
92 2
				if ($updated) {
93 2
					if ($callback === false) {
94 1
						$dt = $this->_getModelViewer ()->getModelDataTable ( [ $instance ], $this->model, 1 );
95 1
						$dt->setGroupByFields(null);
96 1
						$dt->compile ();
97 1
						echo new HtmlContentOnly ( $dt->getFieldValue ( $member ) );
98
					} else {
99 1
						if (\method_exists ( $this, $callback )) {
100 1
							$this->$callback ( $member, $instance );
101
						} else {
102 2
							throw new \Exception ( "The method `" . $callback . "` does not exists in " . get_class () );
103
						}
104
					}
105
				} else {
106 2
					UResponse::setResponseCode ( 404 );
107
				}
108
		} else {
109
			throw new \Exception ( '$_SESSION["instance"] is null' );
110
		}
111
	}
112
	
113
	/**
114
	 * Refreshes the area corresponding to the DataTable
115
	 */
116 1
	public function refresh_() {
117 1
		$model = $this->model;
118 1
		if (isset ( $_POST ['s'] )) {
119 1
			$instances = $this->search ( $model, $_POST ['s'] );
120
		} else {
121
			$page = URequest::post ( 'p', 1 );
122
			$instances = $this->getInstances ( $totalCount, $page );
123
		}
124 1
		if (! isset ( $totalCount )) {
125 1
			$totalCount = DAO::count ( $model, $this->_getAdminData ()->_getInstancesFilter ( $model ) );
126
		}
127 1
		$recordsPerPage = $this->_getModelViewer ()->recordsPerPage ( $model, $totalCount );
128 1
		$grpByFields = $this->_getModelViewer ()->getGroupByFields ();
129 1
		if (isset ( $recordsPerPage )) {
130
			if (! is_array ( $grpByFields )) {
131
				UResponse::asJSON ();
132
				echo $this->refreshAsJson($instances);
133
			} else {
134
				$this->_renderDataTableForRefresh ( $instances, $model, $totalCount );
135
			}
136
		} else {
137 1
			$this->jquery->execAtLast ( '$("#search-query-content").html("' . $_POST ['s'] . '");$("#search-query").show();$("#table-details").html("");' );
138 1
			$this->_renderDataTableForRefresh ( $instances, $model, $totalCount );
139
		}
140
	}
141
	
142
	/**
143
	 * Edits an instance
144
	 *
145
	 * @param string $modal Accept "no" or "modal" for a modal dialog
146
	 * @param string $ids the primary value(s)
147
	 */
148 2
	public function edit($modal = "no", $ids = "") {
149 2
		if (URequest::isAjax ()) {
150 1
			$instance = $this->getModelInstance ( $ids, false );
151 1
			$instance->_new = false;
152 1
			$this->_edit ( $instance, $modal );
153
		} else {
154 2
			$this->jquery->execAtLast ( "$('._edit[data-ajax={$ids}]').trigger('click');" );
155 2
			$this->index ();
156
		}
157
	}
158
	
159
	/**
160
	 * Adds a new instance and edits it
161
	 *
162
	 * @param string $modal Accept "no" or "modal" for a modal dialog
163
	 */
164 1
	public function newModel($modal = "no") {
165 1
		if (URequest::isAjax ()) {
166 1
			$model = $this->model;
167 1
			$instance = new $model ();
168 1
			$this->_getEvents()->onNewInstance($instance);
169 1
			$instance->_new = true;
170 1
			$this->_edit ( $instance, $modal );
171
		} else {
172
			$this->jquery->execAtLast ( "$('.ui.button._new').trigger('click');" );
173
			$this->index ();
174
		}
175
	}
176
177
	/**
178
	 * @param $member
179
	 * @throws \Exception
180
	 *
181
	 * @post
182
	 */
183
	#[\Ubiquity\attributes\items\router\Post]
184 2
	public function editMember($member) {
185 2
		$ids = URequest::post ( "id" );
186 2
		$td = URequest::post ( "td" );
187 2
		$part = URequest::post ( "part" );
188 2
		$instance = $this->getModelInstance ( $ids, false, $member );
189 2
		$_SESSION ["instance"] = $instance;
190 2
		$instance->_new = false;
191 2
		$form = $this->_getModelViewer ()->getMemberForm ( "frm-member-" . $member, $instance, $member, $td, $part, 'updateMember' );
192 2
		$form->setLibraryId ( "_compo_" );
193 2
		$this->jquery->renderView ( "@framework/main/component.html" );
194
	}
195
	
196
	/**
197
	 * Displays an instance
198
	 *
199
	 * @param string $modal
200
	 * @param string $ids
201
	 */
202 2
	public function display($modal = "no", $ids = "") {
203 2
		if (URequest::isAjax ()) {
204 2
			$instance = $this->getModelInstance ( $ids );
205 2
			$key = OrmUtils::getFirstKeyValue ( $instance );
206 2
			$this->jquery->execOn ( "click", "._close", '$("#table-details").html("");$("#dataTable").show();' );
207 2
			$this->jquery->getOnClick ( "._edit", $this->_getBaseRoute () . "/edit/" . $modal . "/" . $key, "#frm-add-update" );
208 2
			$this->jquery->getOnClick ( "._delete", $this->_getBaseRoute () . "/delete/" . $key, "#table-messages" );
209
			
210 2
			$this->_getModelViewer ()->getModelDataElement ( $instance, $this->model, $modal );
211 2
			$this->jquery->renderView ( $this->_getFiles ()->getViewDisplay (), [ "classname" => $this->model,"instance" => $instance,"pk" => $key ] );
212
		} else {
213 2
			$this->jquery->execAtLast ( "$('._display[data-ajax={$ids}]').trigger('click');" );
214 2
			$this->index ();
215
		}
216
	}
217
	
218
	/**
219
	 * Deletes an instance
220
	 *
221
	 * @param mixed $ids
222
	 * @route("methods"=>["post","get"])
223
	 */
224
	#[\Ubiquity\attributes\items\router\Route(methods: ['get','post'])]
225 3
	public function delete($ids) {
226 3
		if (URequest::isAjax ()) {
227 3
			$instance = $this->getModelInstance ( $ids );
228 3
			$instanceString = $this->getInstanceToString ( $instance );
229 3
			if (\count ( $_POST ) > 0) {
230
				try {
231 2
					if (DAO::remove ( $instance )) {
232 1
						$message = new CRUDMessage ( "Deletion of `<b>" . $instanceString . "</b>`", "Deletion", "info", "info circle", 4000 );
233 1
						$message = $this->_getEvents ()->onSuccessDeleteMessage ( $message, $instance );
234 1
						$this->jquery->exec ( "$('._element[data-ajax={$ids}]').remove();", true );
235
					} else {
236 1
						$message = new CRUDMessage ( "Can not delete `" . $instanceString . "`", "Deletion", "warning", "warning circle" );
237 2
						$message = $this->_getEvents ()->onErrorDeleteMessage ( $message, $instance );
238
					}
239
				} catch ( \Exception $e ) {
240
					$message = new CRUDMessage ( "Exception : can not delete `" . $instanceString . "`", "Exception", "warning", "warning" );
241
					$message = $this->_getEvents ()->onErrorDeleteMessage ( $message, $instance );
242
				}
243 2
				$message = $this->showSimpleMessage_ ( $message );
244
			} else {
245 3
				$message = new CRUDMessage ( "Do you confirm the deletion of `<b>" . $instanceString . "</b>`?", "Remove confirmation", "error", "question circle" );
246 3
				$message = $this->_getEvents ()->onConfDeleteMessage ( $message, $instance );
247 3
				$message = $this->showConfMessage_ ( $message, $this->_getBaseRoute () . "/delete/{$ids}", "#table-messages", $ids );
248
			}
249 3
			echo $message;
250 3
			echo $this->jquery->compile ( $this->view );
251
		} else {
252
			$this->jquery->execAtLast ( "$('._delete[data-ajax={$ids}]').trigger('click');" );
253
			$this->index ();
254
		}
255
	}
256
	
257 1
	public function refreshTable($id = null) {
258 1
		$compo = $this->_showModel ( $id );
259 1
		$this->jquery->execAtLast ( '$("#table-details").html("");' );
260 1
		$compo->setLibraryId ( "_compo_" );
261 1
		$this->jquery->renderView ( "@framework/main/component.html" );
262
	}
263
	
264
	/**
265
	 * Updates an instance from the data posted in a form
266
	 *
267
	 * @return object The updated instance
268
	 *
269
	 * @post
270
	 */
271
	#[\Ubiquity\attributes\items\router\Post]
272 2
	public function updateModel() {
273 2
		$message = new CRUDMessage ( "Modifications were successfully saved", "Updating" );
274 2
		$instance = $_SESSION ["instance"] ?? null;
275 2
		if (isset ( $instance )) {
276 2
			$isNew = $instance->_new;
277
			try {
278 2
				$this->_getEvents ()->onBeforeUpdateRequest ( $_POST, $isNew );
279 2
				$updated = CRUDHelper::update ( $instance, $_POST, true, true, function ($inst, $isNew) {
280 2
					$this->_getEvents ()->onBeforeUpdate ( $inst, $isNew );
281 2
				} );
282 2
					if ($updated) {
283 2
						$message->setType ( "success" )->setIcon ( "check circle outline" );
284 2
						$message = $this->_getEvents ()->onSuccessUpdateMessage ( $message, $instance );
285 2
						$this->refreshInstance ( $instance, $isNew );
286
					} else {
287
						$message->setMessage ( "An error has occurred. Can not save changes." )->setType ( "error" )->setIcon ( "warning circle" );
288 2
						$message = $this->_getEvents ()->onErrorUpdateMessage ( $message, $instance );
289
					}
290
			} catch ( \Exception $e ) {
291
				$instanceString = $this->getInstanceToString ( $instance );
292
				$message = new CRUDMessage ( "Exception : can not update `" . $instanceString . "`", "Exception", "warning", "warning" );
293
				$message = $this->_getEvents ()->onErrorUpdateMessage ( $message, $instance );
294
			}
295 2
			echo $this->showSimpleMessage_ ( $message, "updateMsg" );
296 2
			echo $this->jquery->compile ( $this->view );
297 2
			return $instance;
298
		} else {
299
			throw new \Exception ( '$_SESSION["instance"] is null' );
300
		}
301
	}
302
	
303
	/**
304
	 * Shows associated members with foreign keys
305
	 *
306
	 * @param mixed $ids
307
	 */
308 2
	public function showDetail($ids) {
309 2
		if (URequest::isAjax ()) {
310 2
			$instance = $this->getModelInstance ( $ids );
311 2
			$viewer = $this->_getModelViewer ();
312 2
			$hasElements = false;
313 2
			$model = $this->model;
314 2
			$fkInstances = CRUDHelper::getFKIntances ( $instance, $model );
315 2
			$semantic = $this->jquery->semantic ();
316 2
			$grid = $semantic->htmlGrid ( 'detail' );
317 2
			if (($nb = \count ( $fkInstances )) > 0) {
318 2
				$wide = intval ( 16 / $nb );
319 2
				if ($wide < 4) {
320
					$wide = 4;
321
				}
322 2
				foreach ( $fkInstances as $member => $fkInstanceArray ) {
323 2
					$element = $viewer->getFkMemberElementDetails ( $member, $fkInstanceArray ['objectFK'], $fkInstanceArray ['fkClass'], $fkInstanceArray ['fkTable'] );
324 2
					if (isset ( $element )) {
325 2
						$grid->addCol ( $wide )->setContent ( $element );
326 2
						$hasElements = true;
327
					}
328
				}
329 2
				if ($hasElements) {
330 2
					echo $grid;
331 2
					$url = $this->_getFiles ()->getDetailClickURL ( $this->model );
332 2
					if (UString::isNotNull ( $url )) {
333
						$this->detailClick ( $url );
334
					}
335
				}
336 2
				echo $this->jquery->compile ( $this->view );
337
			}
338
		} else {
339 1
			$this->jquery->execAtLast ( "$('tr[data-ajax={$ids}]').trigger('click');" );
340 1
			$this->index ();
341
		}
342
	}
343
	
344 1
	public function detailClick($url,$responseElement='#divTable',$attributes=[ "attr" => "data-ajax"]) {
345 1
		$this->jquery->postOnClick ( ".showTable", $this->_getBaseRoute () . "/" . $url, "{}", $responseElement, $attributes );
346
	}
347
}
348