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

  • Blueprint
  • BlueprintNode
  • BreadcrumbElement
  • Content
  • ContentModel
  • CopyOperation
  • DeleteOperation
  • EditBlock
  • ExportBlock
  • ExportOperation
  • Hooks
  • ImportOperation
  • LanguagesElement
  • ListView
  • ManageBlock
  • Model
  • Module
  • NavigationBranchElement
  • NavigationElement
  • NavigationExcludeOperation
  • NavigationIncludeOperation
  • Page
  • PageController
  • PopPage
  • PopTemplate
  • QueryOperationOperation
  • SaveOperation
  • TemplateEditorsOperation
  • UpdateTreeOperation
  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\Modules\Pages;
 13 
 14 use ICanBoogie\I18n;
 15 
 16 use Brickrouge\Alert;
 17 use Brickrouge\Element;
 18 use Brickrouge\Form;
 19 use Brickrouge\Text;
 20 
 21 use Icybee\Modules\Nodes\Node;
 22 use Icybee\Modules\Editor\EditorElement;
 23 use Icybee\Modules\Editor\MultiEditorElement;
 24 
 25 class Module extends \Icybee\Modules\Nodes\Module
 26 {
 27     /**
 28      * Only the "list" view is available and it is used to create the sitemap.
 29      */
 30     protected function lazy_get_views()
 31     {
 32         return array
 33         (
 34             'list' => array
 35             (
 36                 'title' => 'Sitemap',
 37                 'class' => __NAMESPACE__ . '\ListView',
 38                 'assets' => array(),
 39                 'renders' => \Icybee\Modules\Views\View::RENDERS_MANY
 40             )
 41         );
 42     }
 43 
 44     // FIXME-20110918: this should be an operation
 45     protected function operation_query_delete(WdOperation $operation)
 46     {
 47         $entries = array();
 48 
 49         foreach ($operation->params['entries'] as $id)
 50         {
 51             $record = $this->model[$id];
 52 
 53             if (!$record)
 54             {
 55                 continue;
 56             }
 57 
 58             $entries = array_merge(self::get_all_children_ids($record), $entries);
 59         }
 60 
 61         $entries = array_unique($entries);
 62 
 63         $operation->params['entries'] = $entries;
 64 
 65         return parent::operation_query_delete($operation);
 66     }
 67 
 68     private function get_all_children_ids($record)
 69     {
 70         $ids = array();
 71 
 72         if ($record->children)
 73         {
 74             // FIXME-20100504: `children` only returns online children !
 75 
 76             foreach ($record->children as $child)
 77             {
 78                 $ids = array_merge(self::get_all_children_ids($child), $ids);
 79             }
 80         }
 81 
 82         $ids[] = $record->nid;
 83 
 84         return $ids;
 85     }
 86 
 87     // FIXME-20110918: this should be an operation
 88     protected function operation_query_copy(WdOperation $operation)
 89     {
 90         $entries = $operation->params['entries'];
 91 
 92         return array
 93         (
 94             'title' => 'Copy entries',
 95             'message' => I18n\t('Are you sure you want to copy the :count selected entries ?', array(':count' => count($entries))),
 96             'confirm' => array('Don\'t copy', 'Copy'),
 97             'params' => array
 98             (
 99                 'entries' => $entries
100             )
101         );
102     }
103 
104     public function get_contents_section($nid, $template=null)
105     {
106         list($template, $template_description, $is_inherited) = $this->resolve_template($nid, $template);
107         list($elements, $hiddens) = $this->get_contents_section_elements($nid, $template);
108 
109         if ($elements)
110         {
111             $template_description .= ' ' . I18n\t("The following elements are editable:");
112         }
113         else
114         {
115             $template_description = I18n\t("The <q>:template</q> template does not define any editable element.", array(':template' => $template));
116         }
117 
118         $elements = array_merge
119         (
120             array
121             (
122                 Page::TEMPLATE => new PopTemplate
123                 (
124                     array
125                     (
126                         Element::GROUP => 'contents',
127                         Element::DESCRIPTION => $template_description
128                     )
129                 )
130             ),
131 
132             $elements
133         );
134 
135         return array
136         (
137             array
138             (
139                 Form::HIDDENS => $hiddens,
140 
141                 #
142                 # If the template is inherited, we remove the value in order to have a clean
143                 # inheritence, easier to manage.
144                 #
145 
146                 Form::VALUES => array
147                 (
148                     Page::TEMPLATE => $is_inherited ? null : $template
149                 ),
150 
151                 Element::GROUPS => array
152                 (
153                     'contents' => array
154                     (
155                         'title' => 'Template',
156                         'weight' => 10
157                     ),
158 
159                     'contents.inherit' => array
160                     (
161                         'weight' => 11,
162                         'description' => 'contents.inherit'
163                     )
164                 ),
165 
166                 Element::CHILDREN => $elements
167             ),
168 
169             array
170             (
171                 'name' => $template,
172                 'description' => $template_description,
173                 'inherited' => $is_inherited
174             )
175         );
176     }
177 
178     protected function get_contents_section_elements($nid, $template)
179     {
180         global $core;
181 
182         $info = self::get_template_info($template);
183 
184         if (!$info)
185         {
186             return array(array(), array());
187         }
188 
189         list($editables, $styles) = $info;
190 
191         $elements = array();
192         $hiddens = array();
193 
194         $contents_model = $this->model('contents');
195         $context = $core->site->path;
196 
197         foreach ($editables as $editable)
198         {
199             $id = $editable['id'];
200             $title = $editable['title'];
201             $title = I18n\t($id, array(), array('scope' => array('content', 'title'), 'default' => $title));
202 
203             $does_inherit = !empty($editable['inherit']);
204 
205             $value = null;
206 
207             $editor_id = $editable['editor'];
208             $editor_config = json_decode($editable['config'], true);
209             $editor_description = $editable['description'];
210 
211             #
212             #
213             #
214 
215             $contents = $nid ? $contents_model->where('pageid = ? AND contentid = ?', $nid, $id)->one : null;
216 
217             if ($contents)
218             {
219                 $value = $contents->content;
220 
221                 if (!$editor_id)
222                 {
223                     $editor_id = $contents->editor;
224                 }
225             }
226 
227             if ($does_inherit)
228             {
229                 if (!$contents && $nid)
230                 {
231                     $inherited = null;
232                     $node = $this->model[$nid];
233 
234                     while ($node)
235                     {
236                         $node_contents = $node->contents;
237 
238                         if (isset($node_contents[$id]))
239                         {
240                             $inherited = $node;
241 
242                             break;
243                         }
244 
245                         $node = $node->parent;
246                     }
247 
248                     if (!$node)
249                     {
250                         $node = $core->site->home;
251 
252                         if (isset($node->contents[$id]))
253                         {
254                             $inherited = $node;
255                         }
256                     }
257 
258                     // TODO-20101214: check home page
259 
260                     if ($inherited)
261                     {
262                         $elements[] = new Element
263                         (
264                             'div', array
265                             (
266                                 Form::LABEL => $title,
267                                 Element::GROUP => 'contents.inherit',
268                                 Element::INNER_HTML => '',
269                                 Element::DESCRIPTION => I18n\t
270                                 (
271                                     'This content is currently inherited from the <q><a href="!url">!title</a></q> parent page. <a href="#edit" class="btn">Edit the content</a>', array
272                                     (
273                                         '!url' => $context . '/admin/' . $this->id . '/' . $inherited->nid . '/edit',
274                                         '!title' => $inherited->title
275                                     )
276                                 ),
277 
278                                 \Brickrouge\Section::T_PANEL_CLASS => 'inherit-toggle'
279                             )
280                         );
281                     }
282                     else
283                     {
284                         $editor_description .= I18n\t('No parent page define this content.');
285                     }
286                 }
287             }
288 
289             /*
290              * each editor as a base name `contents[<editable_id>]` and much at least define two
291              * values :
292              *
293              * - `contents[<editable_id>][editor]`: The editor used to edit the contents
294              * - `contents[<editable_id>][contents]`: The content being edited.
295              *
296              */
297 
298             if (isset($editable['editor']))
299             {
300                 if (!isset($core->editors[$editor_id]))
301                 {
302                     $elements["contents[$id]"] = new Alert
303                     (
304                         I18n\t('Éditeur inconnu : %editor', array('%editor' => $editable['editor'])), array
305                         (
306                             Form::LABEL => $title,
307                             Element::GROUP => $does_inherit ? 'contents.inherit' : 'contents',
308                             Alert::CONTEXT => Alert::CONTEXT_ERROR
309                         )
310                     );
311 
312                     continue;
313                 }
314 
315                 $editor = $core->editors[$editor_id];
316 
317                 $elements["contents[$id]"] = $editor->from
318                 (
319                     array
320                     (
321                         Form::LABEL => $title,
322 
323                         EditorElement::STYLESHEETS => $styles,
324                         EditorElement::CONFIG => $editor_config,
325 
326                         Element::GROUP => $does_inherit ? 'contents.inherit' : 'contents',
327                         Element::DESCRIPTION => $editor_description,
328 
329                         'id' => 'editor-' . $id,
330                         'value' => $editor->unserialize($value)
331                     )
332                 );
333 
334                 #
335                 # we add the editor's id as a hidden field
336                 #
337 
338                 $hiddens["editors[$id]"] = $editable['editor'];
339             }
340             else
341             {
342                 $elements["contents[$id]"] = new MultiEditorElement
343                 (
344                     $editor_id, array
345                     (
346                         Form::LABEL => $title,
347 
348                         MultiEditorElement::NOT_SWAPPABLE => isset($editable['editor']),
349                         MultiEditorElement::SELECTOR_NAME => "editors[$id]",
350                         MultiEditorElement::EDITOR_TAGS => array
351                         (
352                             EditorElement::STYLESHEETS => $styles,
353                             EditorElement::CONFIG => $editor_config
354                         ),
355 
356                         Element::GROUP => $does_inherit ? 'contents.inherit' : 'contents',
357                         Element::DESCRIPTION => $editor_description,
358 
359                         'id' => 'editor-' . $id,
360                         'value' => $editor_id ? $core->editors[$editor_id]->unserialize($value) : $value
361                     )
362                 );
363             }
364         }
365 
366         return array($elements, $hiddens);
367     }
368 
369     /**
370      * Returns the template to use for a specified page.
371      *
372      * @param int $nid
373      *
374      * @return array An array composed of the template name, the description and a boolean
375      * representing wheter or not the template is inherited for the specified page.
376      */
377     protected function resolve_template($nid, $request_template=null)
378     {
379         global $core;
380 
381         $inherited = false;
382         $is_alone = !$this->model->select('nid')->filter_by_siteid($core->site_id)->rc;
383 
384         if ($is_alone)
385         {
386             $template = 'home.html';
387         }
388 
389         $description = I18n\t("The template defines a page model of which some elements are editable.");
390 
391         if (!$nid)
392         {
393             if ($is_alone)
394             {
395                 $description .= " Parce que la page est seule elle utilise le gabarit <q>home.html</q>.";
396             }
397             else if (!$request_template)
398             {
399                 $template = 'page.html';
400             }
401             else
402             {
403                 $template = $request_template;
404             }
405 
406             return array($template, $description, $template == 'page.html');
407         }
408 
409         $record = $this->model[$nid];
410         $definer = null;
411         $template = $request_template !== null ? $request_template : $record->template;
412 
413 //      \ICanBoogie\log('template: \1 (requested: \3), is_home: \2', array($template, $record->is_home, $request_template));
414 
415         if ($template == 'page.html' && (!$record->parent || ($record->parent && $record->parent->is_home)))
416         {
417 //          \ICanBoogie\log('page parent is home, hence the page.html template');
418 
419             $inherited = true;
420 
421             // TODO-20100507: à réviser, parce que la page peut ne pas avoir de parent.
422 
423             $description .= ' ' . "Parce qu'aucun gabarit n'est défini pour la page, elle utilise
424             le gabarit <q>page.html</q>.";
425         }
426         else if ($template == 'home.html' && (!$record->parent && $record->weight == 0))
427         {
428             $inherited = true;
429 
430             //$template_description .= ' ' . "Cette page utilise le gabarit &laquo;&nbsp;home.html&nbsp;&raquo;.";
431         }
432         else if (!$request_template)
433         {
434             $definer = $record->parent;
435 
436             if (!$definer)
437             {
438                 $template = 'page.html';
439                 $inherited = true;
440 
441                 $description .= ' ' . "Parce qu'aucun gabarit n'est défini pour la page, elle utilise
442                 le gabarit <q>page.html</q>.";
443             }
444         }
445         else
446         {
447             $definer = $record;
448             $parent = $record->parent;
449 
450 //          \ICanBoogie\log('parent: \1 (\2 ?= \3)', array($definer->title, $definer->template, $template));
451 
452             while ($parent)
453             {
454 //              \ICanBoogie\log('parent: \1, template: \2', array($parent->title, $parent->template));
455 
456                 if ($parent->template == $request_template)
457                 {
458                     break;
459                 }
460 
461                 $parent = $parent->parent;
462             }
463 
464 //          \ICanBoogie\log('end parent: \1', array($parent ? $parent->title : 'none'));
465 
466             if ($parent && $parent->template == $request_template)
467             {
468                 $definer = $parent;
469             }
470 
471 //          \ICanBoogie\log('definer: \1:\3 (\2), record: \4:\5', array($definer->title,  $definer->template, $definer->nid, $record->title, $record->nid));
472         }
473 
474         if ($definer && $definer != $record)
475         {
476 //          \ICanBoogie\log("entry template: $template ($record->nid), from: $inherited->template ($inherited->nid: $inherited->title)");
477 
478             $description .= ' ' . I18n\t
479             (
480                 'This page uses the <q>:template</q> template, inherited from the parent page <q><a href="!url">!title</a></q>.', array
481                 (
482                     'template' => $template,
483                     'url' => \ICanBoogie\Routing\contextualize("/admin/{$this->id}/{$definer->nid}/edit"),
484                     'title' => $definer->title
485                 )
486             );
487 
488             $inherited = true;
489         }
490 
491         return array($template, $description, $inherited);
492     }
493 
494     static public function get_template_info($name)
495     {
496         global $core;
497 
498         $site = $core->site;
499         $path = $site->resolve_path('templates/' . $name);
500 
501         if (!$path)
502         {
503             \ICanBoogie\log_error('Uknown template file %name', array('%name' => $name));
504 
505             return array();
506         }
507 
508         $html = file_get_contents(\ICanBoogie\DOCUMENT_ROOT . $path);
509         $parser = new \Patron\HTMLParser();
510 
511         return self::get_template_info_callback($html, $parser);
512     }
513 
514     static protected function get_template_info_callback($html, $parser)
515     {
516         $styles = array();
517         $contents = array();
518 
519         #
520         # search css files
521         #
522 
523         preg_match_all('#<link.*type="text/css".*>#', $html, $matches);
524 
525         foreach ($matches[0] as $match)
526         {
527             preg_match_all('#(\S+)="([^"]+)"#', $match, $attributes_matches, PREG_SET_ORDER);
528 
529             $attributes = array();
530 
531             foreach ($attributes_matches as $attribute_match)
532             {
533                 list(, $attribute, $value) = $attribute_match;
534 
535                 $attributes[$attribute] = $value;
536             }
537 
538             if (isset($attributes['media']) && $attributes['media'] != 'screen')
539             {
540                 continue;
541             }
542 
543             $styles[] = $attributes['href'];
544         }
545 
546         #
547         #
548         #
549 
550         $tree = $parser->parse($html, \Patron\Engine::PREFIX);
551 
552         //\ICanBoogie\log('tree: \1', array($tree));
553 
554         #
555         # contents
556         #
557 
558         $contents_collection = \Patron\HTMLParser::collectMarkup($tree, 'page:content');
559 
560 //      \ICanBoogie\log('contents collection: \1', array($contents_collection));
561 
562         foreach ($contents_collection as $node)
563         {
564             if (isset($node['children']))
565             {
566                 foreach ($node['children'] as $child)
567                 {
568                     if (!is_array($child))
569                     {
570                         continue;
571                     }
572 
573                     if ($child['name'] != 'with-param')
574                     {
575                         continue;
576                     }
577 
578                     $param = $child['args']['name'];
579 
580                     // TODO: what about arrays ? we should create a tree to string function
581 
582                     $value = '';
583 
584                     foreach ($child['children'] as $cv)
585                     {
586                         $value .= $cv;
587                     }
588 
589                     $node['args'][$param] = $value;
590                 }
591             }
592 
593 //          \ICanBoogie\log('found content: \1', array($node));
594 
595             $contents[] = $node['args'] + array
596             (
597                 'editor' => null,
598                 'config' => null,
599                 'description' => null
600             );
601         }
602 
603         #
604         # recurse on templates
605         #
606 
607         global $core;
608 
609         $site = $core->site;
610         $root = $_SERVER['DOCUMENT_ROOT'];
611 
612         $call_template_collection = \Patron\HTMLParser::collectMarkup($tree, 'call-template');
613 
614         foreach ($call_template_collection as $node)
615         {
616             $template_name = $node['args']['name'];
617 
618             $file = $template_name . '.html';
619             $path = $site->resolve_path('templates/partials/' . $file);
620 
621             if (!$path)
622             {
623                 \ICanBoogie\log_error('Partial template %name not found', array('%name' => $file));
624 
625                 continue;
626             }
627 
628             $template = file_get_contents($root . $path);
629 
630             list($partial_contents, $partial_styles) = self::get_template_info_callback($template, $parser);
631 
632             $contents = array_merge($contents, $partial_contents);
633 
634             if ($partial_styles)
635             {
636                 $styles = array_merge($styles, $partial_styles);
637             }
638         }
639 
640         return array($contents, $styles);
641     }
642 }
Autodoc API documentation generated by ApiGen 2.8.0