Completed
Push — master ( 5f0535...74f4b9 )
by Jean-Christophe
01:50
created

CRUDController::getModelViewer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
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
15
abstract class CRUDController extends ControllerBase implements HasModelViewerInterface{
16
	use MessagesTrait;
17
	protected $model;
18
	protected $modelViewer;
19
	protected $crudFiles;
20
	protected $adminDatas;
21
	protected $activePage;
22
	
23
	/**
24
	 * Default page : list all objects
25
	 */
26
	public function index() {
27
		$objects=$this->getInstances();
28
		$modal=($this->_getModelViewer()->isModal($objects,$this->model))?"modal":"no";
29
		$this->_getModelViewer()->getModelDataTable($objects, $this->model);
30
		$this->jquery->getOnClick ( "#btAddNew", $this->_getBaseRoute() . "/newModel/" . $modal, "#frm-add-update",["hasLoader"=>"internal"] );
31
		$this->jquery->compile($this->view);
32
		$this->loadView($this->_getFiles()->getViewIndex(), [ "classname" => $this->model ]);		
33
	}
34
	
35
	protected function getInstances($page=1,$id=null){
36
		$this->activePage=$page;
37
		$model=$this->model;
38
		$recordsPerPage=$this->_getModelViewer()->recordsPerPage($model,DAO::count($model));
39
		if(is_numeric($recordsPerPage)){
40
			if(isset($id)){
41
				$rownum=DAO::getRownum($model, $id);
42
				$this->activePage=Pagination::getPageOfRow($rownum,$recordsPerPage);
43
			}
44
			return DAO::paginate($model,$this->activePage,$recordsPerPage);
45
		}
46
		return DAO::getAll($model);
47
	}
48
	
49
	protected function search($model,$search){
50
		$fields=$this->_getAdminData()->getSearchFieldNames($model);
51
		return CRUDHelper::search($model, $search, $fields);
52
	}
53
	
54
	public function _refresh(){
55
		$model=$this->model;
56
		if(isset($_POST["s"])){
57
			$instances=$this->search($model, $_POST["s"]);
58
		}else{
59
			$instances=$this->getInstances(URequest::post("p",1));
60
		}
61
		$recordsPerPage=$this->_getModelViewer()->recordsPerPage($model,DAO::count($model));
62
		if(isset($recordsPerPage)){
63
			UResponse::asJSON();
64
			$responseFormatter=new ResponseFormatter();
65
			print_r($responseFormatter->getJSONDatas($instances));
66
		}else{
67
			$this->formModal=($this->_getModelViewer()->isModal($instances,$model))? "modal" : "no";
68
			$compo= $this->_getModelViewer()->getModelDataTable($instances, $model)->refresh(["tbody"]);
69
			$this->jquery->execAtLast('$("#search-query-content").html("'.$_POST["s"].'");');
70
			$this->jquery->renderView("@framework/main/component.html",["compo"=>$compo]);
71
		}
72
	}
73
	
74
	/**
75
	 * Edits an instance
76
	 * @param string $modal Accept "no" or "modal" for a modal dialog
77
	 * @param string $ids the primary value(s)
78
	 */
79
	public function edit($modal="no", $ids="") {
80
		$instance=$this->getModelInstance($ids);
81
		$instance->_new=false;
82
		$this->_edit($instance, $modal);
83
	}
84
	/**
85
	 * Adds a new instance and edits it
86
	 * @param string $modal Accept "no" or "modal" for a modal dialog
87
	 */
88
	public function newModel($modal="no") {
89
		$model=$this->model;
90
		$instance=new $model();
91
		$instance->_new=true;
92
		$this->_edit($instance, $modal);
93
	}
94
	
95
	public function display($modal="no",$ids=""){
96
		$instance=$this->getModelInstance($ids);
97
		$this->jquery->execOn("click","._close",'$("#table-details").html("");$("#dataTable").show();');
98
		echo $this->_getModelViewer()->getModelDataElement($instance, $this->model,$modal);
99
		echo $this->jquery->compile($this->view);
100
	}
101
	
102
	protected function _edit($instance, $modal="no") {
103
		$_SESSION["instance"]=$instance;
104
		$modal=($modal == "modal");
105
		$form=$this->_getModelViewer()->getForm("frmEdit", $instance);
106
		$this->jquery->click("#action-modal-frmEdit-0", "$('#frmEdit').form('submit');", false);
107
		if (!$modal) {
108
			$this->jquery->click("#bt-cancel", "$('#form-container').transition('drop');");
109
			$this->jquery->compile($this->view);
110
			$this->loadView($this->_getFiles()->getViewForm(), [ "modal" => $modal ]);
111
		} else {
112
			$this->jquery->exec("$('#modal-frmEdit').modal('show');", true);
113
			$form=$form->asModal(\get_class($instance));
114
			$form->setActions([ "Okay","Cancel" ]);
115
			$btOkay=$form->getAction(0);
116
			$btOkay->addClass("green")->setValue("Validate modifications");
117
			$form->onHidden("$('#modal-frmEdit').remove();");
118
			echo $form->compile($this->jquery, $this->view);
119
			echo $this->jquery->compile($this->view);
120
		}
121
	}
122
	
123
	protected function _showModel($id=null) {
124
		$model=$this->model;
125
		$datas=$this->getInstances($model,1,$id);
126
		$this->formModal=($this->_getModelViewer()->isModal($datas,$model))? "modal" : "no";
127
		return $this->_getModelViewer()->getModelDataTable($datas, $model,$this->activePage);
128
	}
129
	
130
	/**
131
	 * Deletes an instance
132
	 * @param mixed $ids
133
	 */
134
	public function delete($ids) {
135
		$instance=$this->getModelInstance($ids);
136
		if (method_exists($instance, "__toString"))
137
			$instanceString=$instance . "";
138
		else
139
			$instanceString=get_class($instance);
140
		if (sizeof($_POST) > 0) {
141
			try{
142
				if (DAO::remove($instance)) {
0 ignored issues
show
Bug introduced by
It seems like $instance defined by $this->getModelInstance($ids) on line 135 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...
143
					$message=new CRUDMessage("Deletion of `<b>" . $instanceString . "</b>`","Deletion","info","info circle",4000);
144
					$message=$this->onSuccessDeleteMessage($message);
145
					$this->jquery->exec("$('tr[data-ajax={$ids}]').remove();", true);
146
				} else {
147
					$message=new CRUDMessage("Can not delete `" . $instanceString . "`","Deletion","warning","warning circle");
148
					$message=$this->onErrorDeleteMessage($message);
149
				}
150
			}catch (\Exception $e){
151
				$message=new CRUDMessage("Exception : can not delete `" . $instanceString . "`","Exception", "warning", "warning");
152
				$message=$this->onErrorDeleteMessage($message);
153
			}
154
			$message=$this->_showSimpleMessage($message);
155
		} else {
156
			$message=new CRUDMessage("Do you confirm the deletion of `<b>" . $instanceString . "</b>`?", "Remove confirmation","error");
157
			$this->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...
158
			$message=$this->_showConfMessage($message, $this->_getBaseRoute() . "/delete/{$ids}", "#table-messages", $ids);
159
		}
160
		echo $message;
161
		echo $this->jquery->compile($this->view);
162
	}
163
	
164
	protected function onSuccessDeleteMessage(CRUDMessage $message):CRUDMessage{
165
		return $message;
166
	}
167
	
168
	protected function onErrorDeleteMessage(CRUDMessage $message):CRUDMessage{
169
		return $message;
170
	}
171
	
172
	protected function onConfDeleteMessage(CRUDMessage $message):CRUDMessage{
173
		return $message;
174
	}
175
	
176
	protected function onSuccessUpdateMessage(CRUDMessage $message):CRUDMessage{
177
		return $message;
178
	}
179
	
180
	protected function onErrorUpdateMessage(CRUDMessage $message):CRUDMessage{
181
		return $message;
182
	}
183
	
184
	protected function onNotFoundMessage(CRUDMessage $message):CRUDMessage{
185
		return $message;
186
	}
187
	
188
	public function refreshTable() {
189
		echo $this->_showModel();
190
		echo $this->jquery->compile($this->view);
191
	}
192
	
193
	/**
194
	 * Updates an instance from the data posted in a form
195
	 */
196
	public function update() {
197
		$message=new CRUDMessage("Modifications were successfully saved", "Updating");
198
		$instance=@$_SESSION["instance"];
199
		$updated=CRUDHelper::update($instance, $_POST,$this->_getAdminData()->getUpdateManyToOneInForm(),$this->_getAdminData()->getUpdateManyToManyInForm());
200
		if($updated){
201
			$message->setType("success")->setIcon("check circle outline");
202
			$message=$this->onSuccessUpdateMessage($message);
203
			$this->jquery->get($this->_getBaseRoute() . "/refreshTable", "#lv", [ "jqueryDone" => "replaceWith" ]);
204
		} else {
205
			$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...
206
			$message=$this->onErrorUpdateMessage($message);
207
		}
208
		echo $this->_showSimpleMessage($message,"updateMsg");
209
		echo $this->jquery->compile($this->view);
210
	}
211
	
212
	/**
213
	 * Shows associated members with foreign keys
214
	 * @param mixed $ids
215
	 */
216
	public function showDetail($ids) {
217
		$instance=$this->getModelInstance($ids);
218
		$viewer=$this->_getModelViewer();
219
		$hasElements=false;
220
		$model=$this->model;
221
		$fkInstances=CRUDHelper::getFKIntances($instance, $model);
222
		$semantic=$this->jquery->semantic();
223
		$grid=$semantic->htmlGrid("detail");
224
		if (sizeof($fkInstances) > 0) {
225
			$wide=intval(16 / sizeof($fkInstances));
226
			if ($wide < 4)
227
				$wide=4;
228
				foreach ( $fkInstances as $member=>$fkInstanceArray ) {
229
					$element=$viewer->getFkMemberElementDetails($member,$fkInstanceArray["objectFK"],$fkInstanceArray["fkClass"],$fkInstanceArray["fkTable"]);
230
					if (isset($element)) {
231
						$grid->addCol($wide)->setContent($element);
232
						$hasElements=true;
233
					}
234
				}
235
				if ($hasElements)
236
					echo $grid;
237
				$this->jquery->getOnClick(".showTable", $this->_getBaseRoute() . "/showTableClick", "#divTable", [ "attr" => "data-ajax","ajaxTransition" => "random" ]);
238
				echo $this->jquery->compile($this->view);
239
		}
240
241
	}
242
	
243
	private function getModelInstance($ids) {
244
		$ids=\explode("_", $ids);
245
		$instance=DAO::getOne($this->model, $ids);
246
		if(isset($instance)){
247
			return $instance;
248
		}
249
		$message=new CRUDMessage("This object does not exist!","Get object","warning","warning circle");
250
		$message=$this->onNotFoundMessage($message);
251
		echo $this->_showSimpleMessage($message);
252
		echo $this->jquery->compile($this->view);
253
		exit(1);
254
	}
255
	
256
	/**
257
	 * To override for defining a new adminData
258
	 * @return CRUDDatas
259
	 */
260
	protected function getAdminData ():CRUDDatas{
261
		return new CRUDDatas();
262
	}
263
	
264
	public function _getAdminData ():CRUDDatas{
265
		return $this->getSingleton($this->modelViewer,"getAdminData");
266
	}
267
	
268
	/**
269
	 * To override for defining a new ModelViewer
270
	 * @return ModelViewer
271
	 */
272
	protected function getModelViewer ():ModelViewer{
273
		return new ModelViewer($this);
274
	}
275
	
276
	private function _getModelViewer():modelViewer{
277
		return $this->getSingleton($this->modelViewer,"getModelViewer");
278
	}
279
	
280
	/**
281
	 * To override for changing view files
282
	 * @return CRUDFiles
283
	 */
284
	protected function getFiles ():CRUDFiles{
285
		return new CRUDFiles();
286
	}
287
	
288
	private function _getFiles():CRUDFiles{
289
		return $this->getSingleton($this->crudFiles,"getFiles");
290
	}
291
	
292
	private function getSingleton($value, $method) {
293
		if (! isset ( $value )) {
294
			$value = $this->$method ();
295
		}
296
		return $value;
297
	}
298
}
299
300