|
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->jquery->compile($this->view); |
|
35
|
|
|
$this->loadView($this->_getFiles()->getViewIndex(), [ "classname" => $this->model ]); |
|
36
|
|
|
} |
|
37
|
|
|
|
|
38
|
|
|
protected function getInstances($page=1,$id=null){ |
|
39
|
|
|
$this->activePage=$page; |
|
40
|
|
|
$model=$this->model; |
|
41
|
|
|
$recordsPerPage=$this->_getModelViewer()->recordsPerPage($model,DAO::count($model)); |
|
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); |
|
50
|
|
|
} |
|
51
|
|
|
|
|
52
|
|
|
protected function search($model,$search){ |
|
53
|
|
|
$fields=$this->_getAdminData()->getSearchFieldNames($model); |
|
54
|
|
|
return CRUDHelper::search($model, $search, $fields); |
|
55
|
|
|
} |
|
56
|
|
|
|
|
57
|
|
|
public function refresh_(){ |
|
58
|
|
|
$model=$this->model; |
|
59
|
|
|
if(isset($_POST["s"])){ |
|
60
|
|
|
$instances=$this->search($model, $_POST["s"]); |
|
61
|
|
|
}else{ |
|
62
|
|
|
$instances=$this->getInstances(URequest::post("p",1)); |
|
63
|
|
|
} |
|
64
|
|
|
$recordsPerPage=$this->_getModelViewer()->recordsPerPage($model,DAO::count($model)); |
|
65
|
|
|
if(isset($recordsPerPage)){ |
|
66
|
|
|
UResponse::asJSON(); |
|
67
|
|
|
$responseFormatter=new ResponseFormatter(); |
|
68
|
|
|
print_r($responseFormatter->getJSONDatas($instances)); |
|
69
|
|
|
}else{ |
|
70
|
|
|
$this->formModal=($this->_getModelViewer()->isModal($instances,$model))? "modal" : "no"; |
|
71
|
|
|
$compo= $this->_getModelViewer()->getModelDataTable($instances, $model)->refresh(["tbody"]); |
|
72
|
|
|
$this->jquery->execAtLast('$("#search-query-content").html("'.$_POST["s"].'");$("#search-query").show();$("#table-details").html("");'); |
|
73
|
|
|
$this->jquery->renderView("@framework/main/component.html",["compo"=>$compo]); |
|
74
|
|
|
} |
|
75
|
|
|
} |
|
76
|
|
|
|
|
77
|
|
|
/** |
|
78
|
|
|
* Edits an instance |
|
79
|
|
|
* @param string $modal Accept "no" or "modal" for a modal dialog |
|
80
|
|
|
* @param string $ids the primary value(s) |
|
81
|
|
|
*/ |
|
82
|
|
|
public function edit($modal="no", $ids="") { |
|
83
|
|
|
$instance=$this->getModelInstance($ids); |
|
84
|
|
|
$instance->_new=false; |
|
85
|
|
|
$this->_edit($instance, $modal); |
|
86
|
|
|
} |
|
87
|
|
|
/** |
|
88
|
|
|
* Adds a new instance and edits it |
|
89
|
|
|
* @param string $modal Accept "no" or "modal" for a modal dialog |
|
90
|
|
|
*/ |
|
91
|
|
|
public function newModel($modal="no") { |
|
92
|
|
|
$model=$this->model; |
|
93
|
|
|
$instance=new $model(); |
|
94
|
|
|
$instance->_new=true; |
|
95
|
|
|
$this->_edit($instance, $modal); |
|
96
|
|
|
} |
|
97
|
|
|
|
|
98
|
|
|
/** |
|
99
|
|
|
* Displays an instance |
|
100
|
|
|
* @param string $modal |
|
101
|
|
|
* @param string $ids |
|
102
|
|
|
*/ |
|
103
|
|
|
public function display($modal="no",$ids=""){ |
|
104
|
|
|
$instance=$this->getModelInstance($ids); |
|
105
|
|
|
$key=OrmUtils::getFirstKeyValue($instance); |
|
106
|
|
|
$this->jquery->execOn("click","._close",'$("#table-details").html("");$("#dataTable").show();'); |
|
107
|
|
|
$this->jquery->getOnClick("._edit", $this->_getBaseRoute()."/edit/".$modal."/".$key,"#frm-add-update"); |
|
108
|
|
|
$this->jquery->getOnClick("._delete", $this->_getBaseRoute()."/delete/".$key,"#table-messages"); |
|
109
|
|
|
|
|
110
|
|
|
$this->_getModelViewer()->getModelDataElement($instance, $this->model,$modal); |
|
111
|
|
|
$this->jquery->renderView($this->_getFiles()->getViewDisplay(), [ "classname" => $this->model,"instance"=>$instance,"pk"=>$key ]); |
|
112
|
|
|
} |
|
113
|
|
|
|
|
114
|
|
|
protected function _edit($instance, $modal="no") { |
|
115
|
|
|
$_SESSION["instance"]=$instance; |
|
116
|
|
|
$modal=($modal == "modal"); |
|
117
|
|
|
$form=$this->_getModelViewer()->getForm("frmEdit", $instance); |
|
118
|
|
|
$this->jquery->click("#action-modal-frmEdit-0", "$('#frmEdit').form('submit');", false); |
|
119
|
|
|
if (!$modal) { |
|
120
|
|
|
$this->jquery->click("#bt-cancel", "$('#form-container').transition('drop');"); |
|
121
|
|
|
$this->jquery->compile($this->view); |
|
122
|
|
|
$this->loadView($this->_getFiles()->getViewForm(), [ "modal" => $modal ]); |
|
123
|
|
|
} else { |
|
124
|
|
|
$this->jquery->exec("$('#modal-frmEdit').modal('show');", true); |
|
125
|
|
|
$form=$form->asModal(\get_class($instance)); |
|
126
|
|
|
$form->setActions([ "Okay","Cancel" ]); |
|
127
|
|
|
$btOkay=$form->getAction(0); |
|
128
|
|
|
$btOkay->addClass("green")->setValue("Validate modifications"); |
|
129
|
|
|
$form->onHidden("$('#modal-frmEdit').remove();"); |
|
130
|
|
|
echo $form->compile($this->jquery, $this->view); |
|
131
|
|
|
echo $this->jquery->compile($this->view); |
|
132
|
|
|
} |
|
133
|
|
|
} |
|
134
|
|
|
|
|
135
|
|
|
protected function _showModel($id=null) { |
|
136
|
|
|
$model=$this->model; |
|
137
|
|
|
$datas=$this->getInstances(1,$id); |
|
138
|
|
|
$this->formModal=($this->_getModelViewer()->isModal($datas,$model))? "modal" : "no"; |
|
139
|
|
|
return $this->_getModelViewer()->getModelDataTable($datas, $model,$this->activePage); |
|
140
|
|
|
} |
|
141
|
|
|
|
|
142
|
|
|
/** |
|
143
|
|
|
* Deletes an instance |
|
144
|
|
|
* @param mixed $ids |
|
145
|
|
|
*/ |
|
146
|
|
|
public function delete($ids) { |
|
147
|
|
|
$instance=$this->getModelInstance($ids); |
|
148
|
|
View Code Duplication |
if (method_exists($instance, "__toString")) |
|
|
|
|
|
|
149
|
|
|
$instanceString=$instance . ""; |
|
150
|
|
|
else |
|
151
|
|
|
$instanceString=get_class($instance); |
|
152
|
|
|
if (sizeof($_POST) > 0) { |
|
153
|
|
|
try{ |
|
154
|
|
|
if (DAO::remove($instance)) { |
|
|
|
|
|
|
155
|
|
|
$message=new CRUDMessage("Deletion of `<b>" . $instanceString . "</b>`","Deletion","info","info circle",4000); |
|
156
|
|
|
$message=$this->_getEvents()->onSuccessDeleteMessage($message); |
|
157
|
|
|
$this->jquery->exec("$('._element[data-ajax={$ids}]').remove();", true); |
|
158
|
|
|
} else { |
|
159
|
|
|
$message=new CRUDMessage("Can not delete `" . $instanceString . "`","Deletion","warning","warning circle"); |
|
160
|
|
|
$message=$this->_getEvents()->onErrorDeleteMessage($message); |
|
161
|
|
|
} |
|
162
|
|
|
}catch (\Exception $e){ |
|
163
|
|
|
$message=new CRUDMessage("Exception : can not delete `" . $instanceString . "`","Exception", "warning", "warning"); |
|
164
|
|
|
$message=$this->_getEvents()->onErrorDeleteMessage($message); |
|
165
|
|
|
} |
|
166
|
|
|
$message=$this->_showSimpleMessage($message); |
|
167
|
|
|
} else { |
|
168
|
|
|
$message=new CRUDMessage("Do you confirm the deletion of `<b>" . $instanceString . "</b>`?", "Remove confirmation","error"); |
|
169
|
|
|
$this->_getEvents()->onConfDeleteMessage($message); |
|
|
|
|
|
|
170
|
|
|
$message=$this->_showConfMessage($message, $this->_getBaseRoute() . "/delete/{$ids}", "#table-messages", $ids); |
|
171
|
|
|
} |
|
172
|
|
|
echo $message; |
|
173
|
|
|
echo $this->jquery->compile($this->view); |
|
174
|
|
|
} |
|
175
|
|
|
|
|
176
|
|
|
|
|
177
|
|
|
|
|
178
|
|
|
public function refreshTable($id=null) { |
|
179
|
|
|
$compo= $this->_showModel($id); |
|
180
|
|
|
$this->jquery->execAtLast('$("#table-details").html("");'); |
|
181
|
|
|
$this->jquery->renderView("@framework/main/component.html",["compo"=>$compo]); |
|
182
|
|
|
} |
|
183
|
|
|
|
|
184
|
|
|
/** |
|
185
|
|
|
* Updates an instance from the data posted in a form |
|
186
|
|
|
*/ |
|
187
|
|
|
public function update() { |
|
188
|
|
|
$message=new CRUDMessage("Modifications were successfully saved", "Updating"); |
|
189
|
|
|
$instance=@$_SESSION["instance"]; |
|
190
|
|
|
$isNew=$instance->_new; |
|
191
|
|
|
try{ |
|
192
|
|
|
$updated=CRUDHelper::update($instance, $_POST,$this->_getAdminData()->getUpdateManyToOneInForm(),$this->_getAdminData()->getUpdateManyToManyInForm()); |
|
193
|
|
|
if($updated){ |
|
194
|
|
|
$message->setType("success")->setIcon("check circle outline"); |
|
195
|
|
|
$message=$this->_getEvents()->onSuccessUpdateMessage($message); |
|
196
|
|
|
$this->refreshInstance($instance,$isNew); |
|
197
|
|
|
} else { |
|
198
|
|
|
$message->setMessage("An error has occurred. Can not save changes.")->setType("error")->setIcon("warning circle"); |
|
|
|
|
|
|
199
|
|
|
$message=$this->_getEvents()->onErrorUpdateMessage($message); |
|
200
|
|
|
} |
|
201
|
|
|
}catch(\Exception $e){ |
|
202
|
|
View Code Duplication |
if (method_exists($instance, "__toString")) |
|
|
|
|
|
|
203
|
|
|
$instanceString=$instance . ""; |
|
204
|
|
|
else |
|
205
|
|
|
$instanceString=get_class($instance); |
|
206
|
|
|
$message=new CRUDMessage("Exception : can not update `" . $instanceString . "`","Exception", "warning", "warning"); |
|
207
|
|
|
$message=$this->_getEvents()->onErrorUpdateMessage($message); |
|
208
|
|
|
} |
|
209
|
|
|
echo $this->_showSimpleMessage($message,"updateMsg"); |
|
210
|
|
|
echo $this->jquery->compile($this->view); |
|
211
|
|
|
} |
|
212
|
|
|
|
|
213
|
|
|
protected function refreshInstance($instance,$isNew){ |
|
214
|
|
|
if($this->_getAdminData()->refreshPartialInstance() && !$isNew){ |
|
215
|
|
|
$this->jquery->setJsonToElement(OrmUtils::objectAsJSON($instance)); |
|
216
|
|
|
}else{ |
|
217
|
|
|
$pk=OrmUtils::getFirstKeyValue($instance); |
|
218
|
|
|
$this->jquery->get($this->_getBaseRoute() . "/refreshTable/".$pk, "#lv", [ "jqueryDone" => "replaceWith" ]); |
|
219
|
|
|
} |
|
220
|
|
|
} |
|
221
|
|
|
|
|
222
|
|
|
/** |
|
223
|
|
|
* Shows associated members with foreign keys |
|
224
|
|
|
* @param mixed $ids |
|
225
|
|
|
*/ |
|
226
|
|
|
public function showDetail($ids) { |
|
227
|
|
|
$instance=$this->getModelInstance($ids); |
|
228
|
|
|
$viewer=$this->_getModelViewer(); |
|
229
|
|
|
$hasElements=false; |
|
230
|
|
|
$model=$this->model; |
|
231
|
|
|
$fkInstances=CRUDHelper::getFKIntances($instance, $model); |
|
232
|
|
|
$semantic=$this->jquery->semantic(); |
|
233
|
|
|
$grid=$semantic->htmlGrid("detail"); |
|
234
|
|
|
if (sizeof($fkInstances) > 0) { |
|
235
|
|
|
$wide=intval(16 / sizeof($fkInstances)); |
|
236
|
|
|
if ($wide < 4) |
|
237
|
|
|
$wide=4; |
|
238
|
|
|
foreach ( $fkInstances as $member=>$fkInstanceArray ) { |
|
239
|
|
|
$element=$viewer->getFkMemberElementDetails($member,$fkInstanceArray["objectFK"],$fkInstanceArray["fkClass"],$fkInstanceArray["fkTable"]); |
|
240
|
|
|
if (isset($element)) { |
|
241
|
|
|
$grid->addCol($wide)->setContent($element); |
|
242
|
|
|
$hasElements=true; |
|
243
|
|
|
} |
|
244
|
|
|
} |
|
245
|
|
|
if ($hasElements) |
|
246
|
|
|
echo $grid; |
|
247
|
|
|
$url=$this->_getEvents()->onDetailClickURL($this->model); |
|
248
|
|
|
if(UString::isNotNull($url)){ |
|
249
|
|
|
$this->detailClick($url); |
|
250
|
|
|
} |
|
251
|
|
|
echo $this->jquery->compile($this->view); |
|
252
|
|
|
} |
|
253
|
|
|
|
|
254
|
|
|
} |
|
255
|
|
|
|
|
256
|
|
|
public function detailClick($url) { |
|
257
|
|
|
$this->jquery->postOnClick(".showTable", $this->_getBaseRoute() . "/".$url,"{}", "#divTable", [ "attr" => "data-ajax","ajaxTransition" => "random" ]); |
|
258
|
|
|
} |
|
259
|
|
|
|
|
260
|
|
|
private function getModelInstance($ids) { |
|
261
|
|
|
$ids=\explode("_", $ids); |
|
262
|
|
|
$instance=DAO::getOne($this->model, $ids); |
|
263
|
|
|
if(isset($instance)){ |
|
264
|
|
|
return $instance; |
|
265
|
|
|
} |
|
266
|
|
|
$message=new CRUDMessage("This object does not exist!","Get object","warning","warning circle"); |
|
267
|
|
|
$message=$this->_getEvents()->onNotFoundMessage($message); |
|
268
|
|
|
echo $this->_showSimpleMessage($message); |
|
269
|
|
|
echo $this->jquery->compile($this->view); |
|
270
|
|
|
exit(1); |
|
271
|
|
|
} |
|
272
|
|
|
|
|
273
|
|
|
/** |
|
274
|
|
|
* To override for defining a new adminData |
|
275
|
|
|
* @return CRUDDatas |
|
276
|
|
|
*/ |
|
277
|
|
|
protected function getAdminData ():CRUDDatas{ |
|
278
|
|
|
return new CRUDDatas(); |
|
279
|
|
|
} |
|
280
|
|
|
|
|
281
|
|
|
public function _getAdminData ():CRUDDatas{ |
|
282
|
|
|
return $this->getSingleton($this->modelViewer,"getAdminData"); |
|
283
|
|
|
} |
|
284
|
|
|
|
|
285
|
|
|
/** |
|
286
|
|
|
* To override for defining a new ModelViewer |
|
287
|
|
|
* @return ModelViewer |
|
288
|
|
|
*/ |
|
289
|
|
|
protected function getModelViewer ():ModelViewer{ |
|
290
|
|
|
return new ModelViewer($this); |
|
291
|
|
|
} |
|
292
|
|
|
|
|
293
|
|
|
private function _getModelViewer():ModelViewer{ |
|
294
|
|
|
return $this->getSingleton($this->modelViewer,"getModelViewer"); |
|
295
|
|
|
} |
|
296
|
|
|
|
|
297
|
|
|
/** |
|
298
|
|
|
* To override for changing view files |
|
299
|
|
|
* @return CRUDFiles |
|
300
|
|
|
*/ |
|
301
|
|
|
protected function getFiles ():CRUDFiles{ |
|
302
|
|
|
return new CRUDFiles(); |
|
303
|
|
|
} |
|
304
|
|
|
|
|
305
|
|
|
private function _getFiles():CRUDFiles{ |
|
306
|
|
|
return $this->getSingleton($this->crudFiles,"getFiles"); |
|
307
|
|
|
} |
|
308
|
|
|
|
|
309
|
|
|
/** |
|
310
|
|
|
* To override for changing events |
|
311
|
|
|
* @return CRUDEvents |
|
312
|
|
|
*/ |
|
313
|
|
|
protected function getEvents ():CRUDEvents{ |
|
314
|
|
|
return new CRUDEvents(); |
|
315
|
|
|
} |
|
316
|
|
|
|
|
317
|
|
|
private function _getEvents():CRUDEvents{ |
|
318
|
|
|
return $this->getSingleton($this->events,"getEvents"); |
|
319
|
|
|
} |
|
320
|
|
|
|
|
321
|
|
|
private function getSingleton($value, $method) { |
|
322
|
|
|
if (! isset ( $value )) { |
|
323
|
|
|
$value = $this->$method (); |
|
324
|
|
|
} |
|
325
|
|
|
return $value; |
|
326
|
|
|
} |
|
327
|
|
|
} |
|
328
|
|
|
|
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.