Autodoc
  • Namespace
  • Class
  • Tree

Namespaces

  • BlueTihi
    • Context
  • Brickrouge
    • Element
      • Nodes
    • Renderer
    • Widget
  • ICanBoogie
    • ActiveRecord
    • AutoConfig
    • CLDR
    • Composer
    • Core
    • Event
    • Exception
    • HTTP
      • Dispatcher
      • Request
    • I18n
      • Translator
    • Mailer
    • Modules
      • Taxonomy
        • Support
      • Thumbnailer
        • Versions
    • Object
    • Operation
      • Dispatcher
    • Prototype
    • Routes
    • Routing
      • Dispatcher
    • Session
  • Icybee
    • ActiveRecord
      • Model
    • ConfigOperation
    • Document
    • EditBlock
    • Element
      • ActionbarContextual
      • ActionbarSearch
      • ActionbarToolbar
    • FormBlock
    • Installer
    • ManageBlock
    • Modules
      • Articles
      • Cache
        • Collection
        • ManageBlock
      • Comments
        • ManageBlock
      • Contents
        • ManageBlock
      • Dashboard
      • Editor
        • Collection
      • Files
        • File
        • ManageBlock
      • Forms
        • Form
        • ManageBlock
      • I18n
      • Images
        • ManageBlock
      • Members
      • Modules
        • ManageBlock
      • Nodes
        • ManageBlock
        • Module
      • Pages
        • BreadcrumbElement
        • LanguagesElement
        • ManageBlock
        • NavigationBranchElement
        • NavigationElement
        • Page
        • PageController
      • Registry
      • Search
      • Seo
      • Sites
        • ManageBlock
      • Taxonomy
        • Terms
          • ManageBlock
        • Vocabulary
          • ManageBlock
      • Users
        • ManageBlock
        • NonceLogin
        • Roles
      • Views
        • ActiveRecordProvider
        • Collection
        • View
    • Operation
      • ActiveRecord
      • Constructor
      • Module
      • Widget
    • Rendering
  • None
  • Patron
  • PHP

Classes

  • AdminDecorator
  • AdminIndexController
  • BlockController
  • BlockDecorator
  • ConfigBlock
  • ConfigController
  • ConfigOperation
  • Core
  • DeleteBlock
  • DeleteController
  • Document
  • DocumentDecorator
  • EditBlock
  • EditController
  • FormBlock
  • Hooks
  • InterlockBlock
  • Kses
  • ManageBlock
  • Module
  • Modules
  • StatsDecorator

Constants

  • OPERATION_SAVE_MODE
  • OPERATION_SAVE_MODE_CONTINUE
  • OPERATION_SAVE_MODE_DISPLAY
  • OPERATION_SAVE_MODE_LIST
  • OPERATION_SAVE_MODE_NEW

