Continued:
[core.git] / framework / main / classes / template / image / class_ImageTemplateEngine.php
1 <?php
2 // Own namespace
3 namespace Org\Mxchange\CoreFramework\Template\Engine;
4
5 // Import framework stuff
6 use Org\Mxchange\CoreFramework\Factory\ObjectFactory;
7 use Org\Mxchange\CoreFramework\Filesystem\InvalidDirectoryException;
8 use Org\Mxchange\CoreFramework\Parser\Xml\XmlParser;
9 use Org\Mxchange\CoreFramework\Registry\GenericRegistry;
10 use Org\Mxchange\CoreFramework\Response\Responseable;
11 use Org\Mxchange\CoreFramework\Template\CompileableTemplate;
12 use Org\Mxchange\CoreFramework\Template\Engine\BaseTemplateEngine;
13
14 // Import SPL stuff
15 use \SplFileInfo;
16 use \UnexpectedValueException;
17
18 /**
19  * The own template engine for loading caching and sending out images
20  *
21  * @author              Roland Haeder <webmaster@shipsimu.org>
22  * @version             0.0.0
23  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2019 Core Developer Team
24  * @license             GNU GPL 3.0 or any newer version
25  * @link                http://www.shipsimu.org
26  *
27  * This program is free software: you can redistribute it and/or modify
28  * it under the terms of the GNU General Public License as published by
29  * the Free Software Foundation, either version 3 of the License, or
30  * (at your option) any later version.
31  *
32  * This program is distributed in the hope that it will be useful,
33  * but WITHOUT ANY WARRANTY; without even the implied warranty of
34  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
35  * GNU General Public License for more details.
36  *
37  * You should have received a copy of the GNU General Public License
38  * along with this program. If not, see <http://www.gnu.org/licenses/>.
39  */
40 class ImageTemplateEngine extends BaseTemplateEngine implements CompileableTemplate {
41         /**
42          * Main nodes in the XML tree ('image' is ignored)
43          */
44         private $mainNodes = array(
45                 'base',
46                 'type',
47                 'resolution',
48                 'background-color',
49                 'foreground-color',
50                 'image-string'
51         );
52
53         /**
54          * Sub nodes in the XML tree
55          */
56         private $subNodes = array(
57                 'name',
58                 'string-name',
59                 'x',
60                 'y',
61                 'font-size',
62                 'width',
63                 'height',
64                 'red',
65                 'green',
66                 'blue',
67                 'text'
68         );
69
70         /**
71          * Current main node
72          */
73         private $currMainNode = '';
74
75         /**
76          * Protected constructor
77          *
78          * @return      void
79          */
80         protected function __construct () {
81                 // Call parent constructor
82                 parent::__construct(__CLASS__);
83         }
84
85         /**
86          * Creates an instance of the class TemplateEngine and prepares it for usage
87          *
88          * @return      $templateInstance               An instance of TemplateEngine
89          * @throws      UnexpectedValueException                If the provided $templateBasePath is empty or no string
90          * @throws      InvalidDirectoryException       If $templateBasePath is no
91          *                                                                                      directory or not found
92          * @throws      BasePathReadProtectedException  If $templateBasePath is
93          *                                                                                      read-protected
94          */
95         public static final function createImageTemplateEngine () {
96                 // Get a new instance
97                 $templateInstance = new ImageTemplateEngine();
98
99                 // Get the application instance from registry
100                 $applicationInstance = GenericRegistry::getRegistry()->getInstance('application');
101
102                 // Determine base path
103                 $templateBasePath = $templateInstance->getConfigInstance()->getConfigEntry('application_base_path') . $applicationInstance->getAppShortName(). '/';
104
105                 // Is the base path valid?
106                 if (empty($templateBasePath)) {
107                         // Base path is empty
108                         throw new UnexpectedValueException(sprintf('[%s:%d] Variable templateBasePath is empty.', $templateInstance->__toString(), __LINE__), self::EXCEPTION_UNEXPECTED_EMPTY_STRING);
109                 } elseif (!is_string($templateBasePath)) {
110                         // Is not a string
111                         throw new UnexpectedValueException(sprintf('[%s:%d] %s is not a string with a base path.', $templateInstance->__toString(), __LINE__, $templateBasePath), self::EXCEPTION_INVALID_STRING);
112                 } elseif (!is_dir($templateBasePath)) {
113                         // Is not a path
114                         throw new InvalidDirectoryException(array($templateInstance, $templateBasePath), self::EXCEPTION_INVALID_PATH_NAME);
115                 } elseif (!is_readable($templateBasePath)) {
116                         // Is not readable
117                         throw new BasePathReadProtectedException(array($templateInstance, $templateBasePath), self::EXCEPTION_READ_PROTECED_PATH);
118                 }
119
120                 // Set the base path
121                 $templateInstance->setTemplateBasePath($templateBasePath);
122
123                 // Set template extensions
124                 $templateInstance->setRawTemplateExtension($templateInstance->getConfigInstance()->getConfigEntry('raw_template_extension'));
125                 $templateInstance->setCodeTemplateExtension($templateInstance->getConfigInstance()->getConfigEntry('code_template_extension'));
126
127                 // Absolute output path for compiled templates
128                 $templateInstance->setCompileOutputPath(sprintf('%s%s/',
129                         $templateBasePath,
130                         $templateInstance->getConfigInstance()->getConfigEntry('compile_output_path')
131                 ));
132
133                 // Return the prepared instance
134                 return $templateInstance;
135         }
136
137         /**
138          * Getter for current main node
139          *
140          * @return      $currMainNode   Current main node
141          */
142         public final function getCurrMainNode () {
143                 return $this->currMainNode;
144         }
145
146         /**
147          * Getter for main node array
148          *
149          * @return      $mainNodes      Array with valid main node names
150          */
151         public final function getMainNodes () {
152                 return $this->mainNodes;
153         }
154
155         /**
156          * Getter for sub node array
157          *
158          * @return      $subNodes       Array with valid sub node names
159          */
160         public final function getSubNodes () {
161                 return $this->subNodes;
162         }
163
164         /**
165          * Handles the start element of an XML resource
166          *
167          * @param       $resource               XML parser resource (currently ignored)
168          * @param       $element                The element we shall handle
169          * @param       $attributes             All attributes
170          * @return      void
171          * @throws      InvalidXmlNodeException         If an unknown/invalid XML node name was found
172          */
173         public function startElement ($resource, $element, array $attributes) {
174                 // Initial method name which will never be called...
175                 $methodName = 'initImage';
176
177                 // Make the element name lower-case
178                 $element = strtolower($element);
179
180                 // Is the element a main node?
181                 //* DEBUG: */ echo "START: &gt;".$element."&lt;<br />\n";
182                 if (in_array($element, $this->mainNodes)) {
183                         // Okay, main node found!
184                         $methodName = 'setImage' . self::convertToClassName($element);
185                 } elseif (in_array($element, $this->subNodes)) {
186                         // Sub node found
187                         $methodName = 'setImageProperty' . self::convertToClassName($element);
188                 } elseif ($element != 'image') {
189                         // Invalid node name found
190                         throw new InvalidXmlNodeException(array($this, $element, $attributes), XmlParser::EXCEPTION_XML_NODE_UNKNOWN);
191                 }
192
193                 // Call method
194                 //* DEBUG: */ echo "call: ".$methodName."<br />\n";
195                 call_user_func_array(array($this, $methodName), $attributes);
196         }
197
198         /**
199          * Ends the main or sub node by sending out the gathered data
200          *
201          * @param       $resource       An XML resource pointer (currently ignored)
202          * @param       $nodeName       Name of the node we want to finish
203          * @return      void
204          * @throws      XmlNodeMismatchException        If current main node mismatches the closing one
205          */
206         public function finishElement ($resource, $nodeName) {
207                 // Make all lower-case
208                 $nodeName = strtolower($nodeName);
209
210                 // Does this match with current main node?
211                 //* DEBUG: */ echo "END: &gt;".$nodeName."&lt;<br />\n";
212                 if (($nodeName != $this->getCurrMainNode()) && (in_array($nodeName, $this->getMainNodes()))) {
213                         // Did not match!
214                         throw new XmlNodeMismatchException (array($this, $nodeName, $this->getCurrMainNode()), XmlParser::EXCEPTION_XML_NODE_MISMATCH);
215                 } elseif (in_array($nodeName, $this->getSubNodes())) {
216                         // Silently ignore sub nodes
217                         return;
218                 }
219
220                 // Construct method name
221                 $methodName = 'finish' . self::convertToClassName($nodeName);
222
223                 // Call the corresponding method
224                 call_user_func_array(array($this->getImageInstance(), $methodName), array());
225         }
226
227         /**
228          * Currently not used
229          *
230          * @param       $resource               XML parser resource (currently ignored)
231          * @param       $characters             Characters to handle
232          * @return      void
233          * @todo        Find something usefull with this!
234          */
235         public function characterHandler ($resource, $characters) {
236                 // Trim all spaces away
237                 $characters = trim($characters);
238
239                 // Is this string empty?
240                 if (empty($characters)) {
241                         // Then skip it silently
242                         return;
243                 } // END - if
244
245                 // Unfinished work!
246                 $this->partialStub('Handling extra characters is not yet supported!');
247         }
248
249         /**
250          * Intializes the image
251          *
252          * @return      void
253          * @todo        Add cache creation here
254          */
255         private function initImage () {
256                 // Unfinished work!
257         }
258
259         /**
260          * Set the image type
261          *
262          * @param       $imageType      Code fragment or direct value holding the image type
263          * @return      void
264          */
265         private function setImageType ($imageType) {
266                 // Set group to general
267                 $this->setVariableGroup('general');
268
269                 // Try to compile it first to get the value from variable stack
270                 $imageType = $this->compileRawCode($imageType);
271
272                 // Now make a class name of it
273                 $className = self::convertToClassName($imageType.'_image');
274
275                 // And try to initiate it
276                 $this->setImageInstance(ObjectFactory::createObjectByName($className, array($this)));
277
278                 // Set current main node to type
279                 $this->currMainNode = 'type';
280         }
281
282         /**
283          * "Setter" for resolution, we first need to collect the resolution from the
284          * sub-nodes. So first, this method will prepare an array for it
285          *
286          * @return      void
287          */
288         private function setImageResolution () {
289                 // Call the image class
290                 $this->getImageInstance()->initResolution();
291
292                 // Current main node is resolution
293                 $this->currMainNode = 'resolution';
294         }
295
296         /**
297          * "Setter" for base information. For more details see above method!
298          *
299          * @return      void
300          * @see         ImageTemplateEngine::setImageResolution
301          */
302         private function setImageBase () {
303                 // Call the image class
304                 $this->getImageInstance()->initBase();
305
306                 // Current main node is resolution
307                 $this->currMainNode = 'base';
308         }
309
310         /**
311          * "Setter" for background-color. For more details see above method!
312          *
313          * @return      void
314          * @see         ImageTemplateEngine::setImageResolution
315          */
316         private function setImageBackgroundColor () {
317                 // Call the image class
318                 $this->getImageInstance()->initBackgroundColor();
319
320                 // Current main node is background-color
321                 $this->currMainNode = 'background-color';
322         }
323
324         /**
325          * "Setter" for foreground-color. For more details see above method!
326          *
327          * @return      void
328          * @see         ImageTemplateEngine::setImageResolution
329          */
330         private function setImageForegroundColor () {
331                 // Call the image class
332                 $this->getImageInstance()->initForegroundColor();
333
334                 // Current main node is foreground-color
335                 $this->currMainNode = 'foreground-color';
336         }
337
338         /**
339          * "Setter" for image-string. For more details see above method!
340          *
341          * @param       $groupable      Whether this image string is groupable
342          * @return      void
343          * @see         ImageTemplateEngine::setImageResolution
344          */
345         private function setImageImageString ($groupable = 'single') {
346                 // Call the image class
347                 $this->getImageInstance()->initImageString($groupable);
348
349                 // Current main node is foreground-color
350                 $this->currMainNode = 'image-string';
351         }
352
353         /**
354          * Setter for image name
355          *
356          * @param       $imageName      Name of the image
357          * @return      void
358          */
359         private function setImagePropertyName ($imageName) {
360                 // Call the image class
361                 $this->getImageInstance()->setImageName($imageName);
362         }
363
364         /**
365          * Setter for image width
366          *
367          * @param       $width  Width of the image or variable
368          * @return      void
369          */
370         private function setImagePropertyWidth ($width) {
371                 // Call the image class
372                 $this->getImageInstance()->setWidth($width);
373         }
374
375         /**
376          * Setter for image height
377          *
378          * @param       $height Height of the image or variable
379          * @return      void
380          */
381         private function setImagePropertyHeight ($height) {
382                 // Call the image class
383                 $this->getImageInstance()->setHeight($height);
384         }
385
386         /**
387          * Setter for image red color
388          *
389          * @param       $red    Red color value
390          * @return      void
391          */
392         private function setImagePropertyRed ($red) {
393                 // Call the image class
394                 $this->getImageInstance()->setRed($red);
395         }
396
397         /**
398          * Setter for image green color
399          *
400          * @param       $green  Green color value
401          * @return      void
402          */
403         private function setImagePropertyGreen ($green) {
404                 // Call the image class
405                 $this->getImageInstance()->setGreen($green);
406         }
407
408         /**
409          * Setter for image blue color
410          *
411          * @param       $blue   Blue color value
412          * @return      void
413          */
414         private function setImagePropertyBlue ($blue) {
415                 // Call the image class
416                 $this->getImageInstance()->setBlue($blue);
417         }
418
419         /**
420          * Setter for string name (identifier)
421          *
422          * @param       $stringName             String name (identifier)
423          * @return      void
424          */
425         private function setImagePropertyStringName ($stringName) {
426                 // Call the image class
427                 $this->getImageInstance()->setStringName($stringName);
428         }
429
430         /**
431          * Setter for font size
432          *
433          * @param       $fontSize       Size of the font
434          * @return      void
435          */
436         private function setImagePropertyFontSize ($fontSize) {
437                 // Call the image class
438                 $this->getImageInstance()->setFontSize($fontSize);
439         }
440
441         /**
442          * Setter for image string
443          *
444          * @param       $imageString    Image string to set
445          * @return      void
446          */
447         private function setImagePropertyText ($imageString) {
448                 // Call the image class
449                 $this->getImageInstance()->setString($imageString);
450         }
451
452         /**
453          * Setter for X coordinate
454          *
455          * @param       $x      X coordinate
456          * @return      void
457          */
458         private function setImagePropertyX ($x) {
459                 // Call the image class
460                 $this->getImageInstance()->setX($x);
461         }
462
463         /**
464          * Setter for Y coordinate
465          *
466          * @param       $y      Y coordinate
467          * @return      void
468          */
469         private function setImagePropertyY ($y) {
470                 // Call the image class
471                 $this->getImageInstance()->setY($y);
472         }
473
474         /**
475          * Getter for image cache file instance
476          *
477          * @return      $fileInstance   An instance of a SplFileInfo class
478          */
479         public function getImageCacheFile () {
480                 // Get the instance ready
481                 $fileInstance = new SplFileInfo(sprintf('%s%s%s/%s.%s',
482                         $this->getConfigInstance()->getConfigEntry('root_base_path'),
483                         $this->getGenericBasePath(),
484                         'images/_cache',
485                         md5(
486                                 $this->getImageInstance()->getImageName() . ':' . $this->__toString() . ':' . $this->getImageInstance()->__toString()
487                         ),
488                         $this->getImageInstance()->getImageType()
489                 ));
490
491                 // Return it
492                 return $fileInstance;
493         }
494
495         /**
496          * Outputs the image to the world
497          *
498          * @param       $responseInstance       An instance of a Responseable class
499          * @return      void
500          */
501         public function transferToResponse (Responseable $responseInstance) {
502                 // Set the image instance
503                 $responseInstance->setImageInstance($this->getImageInstance());
504         }
505
506         /**
507          * Load a specified image template into the engine
508          *
509          * @param       $template       The image template we shall load which is
510          *                                              located in 'image' by default
511          * @return      void
512          */
513         public function loadImageTemplate ($template) {
514                 // Set template type
515                 $this->setTemplateType($this->getConfigInstance()->getConfigEntry('image_template_type'));
516
517                 // Load the special template
518                 $this->loadTemplate($template);
519         }
520
521 }