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