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