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