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