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