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

  • CloudElement
  • DeleteBlock
  • DeleteOperation
  • EditBlock
  • Hooks
  • ManageBlock
  • Model
  • Module
  • OrderOperation
  • SaveOperation
  • Vocabulary
  1 <?php
  2 
  3 namespace Icybee\Modules\Taxonomy\Vocabulary;
  4 
  5 use ICanBoogie\Event;
  6 use ICanBoogie\I18n;
  7 
  8 use Brickrouge\Element;
  9 use Brickrouge\Form;
 10 use Brickrouge\Text;
 11 
 12 use Icybee\Modules\Views\ActiveRecordProvider;
 13 use Icybee\Modules\Views\Collection as ViewsCollection;
 14 use Icybee\Modules\Views\Provider;
 15 
 16 class Hooks
 17 {
 18     static private $cache_vocabularies = array();
 19     static private $cache_record_terms = array();
 20     static private $cache_record_properties = array();
 21 
 22     static public function get_term(\ICanBoogie\Object\PropertyEvent $event, \Icybee\Modules\Nodes\Node $target)
 23     {
 24         global $core;
 25 
 26         $property = $event->property;
 27         $cache_record_properties_key = spl_object_hash($target) . '_' . $property;
 28 
 29         if (isset(self::$cache_record_properties[$cache_record_properties_key]))
 30         {
 31             $event->value = self::$cache_record_properties[$cache_record_properties_key];
 32             $event->stop();
 33 
 34             return;
 35         }
 36 
 37         $constructor = $target->constructor;
 38         $siteid = $target->siteid;
 39         $nid = $target->nid;
 40 
 41         $use_slug = false;
 42         $vocabularyslug = $property;
 43 
 44         if (substr($property, -4, 4) === 'slug')
 45         {
 46             $use_slug = true;
 47             $vocabularyslug = substr($property, 0, -4);
 48         }
 49 
 50         $cache_key = $siteid . '>' . $constructor . '>' . $vocabularyslug;
 51         $cache_record_terms_key = $cache_key . '>' . $nid;
 52 
 53         if (!isset(self::$cache_record_terms[$cache_record_terms_key]))
 54         {
 55             #
 56             # vocabulary for this constructor on this website
 57             #
 58 
 59             if (!isset(self::$cache_vocabularies[$cache_key]))
 60             {
 61                 self::$cache_vocabularies[$cache_key] = $core->models['taxonomy.vocabulary']
 62                 ->joins(':taxonomy.vocabulary/scopes')
 63                 ->where('siteid = 0 OR siteid = ?', $target->siteid)
 64                 ->filter_by_constructor((string) $constructor)
 65                 ->filter_by_vocabularyslug($vocabularyslug)
 66                 ->order('siteid DESC')
 67                 ->one;
 68             }
 69 
 70             $vocabulary = self::$cache_vocabularies[$cache_key];
 71 
 72             if (!$vocabulary)
 73             {
 74                 return;
 75             }
 76 
 77             if ($vocabulary->is_required)
 78             {
 79                 $event->value = 'uncategorized';
 80             }
 81 
 82             $terms = $vocabulary->terms;
 83             $rc = null;
 84 
 85             if ($vocabulary->is_multiple || $vocabulary->is_tags)
 86             {
 87                 foreach ($terms as $term)
 88                 {
 89                     if (empty($term->nodes_keys[$nid]))
 90                     {
 91                         continue;
 92                     }
 93 
 94                     $rc[] = $term;
 95                 }
 96             }
 97             else
 98             {
 99                 foreach ($terms as $term)
100                 {
101                     if (empty($term->nodes_keys[$nid]))
102                     {
103                         continue;
104                     }
105 
106                     $rc = $term;
107 
108                     break;
109                 }
110             }
111 
112             self::$cache_record_terms[$cache_record_terms_key] = $rc === null ? false : $rc;
113         }
114 
115         $rc = self::$cache_record_terms[$cache_record_terms_key];
116 
117         if ($rc === false)
118         {
119             return;
120         }
121 
122         if ($use_slug)
123         {
124             if (is_array($rc))
125             {
126                 $terms = $rc;
127                 $rc = array();
128 
129                 foreach ($terms as $term)
130                 {
131                     $rc[] = $term->termslug;
132                 }
133             }
134             else
135             {
136                 $rc = $rc->termslug;
137             }
138         }
139 
140         self::$cache_record_properties[$cache_record_properties_key] = $rc;
141 
142         /*
143         $cache = &self::$cache_record_properties;
144 
145         #
146         # now that we have the value for the property we can set a prototype method to provide the
147         # value without the events overhead.
148         #
149 
150         $target->prototype['get_' . $property] = function(\Icybee\Modules\Nodes\Node $target) use($property, &$cache)
151         {
152             $cache_record_properties_key = spl_object_hash($target) . '_' . $property;
153 
154             var_dump($cache);
155 
156             return $cache[$cache_record_properties_key];
157         };
158         */
159 
160         $target->$property = $rc;
161 
162         $event->value = $rc;
163         $event->stop();
164     }
165 
166     static public function on_nodes_editblock_alter_children(Event $event, \Icybee\Modules\Nodes\EditBlock $block)
167     {
168         global $core;
169 
170         $document = $core->document;
171 
172         $document->css->add(DIR . 'public/support.css');
173         $document->js->add(DIR . 'public/support.js');
174 
175         $vocabularies = $core->models['taxonomy.vocabulary']
176         ->joins('INNER JOIN {self}__scopes USING(vid)')
177         ->where('constructor = ? AND (siteid = 0 OR siteid = ?)', (string) $event->module, $core->site_id)
178         ->order('weight')
179         ->all;
180 
181         // TODO-20101104: use Brickrouge\Form::VALUES instead of setting the 'values' of the elements.
182         // -> because 'properties' are ignored, and that's bad.
183 
184         $terms_model = $core->models['taxonomy.terms'];
185         $nodes_model = $core->models['taxonomy.terms/nodes'];
186 
187         $nid = $event->key;
188         $identifier_base = 'vocabulary[vid]';
189         $children = &$event->children;
190 
191         foreach ($vocabularies as $vocabulary)
192         {
193             $vid = $vocabulary->vid;;
194 
195             $identifier = $identifier_base . '[' . $vid . ']';
196 
197             if ($vocabulary->is_multiple)
198             {
199                 $options = $terms_model->select('term, count(nid)')
200                 ->joins('inner join {self}__nodes using(vtid)')
201                 ->filter_by_vid($vid)
202                 ->group('term')->order('term')->pairs;
203 
204                 $value = $nodes_model->select('term')
205                 ->filter_by_vid_and_nid($vid, $nid)
206                 ->order('term')
207                 ->all(\PDO::FETCH_COLUMN);
208                 $value = implode(', ', $value);
209 
210                 $label = $vocabulary->vocabulary;
211 
212                 $children[] = new Element
213                 (
214                     'div', array
215                     (
216                         Form::LABEL => $label,
217 
218                         Element::GROUP => 'organize',
219                         Element::WEIGHT => 100,
220 
221                         Element::CHILDREN => array
222                         (
223                             new Text
224                             (
225                                 array
226                                 (
227                                     'value' => $value,
228                                     'name' => $identifier
229                                 )
230                             ),
231 
232                             new CloudElement
233                             (
234                                 'ul', array
235                                 (
236                                     Element::OPTIONS => $options,
237                                     'class' => 'cloud'
238                                 )
239                             )
240                         ),
241 
242                         'class' => 'taxonomy-tags widget-bordered'
243                     )
244                 );
245             }
246             else
247             {
248                 $options = $terms_model->select('term.vtid, term')->filter_by_vid($vid)->order('term')->pairs;
249 
250                 if (!$options)
251                 {
252                     //continue;
253                 }
254 
255                 $value = $nodes_model->select('term_node.vtid')->filter_by_vid_and_nid($vid, $nid)->order('term')->rc;
256 
257                 $edit_url = $core->site->path . '/admin/taxonomy.vocabulary/' . $vocabulary->vid . '/edit';
258 
259                 $children[$identifier] = new Element
260                 (
261                     'select', array
262                     (
263                         Form::LABEL => $vocabulary->vocabulary,
264                         Element::GROUP => 'organize',
265                         Element::OPTIONS => array(null => '') + $options,
266                         Element::REQUIRED => $vocabulary->is_required,
267                         Element::INLINE_HELP => '<a href="' . $edit_url . '">' . I18n\t('Edit the vocabulary <q>!vocabulary</q>', array('!vocabulary' => $vocabulary->vocabulary)) . '</a>.',
268 
269                         'value' => $value
270                     )
271                 );
272             }
273         }
274 
275         // FIXME: There is no class to create a _tags_ element. They are created using a collection
276         // of objects in a div, so the key is a numeric, not an identifier.
277 
278         $event->attributes[Element::GROUPS]['organize'] = array
279         (
280             'title' => 'Organization',
281             'weight' => 500
282         );
283     }
284 
285     static public function on_node_save(\ICanBoogie\Operation\ProcessEvent $event, \Icybee\Modules\Nodes\SaveOperation $target)
286     {
287         global $core;
288 
289         $name = 'vocabulary';
290         $request = $event->request;
291         $vocabularies = $request[$name];
292 
293         if (!$vocabularies)
294         {
295             return;
296         }
297 
298         $nid = $event->rc['key'];
299         $vocabularies = $vocabularies['vid'];
300 
301         #
302         # on supprime toutes les liaisons pour cette node
303         #
304 
305         $vocabulary_model = $core->models['taxonomy.vocabulary'];
306         $terms_model = $core->models['taxonomy.terms'];
307         $nodes_model = $core->models['taxonomy.terms/nodes'];
308 
309         $nodes_model->where('nid = ?', $nid)->delete();
310 
311         #
312         # on crée maintenant les nouvelles liaisons
313         #
314 
315         foreach ($vocabularies as $vid => $values)
316         {
317             if (!$values)
318             {
319                 continue;
320             }
321 
322             $vocabulary = $vocabulary_model[$vid];
323 
324             if ($vocabulary->is_tags)
325             {
326                 #
327                 # because tags are provided as a string with coma separated terms,
328                 # we need to get/created terms id before we can update the links between
329                 # terms and nodes
330                 #
331 
332                 $terms = explode(',', $values);
333                 $terms = array_map('trim', $terms);
334 
335                 $values = array();
336 
337                 foreach ($terms as $term)
338                 {
339                     $vtid = $terms_model->select('vtid')->where('vid = ? and term = ?', $vid, $term)->rc;
340 
341                     // FIXME-20090127: only users with 'create tags' permissions should be allowed to create tags
342 
343                     if (!$vtid)
344                     {
345                         $vtid = $terms_model->save
346                         (
347                             array
348                             (
349                                 'vid' => $vid,
350                                 'term' => $term
351                             )
352                         );
353                     }
354 
355                     $values[] = $vtid;
356                 }
357             }
358 
359             foreach ((array) $values as $vtid)
360             {
361                 $nodes_model->insert
362                 (
363                     array
364                     (
365                         'vtid' => $vtid,
366                         'nid' => $nid
367                     ),
368 
369                     array
370                     (
371                         'ignore' => true
372                     )
373                 );
374             }
375         }
376     }
377 
378     static public function on_collect_views(ViewsCollection\CollectEvent $event, ViewsCollection $target)
379     {
380         global $core;
381 
382         $vocabulary = $core->models['taxonomy.vocabulary']->all;
383         $collection = &$event->collection;
384 
385         foreach ($vocabulary as $v)
386         {
387             $scope = $v->scope;
388             $vocabulary_name = $v->vocabulary;
389             $vocabulary_slug = $v->vocabularyslug;
390 
391             foreach ($scope as $constructor)
392             {
393                 $view_home = $constructor . '/home';
394                 $view_home = isset($collection[$view_home]) ? $collection[$view_home] : null;
395 
396                 $view_list = $constructor . '/list';
397                 $view_list = isset($collection[$view_list]) ? $collection[$view_list] : null;
398 
399                 if ($view_home)
400                 {
401                     $collection["$constructor/vocabulary/$vocabulary_slug/vocabulary-home"] = array
402                     (
403                         'title' => 'Home for vocabulary %name',
404                         'title args' => array('name' => $v->vocabulary),
405                         'taxonomy vocabulary' => $v
406                     )
407 
408                     + $view_home;
409                 }
410 
411                 if ($view_list)
412                 {
413                     $collection["$constructor/vocabulary/$vocabulary_slug/list"] = array
414                     (
415                         'title' => 'Records list, in vocabulary %vocabulary and a term',
416                         'title args' => array('vocabulary' => $vocabulary_name),
417                         'taxonomy vocabulary' => $v
418                     )
419 
420                     + $view_list;
421                 }
422 
423                 foreach ($v->terms as $term)
424                 {
425                     $term_name = $term->term;
426                     $term_slug = $term->termslug;
427 
428                     if ($view_home)
429                     {
430                         $collection["$constructor/vocabulary/$vocabulary_slug/$term_slug/home"] = array
431                         (
432                             'title' => 'Records home, in vocabulary %vocabulary and term %term',
433                             'title args' => array('vocabulary' => $vocabulary_name, 'term' => $term_name),
434                             'taxonomy vocabulary' => $v,
435                             'taxonomy term' => $term,
436                         )
437 
438                         + $view_home;
439                     }
440 
441                     if ($view_list)
442                     {
443                         $collection["$constructor/vocabulary/$vocabulary_slug/$term_slug/list"] = array
444                         (
445                             'title' => 'Records list, in vocabulary %vocabulary and term %term',
446                             'title args' => array('vocabulary' => $vocabulary_name, 'term' => $term_name),
447                             'taxonomy vocabulary' => $v,
448                             'taxonomy term' => $term
449                         )
450 
451                         + $view_list;
452                     }
453                 }
454             }
455         }
456     }
457 
458     static public function on_alter_provider_query(\Icybee\Modules\Views\ActiveRecordProvider\AlterQueryEvent $event, \Icybee\Modules\Views\ActiveRecordProvider $provider)
459     {
460         global $core;
461 
462 //      var_dump($event->view);
463 
464         $options = $event->view->options;
465 
466         if (isset($options['taxonomy vocabulary']) && isset($options['taxonomy term']))
467         {
468             return self::for_vocabulary_and_term($event, $provider, $options, $options['taxonomy vocabulary'], $options['taxonomy term']);
469         }
470 
471         if (empty($event->view->options['taxonomy vocabulary']))
472         {
473             return;
474         }
475 
476         $vocabulary = $event->view->options['taxonomy vocabulary'];
477         $condition = $vocabulary->vocabularyslug . 'slug';
478 
479         #
480         # FIXME-20121226: It has to be known that the conditions is `<vocabularyslug>slug`.
481         #
482         # is condition is required by "in vocabulary and a term", but we don't check that, which
483         # can cause problems when the pattern of the page is incorrect e.g. "tagslug" instead of
484         # "tagsslug"
485         #
486 
487         if (empty($event->conditions[$condition]))
488         {
489             # show all by category ?
490 
491             $event->view->range['limit'] = null; // cancel limit TODO-20120403: this should be improved.
492 
493             $core->events->attach(array(__CLASS__, 'on_alter_provider_result'));
494 
495             return;
496         }
497 
498         $condition_value = $event->conditions[$condition];
499 
500         $term = $core->models['taxonomy.terms']->where('vid = ? AND termslug = ?', array($vocabulary->vid, $condition_value))->order('term.weight')->one;
501 
502         $core->events->attach(function(ActiveRecordProvider\AlterContextEvent $event, ActiveRecordProvider $target) use($term) {
503 
504             $event->context['term'] = $term;
505 
506         });
507 
508         $event->query->where('nid IN (SELECT nid FROM {prefix}taxonomy_terms
509         INNER JOIN {prefix}taxonomy_terms__nodes USING(vtid) WHERE vtid = ?)', $term ? $term->vtid : 0);
510 
511         #
512 
513         global $core;
514 
515         $page = isset($core->request->context->page) ? $core->request->context->page : null;
516 
517         if ($page && $term)
518         {
519             $page->title = \ICanBoogie\format($page->title, array(':term' => $term->term));
520         }
521     }
522 
523     static public function on_alter_provider_result(\Icybee\Modules\Views\ActiveRecordProvider\AlterResultEvent $event, \Icybee\Modules\Views\ActiveRecordProvider $provider)
524     {
525         global $core;
526 
527         $vocabulary = $event->view->options['taxonomy vocabulary'];
528 
529         $ids = '';
530         $records_by_id = array();
531 
532         foreach ($event->result as $record)
533         {
534             if (!($record instanceof \Icybee\Modules\Nodes\Node))
535             {
536                 /*
537                  * we return them as [ term: [], nodes: []]
538                  *
539                  * check double event ?
540                  *
541                  * http://demo.icybee.localhost/articles/category/
542                  *
543                 trigger_error(\ICanBoogie\format('Expected instance of <q>Icybee\Modules\Nodes\Node</q> given: \1', array($record)));
544 
545                 var_dump($event); exit;
546                 */
547 
548                 continue;
549             }
550 
551             $nid = $record->nid;
552             $ids .= ',' . $nid;
553             $records_by_id[$nid] = $record;
554         }
555 
556         if (!$ids)
557         {
558             return;
559         }
560 
561         $ids = substr($ids, 1);
562 
563         /*
564         $ids_by_names = $core->models['taxonomy.terms/nodes']
565         ->joins(':nodes')
566         ->select('term, nid')
567         ->order('term.weight, term.term')
568         ->where('vid = ? AND nid IN(' . $ids . ')', $vocabulary->vid)
569         ->all(\PDO::FETCH_GROUP | \PDO::FETCH_COLUMN);
570 
571         var_dump($ids_by_names);
572 
573         $result = array();
574 
575         foreach ($ids_by_names as $name => $ids)
576         {
577             $ids = array_flip($ids);
578 
579             foreach ($event->result as $record)
580             {
581                 if (isset($ids[$record->nid]))
582                 {
583                     $result[$name][] = $record;
584                 }
585             }
586         }
587 
588         $event->result = $result;
589         */
590 
591         $ids_by_vtid = $core->models['taxonomy.terms/nodes']
592         ->joins(':nodes')
593         ->select('vtid, nid')
594         ->order('term.weight, term.term')
595         ->where('vid = ? AND nid IN(' . $ids . ')', $vocabulary->vid)
596         ->all(\PDO::FETCH_GROUP | \PDO::FETCH_COLUMN);
597 
598         $terms = $core->models['taxonomy.terms']->find(array_keys($ids_by_vtid));
599 
600         $result = array();
601 
602         foreach ($ids_by_vtid as $vtid => $ids)
603         {
604             $result[$vtid]['term'] = $terms[$vtid];
605             $result[$vtid]['nodes'] = array_intersect_key($records_by_id, array_combine($ids, $ids));
606         }
607 
608         $event->result = $result;
609     }
610 
611     static private function for_vocabulary_and_term(Event $event, Provider $provider, $options, \Icybee\Modules\Taxonomy\Vocabulary\Vocabulary $vocabulary, \Icybee\Modules\Taxonomy\Terms\Term $term)
612     {
613         $event->query->where('nid IN (SELECT nid FROM {prefix}taxonomy_terms
614         INNER JOIN {prefix}taxonomy_terms__nodes USING(vtid) WHERE vtid = ?)', $term ? $term->vtid : 0);
615 
616 
617 
618         /*
619         $core->events->attach
620         (
621             'Icybee\Modules\Pages\Page::render_title', function()
622             {
623                 var_dump(func_get_args());
624             }
625         );
626         */
627     }
628 
629     static public function before_breadcrumb_render_inner_html(\Icybee\Modules\Pages\BreadcrumbElement\BeforeRenderInnerHTMLEvent $event, \Icybee\Modules\Pages\BreadcrumbElement $target)
630     {
631         foreach ($event->slices as &$slice)
632         {
633             if (strpos($slice['label'], ':term') === false || empty($event->page->node)) continue;
634 
635             $slice['label'] = \ICanBoogie\format($slice['label'], array('term' => (string) $event->page->node->category));
636         }
637     }
638 }
Autodoc API documentation generated by ApiGen 2.8.0