Functions

  • slugize
  • start
  • strip_stopwords
  1 <?php
  2 
  3 /*
  4  * This file is part of the Icybee package.
  5  *
  6  * (c) Olivier Laviale <olivier.laviale@gmail.com>
  7  *
  8  * For the full copyright and license information, please view the LICENSE
  9  * file that was distributed with this source code.
 10  */
 11 
 12 namespace Icybee;
 13 
 14 use ICanBoogie\Debug;
 15 use ICanBoogie\Event;
 16 use ICanBoogie\Events;
 17 use ICanBoogie\Exception;
 18 use ICanBoogie\HTTP\Dispatcher;
 19 use ICanBoogie\HTTP\Request;
 20 use ICanBoogie\HTTP\Response;
 21 use ICanBoogie\HTTP\RedirectResponse;
 22 use ICanBoogie\HTTP\WeightedDispatcher;
 23 use ICanBoogie\Operation;
 24 use ICanBoogie\Routes;
 25 
 26 use Brickrouge\Alert;
 27 
 28 use Icybee\Modules\Pages\PageController;
 29 
 30 class Hooks
 31 {
 32     /*
 33      * Events
 34      */
 35 
 36     static public function on_http_dispatcher_alter(Dispatcher\AlterEvent $event, Dispatcher $dispatcher)
 37     {
 38         /**
 39          * Router for admin routes.
 40          *
 41          * This event hook handles all "/admin/" routes. It may redirect the user to the proper "admin"
 42          * location e.g. '/admin/' => '/fr/admin/'. If the "admin" route is detected, the Icybee admin
 43          * interface is presented, granted the user has an access permission, otherwise the
 44          * user is asked to authenticate.
 45          */
 46         $dispatcher['admin:categories'] = new WeightedDispatcher(function(Request $request)
 47         {
 48             global $core;
 49 
 50             $path = \ICanBoogie\normalize_url_path(\ICanBoogie\Routing\decontextualize($request->path));
 51 
 52             if (strpos($path, '/admin/') !== 0)
 53             {
 54                 return;
 55             }
 56 
 57             $category = substr($path, 7, -1);
 58 
 59             if ($category)
 60             {
 61                 $user = $core->user;
 62                 $routes = $core->routes;
 63 
 64                 foreach ($core->modules->descriptors as $module_id => $descriptor)
 65                 {
 66                     if (!isset($core->modules[$module_id]) || !$user->has_permission(Module::PERMISSION_ACCESS, $module_id)
 67                     || $descriptor[Module::T_CATEGORY] != $category)
 68                     {
 69                         continue;
 70                     }
 71 
 72                     $route_id = "admin:$module_id";
 73 
 74                     if (empty($routes[$route_id]))
 75                     {
 76                         $route_id = "admin:$module_id/manage"; //TODO-20120829: COMPAT, 'manage' should disappear.
 77 
 78                         if (empty($routes[$route_id]))
 79                         {
 80                             continue;
 81                         }
 82                     }
 83 
 84                     $route = $routes[$route_id];
 85 
 86                     return new RedirectResponse
 87                     (
 88                         \ICanBoogie\Routing\contextualize($route->pattern), 302, array
 89                         (
 90                             'Icybee-Redirected-By' => __FILE__ . '::' . __LINE__
 91                         )
 92                     );
 93                 }
 94             }
 95         }, 'before:pages');
 96     }
 97 
 98     static public function before_routes_collect(Routes\BeforeCollectEvent $event, Routes $target)
 99     {
100         static $magic = array
101         (
102             '!admin:manage' => true,
103             '!admin:new' => true,
104             '!admin:config' => true,
105             '!admin:edit' => true
106         );
107 
108         $fragments = array();
109 
110         foreach ($event->fragments as $root => $fragment)
111         {
112             $add_delete_route = false;
113 
114             foreach ($fragment as $id => $route)
115             {
116                 if (empty($magic[$id]))
117                 {
118                     if (isset($route['block']) && empty($route['controller']))
119                     {
120                         $route['controller'] = 'Icybee\BlockController';
121                     }
122 
123                     $fragments[$root][$id] = $route;
124 
125                     continue;
126                 }
127 
128                 $module_id = $route['module'];
129 
130                 switch ($id)
131                 {
132                     case '!admin:manage':
133                     {
134                         $id = "admin:$module_id/manage"; // TODO-20120828: renamed this as "admin:{module_id}"
135 
136                         $route += array
137                         (
138                             'pattern' => "/admin/$module_id",
139                             'controller' => 'Icybee\BlockController',
140                             'title' => '.manage',
141                             'block' => 'manage',
142                             'index' => true
143                         );
144                     }
145                     break;
146 
147                     case '!admin:new':
148                     {
149                         $id = "admin:$module_id/new";
150 
151                         $route += array
152                         (
153                             'pattern' => "/admin/$module_id/new",
154                             'controller' => 'Icybee\BlockController',
155                             'title' => '.new',
156                             'block' => 'edit',
157                             'visibility' => 'visible'
158                         );
159                     }
160                     break;
161 
162                     case '!admin:edit':
163                     {
164                         $id = "admin:$module_id/edit";
165 
166                         $route += array
167                         (
168                             'pattern' => "/admin/$module_id/<\d+>/edit",
169                             'controller' => 'Icybee\EditController',
170                             'title' => '.edit',
171                             'block' => 'edit',
172                             'visibility' => 'auto'
173                         );
174 
175                         $add_delete_route = true;
176                     }
177                     break;
178 
179                     case '!admin:config':
180                     {
181                         $id = "admin:$module_id/config";
182 
183                         $route += array
184                         (
185                             'pattern' => "/admin/$module_id/config",
186                             'controller' => 'Icybee\BlockController',
187                             'title' => '.config',
188                             'block' => 'config',
189                             'permission' => Module::PERMISSION_ADMINISTER,
190                             'visibility' => 'visible'
191                         );
192                     }
193                     break;
194                 }
195 
196                 $fragments[$root][$id] = $route;
197             }
198 
199             if ($add_delete_route)
200             {
201                 $fragments[$root]["admin:$module_id/delete"] = array
202                 (
203                     'pattern' => "/admin/$module_id/<\d+>/delete",
204                     'controller' => 'Icybee\BlockController',
205                     'title' => '.delete',
206                     'block' => 'delete',
207                     'visibility' => 'auto',
208                     'via' => 'ANY',
209                     'module' => $module_id
210                 );
211             }
212         }
213 
214         #
215         # default redirection from categories to a module.
216         #
217 
218         $event->fragments = $fragments;
219     }
220 
221     /**
222      * This is the dispatcher for the QueryOperation operation.
223      *
224      * @param array $params
225      *
226      * @return Operation
227      */
228     static public function dispatch_query_operation(Request $request)
229     {
230         global $core;
231 
232         $class = 'Icybee\Operation\Module\QueryOperation';
233         $try_module = $module = $core->modules[$request['module']];
234 
235         while ($try_module)
236         {
237             $try = Operation::format_class_name($try_module->descriptor[Module::T_NAMESPACE], 'QueryOperation');
238 
239             if (class_exists($try, true))
240             {
241                 $class = $try;
242 
243                 break;
244             }
245 
246             $try_module = $try_module->parent;
247         }
248 
249         return new $class($module, $request);
250     }
251 
252     /**
253      * This callback is used to delete all the locks set by the user while editing records.
254      *
255      * @param Event $event
256      */
257     static public function before_user_logout(Event $event)
258     {
259         global $core;
260 
261         $uid = $core->user_id;
262 
263         if (!$uid)
264         {
265             return;
266         }
267 
268         try
269         {
270             $registry = $core->registry;
271 
272             $names = $registry
273             ->where('name LIKE "activerecord_locks.%" AND value LIKE ?', '{"uid":"' . $uid . '"%')
274             ->delete();
275         }
276         catch (\Exception $e) { };
277     }
278 
279     /**
280      * Alters the response location according to the _operation save mode_.
281      *
282      * The following modes are supported:
283      *
284      * - {@link OPERATION_SAVE_MODE_LIST}: Location is the module's index.
285      * - {@link OPERATION_SAVE_MODE_CONTINUE}: Location is the edit URL of the record.
286      * - {@link OPERATION_SAVE_MODE_NEW}: Location is a blank edit form.
287      * - {@link OPERATION_SAVE_MODE_DISPLAY}: Location is the URL of the record.
288      *
289      * The _operation save mode_ is saved in the session per module:
290      *
291      *     $core->session[operation_save_mode][<module_id>]
292      *
293      * @param \ICanBoogie\Operation\BeforeControlEvent $event
294      * @param \ICanBoogie\SaveOperation $target
295      */
296     static public function before_save_operation_control(\ICanBoogie\Operation\BeforeControlEvent $event, \ICanBoogie\SaveOperation $target)
297     {
298         global $core;
299 
300         $mode = $event->request[OPERATION_SAVE_MODE];
301 
302         if (!$mode)
303         {
304             return;
305         }
306 
307         $core->session->operation_save_mode[$target->module->id] = $mode;
308 
309         $eh = $core->events->attach(function(\ICanBoogie\Operation\ProcessEvent $event, \ICanBoogie\SaveOperation $operation) use($mode, $target, &$eh) {
310 
311             $eh->detach();
312 
313             if ($operation != $target || $event->request->uri != $event->response->location)
314             {
315                 return;
316             }
317 
318             $location = '/admin/' . $target->module->id;
319 
320             switch ($mode)
321             {
322                 case OPERATION_SAVE_MODE_CONTINUE:
323                 {
324                     $location .= '/' . $event->rc['key'] . '/edit';
325                 }
326                 break;
327 
328                 case OPERATION_SAVE_MODE_NEW:
329                 {
330                     $location .= '/new';
331                 }
332                 break;
333 
334                 case OPERATION_SAVE_MODE_DISPLAY:
335                 {
336                     try
337                     {
338                         $url = $target->record->url;
339 
340                         if ($url && $url{0} != '#')
341                         {
342                             $location = $url;
343                         }
344                     }
345                     catch (\Exception $e)
346                     {
347                         return;
348                     }
349                 }
350                 break;
351             }
352 
353             if ($mode != OPERATION_SAVE_MODE_DISPLAY)
354             {
355                 $location = \ICanBoogie\Routing\contextualize($location);
356             }
357 
358             $event->response->location = $location;
359 
360         });
361     }
362 
363     static private $page_controller_loaded_nodes = [];
364 
365     /**
366      * Attaches a hook to the `BlueTihi\Context::loaded_nodes` event to provide data for the
367      * admin menu. The data is consumed by {@link on_page_controller_render}.
368      */
369     static public function before_page_controller_render()
370     {
371         global $core;
372 
373         $core->events->attach(function(\BlueTihi\Context\LoadedNodesEvent $event, \BlueTihi\Context $target) {
374 
375             $nodes = &self::$page_controller_loaded_nodes;
376 
377             foreach ($event->nodes as $node)
378             {
379                 if (!$node instanceof \Icybee\Modules\Nodes\Node)
380                 {
381                     \ICanBoogie\log('Not a node object: {0}', [ $node ]);
382 
383                     continue;
384                 }
385 
386                 $nodes[$node->nid] = $node;
387             }
388 
389         });
390     }
391 
392     /**
393      * Adds the AdminMenu to pages rendered by the page controller.
394      *
395      * @param \Icybee\Modules\Pages\PageController\RenderEvent $event
396      * @param \Icybee\Modules\Pages\PageController $target
397      */
398     static public function on_page_controller_render(\Icybee\Modules\Pages\PageController\RenderEvent $event, \Icybee\Modules\Pages\PageController $target)
399     {
400         $admin_menu = (string) new Element\AdminMenu([
401 
402             Element\AdminMenu::NODES => self::$page_controller_loaded_nodes
403 
404         ]);
405 
406         if ($admin_menu)
407         {
408             $event->html = str_replace('</body>', $admin_menu . '</body>', $event->html);
409         }
410     }
411 
412     /*
413      * Prototypes
414      */
415 
416     static public function get_cldr()
417     {
418         static $cldr;
419 
420         if (!$cldr)
421         {
422             $provider = new \ICanBoogie\CLDR\Provider
423             (
424                 new \ICanBoogie\CLDR\RunTimeCache(new \ICanBoogie\CLDR\FileCache(\ICanBoogie\REPOSITORY . 'cldr' . DIRECTORY_SEPARATOR)),
425                 new \ICanBoogie\CLDR\Retriever
426             );
427 
428             $cldr = new \ICanBoogie\CLDR\Repository($provider);
429         }
430 
431         return $cldr;
432     }
433 
434     /*
435      * Markups
436      */
437 
438     /**
439      * Displays the alerts issued during request processing.
440      *
441      * <pre>
442      * <p:alerts>
443      *     <!-- Content: template? -->
444      * </p:alerts>
445      * </pre>
446      *
447      * A marker is placed in the rendered HTML that will later be replaced by the actual alerts.
448      *
449      * The following alerts are displayed: `success`, `info` and `error`. `debug` alert and
450      * displayed if the debug mode is {@link Debug::MODE_DEV}.
451      *
452      * @param array $args
453      * @param mixed $engine
454      * @param mixed $template
455      *
456      * @return string
457      */
458     static public function markup_alerts(array $args, $engine, $template)
459     {
460         global $core;
461 
462         $key = '<!-- alert-markup-placeholder-' . uniqid() . ' -->';
463 
464         $core->events->attach
465         (
466             function(PageController\RenderEvent $event, PageController $target) use($engine, $template, $key)
467             {
468                 $types = array('success', 'info', 'error');
469 
470                 if (Debug::$mode == Debug::MODE_DEV)
471                 {
472                     $types[] = 'debug';
473                 }
474 
475                 $alerts = '';
476 
477                 foreach ($types as $type)
478                 {
479                     $alerts .= new Alert(Debug::fetch_messages($type), array(Alert::CONTEXT => $type));
480                 }
481 
482                 if ($template)
483                 {
484                     $alerts = $engine($template, $alerts);
485                 }
486 
487                 $event->html = str_replace($key, $alerts, $event->html);
488             }
489         );
490 
491         return $key;
492     }
493 
494     /**
495      * The BODY element.
496      *
497      * <pre>
498      * <p:body
499      *     class = string>
500      *     <!-- Content: with-param*, template? -->
501      * </p:body>
502      * </pre>
503      *
504      * The `class` attribute of the element can be specified with the `class` param. It is extended
505      * with the class of the {@link \Icybee\Document} instance.
506      *
507      * @param array $args
508      * @param mixed $engine
509      * @param mixed $template
510      *
511      * @return string
512      */
513     static public function markup_body(array $args, $engine, $template)
514     {
515         global $core;
516 
517         return '<body class="' . trim($args['class'] . ' ' . $core->document->css_class) . '">' . $engine($template) . '</body>';
518     }
519 }
Autodoc API documentation generated by ApiGen 2.8.0