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