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