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