]> git.mxchange.org Git - core.git/blob - framework/main/classes/template/xml/class_BaseXmlTemplateEngine.php
Continued:
[core.git] / framework / main / classes / template / xml / class_BaseXmlTemplateEngine.php
1 <?php
2 // Own namespace
3 namespace Org\Mxchange\CoreFramework\Template\Engine\Xml;
4
5 // Import framework stuff
6 use Org\Mxchange\CoreFramework\Bootstrap\FrameworkBootstrap;
7 use Org\Mxchange\CoreFramework\Factory\ObjectFactory;
8 use Org\Mxchange\CoreFramework\Factory\Template\XmlTemplateEngineFactory;
9 use Org\Mxchange\CoreFramework\Registry\GenericRegistry;
10 use Org\Mxchange\CoreFramework\Template\CompileableTemplate;
11 use Org\Mxchange\CoreFramework\Template\Engine\BaseTemplateEngine;
12 use Org\Mxchange\CoreFramework\Traits\Stacker\StackableTrait;
13 use Org\Mxchange\CoreFramework\Utils\String\StringUtils;
14
15 // Import SPL stuff
16 use \InvalidArgumentException;
17
18 /**
19  * A generic XML template engine class
20  *
21  * @author              Roland Haeder <webmaster@shipsimu.org>
22  * @version             0.0.0
23  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2018 Hub Developer Team
24  * @license             GNU GPL 3.0 or any newer version
25  * @link                http://www.shipsimu.org
26  * @todo                This template engine does not make use of setTemplateType()
27  *
28  * This program is free software: you can redistribute it and/or modify
29  * it under the terms of the GNU General Public License as published by
30  * the Free Software Foundation, either version 3 of the License, or
31  * (at your option) any later version.
32  *
33  * This program is distributed in the hope that it will be useful,
34  * but WITHOUT ANY WARRANTY; without even the implied warranty of
35  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
36  * GNU General Public License for more details.
37  *
38  * You should have received a copy of the GNU General Public License
39  * along with this program. If not, see <http://www.gnu.org/licenses/>.
40  */
41 abstract class BaseXmlTemplateEngine extends BaseTemplateEngine {
42         // Load traits
43         use StackableTrait;
44
45         /**
46          * Main nodes in the XML tree
47          */
48         private $mainNodes = [];
49
50         /**
51          * Sub nodes in the XML tree
52          */
53         private $subNodes = [];
54
55         /**
56          * Current main node
57          */
58         private $curr = [];
59
60         /**
61          * XML template type
62          */
63         private $xmlTemplateType = 'xml';
64
65         /**
66          * Type prefix
67          */
68         private $typePrefix = 'xml';
69
70         /**
71          * Name of stacker
72          */
73         private $stackerName = '';
74
75         /**
76          * Content from dependency
77          */
78         protected $dependencyContent = [];
79
80         /**
81          * Template engine instance
82          */
83         private $templateInstance = NULL;
84
85         /**
86          * Protected constructor
87          *
88          * @param       $className      Name of the class
89          * @return      void
90          */
91         protected function __construct (string $className) {
92                 // Call parent constructor
93                 parent::__construct($className);
94         }
95
96         /**
97          * Does a generic initialization of the template engine
98          *
99          * @param       $typePrefix                             Type prefix
100          * @param       $xmlTemplateType                Type of XML template
101          * @return      $templateInstance               An instance of TemplateEngine
102          * @throws      BasePathIsEmptyException                If the provided $templateBasePath is empty
103          * @throws      InvalidBasePathStringException  If $templateBasePath is no string
104          * @throws      BasePathIsNoDirectoryException  If $templateBasePath is no
105          *                                                                                      directory or not found
106          * @throws      BasePathReadProtectedException  If $templateBasePath is
107          *                                                                                      read-protected
108          */
109         protected function initXmlTemplateEngine (string $typePrefix, string $xmlTemplateType) {
110                 // Set XML template type and prefix
111                 $this->xmlTemplateType = $xmlTemplateType;
112                 $this->typePrefix      = $typePrefix;
113
114                 // Get template instance
115                 $applicationInstance = GenericRegistry::getRegistry()->getInstance('application');
116
117                 // Determine base path
118                 $templateBasePath = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('application_base_path') . FrameworkBootstrap::getRequestInstance()->getRequestElement('app') . '/';
119
120                 // Is the base path valid?
121                 if (empty($templateBasePath)) {
122                         // Base path is empty
123                         throw new BasePathIsEmptyException($this, self::EXCEPTION_UNEXPECTED_EMPTY_STRING);
124                 } elseif (!is_string($templateBasePath)) {
125                         // Is not a string
126                         throw new InvalidBasePathStringException(array($this, $templateBasePath), self::EXCEPTION_INVALID_STRING);
127                 } elseif (!is_dir($templateBasePath)) {
128                         // Is not a path
129                         throw new BasePathIsNoDirectoryException(array($this, $templateBasePath), self::EXCEPTION_INVALID_PATH_NAME);
130                 } elseif (!is_readable($templateBasePath)) {
131                         // Is not readable
132                         throw new BasePathReadProtectedException(array($this, $templateBasePath), self::EXCEPTION_READ_PROTECED_PATH);
133                 }
134
135                 // Set the base path
136                 $this->setTemplateBasePath($templateBasePath);
137
138                 // Set template extensions
139                 $this->setRawTemplateExtension(FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('raw_template_extension'));
140                 $this->setCodeTemplateExtension(FrameworkBootstrap::getConfigurationInstance()->getConfigEntry($typePrefix . '_message_template_extension'));
141
142                 // Absolute output path for compiled templates
143                 $this->setCompileOutputPath(sprintf('%s%s',
144                         $templateBasePath,
145                         FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('compile_output_path')
146                 ));
147
148                 // Init a variable stacker
149                 $stackInstance = ObjectFactory::createObjectByConfiguredName($typePrefix . '_' . $xmlTemplateType . '_stacker_class');
150
151                 // Set name
152                 $this->stackerName = $typePrefix . '_' . $xmlTemplateType;
153
154                 // Init stacker
155                 $stackInstance->initStack($this->stackerName);
156
157                 // Set it
158                 $this->setStackInstance($stackInstance);
159
160                 // Set it in main nodes
161                 array_push($this->mainNodes, str_replace('_', '-', $xmlTemplateType));
162         }
163
164         /**
165          * Load a specified XML template into the engine
166          *
167          * @param       $templateName   Optional name of template
168          * @return      void
169          */
170         public function loadXmlTemplate (string $templateName = '') {
171                 // Is the template name empty?
172                 if (empty($templateName)) {
173                         // Set generic template name
174                         $templateName = $this->typePrefix . '_' . $this->xmlTemplateType . '_template_type';
175                 } // END - if
176
177                 // Set template type
178                 $this->setTemplateType(FrameworkBootstrap::getConfigurationInstance()->getConfigEntry($templateName));
179
180                 // Load the special template
181                 $this->loadTemplate($this->xmlTemplateType);
182         }
183
184         /**
185          * Getter for current main node
186          *
187          * @return      $currMainNode   Current main node
188          */
189         public final function getCurrMainNode () {
190                 return $this->curr['main_node'];
191         }
192
193         /**
194          * Setter for current main node
195          *
196          * @param       $element                Element name to set as current main node
197          * @return      $currMainNode   Current main node
198          */
199         private final function setCurrMainNode ($element) {
200                 $this->curr['main_node'] = (string) $element;
201         }
202
203         /**
204          * Getter for main node array
205          *
206          * @return      $mainNodes      Array with valid main node names
207          */
208         public final function getMainNodes () {
209                 return $this->mainNodes;
210         }
211
212         /**
213          * Getter for stacker name
214          *
215          * @return      $stackerName    Name of stacker of this class
216          */
217         protected final function getStackerName () {
218                 return $this->stackerName;
219         }
220
221         /**
222          * Setter for sub node array
223          *
224          * @param       $subNodes       Array with valid sub node names
225          * @return      void
226          */
227         public final function setSubNodes (array $subNodes) {
228                 $this->subNodes = $subNodes;
229         }
230
231         /**
232          * Getter for sub node array
233          *
234          * @return      $subNodes       Array with valid sub node names
235          */
236         public final function getSubNodes () {
237                 return $this->subNodes;
238         }
239
240         /**
241          * Setter for template engine instances
242          *
243          * @param       $templateInstance       An instance of a template engine class
244          * @return      void
245          */
246         protected final function setTemplateInstance (CompileableTemplate $templateInstance) {
247                 $this->templateInstance = $templateInstance;
248         }
249
250         /**
251          * Getter for template engine instances
252          *
253          * @return      $templateInstance       An instance of a template engine class
254          */
255         protected final function getTemplateInstance () {
256                 return $this->templateInstance;
257         }
258
259         /**
260          * Read XML variables by calling readVariable() with 'general' as
261          * variable stack.
262          *
263          * @param       $key    Key to read from
264          * @return      $value  Value from variable
265          */
266         public function readXmlData (string $key) {
267                 // Is key parameter valid?
268                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-XML-TEMPLATE-ENGINE: key=%s - CALLED!', $key));
269                 if (empty($key)) {
270                         // Throw exception
271                         throw new InvalidArgumentException('Parameter key is empty');
272                 }
273
274                 // Read the variable
275                 $value = parent::readVariable($key, 'general');
276
277                 // Is this null?
278                 if (is_null($value)) {
279                         // Bah, needs fixing.
280                         $this->debugInstance(sprintf('[%s:%d]: key=%s returns NULL', __METHOD__, __LINE__, $key));
281                 } // END - if
282
283                 // Return value
284                 return $value;
285         }
286
287         /**
288          * Handles the template dependency for given XML node
289          *
290          * @param       $node                                   The XML node we should load a dependency template
291          * @param       $templateDependency             A template to load to satisfy dependencies
292          * @return      void
293          */
294         protected function handleTemplateDependency ($node, $templateDependency) {
295                 // Check that the XML node is not empty
296                 assert(!empty($node));
297
298                 // Is the template dependency set?
299                 if ((!empty($templateDependency)) && (!isset($this->dependencyContent[$node]))) {
300                         // Get a temporay template instance
301                         $templateInstance = XmlTemplateEngineFactory::createXmlTemplateEngineInstance($this->typePrefix . '_' . self::convertDashesToUnderscores($node) . '_' . $this->xmlTemplateType . '_template_class');
302
303                         // Then load it
304                         $templateInstance->loadXmlTemplate($templateDependency);
305
306                         // Parse the XML content
307                         $templateInstance->renderXmlContent();
308
309                         // Save the parsed raw content in our dependency array
310                         $this->dependencyContent[$node] = $templateInstance->getRawTemplateData();
311                 } // END - if
312         }
313
314         /**
315          * Handles the start element of an XML resource
316          *
317          * @param       $resource               XML parser resource (currently ignored)
318          * @param       $element                The element we shall handle
319          * @param       $attributes             All attributes
320          * @return      void
321          * @throws      InvalidXmlNodeException         If an unknown/invalid XML node name was found
322          */
323         public final function startElement ($resource, $element, array $attributes) {
324                 // Initial method name which will never be called...
325                 $methodName = 'init' . StringUtils::convertToClassName($this->xmlTemplateType);
326
327                 // Make the element name lower-case
328                 $element = strtolower($element);
329
330                 // Is the element a main node?
331                 //* DEBUG: */ echo "START: &gt;".$element."&lt;<br />\n";
332                 if (in_array($element, $this->getMainNodes())) {
333                         // Okay, main node found!
334                         $methodName = 'start' . StringUtils::convertToClassName($element);
335
336                         // Set it
337                         $this->setCurrMainNode($element);
338                 } elseif (in_array($element, $this->getSubNodes())) {
339                         // Sub node found
340                         $methodName = 'start' . StringUtils::convertToClassName($element);
341                 } else {
342                         // Invalid node name found
343                         throw new InvalidXmlNodeException(array($this, $element, $attributes), XmlParser::EXCEPTION_XML_NODE_UNKNOWN);
344                 }
345
346                 // Call method
347                 call_user_func_array(array($this, $methodName), $attributes);
348         }
349
350         /**
351          * Ends the main or sub node by sending out the gathered data
352          *
353          * @param       $resource       An XML resource pointer (currently ignored)
354          * @param       $nodeName       Name of the node we want to finish
355          * @return      void
356          * @throws      XmlNodeMismatchException        If current main node mismatches the closing one
357          */
358         public final function finishElement ($resource, $nodeName) {
359                 // Make all lower-case
360                 $nodeName = strtolower($nodeName);
361
362                 // Does this match with current main node?
363                 //* DEBUG: */ echo "END: &gt;".$nodeName."&lt;<br />\n";
364                 if (($nodeName != $this->getCurrMainNode()) && (in_array($nodeName, $this->getMainNodes()))) {
365                         // Did not match!
366                         throw new XmlNodeMismatchException (array($this, $nodeName, $this->getCurrMainNode()), XmlParser::EXCEPTION_XML_NODE_MISMATCH);
367                 } // END - if
368
369                 // Construct method name
370                 $methodName = 'finish' . StringUtils::convertToClassName($nodeName);
371
372                 // Call the corresponding method
373                 //* DEBUG: */ echo "call: ".$methodName."<br />\n";
374                 call_user_func_array(array($this, $methodName), array());
375         }
376
377 }