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