Completed
Push — master ( 9aea22...ab0022 )
by Jean-Christophe
02:12
created

CRUDController::crudLoadView()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 14
nc 3
nop 2
1
<?php
2
3
namespace Ubiquity\controllers\crud;
4
5
use Ubiquity\orm\DAO;
6
use Ubiquity\controllers\ControllerBase;
7
use Ubiquity\controllers\admin\interfaces\HasModelViewerInterface;
8
use Ubiquity\controllers\admin\viewers\ModelViewer;
9
use Ubiquity\controllers\semantic\MessagesTrait;
10
use Ubiquity\utils\http\URequest;
11
use Ubiquity\utils\http\UResponse;
12
use Ubiquity\controllers\rest\ResponseFormatter;
13
use Ajax\semantic\widgets\datatable\Pagination;
14
use Ubiquity\orm\OrmUtils;
15
use Ubiquity\utils\base\UString;
16
17
abstract class CRUDController extends ControllerBase implements HasModelViewerInterface{
18
	use MessagesTrait;
19
	protected $model;
20
	protected $modelViewer;
21
	protected $events;
22
	protected $crudFiles;
23
	protected $adminDatas;
24
	protected $activePage;
25
	
26
	/**
27
	 * Default page : list all objects
28
	 */
29
	public function index() {
30
		$objects=$this->getInstances();
31
		$modal=($this->_getModelViewer()->isModal($objects,$this->model))?"modal":"no";
32
		$this->_getModelViewer()->getModelDataTable($objects, $this->model);
33
		$this->jquery->getOnClick ( "#btAddNew", $this->_getBaseRoute() . "/newModel/" . $modal, "#frm-add-update",["hasLoader"=>"internal"] );
34
		$this->crudLoadView($this->_getFiles()->getViewIndex(), [ "classname" => $this->model ]);		
35
	}
36
	
37
	protected function getInstances($page=1,$id=null){
38
		$this->activePage=$page;
39
		$model=$this->model;
40
		$condition=$this->_getInstancesFilter($model);
41
		$recordsPerPage=$this->_getModelViewer()->recordsPerPage($model,DAO::count($model,$condition));
42
		if(is_numeric($recordsPerPage)){
43
			if(isset($id)){
44
				$rownum=DAO::getRownum($model, $id);
45
				$this->activePage=Pagination::getPageOfRow($rownum,$recordsPerPage);
46
			}
47
			return DAO::paginate($model,$this->activePage,$recordsPerPage);
48
		}
49
		return DAO::getAll($model,$condition);
50
	}
51
	
52
	public function _getInstancesFilter($model){
53
		return "1=1";
54
	}
55
	
56
	protected function search($model,$search){
57
		$fields=$this->_getAdminData()->getSearchFieldNames($model);
58
		$condition=$this->_getInstancesFilter($model);
59
		return CRUDHelper::search($model, $search, $fields,$condition);
60
	}
61
	
62
	public function refresh_(){
63
		$model=$this->model;
64
		if(isset($_POST["s"])){
65
			$instances=$this->search($model, $_POST["s"]);
66
		}else{
67
			$instances=$this->getInstances(URequest::post("p",1));
68
		}
69
		$recordsPerPage=$this->_getModelViewer()->recordsPerPage($model,DAO::count($model,$this->_getInstancesFilter($model)));
70
		if(isset($recordsPerPage)){
71
			UResponse::asJSON();
72
			$responseFormatter=new ResponseFormatter();
73
			print_r($responseFormatter->getJSONDatas($instances));
74
		}else{
75
			$this->formModal=($this->_getModelViewer()->isModal($instances,$model))? "modal" : "no";
76
			$compo= $this->_getModelViewer()->getModelDataTable($instances, $model)->refresh(["tbody"]);
77
			$this->jquery->execAtLast('$("#search-query-content").html("'.$_POST["s"].'");$("#search-query").show();$("#table-details").html("");');
78
			$this->jquery->renderView("@framework/main/component.html",["compo"=>$compo]);
79
		}
80
	}
81
	
82
	/**
83
	 * Edits an instance
84
	 * @param string $modal Accept "no" or "modal" for a modal dialog
85
	 * @param string $ids the primary value(s)
86
	 */
87
	public function edit($modal="no", $ids="") {
88
		$instance=$this->getModelInstance($ids);
89
		$instance->_new=false;
90
		$this->_edit($instance, $modal);
91
	}
92
	/**
93
	 * Adds a new instance and edits it
94
	 * @param string $modal Accept "no" or "modal" for a modal dialog
95
	 */
96
	public function newModel($modal="no") {
97
		$model=$this->model;
98
		$instance=new $model();
99
		$instance->_new=true;
100
		$this->_edit($instance, $modal);
101
	}
102
	
103
	/**
104
	 * Displays an instance
105
	 * @param string $modal
106
	 * @param string $ids
107
	 */
108
	public function display($modal="no",$ids=""){
109
		$instance=$this->getModelInstance($ids);
110
		$key=OrmUtils::getFirstKeyValue($instance);
111
		$this->jquery->execOn("click","._close",'$("#table-details").html("");$("#dataTable").show();');
112
		$this->jquery->getOnClick("._edit", $this->_getBaseRoute()."/edit/".$modal."/".$key,"#frm-add-update");
113
		$this->jquery->getOnClick("._delete", $this->_getBaseRoute()."/delete/".$key,"#table-messages");
114
		
115
		$this->_getModelViewer()->getModelDataElement($instance, $this->model,$modal);
116
		$this->jquery->renderView($this->_getFiles()->getViewDisplay(), [ "classname" => $this->model,"instance"=>$instance,"pk"=>$key ]);
117
	}
118
	
119
	protected function _edit($instance, $modal="no") {
120
		$_SESSION["instance"]=$instance;
121
		$modal=($modal == "modal");
122
		$form=$this->_getModelViewer()->getForm("frmEdit", $instance);
123
		$this->jquery->click("#action-modal-frmEdit-0", "$('#frmEdit').form('submit');", false);
124
		if (!$modal) {
125
			$this->jquery->click("#bt-cancel", "$('#form-container').transition('drop');");
126
			$this->jquery->compile($this->view);
127
			$this->loadView($this->_getFiles()->getViewForm(), [ "modal" => $modal ]);
128
		} else {
129
			$this->jquery->exec("$('#modal-frmEdit').modal('show');", true);
130
			$form=$form->asModal(\get_class($instance));
131
			$form->setActions([ "Okay","Cancel" ]);
132
			$btOkay=$form->getAction(0);
133
			$btOkay->addClass("green")->setValue("Validate modifications");
134
			$form->onHidden("$('#modal-frmEdit').remove();");
135
			echo $form->compile($this->jquery, $this->view);
136
			echo $this->jquery->compile($this->view);
137
		}
138
	}
139
	
140
	protected function _showModel($id=null) {
141
		$model=$this->model;
142
		$datas=$this->getInstances(1,$id);
143
		$this->formModal=($this->_getModelViewer()->isModal($datas,$model))? "modal" : "no";
144
		return $this->_getModelViewer()->getModelDataTable($datas, $model,$this->activePage);
145
	}
146
	
147
	/**
148
	 * Deletes an instance
149
	 * @param mixed $ids
150
	 */
151
	public function delete($ids) {
152
		$instance=$this->getModelInstance($ids);
153 View Code Duplication
		if (method_exists($instance, "__toString"))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
154
			$instanceString=$instance . "";
155
		else
156
			$instanceString=get_class($instance);
157
		if (sizeof($_POST) > 0) {
158
			try{
159
				if (DAO::remove($instance)) {
0 ignored issues
show
Bug introduced by
It seems like $instance defined by $this->getModelInstance($ids) on line 152 can also be of type null; however, Ubiquity\orm\traits\DAOUpdatesTrait::remove() does only seem to accept object, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
160
					$message=new CRUDMessage("Deletion of `<b>" . $instanceString . "</b>`","Deletion","info","info circle",4000);
161
					$message=$this->_getEvents()->onSuccessDeleteMessage($message);
162
					$this->jquery->exec("$('._element[data-ajax={$ids}]').remove();", true);
163
				} else {
164
					$message=new CRUDMessage("Can not delete `" . $instanceString . "`","Deletion","warning","warning circle");
165
					$message=$this->_getEvents()->onErrorDeleteMessage($message);
166
				}
167
			}catch (\Exception $e){
168
				$message=new CRUDMessage("Exception : can not delete `" . $instanceString . "`","Exception", "warning", "warning");
169
				$message=$this->_getEvents()->onErrorDeleteMessage($message);
170
			}
171
			$message=$this->_showSimpleMessage($message);
172
		} else {
173
			$message=new CRUDMessage("Do you confirm the deletion of `<b>" . $instanceString . "</b>`?", "Remove confirmation","error");
174
			$this->_getEvents()->onConfDeleteMessage($message);
0 ignored issues
show
Unused Code introduced by
The call to the method Ubiquity\controllers\cru...::onConfDeleteMessage() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
175
			$message=$this->_showConfMessage($message, $this->_getBaseRoute() . "/delete/{$ids}", "#table-messages", $ids);
176
		}
177
		echo $message;
178
		echo $this->jquery->compile($this->view);
179
	}
180
	
181
182
	
183
	public function refreshTable($id=null) {
184
		$compo= $this->_showModel($id);
185
		$this->jquery->execAtLast('$("#table-details").html("");');
186
		$this->jquery->renderView("@framework/main/component.html",["compo"=>$compo]);	
187
	}
188
	
189
	/**
190
	 * Updates an instance from the data posted in a form
191
	 */
192
	public function update() {
193
		$message=new CRUDMessage("Modifications were successfully saved", "Updating");
194
		$instance=@$_SESSION["instance"];
195
		$isNew=$instance->_new;
196
		try{
197
			$updated=CRUDHelper::update($instance, $_POST,$this->_getAdminData()->getUpdateManyToOneInForm(),$this->_getAdminData()->getUpdateManyToManyInForm());
198
			if($updated){
199
				$message->setType("success")->setIcon("check circle outline");
200
				$message=$this->_getEvents()->onSuccessUpdateMessage($message);
201
				$this->refreshInstance($instance,$isNew);
202
			} else {
203
				$message->setMessage("An error has occurred. Can not save changes.")->setType("error")->setIcon("warning circle");
0 ignored issues
show
Bug introduced by
The method setType cannot be called on $message->setMessage('An...Can not save changes.') (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
204
				$message=$this->_getEvents()->onErrorUpdateMessage($message);
205
			}
206
		}catch(\Exception $e){
207 View Code Duplication
			if (method_exists($instance, "__toString"))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
208
				$instanceString=$instance . "";
209
			else
210
				$instanceString=get_class($instance);
211
			$message=new CRUDMessage("Exception : can not update `" . $instanceString . "`","Exception", "warning", "warning");
212
			$message=$this->_getEvents()->onErrorUpdateMessage($message);
213
		}
214
		echo $this->_showSimpleMessage($message,"updateMsg");
215
		echo $this->jquery->compile($this->view);
216
	}
217
	
218
	protected function refreshInstance($instance,$isNew){
219
		if($this->_getAdminData()->refreshPartialInstance() && !$isNew){
220
			$this->jquery->setJsonToElement(OrmUtils::objectAsJSON($instance));
221
		}else{
222
			$pk=OrmUtils::getFirstKeyValue($instance);
223
			$this->jquery->get($this->_getBaseRoute() . "/refreshTable/".$pk, "#lv", [ "jqueryDone" => "replaceWith" ]);
224
		}
225
	}
226
	
227
	/**
228
	 * Shows associated members with foreign keys
229
	 * @param mixed $ids
230
	 */
231
	public function showDetail($ids) {
232
		$instance=$this->getModelInstance($ids);
233
		$viewer=$this->_getModelViewer();
234
		$hasElements=false;
235
		$model=$this->model;
236
		$fkInstances=CRUDHelper::getFKIntances($instance, $model);
237
		$semantic=$this->jquery->semantic();
238
		$grid=$semantic->htmlGrid("detail");
239
		if (sizeof($fkInstances) > 0) {
240
			$wide=intval(16 / sizeof($fkInstances));
241
			if ($wide < 4)
242
				$wide=4;
243
				foreach ( $fkInstances as $member=>$fkInstanceArray ) {
244
					$element=$viewer->getFkMemberElementDetails($member,$fkInstanceArray["objectFK"],$fkInstanceArray["fkClass"],$fkInstanceArray["fkTable"]);
245
					if (isset($element)) {
246
						$grid->addCol($wide)->setContent($element);
247
						$hasElements=true;
248
					}
249
				}
250
				if ($hasElements)
251
					echo $grid;
252
					$url=$this->_getEvents()->onDetailClickURL($this->model);
253
				if(UString::isNotNull($url)){
254
					$this->detailClick($url);
255
				}
256
				echo $this->jquery->compile($this->view);
257
		}
258
259
	}
260
	
261
	public function detailClick($url) {
262
		$this->jquery->postOnClick(".showTable", $this->_getBaseRoute() . "/".$url,"{}", "#divTable", [ "attr" => "data-ajax","ajaxTransition" => "random" ]);
263
	}
264
	
265
	private function getModelInstance($ids) {
266
		$ids=\explode("_", $ids);
267
		$instance=DAO::getOne($this->model, $ids);
268
		if(isset($instance)){
269
			return $instance;
270
		}
271
		$message=new CRUDMessage("This object does not exist!","Get object","warning","warning circle");
272
		$message=$this->_getEvents()->onNotFoundMessage($message);
273
		echo $this->_showSimpleMessage($message);
274
		echo $this->jquery->compile($this->view);
275
		exit(1);
276
	}
277
	
278
	/**
279
	 * To override for defining a new adminData
280
	 * @return CRUDDatas
281
	 */
282
	protected function getAdminData ():CRUDDatas{
283
		return new CRUDDatas();
284
	}
285
	
286
	public function _getAdminData ():CRUDDatas{
287
		return $this->getSingleton($this->modelViewer,"getAdminData");
288
	}
289
	
290
	/**
291
	 * To override for defining a new ModelViewer
292
	 * @return ModelViewer
293
	 */
294
	protected function getModelViewer ():ModelViewer{
295
		return new ModelViewer($this);
296
	}
297
	
298
	private function _getModelViewer():ModelViewer{
299
		return $this->getSingleton($this->modelViewer,"getModelViewer");
300
	}
301
	
302
	/**
303
	 * To override for changing view files
304
	 * @return CRUDFiles
305
	 */
306
	protected function getFiles ():CRUDFiles{
307
		return new CRUDFiles();
308
	}
309
	
310
	private function _getFiles():CRUDFiles{
311
		return $this->getSingleton($this->crudFiles,"getFiles");
312
	}
313
	
314
	/**
315
	 * To override for changing events
316
	 * @return CRUDEvents
317
	 */
318
	protected function getEvents ():CRUDEvents{
319
		return new CRUDEvents();
320
	}
321
	
322
	private function _getEvents():CRUDEvents{
323
		return $this->getSingleton($this->events,"getEvents");
324
	}
325
	
326
	private function getSingleton($value, $method) {
327
		if (! isset ( $value )) {
328
			$value = $this->$method ();
329
		}
330
		return $value;
331
	}
332
	
333
	private function crudLoadView($viewName,$vars=[]){
334
		if(!URequest::isAjax()){
335
			$files=$this->_getFiles();
336
			$mainTemplate=$files->getBaseTemplate();
1 ignored issue
show
Bug introduced by
Are you sure the assignment to $mainTemplate is correct as $files->getBaseTemplate() (which targets Ubiquity\controllers\cru...iles::getBaseTemplate()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
337
			if(isset($mainTemplate)){
338
				$vars["_viewname"]=$viewName;
339
				$vars["_base"]=$mainTemplate;
340
				$this->jquery->renderView($files->getViewBaseTemplate(),$vars);
341
			}else{
342
				$vars["hasScript"]=true;
343
				$this->jquery->renderView($viewName,$vars);
344
			}
345
		}else{
346
			$vars["hasScript"]=true;
347
			$this->jquery->renderView($viewName,$vars);
348
		}
349
	}
350
}
351