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