Renamed Registry -> GenericRegistry to make it clear that this registry does
[core.git] / framework / main / classes / template / menu / class_MenuTemplateEngine.php
1 <?php
2 // Own namespace
3 namespace Org\Mxchange\CoreFramework\Template\Engine;
4
5 // Import framework stuff
6 use Org\Mxchange\CoreFramework\Factory\ObjectFactory;
7 use Org\Mxchange\CoreFramework\Filesystem\InvalidDirectoryException;
8 use Org\Mxchange\CoreFramework\Parser\Xml\XmlParser;
9 use Org\Mxchange\CoreFramework\Registry\GenericRegistry;
10 use Org\Mxchange\CoreFramework\Template\CompileableTemplate;
11 use Org\Mxchange\CoreFramework\Template\Engine\BaseTemplateEngine;
12
13 // Import SPL stuff
14 use \SplFileInfo;
15 use \UnexpectedValueException;
16
17 /**
18  * A Menu template engine class
19  *
20  * @author              Roland Haeder <webmaster@shipsimu.org>
21  * @version             0.0.0
22  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Core Developer Team
23  * @license             GNU GPL 3.0 or any newer version
24  * @link                http://www.shipsimu.org
25  *
26  * This program is free software: you can redistribute it and/or modify
27  * it under the terms of the GNU General Public License as published by
28  * the Free Software Foundation, either version 3 of the License, or
29  * (at your option) any later version.
30  *
31  * This program is distributed in the hope that it will be useful,
32  * but WITHOUT ANY WARRANTY; without even the implied warranty of
33  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
34  * GNU General Public License for more details.
35  *
36  * You should have received a copy of the GNU General Public License
37  * along with this program. If not, see <http://www.gnu.org/licenses/>.
38  */
39 class MenuTemplateEngine extends BaseTemplateEngine implements CompileableTemplate {
40         /**
41          * Main nodes in the XML tree ('menu' is ignored)
42          */
43         private $mainNodes = array(
44                 'block-list',
45         );
46
47         /**
48          * Sub nodes in the XML tree
49          */
50         private $subNodes = array(
51                 'entry-list',
52                 'entry',
53                 'entry-id',
54                 'entries-content',
55                 'block-header',
56                 'block-footer',
57                 'footer-id',
58                 'footer-class',
59                 'footer-text',
60                 'block',
61                 'title',
62                 'title-id',
63                 'title-class',
64                 'title-text',
65                 'design',
66                 'text',
67                 'advert',
68                 'anchor',
69                 'anchor-id',
70                 'anchor-text',
71                 'anchor-title',
72                 'anchor-href',
73         );
74
75         /**
76          * Variables for a menu entry
77          */
78         private $menuEntryVariables = array(
79                 // List entry
80                 'entry_id',
81                 // Anchor
82                 'anchor-id',
83                 'anchor-text',
84                 'anchor-title',
85                 'anchor-href',
86         );
87
88         /**
89          * Variables for a menu block
90          */
91         private $menuBlockVariables = array(
92                 // Title
93                 'title_id',
94                 'title_class',
95                 'title_text',
96                 // Content is taken from menuEntries
97                 // Footer
98                 'footer_id',
99                 'footer_class',
100                 'footer_text',
101         );
102
103         /**
104          * Rendered menu entries
105          */
106         private $menuEntries = array();
107
108         /**
109          * Rendered menu blocks
110          */
111         private $menuBlocks = array();
112
113         /**
114          * Menu instance
115          */
116         private $menuInstance = NULL;
117
118         /**
119          * Current main node
120          */
121         private $curr = array();
122
123         /**
124          * Content from dependency
125          */
126         private $dependencyContent = array();
127
128         /**
129          * Protected constructor
130          *
131          * @return      void
132          */
133         protected function __construct () {
134                 // Call parent constructor
135                 parent::__construct(__CLASS__);
136         }
137
138         /**
139          * Creates an instance of the class TemplateEngine and prepares it for usage
140          *
141          * @param       $menuInstance                   A RenderableMenu instance
142          * @return      $templateInstance               An instance of TemplateEngine
143          * @throws      UnexpectedValueException                If the found $templateBasePath is empty or not a string
144          * @throws      InvalidDirectoryException       If $templateBasePath is no directory or not found
145          * @throws      BasePathReadProtectedException  If $templateBasePath is
146          *                                                                                      read-protected
147          */
148         public static final function createMenuTemplateEngine (RenderableMenu $menuInstance) {
149                 // Get a new instance
150                 $templateInstance = new MenuTemplateEngine();
151
152                 // Get the application instance from registry
153                 $applicationInstance = GenericRegistry::getRegistry()->getInstance('app');
154
155                 // Determine base path
156                 $templateBasePath = $templateInstance->getConfigInstance()->getConfigEntry('application_base_path') . $applicationInstance->getAppShortName(). '/';
157
158                 // Is the base path valid?
159                 if (empty($templateBasePath)) {
160                         // Base path is empty
161                         throw new UnexpectedValueException(sprintf('[%s:%d] Variable templateBasePath is empty.', $templateInstance->__toString(), __LINE__), self::EXCEPTION_UNEXPECTED_EMPTY_STRING);
162                 } elseif (!is_string($templateBasePath)) {
163                         // Is not a string
164                         throw new UnexpectedValueException(sprintf('[%s:%d] %s is not a string with a base path.', $templateInstance->__toString(), __LINE__, $templateBasePath), self::EXCEPTION_INVALID_STRING);
165                 } elseif (!is_dir($templateBasePath)) {
166                         // Is not a path
167                         throw new InvalidDirectoryException(array($templateInstance, $templateBasePath), self::EXCEPTION_INVALID_PATH_NAME);
168                 } elseif (!is_readable($templateBasePath)) {
169                         // Is not readable
170                         throw new BasePathReadProtectedException(array($templateInstance, $templateBasePath), self::EXCEPTION_READ_PROTECED_PATH);
171                 }
172
173                 // Set the base path
174                 $templateInstance->setTemplateBasePath($templateBasePath);
175
176                 // Set template extensions
177                 $templateInstance->setRawTemplateExtension($templateInstance->getConfigInstance()->getConfigEntry('raw_template_extension'));
178                 $templateInstance->setCodeTemplateExtension($templateInstance->getConfigInstance()->getConfigEntry('menu_template_extension'));
179
180                 // Absolute output path for compiled templates
181                 $templateInstance->setCompileOutputPath(sprintf('%s%s/',
182                         $templateBasePath,
183                         $templateInstance->getConfigInstance()->getConfigEntry('compile_output_path')
184                 ));
185
186                 // Set the menu instance
187                 $templateInstance->setMenuInstance($menuInstance);
188
189                 // Init a variable stacker
190                 $stackInstance = ObjectFactory::createObjectByConfiguredName('menu_stacker_class');
191
192                 // Set it
193                 $templateInstance->setStackInstance($stackInstance);
194
195                 // Return the prepared instance
196                 return $templateInstance;
197         }
198
199         /**
200          * Load a specified menu template into the engine
201          *
202          * @param       $template       The menu template we shall load which is
203          *                                              located in 'menu' by default
204          * @return      void
205          */
206         public function loadMenuTemplate ($template) {
207                 // Set template type
208                 $this->setTemplateType($this->getConfigInstance()->getConfigEntry('menu_template_type'));
209
210                 // Load the special template
211                 $this->loadTemplate($template);
212         }
213
214         /**
215          * Getter for current main node
216          *
217          * @return      $currMainNode   Current main node
218          */
219         public final function getCurrMainNode () {
220                 return $this->curr['main_node'];
221         }
222
223         /**
224          * Setter for current main node
225          *
226          * @param       $element                Element name to set as current main node
227          * @return      $currMainNode   Current main node
228          */
229         private final function setCurrMainNode ($element) {
230                 $this->curr['main_node'] = (string) $element;
231         }
232
233         /**
234          * Getter for main node array
235          *
236          * @return      $mainNodes      Array with valid main node names
237          */
238         public final function getMainNodes () {
239                 return $this->mainNodes;
240         }
241
242         /**
243          * Getter for sub node array
244          *
245          * @return      $subNodes       Array with valid sub node names
246          */
247         public final function getSubNodes () {
248                 return $this->subNodes;
249         }
250
251         /**
252          * Handles the start element of an XML resource
253          *
254          * @param       $resource               XML parser resource (currently ignored)
255          * @param       $element                The element we shall handle
256          * @param       $attributes             All attributes
257          * @return      void
258          * @throws      InvalidXmlNodeException         If an unknown/invalid XML node name was found
259          */
260         public function startElement ($resource, $element, array $attributes) {
261                 // Initial method name which will never be called...
262                 $methodName = 'initMenu';
263
264                 // Make the element name lower-case
265                 $element = strtolower($element);
266
267                 // Is the element a main node?
268                 //* DEBUG: */ echo "START: &gt;".$element."&lt;<br />\n";
269                 if (in_array($element, $this->getMainNodes())) {
270                         // Okay, main node found!
271                         $methodName = 'start' . self::convertToClassName($element);
272
273                         // Set it
274                         $this->setCurrMainNode($element);
275                 } elseif (in_array($element, $this->getSubNodes())) {
276                         // Sub node found
277                         $methodName = 'start' . self::convertToClassName($element);
278                 } elseif ($element != 'menu') {
279                         // Invalid node name found
280                         throw new InvalidXmlNodeException(array($this, $element, $attributes), XmlParser::EXCEPTION_XML_NODE_UNKNOWN);
281                 }
282
283                 // Call method
284                 //* DEBUG: */ echo "call: ".$methodName."<br />\n";
285                 call_user_func_array(array($this, $methodName), $attributes);
286         }
287
288         /**
289          * Ends the main or sub node by sending out the gathered data
290          *
291          * @param       $resource       An XML resource pointer (currently ignored)
292          * @param       $nodeName       Name of the node we want to finish
293          * @return      void
294          * @throws      XmlNodeMismatchException        If current main node mismatches the closing one
295          */
296         public function finishElement ($resource, $nodeName) {
297                 // Make all lower-case
298                 $nodeName = strtolower($nodeName);
299
300                 // Does this match with current main node?
301                 //* DEBUG: */ echo "END: &gt;".$nodeName."&lt;<br />\n";
302                 if (($nodeName != $this->getCurrMainNode()) && (in_array($nodeName, $this->getMainNodes()))) {
303                         // Did not match!
304                         throw new XmlNodeMismatchException (array($this, $nodeName, $this->getCurrMainNode()), XmlParser::EXCEPTION_XML_NODE_MISMATCH);
305                 } // END - if
306
307                 // Construct method name
308                 $methodName = 'finish' . self::convertToClassName($nodeName);
309
310                 // Call the corresponding method
311                 //* DEBUG: */ echo "call: ".$methodName."<br />\n";
312                 call_user_func_array(array($this, $methodName), array());
313         }
314
315         /**
316          * Currently not used
317          *
318          * @param       $resource               XML parser resource (currently ignored)
319          * @param       $characters             Characters to handle
320          * @return      void
321          * @todo        Find something useful with this!
322          */
323         public function characterHandler ($resource, $characters) {
324                 // Trim all spaces away
325                 $characters = trim($characters);
326
327                 // Is this string empty?
328                 if (empty($characters)) {
329                         // Then skip it silently
330                         return;
331                 } // END - if
332
333                 // Assign the found characters to variable and use the last entry from
334                 // stack as the name
335                 parent::assignVariable($this->getStackInstance()->getNamed('current_node'), $characters);
336         }
337
338         /**
339          * Handles the template dependency for given node
340          *
341          * @param       $node                                   The node we should load a dependency template
342          * @param       $templateDependency             A template to load to satisfy dependencies
343          * @return      void
344          */
345         private function handleTemplateDependency ($node, $templateDependency) {
346                 // Is the template dependency set?
347                 if ((!empty($templateDependency)) && (!isset($this->dependencyContent[$node]))) {
348                         // Get a temporay menu template instance
349                         $templateInstance = ObjectFactory::createObjectByConfiguredName('menu_template_class', array($this->getMenuInstance()));
350
351                         // Then load it
352                         $templateInstance->loadMenuTemplate($templateDependency);
353
354                         // Parse the XML content
355                         $templateInstance->renderXmlContent();
356
357                         // Save the parsed raw content in our dependency array
358                         $this->dependencyContent[$node] = $templateInstance->getRawTemplateData();
359                 } // END - if
360         }
361
362         /**
363          * Intializes the menu
364          *
365          * @param       $templateDependency             A template to load to satisfy dependencies
366          * @return      void
367          * @todo        Add cache creation here
368          */
369         private function initMenu ($templateDependency = '') {
370                 // Get web template engine
371                 $this->setTemplateInstance(ObjectFactory::createObjectByConfiguredName('html_template_class', array(Registry::getRegistry()->getInstance('app'))));
372
373                 // Handle the dependency template
374                 $this->handleTemplateDependency('menu', $templateDependency);
375
376                 // Push the node name on the stacker
377                 $this->getStackInstance()->pushNamed('current_node', 'menu');
378         }
379
380         /**
381          * Starts the menu entries
382          *
383          * @param       $templateDependency             A template to load to satisfy dependencies
384          * @return      void
385          */
386         private function startEntryList () {
387                 // Push the node name on the stacker
388                 $this->getStackInstance()->pushNamed('current_node', 'entry-list');
389         }
390
391         /**
392          * Starts the menu block header
393          *
394          * @return      void
395          */
396         private function startBlockHeader () {
397                 // Push the node name on the stacker
398                 $this->getStackInstance()->pushNamed('current_node', 'block-header');
399         }
400
401         /**
402          * Starts the menu block footer
403          *
404          * @return      void
405          */
406         private function startBlockFooter () {
407                 // Push the node name on the stacker
408                 $this->getStackInstance()->pushNamed('current_node', 'block-footer');
409         }
410
411         /**
412          * Starts the menu property 'block-list'
413          *
414          * @return      void
415          */
416         private function startBlockList () {
417                 // Push the node name on the stacker
418                 $this->getStackInstance()->pushNamed('current_node', 'block-list');
419         }
420
421         /**
422          * Starts the menu property 'block'
423          *
424          * @return      void
425          */
426         private function startBlock () {
427                 // Push the node name on the stacker
428                 $this->getStackInstance()->pushNamed('current_node', 'block');
429         }
430
431         /**
432          * Starts the menu property 'title'
433          *
434          * @return      void
435          */
436         private function startTitle () {
437                 // Push the node name on the stacker
438                 $this->getStackInstance()->pushNamed('current_node', 'title');
439         }
440
441         /**
442          * Starts the menu property 'title-id'
443          *
444          * @return      void
445          */
446         private function startTitleId () {
447                 // Push the node name on the stacker
448                 $this->getStackInstance()->pushNamed('current_node', 'title-id');
449         }
450
451         /**
452          * Starts the menu property 'title-class'
453          *
454          * @return      void
455          */
456         private function startTitleClass () {
457                 // Push the node name on the stacker
458                 $this->getStackInstance()->pushNamed('current_node', 'title-class');
459         }
460
461         /**
462          * Starts the menu property 'title-text'
463          *
464          * @return      void
465          */
466         private function startTitleText () {
467                 // Push the node name on the stacker
468                 $this->getStackInstance()->pushNamed('current_node', 'title-text');
469         }
470
471         /**
472          * Starts the menu property 'entry'
473          *
474          * @return      void
475          */
476         private function startEntry () {
477                 // Push the node name on the stacker
478                 $this->getStackInstance()->pushNamed('current_node', 'entry');
479         }
480
481         /**
482          * Starts the menu property 'entry-id'
483          *
484          * @return      void
485          */
486         private function startEntryId () {
487                 // Push the node name on the stacker
488                 $this->getStackInstance()->pushNamed('current_node', 'entry-id');
489         }
490
491         /**
492          * Starts the menu property 'anchor'
493          *
494          * @return      void
495          */
496         private function startAnchor () {
497                 // Push the node name on the stacker
498                 $this->getStackInstance()->pushNamed('current_node', 'anchor');
499         }
500
501         /**
502          * Starts the menu property 'anchor-id'
503          *
504          * @return      void
505          */
506         private function startAnchorId () {
507                 // Push the node name on the stacker
508                 $this->getStackInstance()->pushNamed('current_node', 'anchor-id');
509         }
510
511         /**
512          * Starts the menu property 'anchor-text'
513          *
514          * @return      void
515          */
516         private function startAnchorText () {
517                 // Push the node name on the stacker
518                 $this->getStackInstance()->pushNamed('current_node', 'anchor-text');
519         }
520
521         /**
522          * Starts the menu property 'anchor-title'
523          *
524          * @return      void
525          */
526         private function startAnchorTitle () {
527                 // Push the node name on the stacker
528                 $this->getStackInstance()->pushNamed('current_node', 'anchor-title');
529         }
530
531         /**
532          * Starts the menu property 'anchor-href'
533          *
534          * @return      void
535          */
536         private function startAnchorHref () {
537                 // Push the node name on the stacker
538                 $this->getStackInstance()->pushNamed('current_node', 'anchor-href');
539         }
540
541         /**
542          * Starts the menu property 'footer-id'
543          *
544          * @return      void
545          */
546         private function startFooterId () {
547                 // Push the node name on the stacker
548                 $this->getStackInstance()->pushNamed('current_node', 'footer-id');
549         }
550
551         /**
552          * Starts the menu property 'footer-class'
553          *
554          * @return      void
555          */
556         private function startFooterClass () {
557                 // Push the node name on the stacker
558                 $this->getStackInstance()->pushNamed('current_node', 'footer-class');
559         }
560
561         /**
562          * Starts the menu property 'footer-text'
563          *
564          * @return      void
565          */
566         private function startFooterText () {
567                 // Push the node name on the stacker
568                 $this->getStackInstance()->pushNamed('current_node', 'footer-text');
569         }
570
571         /**
572          * Finishes the title node by added another template to the menu
573          *
574          * @return      void
575          */
576         private function finishTitle () {
577                 // Pop the last entry
578                 $this->getStackInstance()->popNamed('current_node');
579         }
580
581         /**
582          * Finishes the title-id node by
583          *
584          * @return      void
585          */
586         private function finishTitleId () {
587                 // Pop the last entry
588                 $this->getStackInstance()->popNamed('current_node');
589         }
590
591         /**
592          * Finishes the title-class node
593          *
594          * @return      void
595          */
596         private function finishTitleClass () {
597                 // Pop the last entry
598                 $this->getStackInstance()->popNamed('current_node');
599         }
600
601         /**
602          * Finishes the title-class node
603          *
604          * @return      void
605          */
606         private function finishTitleText () {
607                 // Pop the last entry
608                 $this->getStackInstance()->popNamed('current_node');
609         }
610
611         /**
612          * Finishes the footer-text node
613          *
614          * @return      void
615          */
616         private function finishFooterText () {
617                 // Pop the last entry
618                 $this->getStackInstance()->popNamed('current_node');
619         }
620
621         /**
622          * Finishes the footer-class node
623          *
624          * @return      void
625          */
626         private function finishFooterClass () {
627                 // Pop the last entry
628                 $this->getStackInstance()->popNamed('current_node');
629         }
630
631         /**
632          * Finishes the footer-id node
633          *
634          * @return      void
635          */
636         private function finishFooterId () {
637                 // Pop the last entry
638                 $this->getStackInstance()->popNamed('current_node');
639         }
640
641         /**
642          * Finishes the anchor-href node
643          *
644          * @return      void
645          */
646         private function finishAnchorHref () {
647                 // Pop the last entry
648                 $this->getStackInstance()->popNamed('current_node');
649         }
650
651         /**
652          * Finishes the anchor-title node
653          *
654          * @return      void
655          */
656         private function finishAnchorTitle () {
657                 // Pop the last entry
658                 $this->getStackInstance()->popNamed('current_node');
659         }
660
661         /**
662          * Finishes the anchor-text node
663          *
664          * @return      void
665          */
666         private function finishAnchorText () {
667                 // Pop the last entry
668                 $this->getStackInstance()->popNamed('current_node');
669         }
670
671         /**
672          * Finishes the anchor-id node
673          *
674          * @return      void
675          */
676         private function finishAnchorId () {
677                 // Pop the last entry
678                 $this->getStackInstance()->popNamed('current_node');
679         }
680
681         /**
682          * Finishes the anchor node
683          *
684          * @return      void
685          */
686         private function finishAnchor () {
687                 // Pop the last entry
688                 $this->getStackInstance()->popNamed('current_node');
689         }
690
691         /**
692          * Finishes the entry-id node
693          *
694          * @return      void
695          */
696         private function finishEntryId () {
697                 // Pop the last entry
698                 $this->getStackInstance()->popNamed('current_node');
699         }
700
701         /**
702          * Finishes the entry node
703          *
704          * @return      void
705          */
706         private function finishEntry () {
707                 // Pop the last entry
708                 $this->getStackInstance()->popNamed('current_node');
709
710                 // Render this menu entry
711                 $this->renderMenuEntry();
712         }
713
714         /**
715          * Finishes the block node
716          *
717          * @return      void
718          */
719         private function finishBlock () {
720                 // Pop the last entry
721                 $this->getStackInstance()->popNamed('current_node');
722
723                 // Render this menu block
724                 $this->renderMenuBlock();
725         }
726
727         /**
728          * Finishes the block-list node
729          *
730          * @return      void
731          */
732         private function finishBlockList () {
733                 // Pop the last entry
734                 $this->getStackInstance()->popNamed('current_node');
735         }
736
737         /**
738          * Finishes the menu entries
739          *
740          * @return      void
741          */
742         private function finishEntryList () {
743                 // Pop the last entry
744                 $this->getStackInstance()->popNamed('current_node');
745         }
746
747         /**
748          * Finishes the menu block header
749          *
750          * @return      void
751          */
752         private function finishBlockHeader () {
753                 // Pop the last entry
754                 $this->getStackInstance()->popNamed('current_node');
755         }
756
757         /**
758          * Finishes the menu block footer
759          *
760          * @return      void
761          */
762         private function finishBlockFooter () {
763                 // Pop the last entry
764                 $this->getStackInstance()->popNamed('current_node');
765         }
766
767         /**
768          * Finishes the menu
769          *
770          * @return      void
771          */
772         private function finishMenu () {
773                 // Pop the last entry
774                 $this->getStackInstance()->popNamed('current_node');
775         }
776
777         /**
778          * Renders this menu entry, as every block all variables got overwritten
779          * with data from next entry.
780          *
781          * @return      void
782          */
783         private function renderMenuEntry () {
784                 // Prepare template engine
785                 $templateInstance = $this->prepareTemplateInstance();
786
787                 // Load menu entry template
788                 $templateInstance->loadCodeTemplate('menu_entry');
789
790                 // Copy all variables over to it
791                 foreach ($this->menuEntryVariables as $variableName) {
792                         // Copy variable
793                         $variableValue = $this->readVariable($variableName);
794
795                         // Is the key 'anchor-href'?
796                         if ($variableName == 'anchor-href') {
797                                 // Expand variable with URL then
798                                 $variableValue = '{?base_url?}/' . $variableValue;
799                         } // END - if
800
801                         // ... into the instance
802                         $templateInstance->assignVariable($variableName, $variableValue);
803                 } // END - foreach
804
805                 // Compile template + variables
806                 $templateInstance->compileTemplate();
807                 $templateInstance->compileVariables();
808
809                 // Remember it here
810                 $this->menuEntries[$this->readVariable('entry_id')] = $templateInstance->getRawTemplateData();
811         }
812
813         /**
814          * Renders this menu block, as next block all data is overwritten with
815          * next block.
816          *
817          * @return      void
818          */
819         private function renderMenuBlock () {
820                 // Init block content
821                 $blockContent = implode('', $this->menuEntries);
822
823                 // Prepare template engine
824                 $templateInstance = $this->prepareTemplateInstance();
825
826                 // Load menu entry template
827                 $templateInstance->loadCodeTemplate('menu_block');
828
829                 // Copy all variables over to it
830                 foreach ($this->menuBlockVariables as $variableName) {
831                         // Copy variable
832                         $variableValue = $this->readVariable($variableName);
833
834                         // ... into the instance
835                         $templateInstance->assignVariable($variableName, $variableValue);
836                 } // END - foreach
837
838                 // Assign block content
839                 $templateInstance->assignVariable('block_content', $blockContent);
840
841                 // Compile template + variables
842                 $templateInstance->compileTemplate();
843                 $templateInstance->compileVariables();
844
845                 // Remember it here
846                 array_push($this->menuBlocks, $templateInstance->getRawTemplateData());
847
848                 // Reset rendered menu entries array
849                 $this->menuEntries = array();
850         }
851
852         /**
853          * "Getter" for menu content
854          *
855          * @return      $menuContent    Returned menu content
856          */
857         public function getMenuContent () {
858                 // Implode menuBlocks
859                 $menuContent = implode('', $this->menuBlocks);
860
861                 // Clean variable
862                 $this->menuBlocks = array();
863
864                 // And return it
865                 return $menuContent;
866         }
867
868         /**
869          * Getter for menu cache file instance
870          *
871          * @return      $fileInstance   Full-qualified file name of the menu cache
872          */
873         public function getMenuCacheFile () {
874                 // Get the application instance from registry
875                 $applicationInstance = GenericRegistry::getRegistry()->getInstance('app');
876
877                 // Get the file instance ready
878                 $fileInstance = new SplFileInfo(sprintf('%s%smenus/_cache/%s.%s',
879                         $this->getConfigInstance()->getConfigEntry('application_base_path'),
880                         $applicationInstance->getAppShortName(),
881                         md5(
882                                 $this->getMenuInstance()->getMenuName() . ':' .
883                                 $this->__toString() . ':' .
884                                 $this->getMenuInstance()->__toString()
885                         ),
886                         $this->getMenuInstance()->getMenuType()
887                 ));
888
889                 // Return it
890                 return $fileInstance;
891         }
892
893 }