|
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\semantic\MessagesTrait; |
|
9
|
|
|
use Ubiquity\utils\http\URequest; |
|
10
|
|
|
use Ubiquity\utils\http\UResponse; |
|
11
|
|
|
use Ubiquity\controllers\rest\ResponseFormatter; |
|
12
|
|
|
use Ubiquity\orm\OrmUtils; |
|
13
|
|
|
use Ubiquity\utils\base\UString; |
|
14
|
|
|
use Ajax\semantic\html\collections\HtmlMessage; |
|
15
|
|
|
use Ajax\common\html\HtmlContentOnly; |
|
16
|
|
|
|
|
17
|
|
|
abstract class CRUDController extends ControllerBase implements HasModelViewerInterface{ |
|
18
|
|
|
use MessagesTrait,CRUDControllerUtilitiesTrait; |
|
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
|
|
|
* Uses modelViewer.isModal, modelViewer.getModelDataTable |
|
29
|
|
|
* Uses CRUDFiles.getViewIndex template (default : @framework/crud/index.html) |
|
30
|
|
|
* Triggers the events onDisplayElements,beforeLoadView |
|
31
|
|
|
*/ |
|
32
|
|
|
public function index() { |
|
33
|
|
|
$objects=$this->getInstances($totalCount); |
|
34
|
|
|
$modal=($this->_getModelViewer()->isModal($objects,$this->model))?"modal":"no"; |
|
35
|
|
|
$dt=$this->_getModelViewer()->getModelDataTable($objects, $this->model,$totalCount); |
|
36
|
|
|
$this->jquery->getOnClick ( "#btAddNew", $this->_getBaseRoute() . "/newModel/" . $modal, "#frm-add-update",["hasLoader"=>"internal"] ); |
|
37
|
|
|
$this->_getEvents()->onDisplayElements($dt,$objects,false); |
|
38
|
|
|
$this->crudLoadView($this->_getFiles()->getViewIndex(), [ "classname" => $this->model ,"messages"=>$this->jquery->semantic()->matchHtmlComponents(function($compo){return $compo instanceof HtmlMessage;})]); |
|
39
|
|
|
} |
|
40
|
|
|
|
|
41
|
|
|
public function updateMember($member,$callback=false){ |
|
42
|
|
|
$instance=@$_SESSION["instance"]; |
|
43
|
|
|
$updated=CRUDHelper::update($instance, $_POST); |
|
44
|
|
|
if($updated){ |
|
45
|
|
|
if($callback===false){ |
|
46
|
|
|
$dt=$this->_getModelViewer()->getModelDataTable([$instance], $this->model, 1); |
|
47
|
|
|
$dt->compile(); |
|
48
|
|
|
echo new HtmlContentOnly($dt->getFieldValue($member)); |
|
49
|
|
|
}else{ |
|
50
|
|
|
if(method_exists($this, $callback)){ |
|
51
|
|
|
$this->$callback($member,$instance); |
|
52
|
|
|
}else{ |
|
53
|
|
|
throw new \Exception("The method `".$callback."` does not exists in ".get_class()); |
|
54
|
|
|
} |
|
55
|
|
|
} |
|
56
|
|
|
}else{ |
|
57
|
|
|
UResponse::setResponseCode(404); |
|
58
|
|
|
} |
|
59
|
|
|
} |
|
60
|
|
|
|
|
61
|
|
|
/** |
|
62
|
|
|
* Refreshes the area corresponding to the DataTable |
|
63
|
|
|
*/ |
|
64
|
|
|
public function refresh_(){ |
|
65
|
|
|
$model=$this->model; |
|
66
|
|
|
if(isset($_POST["s"])){ |
|
67
|
|
|
$instances=$this->search($model, $_POST["s"]); |
|
68
|
|
|
}else{ |
|
69
|
|
|
$page=URequest::post("p",1); |
|
70
|
|
|
$instances=$this->getInstances($totalCount,$page); |
|
71
|
|
|
} |
|
72
|
|
|
if(!isset($totalCount)){ |
|
73
|
|
|
$totalCount=DAO::count($model,$this->_getAdminData()->_getInstancesFilter($model)); |
|
74
|
|
|
} |
|
75
|
|
|
$recordsPerPage=$this->_getModelViewer()->recordsPerPage($model,$totalCount); |
|
76
|
|
|
$grpByFields=$this->_getModelViewer()->getGroupByFields(); |
|
77
|
|
|
if(isset($recordsPerPage)){ |
|
78
|
|
|
if(!is_array($grpByFields)){ |
|
79
|
|
|
UResponse::asJSON(); |
|
80
|
|
|
$responseFormatter=new ResponseFormatter(); |
|
81
|
|
|
print_r($responseFormatter->getJSONDatas($instances)); |
|
82
|
|
|
}else{ |
|
83
|
|
|
$this->_renderDataTableForRefresh($instances, $model,$totalCount); |
|
84
|
|
|
} |
|
85
|
|
|
}else{ |
|
86
|
|
|
$this->jquery->execAtLast('$("#search-query-content").html("'.$_POST["s"].'");$("#search-query").show();$("#table-details").html("");'); |
|
87
|
|
|
$this->_renderDataTableForRefresh($instances, $model,$totalCount); |
|
88
|
|
|
} |
|
89
|
|
|
} |
|
90
|
|
|
|
|
91
|
|
|
/** |
|
92
|
|
|
* Edits an instance |
|
93
|
|
|
* @param string $modal Accept "no" or "modal" for a modal dialog |
|
94
|
|
|
* @param string $ids the primary value(s) |
|
95
|
|
|
*/ |
|
96
|
|
View Code Duplication |
public function edit($modal="no", $ids="") { |
|
|
|
|
|
|
97
|
|
|
if(URequest::isAjax()){ |
|
98
|
|
|
$instance=$this->getModelInstance($ids); |
|
99
|
|
|
$instance->_new=false; |
|
100
|
|
|
$this->_edit($instance, $modal); |
|
101
|
|
|
}else{ |
|
102
|
|
|
$this->jquery->execAtLast("$('._edit[data-ajax={$ids}]').trigger('click');"); |
|
103
|
|
|
$this->index(); |
|
104
|
|
|
} |
|
105
|
|
|
} |
|
106
|
|
|
/** |
|
107
|
|
|
* Adds a new instance and edits it |
|
108
|
|
|
* @param string $modal Accept "no" or "modal" for a modal dialog |
|
109
|
|
|
*/ |
|
110
|
|
View Code Duplication |
public function newModel($modal="no") { |
|
|
|
|
|
|
111
|
|
|
if(URequest::isAjax()){ |
|
112
|
|
|
$model=$this->model; |
|
113
|
|
|
$instance=new $model(); |
|
114
|
|
|
$instance->_new=true; |
|
115
|
|
|
$this->_edit($instance, $modal); |
|
116
|
|
|
}else{ |
|
117
|
|
|
$this->jquery->execAtLast("$('.ui.button._new').trigger('click');"); |
|
118
|
|
|
$this->index(); |
|
119
|
|
|
} |
|
120
|
|
|
} |
|
121
|
|
|
|
|
122
|
|
|
public function editMember($member){ |
|
123
|
|
|
$ids=URequest::post("id"); |
|
124
|
|
|
$td=URequest::post("td"); |
|
125
|
|
|
$part=URequest::post("part"); |
|
126
|
|
|
$instance=$this->getModelInstance($ids,$member); |
|
127
|
|
|
$_SESSION["instance"]=$instance; |
|
128
|
|
|
$instance->_new=false; |
|
129
|
|
|
$form=$this->_getModelViewer()->getMemberForm("frm-member-".$member, $instance, $member,$td,$part); |
|
130
|
|
|
$form->setLibraryId("_compo_"); |
|
131
|
|
|
$this->jquery->renderView("@framework/main/component.html"); |
|
132
|
|
|
} |
|
133
|
|
|
|
|
134
|
|
|
/** |
|
135
|
|
|
* Displays an instance |
|
136
|
|
|
* @param string $modal |
|
137
|
|
|
* @param string $ids |
|
138
|
|
|
*/ |
|
139
|
|
|
public function display($modal="no",$ids=""){ |
|
140
|
|
|
if(URequest::isAjax()){ |
|
141
|
|
|
$instance=$this->getModelInstance($ids); |
|
142
|
|
|
$key=OrmUtils::getFirstKeyValue($instance); |
|
143
|
|
|
$this->jquery->execOn("click","._close",'$("#table-details").html("");$("#dataTable").show();'); |
|
144
|
|
|
$this->jquery->getOnClick("._edit", $this->_getBaseRoute()."/edit/".$modal."/".$key,"#frm-add-update"); |
|
145
|
|
|
$this->jquery->getOnClick("._delete", $this->_getBaseRoute()."/delete/".$key,"#table-messages"); |
|
146
|
|
|
|
|
147
|
|
|
$this->_getModelViewer()->getModelDataElement($instance, $this->model,$modal); |
|
148
|
|
|
$this->jquery->renderView($this->_getFiles()->getViewDisplay(), [ "classname" => $this->model,"instance"=>$instance,"pk"=>$key ]); |
|
149
|
|
|
}else{ |
|
150
|
|
|
$this->jquery->execAtLast("$('._display[data-ajax={$ids}]').trigger('click');"); |
|
151
|
|
|
$this->index(); |
|
152
|
|
|
} |
|
153
|
|
|
} |
|
154
|
|
|
|
|
155
|
|
|
/** |
|
156
|
|
|
* Deletes an instance |
|
157
|
|
|
* @param mixed $ids |
|
158
|
|
|
*/ |
|
159
|
|
|
public function delete($ids) { |
|
160
|
|
|
if(URequest::isAjax()){ |
|
161
|
|
|
$instance=$this->getModelInstance($ids); |
|
162
|
|
View Code Duplication |
if (method_exists($instance, "__toString")) |
|
|
|
|
|
|
163
|
|
|
$instanceString=$instance . ""; |
|
164
|
|
|
else |
|
165
|
|
|
$instanceString=get_class($instance); |
|
166
|
|
|
if (sizeof($_POST) > 0) { |
|
167
|
|
|
try{ |
|
168
|
|
|
if (DAO::remove($instance)) { |
|
|
|
|
|
|
169
|
|
|
$message=new CRUDMessage("Deletion of `<b>" . $instanceString . "</b>`","Deletion","info","info circle",4000); |
|
170
|
|
|
$message=$this->_getEvents()->onSuccessDeleteMessage($message,$instance); |
|
|
|
|
|
|
171
|
|
|
$this->jquery->exec("$('._element[data-ajax={$ids}]').remove();", true); |
|
172
|
|
|
} else { |
|
173
|
|
|
$message=new CRUDMessage("Can not delete `" . $instanceString . "`","Deletion","warning","warning circle"); |
|
174
|
|
|
$message=$this->_getEvents()->onErrorDeleteMessage($message,$instance); |
|
|
|
|
|
|
175
|
|
|
} |
|
176
|
|
|
}catch (\Exception $e){ |
|
177
|
|
|
$message=new CRUDMessage("Exception : can not delete `" . $instanceString . "`","Exception", "warning", "warning"); |
|
178
|
|
|
$message=$this->_getEvents()->onErrorDeleteMessage($message,$instance); |
|
|
|
|
|
|
179
|
|
|
} |
|
180
|
|
|
$message=$this->_showSimpleMessage($message); |
|
181
|
|
|
} else { |
|
182
|
|
|
$message=new CRUDMessage("Do you confirm the deletion of `<b>" . $instanceString . "</b>`?", "Remove confirmation","error","question circle"); |
|
183
|
|
|
$message=$this->_getEvents()->onConfDeleteMessage($message,$instance); |
|
|
|
|
|
|
184
|
|
|
$message=$this->_showConfMessage($message, $this->_getBaseRoute() . "/delete/{$ids}", "#table-messages", $ids); |
|
185
|
|
|
} |
|
186
|
|
|
echo $message; |
|
187
|
|
|
echo $this->jquery->compile($this->view); |
|
188
|
|
|
}else{ |
|
189
|
|
|
$this->jquery->execAtLast("$('._delete[data-ajax={$ids}]').trigger('click');"); |
|
190
|
|
|
$this->index(); |
|
191
|
|
|
} |
|
192
|
|
|
} |
|
193
|
|
|
|
|
194
|
|
|
public function refreshTable($id=null) { |
|
195
|
|
|
$compo= $this->_showModel($id); |
|
196
|
|
|
$this->jquery->execAtLast('$("#table-details").html("");'); |
|
197
|
|
|
$compo->setLibraryId("_compo_"); |
|
198
|
|
|
$this->jquery->renderView("@framework/main/component.html"); |
|
199
|
|
|
} |
|
200
|
|
|
|
|
201
|
|
|
/** |
|
202
|
|
|
* Updates an instance from the data posted in a form |
|
203
|
|
|
* @return object The updated instance |
|
204
|
|
|
*/ |
|
205
|
|
|
public function update() { |
|
206
|
|
|
$message=new CRUDMessage("Modifications were successfully saved", "Updating"); |
|
207
|
|
|
$instance=@$_SESSION["instance"]; |
|
208
|
|
|
$isNew=$instance->_new; |
|
209
|
|
|
try{ |
|
210
|
|
|
$updated=CRUDHelper::update($instance, $_POST); |
|
211
|
|
|
if($updated){ |
|
212
|
|
|
$message->setType("success")->setIcon("check circle outline"); |
|
213
|
|
|
$message=$this->_getEvents()->onSuccessUpdateMessage($message,$instance); |
|
214
|
|
|
$this->refreshInstance($instance,$isNew); |
|
215
|
|
|
} else { |
|
216
|
|
|
$message->setMessage("An error has occurred. Can not save changes.")->setType("error")->setIcon("warning circle"); |
|
217
|
|
|
$message=$this->_getEvents()->onErrorUpdateMessage($message,$instance); |
|
218
|
|
|
} |
|
219
|
|
|
}catch(\Exception $e){ |
|
220
|
|
View Code Duplication |
if (method_exists($instance, "__toString")) |
|
|
|
|
|
|
221
|
|
|
$instanceString=$instance . ""; |
|
222
|
|
|
else |
|
223
|
|
|
$instanceString=get_class($instance); |
|
224
|
|
|
$message=new CRUDMessage("Exception : can not update `" . $instanceString . "`","Exception", "warning", "warning"); |
|
225
|
|
|
$message=$this->_getEvents()->onErrorUpdateMessage($message,$instance); |
|
226
|
|
|
} |
|
227
|
|
|
echo $this->_showSimpleMessage($message,"updateMsg"); |
|
228
|
|
|
echo $this->jquery->compile($this->view); |
|
229
|
|
|
return $instance; |
|
230
|
|
|
} |
|
231
|
|
|
|
|
232
|
|
|
|
|
233
|
|
|
/** |
|
234
|
|
|
* Shows associated members with foreign keys |
|
235
|
|
|
* @param mixed $ids |
|
236
|
|
|
*/ |
|
237
|
|
|
public function showDetail($ids) { |
|
238
|
|
|
if(URequest::isAjax()){ |
|
239
|
|
|
$instance=$this->getModelInstance($ids); |
|
240
|
|
|
$viewer=$this->_getModelViewer(); |
|
241
|
|
|
$hasElements=false; |
|
242
|
|
|
$model=$this->model; |
|
243
|
|
|
$fkInstances=CRUDHelper::getFKIntances($instance, $model); |
|
244
|
|
|
$semantic=$this->jquery->semantic(); |
|
245
|
|
|
$grid=$semantic->htmlGrid("detail"); |
|
246
|
|
|
if (sizeof($fkInstances) > 0) { |
|
247
|
|
|
$wide=intval(16 / sizeof($fkInstances)); |
|
248
|
|
|
if ($wide < 4) |
|
249
|
|
|
$wide=4; |
|
250
|
|
|
foreach ( $fkInstances as $member=>$fkInstanceArray ) { |
|
251
|
|
|
$element=$viewer->getFkMemberElementDetails($member,$fkInstanceArray["objectFK"],$fkInstanceArray["fkClass"],$fkInstanceArray["fkTable"]); |
|
252
|
|
|
if (isset($element)) { |
|
253
|
|
|
$grid->addCol($wide)->setContent($element); |
|
254
|
|
|
$hasElements=true; |
|
255
|
|
|
} |
|
256
|
|
|
} |
|
257
|
|
|
if ($hasElements){ |
|
258
|
|
|
echo $grid; |
|
259
|
|
|
$url=$this->_getFiles()->getDetailClickURL($this->model); |
|
260
|
|
|
if(UString::isNotNull($url)){ |
|
261
|
|
|
$this->detailClick($url); |
|
262
|
|
|
} |
|
263
|
|
|
} |
|
264
|
|
|
echo $this->jquery->compile($this->view); |
|
265
|
|
|
} |
|
266
|
|
|
}else{ |
|
267
|
|
|
$this->jquery->execAtLast("$('tr[data-ajax={$ids}]').trigger('click');"); |
|
268
|
|
|
$this->index(); |
|
269
|
|
|
} |
|
270
|
|
|
|
|
271
|
|
|
} |
|
272
|
|
|
|
|
273
|
|
|
public function detailClick($url) { |
|
274
|
|
|
$this->jquery->postOnClick(".showTable", $this->_getBaseRoute() . "/".$url,"{}", "#divTable", [ "attr" => "data-ajax","ajaxTransition" => "random" ]); |
|
275
|
|
|
} |
|
276
|
|
|
|
|
277
|
|
|
} |
|
278
|
|
|
|
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.