Ubiquity  2.0.0
php rapid development framework
UbiquityMyAdminViewer.php
Go to the documentation of this file.
1 <?php
2 
4 
5 use Ajax\JsUtils;
37 
48  private $jquery;
49 
54  private $controller;
55 
57  $this->jquery=$controller->jquery;
58  $this->controller=$controller;
59  }
60 
67  public function getForm($identifier, $instance) {
68  $type=($instance->_new) ? "new" : "edit";
69  $messageInfos=[ "new" => [ "icon" => HtmlIconGroups::corner("table", "plus", "big"),"message" => "New object creation" ],"edit" => [ "icon" => HtmlIconGroups::corner("table", "edit", "big"),"message" => "Editing an existing object" ] ];
70  $message=$messageInfos[$type];
71  $form=$this->jquery->semantic()->dataForm($identifier, $instance);
72  $className=\get_class($instance);
73  $fields=$this->controller->_getAdminData()->getFormFieldNames($className);
74  $form->setFields($fields);
75  $form->insertField(0, "_message");
76  $form->fieldAsMessage("_message", [ "icon" => $message["icon"] ]);
77  $instance->_message=$className;
78  $fieldTypes=OrmUtils::getFieldTypes($className);
79  foreach ( $fieldTypes as $property => $type ) {
80  switch($type) {
81  case "tinyint(1)":
82  $form->fieldAsCheckbox($property);
83  break;
84  case "int":
85  case "integer":
86  $form->fieldAsInput($property, [ "inputType" => "number" ]);
87  break;
88  case "date":
89  $form->fieldAsInput($property, [ "inputType" => "date" ]);
90  break;
91  }
92  }
93  $this->relationMembersInForm($form, $instance, $className);
94  $form->setCaptions($this->getFormCaptions($form->getInstanceViewer()->getVisibleProperties(), $className, $instance));
95  $form->setCaption("_message", $message["message"]);
96  $form->setSubmitParams($this->controller->_getAdminFiles()->getAdminBaseRoute() . "/update", "#frm-add-update");
97  return $form;
98  }
99 
106  public function getModelDataTable($instances, $model) {
107  $adminRoute=$this->controller->_getAdminFiles()->getAdminBaseRoute();
108  $semantic=$this->jquery->semantic();
109 
110  $modal=($this->isModal($instances, $model) ? "modal" : "no");
111  $lv=$semantic->dataTable("lv", $model, $instances);
112  $attributes=$this->controller->getFieldNames($model);
113 
114  $lv->setCaptions($this->getCaptions($attributes, $model));
115  $lv->setFields($attributes);
116  $lv->onPreCompile(function () use ($attributes, &$lv) {
117  $lv->getHtmlComponent()->colRight(\count($attributes));
118  });
119 
120  $lv->setIdentifierFunction($this->controller->getIdentifierFunction($model));
121  $lv->getOnRow("click", $adminRoute . "/showDetail", "#table-details", [ "attr" => "data-ajax" ]);
122  $lv->setUrls([ "delete" => $adminRoute . "/delete","edit" => $adminRoute . "/edit/" . $modal ]);
123  $lv->setTargetSelector([ "delete" => "#table-messages","edit" => "#frm-add-update" ]);
124  $lv->addClass("small very compact");
125  $lv->addEditDeleteButtons(false, [ "ajaxTransition" => "random" ], function ($bt) {
126  $bt->addClass("circular");
127  }, function ($bt) {
128  $bt->addClass("circular");
129  });
130  $lv->setActiveRowSelector("error");
131  $this->jquery->getOnClick("#btAddNew", $adminRoute . "/newModel/" . $modal, "#frm-add-update");
132  $this->jquery->click("_.edit", "console.log($(this).closest('.ui.button'));");
133  return $lv;
134  }
135 
142  public function isModal($objects, $model) {
143  return \count($objects) > 5;
144  }
145 
151  public function getCaptions($captions, $className) {
152  return array_map("ucfirst", $captions);
153  }
154 
160  public function getFormCaptions($captions, $className, $instance) {
161  return array_map("ucfirst", $captions);
162  }
163 
164  public function getFkHeaderElement($member, $className, $object) {
165  return new HtmlHeader("", 4, $member, "content");
166  }
167 
168  public function getFkHeaderList($member, $className, $list) {
169  return new HtmlHeader("", 4, $member . " (" . \count($list) . ")", "content");
170  }
171 
179  public function getFkElement($member, $className, $object) {
180  return $this->jquery->semantic()->htmlLabel("element-" . $className . "." . $member, $object . "");
181  }
182 
190  public function getFkList($member, $className, $list) {
191  $element=$this->jquery->semantic()->htmlList("list-" . $className . "." . $member);
192  return $element->addClass("animated divided celled");
193  }
194 
195  public function displayFkElementList($element, $member, $className, $object) {
196  }
197 
198  public function getMainMenuElements() {
199  return [ "models" => [ "Models","sticky note","Used to perform CRUD operations on data." ],"routes" => [ "Routes","car","Displays defined routes with annotations" ],"controllers" => [ "Controllers","heartbeat","Displays controllers and actions" ],"cache" => [ "Cache","lightning","Annotations, models, router and controller cache" ],"rest" => [ "Rest","server","Restfull web service" ],"config" => [ "Config","settings","Configuration variables" ],"seo" => [ "Seo","google","Search Engine Optimization" ],"logs" => [ "Logs","bug","Log files" ] ];
200  }
201 
202  public function getRoutesDataTable($routes, $dtName="dtRoutes") {
203  $errors=[ ];
204  $messages="";
205  foreach ( $routes as $route ) {
206  $errors=\array_merge($errors, $route->getMessages());
207  }
208  if (\sizeof($errors) > 0) {
209  $messages=$this->controller->showSimpleMessage($errors, "error", "warning");
210  }
211  $dt=$this->jquery->semantic()->dataTable($dtName, "Ubiquity\controllers\admin\popo\Route", $routes);
212  $dt->setIdentifierFunction(function ($i, $instance) {
213  return $instance->getId();
214  });
215  $dt->setFields([ "path","methods","controller","action","cache","expired","name" ]);
216  $dt->setCaptions([ "Path","Methods","Controller","Action & parameters","Cache","Expired","Name","" ]);
217  $dt->fieldAsLabel("path", "car");
218  $this->_dtCache($dt);
219  $this->_dtMethods($dt);
220  $this->_dtAction($dt);
221  $this->_dtExpired($dt);
222  $dt->onRowClick('$("#filter-routes").val($(this).find(".ui.label").text());');
223  $dt->onPreCompile(function ($dTable) {
224  $dTable->setColAlignment(7, TextAlignment::RIGHT);
225  $dTable->setColAlignment(5, TextAlignment::CENTER);
226  });
227  $this->addGetPostButtons($dt);
228  $dt->setActiveRowSelector("warning");
229  $dt->wrap($messages);
230  $dt->setEdition()->addClass("compact");
231  return $dt;
232  }
233 
234  public function getControllersDataTable($controllers) {
235  $dt=$this->jquery->semantic()->dataTable("dtControllers", "Ubiquity\controllers\admin\popo\ControllerAction", $controllers);
236  $dt->setFields([ "controller","action","dValues" ]);
237  $dt->setIdentifierFunction(function ($i, $instance) {
238  return \urlencode($instance->getController());
239  });
240  $dt->setCaptions([ "Controller","Action [routes]","Default values","" ]);
241  $this->addGetPostButtons($dt);
242  $dt->setValueFunction("controller", function ($v, $instance, $index) {
243  $bts=new HtmlButtonGroups("bt-" . \urlencode($v), [ $v ]);
244  $bts->addClass("basic");
245  $bt=$bts->getItem(0);
246  $bt->addClass("_clickFirst")->setIdentifier("bt-0-" . $v);
247  $bt->addIcon("heartbeat", true, true);
248  $bt->setToggle();
249  $dd=$bts->addDropdown([ "Add new action in <b>{$v}</b>..." ]);
250  $dd->setIcon("plus");
251  $item=$dd->getItem(0);
252  $item->addClass("_add-new-action")->setProperty("data-controller", $instance->getController());
253  $bt->onClick("$(\"tr[data-ajax='" . \urlencode($instance->getController()) . "'] td:not([rowspan])\").toggle(!$(this).hasClass('active'));");
254  return $bts;
255  });
256  $dt->setValueFunction("action", function ($v, $instance, $index) {
257  $action=$v;
258  $controller=ClassUtils::getClassSimpleName($instance->getController());
259  $r=new \ReflectionMethod($instance->getController(), $action);
260  $lines=file($r->getFileName());
261  $params=$instance->getParameters();
262  \array_walk($params, function (&$item) {
263  $item=$item->name;
264  });
265  $params=" (" . \implode(" , ", $params) . ")";
266  $v=new HtmlSemDoubleElement("", "span", "", "<b>" . $v . "</b>");
267  $v->setProperty("style", "color: #3B83C0;");
268  $v->addIcon("lightning");
269  $v.=new HtmlSemDoubleElement("", "span", "", $params);
270  $annots=$instance->getAnnots();
271  foreach ( $annots as $path => $annotDetail ) {
272  $lbl=new HtmlLabel("", $path, "car");
273  $lbl->setProperty("data-ajax", \htmlspecialchars(($path)));
274  $lbl->addClass("_route");
275  $v.="&nbsp;" . $lbl;
276  }
277  $v=\array_merge([ $v,"<span class='_views-container'>" ], $this->getActionViews($instance->getController(), $controller, $action, $r, $lines));
278  $v[]="</span>";
279  return $v;
280  });
281  $dt->onPreCompile(function ($dt) {
282  $dt->setColAlignment(3, TextAlignment::RIGHT);
283  $dt->getHtmlComponent()->mergeIdentiqualValues(0);
284  });
285  $dt->setEdition(true);
286  $dt->addClass("compact");
287  return $dt;
288  }
289 
290  public function getActionViews($controllerFullname, $controller, $action, \ReflectionMethod $r, $lines) {
291  $result=[ ];
292  $loadedViews=UIntrospection::getLoadedViews($r, $lines);
293  foreach ( $loadedViews as $view ) {
294  if (\file_exists(ROOT . DS . "views" . DS . $view)) {
295  $lbl=new HtmlLabel("lbl-view-" . $controller . $action . $view, $view, "browser", "span");
296  $lbl->addClass("violet");
297  $lbl->addPopupHtml("<i class='icon info circle green'></i>&nbsp;<b>" . $view . "</b> is ok.");
298  } else {
299  $lbl=new HtmlLabel("lbl-view-" . $controller . $action . $view, $view, "warning", "span");
300  $lbl->addClass("orange");
301  $lbl->addPopupHtml("<i class='icon warning circle'></i>&nbsp;<b>" . $view . "</b> file is missing.");
302  }
303  $result[]=$lbl;
304  }
305  $viewname=$controller . "/" . $action . ".html";
306  if (!\file_exists(ROOT . DS . "views" . DS . $viewname)) {
307  $bt=new HtmlButton("", "Create view " . $viewname);
308  $bt->setProperty("data-action", $action);
309  $bt->setProperty("data-controller", $controller);
310  $bt->setProperty("data-controllerFullname", $controllerFullname);
311  $bt->addClass("_create-view visibleover basic violet mini")->setProperty("style", "visibility: hidden;")->addIcon("plus");
312  $result[]=$bt;
313  } elseif (\array_search($viewname, $loadedViews) === false) {
314  $lbl=new HtmlLabel("lbl-view-" . $controller . $action . $viewname, $viewname, "browser", "span");
315  $lbl->addPopupHtml("<i class='icon warning circle'></i>&nbsp;<b>" . $viewname . "</b> exists but is never loaded in action <b>" . $action . "</b>.");
316  $result[]=$lbl;
317  }
318  return $result;
319  }
320 
321  protected function addGetPostButtons(DataTable $dt) {
322  $dt->addFieldButtons([ "GET","POST" ], true, function (HtmlButtonGroups $bts, $instance, $index) {
323  $path=$instance->getPath();
324  $path=\str_replace("(.*?)", "", $path);
325  $path=\str_replace("(index/)?", "", $path);
326  $bts->setIdentifier("bts-" . $instance->getId() . "-" . $index);
327  $bts->getItem(0)->addClass("_get")->setProperty("data-url", $path);
328  $bts->getItem(1)->addClass("_post")->setProperty("data-url", $path);
329  $item=$bts->addDropdown([ "Post with parameters..." ])->getItem(0);
330  $item->addClass("_postWithParams")->setProperty("data-url", $path);
331  });
332  }
333 
334  public function getCacheDataTable($cacheFiles) {
335  $dt=$this->jquery->semantic()->dataTable("dtCacheFiles", "Ubiquity\controllers\admin\popo\CacheFile", $cacheFiles);
336  $dt->setFields([ "type","name","timestamp","size" ]);
337  $dt->setCaptions([ "Type","Name","Timestamp","Size","" ]);
338  $dt->setValueFunction("type", function ($v, $instance, $index) {
339  $item=$this->jquery->semantic()->htmlDropdown("dd-type-" . $v, $v);
340  $item->addItems([ "Delete all","(Re-)Init cache" ]);
341  $item->setPropertyValues("data-ajax", $v);
342  $item->getItem(0)->addClass("_delete-all");
343  if ($instance->getFile() === "")
344  $item->getItem(0)->setDisabled();
345  $item->getItem(1)->addClass("_init");
346  if ($instance->getType() !== "Models" && $instance->getType() !== "Controllers")
347  $item->getItem(1)->setDisabled();
348  $item->asButton()->addIcon("folder", true, true);
349  return $item;
350  });
351  $dt->addDeleteButton(true, [ ], function ($o, $instance) {
352  if ($instance->getFile() == "")
353  $o->setDisabled();
354  $type=$instance->getType();
355  $o->setProperty("data-type", $type);
356  $type=\strtolower($type);
357  if ($type == 'models' || $type == 'controllers') {
358  $o->setProperty("data-key", $instance->getName());
359  } else {
360  $o->setProperty("data-key", $instance->getFile());
361  }
362  });
363  $dt->setIdentifierFunction("getFile");
364  $dt->setValueFunction("timestamp", function ($v) {
365  if ($v !== "")
366  return date(DATE_RFC2822, $v);
367  });
368  $dt->setValueFunction("size", function ($v) {
369  if ($v !== "")
370  return self::formatBytes($v);
371  });
372  $dt->setValueFunction("name", function ($name, $instance, $i) {
373  if (JString::isNotNull($name)) {
374  $link=new HtmlLink("lnl-" . $i);
375  $link->setContent($name);
376  $link->addIcon("edit");
377  $link->addClass("_lnk");
378  $link->setProperty("data-type", $instance->getType());
379  $link->setProperty("data-ajax", $instance->getFile());
380  $link->setProperty("data-key", $instance->getName());
381  return $link;
382  }
383  });
384  $dt->onPreCompile(function ($dt) {
385  $dt->getHtmlComponent()->mergeIdentiqualValues(0);
386  });
387  $this->jquery->postOnClick("._lnk", $this->controller->_getAdminFiles()->getAdminBaseRoute() . "/_showFileContent", "{key:$(this).attr('data-key'),type:$(this).attr('data-type'),filename:$(this).attr('data-ajax')}", "#modal", [ "hasLoader" => false ]);
388  $this->jquery->postFormOnClick("._delete", $this->controller->_getAdminFiles()->getAdminBaseRoute() . "/deleteCacheFile", "frmCache", "#dtCacheFiles tbody", [ "jqueryDone" => "replaceWith","params" => "{type:$(this).attr('data-type'),toDelete:$(this).attr('data-key')}" ]);
389  $this->jquery->postFormOnClick("._delete-all", $this->controller->_getAdminFiles()->getAdminBaseRoute() . "/deleteAllCacheFiles", "frmCache", "#dtCacheFiles tbody", [ "jqueryDone" => "replaceWith","params" => "{type:$(this).attr('data-ajax')}" ]);
390  $this->jquery->postFormOnClick("._init", $this->controller->_getAdminFiles()->getAdminBaseRoute() . "/initCacheType", "frmCache", "#dtCacheFiles tbody", [ "jqueryDone" => "replaceWith","params" => "{type:$(this).attr('data-ajax')}" ]);
391  return $dt;
392  }
393 
394  public function getModelsStructureDataTable($datas) {
395  $de=$this->jquery->semantic()->dataElement("dtStructure", $datas);
396  $fields=\array_keys($datas);
397  $de->setFields($fields);
398  $de->setCaptions($fields);
399  foreach ( $fields as $key ) {
400  $de->setValueFunction($key, function ($value) {
401  if ($value instanceof \stdClass) {
402  $value=( array ) $value;
403  }
404  return \print_r($value, true);
405  });
406  }
407  return $de;
408  }
409 
410  public function getRestRoutesTab($datas) {
411  $tabs=$this->jquery->semantic()->htmlTab("tabsRest");
412 
413  foreach ( $datas as $controller => $restAttributes ) {
414  $doc="";
415  $list=new HtmlList("attributes", [ [ "heartbeat","Controller",$controller ],[ "car","Route",$restAttributes["restAttributes"]["route"] ] ]);
416  $list->setHorizontal();
417  if (\class_exists($controller)) {
419  $desc=$parser->getDescriptionAsHtml();
420  if (isset($desc)) {
421  $doc=new HtmlMessage("msg-doc-controller-" . $controller, $desc);
422  $doc->setIcon("help blue circle")->setDismissable()->addClass("transition hidden");
423  }
424  }
425  $routes=Route::init($restAttributes["routes"]);
426  $errors=[ ];
427  foreach ( $routes as $route ) {
428  $errors=\array_merge($errors, $route->getMessages());
429  }
430  $resource=$restAttributes["restAttributes"]["resource"];
431  $tab=$tabs->addTab($resource, [ $doc,$list,$this->_getRestRoutesDataTable($routes, "dtRest", $resource, $restAttributes["restAttributes"]["authorizations"]) ]);
432  if (\sizeof($errors) > 0) {
433  $tab->menuTab->addLabel("error")->setColor("red")->addIcon("warning sign");
434  $tab->addContent($this->controller->showSimpleMessage(\array_values($errors), "error", "warning"), true);
435  }
436  if ($doc !== "") {
437  $tab->menuTab->addIcon("help circle blue")->onClick("$('#" . $doc->getIdentifier() . "').transition('horizontal flip');");
438  }
439  }
440  return $tabs;
441  }
442 
443  protected function _getRestRoutesDataTable($routes, $dtName, $resource, $authorizations) {
444  $dt=$this->jquery->semantic()->dataTable($dtName, "Ubiquity\controllers\admin\popo\Route", $routes);
445  $dt->setIdentifierFunction(function ($i, $instance) {
446  return $instance->getPath();
447  });
448  $dt->setFields([ "path","methods","action","cache","expired" ]);
449  $dt->setCaptions([ "Path","Methods","Action & Parameters","Cache","Exp?","" ]);
450  $dt->fieldAsLabel("path", "car");
451  $this->_dtCache($dt);
452  $this->_dtMethods($dt);
453  $dt->setValueFunction("action", function ($v, $instance) use ($authorizations) {
454  $auth="";
455  if (\array_search($v, $authorizations) !== false) {
456  $auth=new HtmlIcon("lock-" . $instance->getController() . $v, "lock alternate");
457  $auth->addPopup("Authorization", "This route require a valid access token");
458  }
459  $result=[ "<span style=\"color: #3B83C0;\">" . $v . "</span>" . $instance->getCompiledParams() . "<i class='ui icon help circle blue hidden transition _showMsgHelp' id='" . JString::cleanIdentifier("help-" . $instance->getAction() . $instance->getController()) . "' data-show='" . JString::cleanIdentifier("msg-help-" . $instance->getAction() . $instance->getController()) . "'></i>",$auth ];
460  return $result;
461  });
462  $this->_dtExpired($dt);
463  $dt->addFieldButton("Test", true, function ($bt, $instance) use ($resource) {
464  $bt->addClass("toggle _toTest basic circular")->setProperty("data-resource", ClassUtils::cleanClassname($resource));
465  $bt->setProperty("data-action", $instance->getAction())->setProperty("data-controller", \urlencode($instance->getController()));
466  });
467  $dt->onPreCompile(function ($dTable) {
468  $dTable->setColAlignment(5, TextAlignment::RIGHT);
469  $dTable->setColAlignment(4, TextAlignment::CENTER);
470  });
471  $dt->setEdition()->addClass("compact");
472  return $dt;
473  }
474 
475  protected function _dtMethods(DataTable $dt) {
476  $dt->setValueFunction("methods", function ($v) {
477  $result="";
478  if (UString::isNotNull($v)) {
479  if (!\is_array($v)) {
480  $v=[ $v ];
481  }
482  $result=new HtmlLabelGroups("lbls-method", $v, [ "color" => "grey" ]);
483  }
484  return $result;
485  });
486  }
487 
488  protected function _dtCache(DataTable $dt) {
489  $dt->setValueFunction("cache", function ($v, $instance) {
490  $ck=new HtmlFormCheckbox("ck-" . $instance->getPath(), $instance->getDuration() . "");
491  $ck->setChecked(UString::isBooleanTrue($v));
492  $ck->setDisabled();
493  return $ck;
494  });
495  }
496 
497  protected function _dtExpired(DataTable $dt) {
498  $dt->setValueFunction("expired", function ($v, $instance, $index) {
499  $icon=null;
500  $expired=null;
501  if ($instance->getCache()) {
502  if (\sizeof($instance->getParameters()) === 0 || $instance->getParameters() === null)
503  $expired=CacheManager::isExpired($instance->getPath(), $instance->getDuration());
504  if ($expired === false) {
505  $icon="hourglass full";
506  } elseif ($expired === true) {
507  $icon="hourglass empty orange";
508  } else {
509  $icon="help";
510  }
511  }
512  return new HtmlIcon("", $icon);
513  });
514  }
515 
516  protected function _dtAction(DataTable $dt) {
517  $dt->setValueFunction("action", function ($v, $instance) {
518  $result="<span style=\"font-weight: bold;color: #3B83C0;\">" . $v . "</span>";
519  $result.=$instance->getCompiledParams();
520  if (!\method_exists($instance->getController(), $v)) {
521  $errorLbl=new HtmlIcon("error-" . $v, "warning sign red");
522  $errorLbl->addPopup("", "Missing method!");
523  return [ $result,$errorLbl ];
524  }
525  return $result;
526  });
527  }
528 
529  public function getConfigDataElement($config) {
530  $de=$this->jquery->semantic()->dataElement("deConfig", $config);
531  $fields=\array_keys($config);
532  $de->setFields($fields);
533  $de->setCaptions($fields);
534  $de->setValueFunction("database", function ($v, $instance, $index) {
535  $dbDe=new DataElement("", $v);
536  $dbDe->setFields([ "type","dbName","serverName","port","user","password","cache" ]);
537  $dbDe->setCaptions([ "Type","dbName","serverName","port","user","password","cache" ]);
538  return $dbDe;
539  });
540  $de->setValueFunction("templateEngineOptions", function ($v, $instance, $index) {
541  $teoDe=new DataElement("", $v);
542  $teoDe->setFields([ "cache" ]);
543  $teoDe->setCaptions([ "cache" ]);
544  $teoDe->fieldAsCheckbox("cache", [ "class" => "ui checkbox slider" ]);
545  return $teoDe;
546  });
547  $de->setValueFunction("mvcNS", function ($v, $instance, $index) {
548  $mvcDe=new DataElement("", $v);
549  $mvcDe->setFields([ "models","controllers","rest" ]);
550  $mvcDe->setCaptions([ "Models","Controllers","Rest" ]);
551  return $mvcDe;
552  });
553  $de->setValueFunction("di", function ($v, $instance, $index) use ($config) {
554  $diDe=new DataElement("", $v);
555  $keys=\array_keys($config["di"]);
556  $diDe->setFields($keys);
557  foreach ( $keys as $key ) {
558  $diDe->setValueFunction($key, function ($value) use ($config, $key) {
559  $r=$config['di'][$key];
560  if (\is_callable($r))
561  return \nl2br(\htmlentities(UIntrospection::closure_dump($r)));
562  return $value;
563  });
564  }
565  return $diDe;
566  });
567  $de->setValueFunction("isRest", function ($v) use ($config) {
568  $r=$config["isRest"];
569  if (\is_callable($r))
570  return \nl2br(\htmlentities(UIntrospection::closure_dump($r)));
571  return $v;
572  });
573  $de->fieldAsCheckbox("test", [ "class" => "ui checkbox slider" ]);
574  $de->fieldAsCheckbox("debug", [ "class" => "ui checkbox slider" ]);
575  return $de;
576  }
577 
578  private static function formatBytes($size, $precision=2) {
579  $base=log($size, 1024);
580  $suffixes=array ('o','Ko','Mo','Go','To' );
581  return round(pow(1024, $base - floor($base)), $precision) . ' ' . $suffixes[floor($base)];
582  }
583 
584  protected function relationMembersInForm($form, $instance, $className) {
585  $relations=OrmUtils::getFieldsInRelations($className);
586  foreach ( $relations as $member ) {
587  if ($this->controller->_getAdminData()->getUpdateManyToOneInForm() && OrmUtils::getAnnotationInfoMember($className, "#manyToOne", $member) !== false) {
588  $this->manyToOneFormField($form, $member, $className, $instance);
589  } elseif ($this->controller->_getAdminData()->getUpdateOneToManyInForm() && ($annot=OrmUtils::getAnnotationInfoMember($className, "#oneToMany", $member)) !== false) {
590  $this->oneToManyFormField($form, $member, $instance, $annot);
591  } elseif ($this->controller->_getAdminData()->getUpdateManyToManyInForm() && ($annot=OrmUtils::getAnnotationInfoMember($className, "#manyToMany", $member)) !== false) {
592  $this->manyToManyFormField($form, $member, $instance, $annot);
593  }
594  }
595  }
596 
597  protected function manyToOneFormField(DataForm $form, $member, $className, $instance) {
598  $joinColumn=OrmUtils::getAnnotationInfoMember($className, "#joinColumn", $member);
599  if ($joinColumn) {
600  $fkObject=Reflexion::getMemberValue($instance, $member);
601  $fkClass=$joinColumn["className"];
602  if ($fkObject === null) {
603  $fkObject=new $fkClass();
604  }
605  $fkId=OrmUtils::getFirstKey($fkClass);
606  $fkIdGetter="get" . \ucfirst($fkId);
607  if (\method_exists($fkObject, "__toString") && \method_exists($fkObject, $fkIdGetter)) {
608  $fkField=$joinColumn["name"];
609  $fkValue=OrmUtils::getFirstKeyValue($fkObject);
610  if (!Reflexion::setMemberValue($instance, $fkField, $fkValue)) {
611  $instance->{$fkField}=OrmUtils::getFirstKeyValue($fkObject);
612  $form->addField($fkField);
613  }
614  $form->fieldAsDropDown($fkField, JArray::modelArray(DAO::getAll($fkClass), $fkIdGetter, "__toString"));
615  $form->setCaption($fkField, \ucfirst($member));
616  }
617  }
618  }
619 
620  protected function oneToManyFormField(DataForm $form, $member, $instance, $annot) {
621  $newField=$member . "Ids";
622  $fkClass=$annot["className"];
623  $fkId=OrmUtils::getFirstKey($fkClass);
624  $fkIdGetter="get" . \ucfirst($fkId);
625  $fkInstances=DAO::getOneToMany($instance, $member);
626  $form->addField($newField);
627  $ids=\array_map(function ($elm) use ($fkIdGetter) {
628  return $elm->{$fkIdGetter}();
629  }, $fkInstances);
630  $instance->{$newField}=\implode(",", $ids);
631  $form->fieldAsDropDown($newField, JArray::modelArray(DAO::getAll($fkClass), $fkIdGetter, "__toString"), true);
632  $form->setCaption($newField, \ucfirst($member));
633  }
634 
635  protected function manyToManyFormField(DataForm $form, $member, $instance, $annot) {
636  $newField=$member . "Ids";
637  $fkClass=$annot["targetEntity"];
638  $fkId=OrmUtils::getFirstKey($fkClass);
639  $fkIdGetter="get" . \ucfirst($fkId);
640  $fkInstances=DAO::getManyToMany($instance, $member);
641  $form->addField($newField);
642  $ids=\array_map(function ($elm) use ($fkIdGetter) {
643  return $elm->{$fkIdGetter}();
644  }, $fkInstances);
645  $instance->{$newField}=\implode(",", $ids);
646  $form->fieldAsDropDown($newField, JArray::modelArray($this->controller->_getAdminData()->getManyToManyDatas($fkClass, $instance, $member), $fkIdGetter, "__toString"), true, [ "jsCallback" => function ($elm) {
647  $elm->getField()->asSearch();
648  } ]);
649  $form->setCaption($newField, \ucfirst($member));
650  }
651 
652  public function getMainIndexItems($identifier,$array):HtmlItems{
653  $items=$this->jquery->semantic()->htmlItems($identifier);
654 
655  $items->fromDatabaseObjects($array, function ($e) {
656  $item=new HtmlItem("");
657  $item->addIcon($e[1] . " bordered circular")->setSize("big");
658  $item->addItemHeaderContent($e[0], [ ], $e[2]);
659  $item->setProperty("data-ajax", \strtolower($e[0]));
660  return $item;
661  });
662  $items->getOnClick($this->controller->_getAdminFiles()->getAdminBaseRoute(), "#main-content", [ "attr" => "data-ajax" ]);
663  return $items->addClass("divided relaxed link");
664  }
665 }
static getFieldsInRelations($class)
Definition: OrmUtils.php:222
oneToManyFormField(DataForm $form, $member, $instance, $annot)
_getRestRoutesDataTable($routes, $dtName, $resource, $authorizations)
static getAnnotationInfoMember($class, $keyAnnotation, $member)
Definition: OrmUtils.php:200
static setMemberValue($instance, $member, $value)
Definition: Reflexion.php:41
__construct(UbiquityMyAdminBaseController $controller)
static getFirstKey($class)
Definition: OrmUtils.php:121
getModelDataTable($instances, $model)
Returns the dataTable responsible for displaying instances of the model.
static getFirstKeyValue($instance)
Definition: OrmUtils.php:126
getFormCaptions($captions, $className, $instance)
Returns the captions for form fields.
static getManyToMany($instance, $member, $array=null, $useCache=NULL)
Assigns / loads the child records in the $member member of $instance.
Definition: DAO.php:127
static getAll($className, $condition='', $loadManyToOne=true, $loadOneToMany=false, $useCache=NULL)
Returns an array of $className objects from the database.
Definition: DAO.php:193
isModal($objects, $model)
Condition to determine if the edit or add form is modal for $model objects.
static getMemberValue($instance, $member)
Definition: Reflexion.php:35
manyToOneFormField(DataForm $form, $member, $className, $instance)
static getFieldTypes($className)
Definition: OrmUtils.php:85
static getOneToMany($instance, $member, $useCache=NULL, $annot=null)
Assign / load the child records in the $member member of $instance.
Definition: DAO.php:71
getCaptions($captions, $className)
Returns the captions for list fields in showTable action.
static cleanClassname($classname)
Definition: ClassUtils.php:20
static getLoadedViews(\ReflectionMethod $r, $lines)
getActionViews($controllerFullname, $controller, $action, \ReflectionMethod $r, $lines)
manyToManyFormField(DataForm $form, $member, $instance, $annot)
displayFkElementList($element, $member, $className, $object)
static getClassSimpleName($classnameWithNamespace)
Definition: ClassUtils.php:129
getForm($identifier, $instance)
Returns the form for adding or modifying an object.