Ubiquity  2.0.3
php rapid development framework
RestTrait.php
Go to the documentation of this file.
1 <?php
2 
4 
19 
26 class RestTrait{
27 
28  abstract public function _getAdminFiles();
29 
30  abstract public function _getAdminViewer();
31 
41  abstract protected function showSimpleMessage($content, $type, $title=null,$icon="info", $timeout=NULL, $staticName=null):HtmlMessage;
42 
43  public function initRestCache($refresh=true) {
44  $config=Startup::getConfig();
45  \ob_start();
46  CacheManager::initCache($config, "rest");
47  CacheManager::initCache($config, "controllers");
48  $message=\ob_get_clean();
49  echo $this->showSimpleMessage(\nl2br($message), "info","Rest", "info", 4000);
50  if ($refresh === true)
51  $this->_refreshRest(true);
52  echo $this->jquery->compile($this->view);
53  }
54 
55  protected function _refreshRest($refresh=false) {
56  $result="";
57  try {
58  $restRoutes=CacheManager::getRestRoutes();
59  if (\sizeof($restRoutes) > 0) {
60  $result=$this->_getAdminViewer()->getRestRoutesTab($restRoutes);
61  } else {
62  $result=$this->showSimpleMessage("No resource Rest found. You can add a new resource.", "","Rest", "warning circle", null, "tabsRest");
63  }
64  } catch ( UbiquityException $e ) {
65  $result.=$this->showSimpleMessage(\nl2br($e->getMessage()), "error","Rest error", "warning circle", null, "tabsRest");
66  }
68  if ($refresh) {
69  echo $result;
70  }
71  }
72 
73  public function _displayRestFormTester() {
74  $path=@$_POST["path"];
75  $resource=@$_POST["resource"];
76  $controller=@$_POST["controller"];
77  $controller=\urldecode($controller);
78  $action=@$_POST["action"];
79  $msgHelp=$this->_displayActionDoc($controller, $action);
80  $frm=$this->jquery->semantic()->htmlForm("frmTester-" . $path);
81  $pathId=JString::cleanIdentifier($path);
82  $containerId="div-tester-" . $pathId;
83  $input=$frm->addInput("path", null, "text", $path);
84  $pathField=$input->getDataField()->setIdentifier("path-" . $path)->addClass("_path");
85  $dd=$input->addDropdown("GET", Constants::REQUEST_METHODS);
86  $methodField=$dd->setIdentifier("dd-method-" . $path)->getDataField()->setProperty("name", "method");
87  $methodField->setIdentifier("method-" . $path)->addClass("_method");
88  $input->addAction("Headers...", "right", "barcode")->addClass("basic _requestWithHeaders")->setTagName("div");
89  $input->addAction("Parameters...", "right", "settings")->addClass("basic _requestWithParams")->setTagName("div");
90  $btGo=$input->addAction("Send")->setColor("blue");
91  $btGo->addIcon("send");
92  $btGo->setIdentifier("btGo-" . $path);
93 
94  $frmHeaders=new HtmlForm("frm-headers-" . $path);
95  $frmParameters=new HtmlForm("frm-parameters-" . $path);
96 
97  $this->jquery->postOnClick("#" . $btGo->getIdentifier(), $this->_getAdminFiles()->getAdminBaseRoute() . "/_runRestMethod", "{pathId: '" . $path . "',path: $('#" . $pathField->getIdentifier() . "').val(),method: $('#" . $methodField->getIdentifier() . "').val(),headers:$('#" . $frmHeaders->getIdentifier() . "').serialize(),params:$('#" . $frmParameters->getIdentifier() . "').serialize()}", "#" . $containerId . " ._runRestMethod", [ ]);
98  $this->jquery->postOnClick("#" . $containerId . " ._requestWithParams", $this->_getAdminFiles()->getAdminBaseRoute() . "/_runPostWithParams/_/parameter/rest", "{actualParams:$('#" . $frmParameters->getIdentifier() . "').serialize(),model: '" . $resource . "',toUpdate:'" . $frmParameters->getIdentifier() . "',method:$('#" . $containerId . " ._method').val(),url:$('#" . $containerId . " ._path').val()}", "#modal", [ "attr" => "","hasLoader" => false ]);
99  $this->jquery->postOnClick("#" . $containerId . " ._requestWithHeaders", $this->_getAdminFiles()->getAdminBaseRoute() . "/_runPostWithParams/_/header/rest", "{actualParams: $('#" . $frmHeaders->getIdentifier() . "').serialize(),model: '" . $resource . "',toUpdate:'" . $frmHeaders->getIdentifier() . "',method:$('#" . $containerId . " ._method').val(),url:$('#" . $containerId . " ._path').val()}", "#modal", [ "attr" => "","hasLoader" => false ]);
100  if (!$msgHelp->_empty) {
101  $this->jquery->exec('$("#' . JString::cleanIdentifier("help-" . $action . $controller) . '").transition("show");', true);
102  }
103  $this->jquery->compile($this->view);
104  $this->loadView($this->_getAdminFiles()->getViewRestFormTester(), [ "frmHeaders" => $frmHeaders,"frmParameters" => $frmParameters,"frmTester" => $frm,"pathId" => $pathId,"msgHelp" => $msgHelp ]);
105  }
106 
107  protected function _displayActionDoc($controller, $action) {
108  $docParser=DocParser::docMethodParser($controller, $action);
109  $msg=$this->showSimpleMessage($docParser->getDescriptionAsHtml(), "", "","help circle blue", null, "msg-help-" . $action . $controller);
110  $msg->addHeader("Method " . $action);
111  $msg->addList($docParser->getMethodParamsReturnAsHtml());
112  $msg->addClass("hidden transition");
113  $msg->_empty=$docParser->isEmpty();
114  return $msg;
115  }
116 
117  public function _frmNewResource() {
118  $config=Startup::getConfig();
119  $frm=$this->jquery->semantic()->htmlForm("frmNewResource");
120  $frm->addMessage("msg", "Creating a new REST controller...", "New resource", HtmlIconGroups::corner("heartbeat", "plus"));
121  $input=$frm->addInput("ctrlName", "Controller name")->addRule("empty");
122  $input->labeled(RestServer::getRestNamespace() . "\\");
123  $fields=$frm->addFields();
124  $resources=CacheManager::getModels($config, true);
125  $resources=\array_combine($resources, $resources);
126  $fields->addDropdown("resource", $resources, "Resource", end($resources))->addRule([ "exactCount[1]" ]);
127  $fields->addInput("route", "Main route path", "text", "/rest/")->addRule("empty");
128  $frm->addCheckbox("re-init", "Re-init Rest cache (recommanded)", "reInit")->setChecked(true);
129 
130  $frm->addDivider();
131  $fields=$frm->addFields();
132  $bt=$fields->addButton("bt-create-new-resource", "Create new controller", "teal");
133  $bt->addIcon("plus");
134  $fields->addButton("bt-cancel-new-resource", "Cancel", "", "$('#frmNewResource').hide();$('#divRest').show();");
135  $frm->setValidationParams([ "on" => "blur","inline" => false ]);
136  $frm->addErrorMessage();
137  $frm->setSubmitParams($this->_getAdminFiles()->getAdminBaseRoute() . "/_createNewResource", "#divRest", [ "dataType" => "html" ]);
138  $this->jquery->exec("$('#divRest').hide();$('#div-new-resource').show();", true);
139  echo $frm->compile($this->jquery, $this->view);
140  echo $this->jquery->compile($this->view);
141  }
142 
143  public function _createNewResource() {
144  if (URequest::isPost()) {
145  if (isset($_POST["ctrlName"]) && $_POST["ctrlName"] !== "") {
146  $namespace="";
147  $resource=$_POST["resource"];
148  $route=$_POST["route"];
149  $restControllerNS=RestServer::getRestNamespace();
150  $restControllersDir=ROOT . DS . str_replace("\\", DS, $restControllerNS);
151  UFileSystem::safeMkdir($restControllersDir);
152  $controllerName=\ucfirst($_POST["ctrlName"]);
153  $filename=$restControllersDir . DS . $controllerName . ".php";
154  if (!\file_exists($filename)) {
155  $frameworkDir=Startup::getFrameworkDir();
156  if ($restControllerNS !== "")
157  $namespace="namespace " . $restControllerNS . ";";
158  UFileSystem::openReplaceWriteFromTemplateFile($frameworkDir . "/admin/templates/restController.tpl", $filename, [ "%resource%" => $resource,"%route%" => $route,"%controllerName%" => $controllerName,"%namespace%" => $namespace ]);
159  echo $this->showSimpleMessage("The <b>" . $controllerName . "</b> Rest controller has been created in <b>" . UFileSystem::cleanPathname($filename) . "</b>.", "success","Rest creation" ,"checkmark circle", 30000, "msgGlobal");
160  if (isset($_POST["re-init"])) {
161  $this->initRestCache(false);
162  }
163  } else {
164  echo $this->showSimpleMessage("The file <b>" . $filename . "</b> already exists.<br>Can not create the <b>" . $controllerName . "</b> Rest controller!", "warning","Rest error", "warning circle", 30000, "msgGlobal");
165  }
166  $this->_refreshRest(true);
167  }
168  $this->jquery->exec("$('#div-new-resource').hide();$('#divRest').show();", true);
169  echo $this->jquery->compile($this->view);
170  }
171  }
172 
173  protected function _addRestDataTableBehavior() {
174  $this->jquery->click("._toTest", "if(!$(this).hasClass('active')){
175  \$(this).closest('tr').after('<tr class=\"active\"><td id=\"sub-td'+$(this).closest('tr').attr('id')+'\" colspan=\"'+$(this).closest('tr').children('td').length+'\">test</td></tr>');
176  $(this).addClass('active').removeClass('visibleover');}else{
177  $(this).removeClass('active').addClass('visibleover');
178  $(this).closest('tr').find('.ui.icon.help').transition('hide');
179  $('#sub-td'+$(this).closest('tr').attr('id')).remove();
180  }", false, false, true);
181  $this->jquery->click("._showMsgHelp", '$("#"+$(this).attr("data-show")).transition();');
182  $this->jquery->postOnClick("._toTest", $this->_getAdminFiles()->getAdminBaseRoute() . "/_displayRestFormTester", "{resource:$(this).attr('data-resource'),controller:$(this).attr('data-controller'),action:$(this).attr('data-action'),path:$(this).closest('tr').attr('data-ajax')}", "'#sub-td'+$(self).closest('tr').attr('id')", [ "ajaxTransition" => "random","stopPropagation" => true,"jsCondition" => "!$(self).hasClass('active')" ]);
183  $this->jquery->exec("addToken=function(jqXHR){
184  if(jqXHR.getResponseHeader('authorization')!=null && jqXHR.getResponseHeader('authorization').trim().startsWith('Bearer')){
185  var bearer=jqXHR.getResponseHeader('authorization').trim().slice(7);
186  $('#access-token').val(bearer);
187  $('#access-token').trigger('change');
188  }
189  }", true);
190  }
191 
192  public function _runRestMethod() {
193  $headers=$this->getRestRequestHeaders();
194  $method=$_POST["method"];
195  $path=$_POST["path"];
196  $formId="sub-tddtRest-tr-" . JString::cleanIdentifier($_POST["pathId"]);
197  $this->jquery->ajax($method, $path, "#" . $formId . " ._restResponse", [ "jsCallback" => "$('#" . $formId . " ._restResponse').html(JSON.stringify(data,null,2))","complete" => "var status = { 200 : 'green', 401 : 'orange', 403 : 'brown', 404 : 'black', 500 : 'red' };
198  var headers=jqXHR.getAllResponseHeaders();
199  headers=headers.split(/\\r\\n/);
200  var bHeaders=[];
201  $.each(headers,function(index,header){
202  var vp=header.split(':');
203  if(vp[0]!='')
204  bHeaders.push('\"'+vp[0]+'\":\"'+vp[1]+'\"');
205  });
206  headers=$.parseJSON('{'+bHeaders.join(',')+'}');
207  $('#" . $formId . " ._responseHeaders').html(JSON.stringify(headers,null,2));
208  if(jqXHR.responseText==null){
209  $('#" . $formId . " ._restResponse').html('The response is empty');
210  }else if(jqXHR.status!=200){
211  $('#" . $formId . " ._restResponse').html(jqXHR.responseText);
212  }
213  $('#" . $formId . " ._statusText').html(jqXHR.statusText);
214  $('#" . $formId . " ._status').html(jqXHR.status);
215  $('#" . $formId . " ._status').removeClass('red black brown orange green').addClass(status[jqXHR.status]);
216  addToken(jqXHR);","dataType" => "json","headers" => $headers,"params" => $this->getRestRequestParams() ]);
217  echo '<div><h5 class="ui top block attached header">Response headers</h5><div class="ui attached segment"><pre style="font-size: 10px;" class="_responseHeaders"></pre></div></div>';
218  echo $this->jquery->compile($this->view);
219  }
220 
221  protected function getRestRequestHeaders() {
222  $result=[ '"Authorization": "Bearer "+$("#access-token").val()' ];
223  if (isset($_POST["headers"])) {
224  $headers=urldecode($_POST["headers"]);
225  \parse_str($headers, $output);
226  $this->_getParamsForJSON($result, $output);
227  }
228  return "{" . \implode(",", $result) . "}";
229  }
230 
231  protected function getRestRequestParams() {
232  $result=[ ];
233  if (isset($_POST["params"])) {
234  $headers=urldecode($_POST["params"]);
235  \parse_str($headers, $output);
236  $this->_getParamsForJSON($result, $output);
237  }
238  return "{" . \implode(",", $result) . "}";
239  }
240 
241  protected function _getParamsForJSON(&$result, $params) {
242  if (isset($params["name"])) {
243  $names=$params["name"];
244  $values=$params["value"];
245  $count=\sizeof($names);
246  for($i=0; $i < $count; $i++) {
247  $name=$names[$i];
248  if (UString::isNotNull($name)) {
249  if (isset($values[$i]))
250  $result[]='"' . $name . '": "' . \addslashes($values[$i]) . '"';
251  }
252  }
253  }
254  }
255 
256  public function _saveToken() {
257  if (isset($_POST["_token"]))
258  $_SESSION["_token"]=$_POST["_token"];
259  }
260 
261  public function _saveRequestParams($type="parameter") {
262  $keys=$_POST["name"];
263  $values=$_POST["value"];
264  $toUpdate=$_POST["toUpdate"];
265  $frm=$this->jquery->semantic()->htmlForm($toUpdate);
266  $frm->setSize("mini");
267  $count=\sizeof($values);
268  for($i=0; $i < $count; $i++) {
269  if (JString::isNull($keys[$i])) {
270  unset($keys[$i]);
271  unset($values[$i]);
272  }
273  }
274  $keys=\array_values($keys);
275  $values=\array_values($values);
276  $count=\sizeof($values);
277  if ($count > 0) {
278  $fields=$frm->addFields();
279  $fields->addElement("", "Name", "", "div", "ui label mini black pointing below");
280  $fields->addElement("", "Value", "", "div", "ui label mini black pointing below");
281  for($i=0; $i < $count; $i++) {
282  $fields=$frm->addFields();
283  $fields->addInput("name[]", "", "text", $keys[$i])->setIdentifier("name-" . $i);
284  $input=$fields->addInput("value[]", "", "text", $values[$i])->setIdentifier("value-" . $i);
285  $input->addAction("", true, "remove")->addClass("icon basic mini _deleteParameter");
286  }
287  } else {
288  $frm->addItem(new HtmlLabel("", "No " . $type . "s"));
289  }
290  $this->jquery->click("._deleteParameter", "
291  $(this).parents('.fields').remove();
292  if($('#" . $toUpdate . "').find('.fields').length==1){
293  $('#" . $toUpdate . "').children('.fields').remove();
294  $('#" . $toUpdate . "').append('<div class=\"ui label\">No " . $type . "s</div>');
295  }
296  ", true, true, true);
297  echo $frm;
298  echo $this->jquery->compile($this->view);
299  }
300 }
static isPost()
Returns true if the request is sent by the POST method.
Definition: URequest.php:109
static docMethodParser($classname, $method)
Definition: DocParser.php:120
static getModels(&$config, $silent=false)
static openReplaceWriteFromTemplateFile($source, $destination, $keyAndValues)
Definition: UFileSystem.php:73
showSimpleMessage($content, $type, $title=null, $icon="info", $timeout=NULL, $staticName=null)
static initCache(&$config, $type="all", $silent=false)