Ubiquity  2.0.3
php rapid development framework
SeoTrait.php
Go to the documentation of this file.
1 <?php
2 
4 
18 
25 class SeoTrait{
26 
27  abstract public function _getAdminData();
28 
29  abstract public function _getAdminViewer();
30 
31  abstract public function _getAdminFiles();
32 
33  abstract public function loadView($viewName, $pData = NULL, $asString = false);
34 
35  abstract public function seo();
36 
37  abstract protected function _seo();
38 
39  abstract protected function showConfMessage($content, $type,$title, $url, $responseElement, $data, $attributes = NULL): HtmlMessage;
40 
41  abstract protected function showSimpleMessage($content, $type, $title=null,$icon = "info", $timeout = NULL, $staticName = null): HtmlMessage;
42 
43  abstract protected function _createController($controllerName, $variables = [], $ctrlTemplate = 'controller.tpl', $hasView = false, $jsCallback = "");
44 
45  public function displaySiteMap(...$params) {
46  $controllerClass = \implode ( "\\", $params );
47  if (\class_exists ( $controllerClass )) {
48  $controllerSeo = new $controllerClass ();
49  USession::set ( "seo-sitemap", $controllerSeo );
50  $array = $controllerSeo->_getArrayUrls ();
51  $parser = new UrlParser ();
52  $parser->parseArray ( $array, true );
53  $parser->parse ();
54  $urls = $parser->getUrls ();
55  $dt = $this->jquery->semantic ()->dataTable ( "dtSiteMap", 'Ubiquity\seo\Url', $urls );
56  $dt->setFields ( [ 'location','lastModified','changeFrequency','priority' ] );
57  $dt->setCaptions ( [ 'Location','Last Modified','Change Frequency','Priority' ] );
58  $dt->fieldAsInput ( "location" );
59  $dt->setValueFunction ( "lastModified", function ($v, $o, $i) {
60  $d = date ( 'Y-m-d\TH:i', $v );
61  $input = new HtmlInput ( "date-" . $i, 'datetime-local', $d );
62  $input->setName ( "lastModified[]" );
63  return $input;
64  } );
66  $dt->fieldAsDropDown ( 'changeFrequency', \array_combine ( $freq, $freq ) );
67  $dt->setValueFunction ( "priority", function ($v, $o, $i) {
68  $input = new HtmlInput ( "priority-" . $i, 'number', $v );
69  $f = $input->getDataField ();
70  $f->setProperty ( 'name', 'priority[]' );
71  $f->setProperty ( 'max', '1' )->setProperty ( 'min', '0' )->setProperty ( 'step', '0.1' );
72  return $input;
73  } );
74  $dt->onNewRow ( function ($row, $instance) {
75  if ($instance->getExisting ()) {
76  $row->addClass ( 'positive' );
77  } else {
78  $row->setProperty ( 'style', 'display: none;' )->addClass ( 'toToggle' );
79  }
80  } );
81  $dt->setHasCheckboxes ( true );
82  $dt->setCheckedCallback ( function ($object) {
83  return $object->getExisting ();
84  } );
85  $dt->asForm ();
86  $dt->setSubmitParams ( $this->_getAdminFiles ()->getAdminBaseRoute () . "/saveUrls", "#seo-details", [ 'attr' => '' ] );
87  $this->jquery->execOn ( "click", "#saveUrls", '$("#frm-dtSiteMap").form("submit");' );
88  $this->jquery->exec ( '$("#displayAllRoutes").checkbox();', true );
89  $this->jquery->execOn ( 'change', 'input[name="selection[]"]', '$(this).parents("tr").toggleClass("_checked",$(this).prop("checked"));' );
90  $this->jquery->click ( '#displayAllRoutes', '$(".toToggle:not(._checked)").toggle();' );
91  $this->jquery->execAtLast ( $this->jquery->execOn ( 'change', '#frm-dtSiteMap input', '$("#saveUrls").show();', [ "immediatly" => false ] ) );
92  $this->jquery->compile ( $this->view );
93 
94  $this->loadView ( $this->_getAdminFiles ()->getViewSeoDetails (), [ "controllerClass" => $controllerClass,"urlsFile" => $controllerSeo->_getUrlsFilename () ] );
95  } else {
96  echo $this->showSimpleMessage ( "The controller <b>`{$controllerClass}`</b> does not exists!", "warning", "warning circle" );
97  echo $this->jquery->compile ( $this->view );
98  }
99  }
100 
101  public function generateRobots() {
102  $frameworkDir = Startup::getFrameworkDir ();
103  $config = Startup::getConfig ();
104  $siteUrl = $config ["siteUrl"];
105  $content = [ ];
106  if (URequest::isPost ()) {
107  $template = UFileSystem::load ( $frameworkDir . "/admin/templates/robots.tpl" );
108  $seoCtrls = URequest::post ( 'selection', [ ] );
109  foreach ( $seoCtrls as $ctrl ) {
110  if (\class_exists ( $ctrl )) {
111  $controllerSeo = new ControllerSeo ( $ctrl );
112  $content [] = \str_replace ( "%url%", URequest::cleanUrl ( $siteUrl . $controllerSeo->getPath () ), $template );
113  }
114  }
115  if (\sizeof ( $content ) > 0) {
116  $appDir = Startup::getApplicationDir ();
117  $content = \implode ( "\n", $content );
118  UFileSystem::save ( $appDir . DS . 'robots.txt', $content );
119  $msg = $this->showSimpleMessage ( "The file <b>robots.txt</b> has been generated in " . $appDir, "success", "info circle" );
120  $this->jquery->get ( $this->_getAdminFiles ()->getAdminBaseRoute () . "/seoRefresh", "#seoCtrls", [ 'hasLoader' => false,'jqueryDone' => 'replaceWith' ] );
121  } else {
122  $msg = $this->showSimpleMessage ( "Can not generate <b>robots.txt</b> if no SEO controller is selected.", "warning", "warning circle" );
123  }
124  echo $msg;
125  echo $this->jquery->compile ( $this->view );
126  }
127  }
128 
129  public function seoRefresh() {
130  echo $this->_seo ();
131  echo $this->jquery->compile ( $this->view );
132  }
133 
134  public function _newSeoController() {
135  $modal = $this->jquery->semantic ()->htmlModal ( "modalNewSeo", "Creating a new Seo controller" );
136  $modal->setInverted ();
137  $frm = $this->jquery->semantic ()->htmlForm ( "frmNewSeo" );
138  $fc = $frm->addField ( 'controllerName' )->addRule ( [ "checkController","Controller {value} already exists!" ] );
139  $fc->labeled ( Startup::getNS () );
140  $fields = $frm->addFields ( [ "urlsFile","sitemapTemplate" ], "Urls file & sitemap twig template" );
141  $fields->setFieldsPropertyValues ( "value", [ "urls","@framework/Seo/sitemap.xml.html" ] );
142  $fields->getItem ( 0 )->addRules ( [ "empty" ] );
143 
144  $frm->addCheckbox ( "ck-add-route", "Add route..." );
145 
146  $frm->addContent ( "<div id='div-new-route' style='display: none;'>" );
147  $frm->addDivider ();
148  $frm->addInput ( "path", "", "text", "" )->addRule ( [ "checkRoute","Route {value} already exists!" ] );
149  $frm->addContent ( "</div>" );
150 
151  $frm->setValidationParams ( [ "on" => "blur","inline" => true ] );
152  $frm->setSubmitParams ( $this->_getAdminFiles ()->getAdminBaseRoute () . "/createSeoController", "#messages", [ "hasLoader" => false ] );
153  $modal->setContent ( $frm );
154  $modal->addAction ( "Validate" );
155  $this->jquery->click ( "#action-modalNewSeo-0", "$('#frmNewSeo').form('submit');", false, false );
156  $modal->addAction ( "Close" );
157  $this->jquery->change ( '#controllerName', 'if($("#ck-add-route").is(":checked")){$("#path").val($(this).val());}' );
158  $this->jquery->exec ( "$('.dimmer.modals.page').html('');$('#modalNewSeo').modal('show');", true );
159  $this->jquery->jsonOn ( "change", "#ck-add-route", $this->_getAdminFiles ()->getAdminBaseRoute () . "/_addRouteWithNewAction", "post", [ "context" => "$('#frmNewSeo')","params" => "$('#frmNewSeo').serialize()","jsCondition" => "$('#ck-add-route').is(':checked')" ] );
160  $this->jquery->exec ( Rule::ajax ( $this->jquery, "checkRoute", $this->_getAdminFiles ()->getAdminBaseRoute () . "/_checkRoute", "{}", "result=data.result;", "postForm", [ "form" => "frmNewSeo" ] ), true );
161  $this->jquery->exec ( Rule::ajax ( $this->jquery, "checkController", $this->_getAdminFiles ()->getAdminBaseRoute () . "/_checkController", "{}", "result=data.result;", "postForm", [ "form" => "frmNewSeo" ] ), true );
162  $this->jquery->change ( "#ck-add-route", '$("#div-new-route").toggle($(this).is(":checked"));if($(this).is(":checked")){$("#path").val($("#controllerName").val());}' );
163  echo $modal;
164  echo $this->jquery->compile ( $this->view );
165  }
166 
167  public function createSeoController($force = null) {
168  if (URequest::isPost ()) {
169  $variables = [ ];
170  $path = URequest::post ( "path" );
171  $variables ["%path%"] = $path;
172  if (isset ( $path )) {
173  $variables ["%route%"] = '@route("' . $path . '")';
174  }
175  $variables ["%urlsFile%"] = URequest::post ( "urlsFile", "urls" );
176  $variables ["%sitemapTemplate%"] = URequest::post ( "sitemapTemplate", "@framework/Seo/sitemap.xml.html" );
177 
178  echo $this->_createController ( $_POST ["controllerName"], $variables, 'seoController.tpl', false, $this->jquery->getDeferred ( $this->_getAdminFiles ()->getAdminBaseRoute () . "/seoRefresh", "#seoCtrls", [ 'hasLoader' => false,'jqueryDone' => 'replaceWith',
179  'jsCallback' => '$("#seo-details").html("");' ] ) );
180  }
181  $this->jquery->get ( $this->_getAdminFiles ()->getAdminBaseRoute () . "/seoRefresh", "#seoCtrls", [ 'hasLoader' => false,'jqueryDone' => 'replaceWith','jsCallback' => '$("#seo-details").html("");' ] );
182  echo $this->jquery->compile ( $this->view );
183  }
184 
185  public function _checkController() {
186  if (URequest::isPost ()) {
187  $result = [ ];
188  $controllers = CacheManager::getControllers ();
189  $ctrlNS = Startup::getNS ();
190  header ( 'Content-type: application/json' );
191  $controller = $ctrlNS . $_POST ["controllerName"];
192  $result ["result"] = (\array_search ( $controller, $controllers ) === false);
193  echo json_encode ( $result );
194  }
195  }
196 
197  public function saveUrls() {
198  $result = [ ];
199  $selections = URequest::post ( "selection", [ ] );
200  $locations = URequest::post ( "location", [ ] );
201  $lastModified = URequest::post ( "lastModified", [ ] );
202  $changeFrequency = URequest::post ( "changeFrequency", [ ] );
203  $priority = URequest::post ( "priority", [ ] );
204  foreach ( $selections as $index ) {
205  $result [] = [ "location" => $locations [$index - 1],"lastModified" => \strtotime ( $lastModified [$index - 1] ),"changeFrequency" => $changeFrequency [$index - 1],"priority" => $priority [$index - 1] ];
206  }
207  $seoController = USession::get ( "seo-sitemap" );
208  if (isset ( $seoController ) && $seoController instanceof SeoController) {
209  try {
210  $seoController->_save ( $result );
211  $r = new \ReflectionClass ( $seoController );
212  $this->displaySiteMap ( $r->getNamespaceName (), $r->getShortName () );
213  $filename = $seoController->_getUrlsFilename ();
214  $message = $this->showSimpleMessage ( UString::pluralize ( \sizeof ( $selections ), '<b>`' . $filename . '`</b> saved with no url.', '<b>`' . $filename . '`</b> saved with {count} url.', '<b>`' . $filename . '`</b> saved with {count} urls.' ), "success", "info circle" );
215  } catch ( \Ubiquity\exceptions\CacheException $e ) {
216  $message = $this->showSimpleMessage ( "Unable to write urls file `" . $filename . "`", "warning", "warning" );
217  }
218  $this->jquery->html ( "#messages", $message, true );
219  echo $this->jquery->compile ( $this->view );
220  }
221  }
222 
223  public function deleteSeoController(...$params) {
224  $controllerName = \implode ( "\\", $params );
225  if (sizeof ( $_POST ) > 0) {
226  $controllerName = \urldecode ( $_POST ["data"] );
227  if ($this->_deleteController ( $controllerName )) {
228  $message = $this->showSimpleMessage ( "Deletion of SEO controller `<b>" . $controllerName . "</b>`", "info", "info", 4000 );
229  $this->jquery->get ( $this->_getAdminFiles ()->getAdminBaseRoute () . "/seoRefresh", "#seoCtrls", [ 'hasLoader' => false,'jqueryDone' => 'replaceWith','jsCallback' => '$("#seo-details").html("");' ] );
230  } else {
231  $message = $this->showSimpleMessage ( "Can not delete SEO controller `" . $controllerName . "`", "warning", "warning" );
232  }
233  } else {
234  $message = $this->showConfMessage ( "Do you confirm the deletion of SEO controller `<b>" . $controllerName . "</b>`?", "error", $this->_getAdminFiles ()->getAdminBaseRoute () . "/deleteSeoController/{$params[0]}/{$params[1]}", "#messages", \urlencode ( $controllerName ) );
235  }
236  echo $message;
237  echo $this->jquery->compile ( $this->view );
238  }
239 
240  protected function _deleteController($controllerName) {
241  $controllerName = \urldecode ( $controllerName );
242  if (\class_exists ( $controllerName )) {
243  $rClass = new \ReflectionClass ( $controllerName );
244  return UFileSystem::deleteFile ( $rClass->getFileName () );
245  }
246  return false;
247  }
248 
249  public function seeSeoUrl(...$params) {
250  $controllerName = \implode ( "\\", $params );
251  $ctrl = new $controllerName ();
252  \ob_start ();
253  $ctrl->index ();
254  $content = \ob_get_clean ();
256  $modal = $this->jquery->semantic ()->htmlModal ( "seeSeo", "sitemap file for {$ctrl->getPath()} url" );
257  $modal->setInverted ();
258  $modal->setContent ( "<pre><code>" . \htmlentities ( $content ) . "</pre></code>" );
259  $modal->addAction ( "Close" );
260  $this->jquery->exec ( "$('.dimmer.modals.page').html('');$('#seeSeo').modal('show');", true );
261  echo $modal;
262  echo $this->jquery->compile ( $this->view );
263  }
264 }
static isPost()
Returns true if the request is sent by the POST method.
Definition: URequest.php:109
_createController($controllerName, $variables=[], $ctrlTemplate='controller.tpl', $hasView=false, $jsCallback="")
static asHtml($encoding='utf-8')
Sets the response content-type to text/html.
Definition: UResponse.php:86
loadView($viewName, $pData=NULL, $asString=false)
static pluralize($count, $zero, $one, $other)
Pluralize an expression.
Definition: UString.php:59
static post($key, $default=NULL)
Returns the value of the $key variable passed by the post method or $default if the $key variable doe...
Definition: URequest.php:146
showConfMessage($content, $type, $title, $url, $responseElement, $data, $attributes=NULL)
static getNS($part="controllers")
Definition: Startup.php:45
showSimpleMessage($content, $type, $title=null, $icon="info", $timeout=NULL, $staticName=null)
static set($key, $value)
Adds or sets a value to the Session at position $key.
Definition: USession.php:151
static getControllers($subClass="\biquity\ontrollers\ontroller", $backslash=false, $includeSubclass=false)
static get($key, $default=NULL)
Returns the value stored at the key position in session.
Definition: USession.php:139
static deleteFile($filename)
Definition: UFileSystem.php:28
static save($filename, $content, $flags=LOCK_EX)