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