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