908e4265edf767cfbdc66bfb272c00a69a6e405d
[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 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       $appInstance    A manageable application
73          * @return      $tplInstance    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 final static function createImageTemplateEngine (ManageableApplication $appInstance) {
82                 // Get a new instance
83                 $templateInstance = new ImageTemplateEngine();
84
85                 // Get language and file I/O instances from application
86                 $langInstance = $appInstance->getLanguageInstance();
87                 $ioInstance = $appInstance->getFileIoInstance();
88
89                 // Determine base path
90                 $templateBasePath = $templateInstance->getConfigInstance()->getConfigEntry('application_base_path') . $appInstance->getRequestInstance()->getRequestElement('app') . '/';
91
92                 // Is the base path valid?
93                 if (empty($templateBasePath)) {
94                         // Base path is empty
95                         throw new BasePathIsEmptyException($templateInstance, self::EXCEPTION_UNEXPECTED_EMPTY_STRING);
96                 } elseif (!is_string($templateBasePath)) {
97                         // Is not a string
98                         throw new InvalidBasePathStringException(array($templateInstance, $templateBasePath), self::EXCEPTION_INVALID_STRING);
99                 } elseif (!is_dir($templateBasePath)) {
100                         // Is not a path
101                         throw new BasePathIsNoDirectoryException(array($templateInstance, $templateBasePath), self::EXCEPTION_INVALID_PATH_NAME);
102                 } elseif (!is_readable($templateBasePath)) {
103                         // Is not readable
104                         throw new BasePathReadProtectedException(array($templateInstance, $templateBasePath), self::EXCEPTION_READ_PROTECED_PATH);
105                 }
106
107                 // Get configuration instance
108                 $configInstance = FrameworkConfiguration::getInstance();
109
110                 // Set the base path
111                 $templateInstance->setTemplateBasePath($templateBasePath);
112
113                 // Set the language and IO instances
114                 $templateInstance->setLanguageInstance($langInstance);
115                 $templateInstance->setFileIoInstance($ioInstance);
116
117                 // Set template extensions
118                 $templateInstance->setRawTemplateExtension($configInstance->getConfigEntry('raw_template_extension'));
119                 $templateInstance->setCodeTemplateExtension($configInstance->getConfigEntry('code_template_extension'));
120
121                 // Absolute output path for compiled templates
122                 $templateInstance->setCompileOutputPath($configInstance->getConfigEntry('base_path') . $configInstance->getConfigEntry('compile_output_path'));
123
124                 // Return the prepared instance
125                 return $templateInstance;
126         }
127
128         /**
129          * Getter for current main node
130          *
131          * @return      $currMainNode   Current main node
132          */
133         public final function getCurrMainNode () {
134                 return $this->currMainNode;
135         }
136
137         /**
138          * Getter for main node array
139          *
140          * @return      $mainNodes      Array with valid main node names
141          */
142         public final function getMainNodes () {
143                 return $this->mainNodes;
144         }
145
146         /**
147          * Getter for sub node array
148          *
149          * @return      $subNodes       Array with valid sub node names
150          */
151         public final function getSubNodes () {
152                 return $this->subNodes;
153         }
154
155         /**
156          * Handles the start element of an XML resource
157          *
158          * @param       $resource               XML parser resource (currently ignored)
159          * @param       $element                The element we shall handle
160          * @param       $attributes             All attributes
161          * @return      void
162          * @throws      InvalidXmlNodeException         If an unknown/invalid XML node name was found
163          */
164         public function startElement ($resource, $element, array $attributes) {
165                 // Initial method name which will never be called...
166                 $methodName = 'initImage';
167
168                 // Make the element name lower-case
169                 $element = strtolower($element);
170
171                 // Is the element a main node?
172                 //* DEBUG: */ echo "START: &gt;".$element."&lt;<br />\n";
173                 if (in_array($element, $this->mainNodes)) {
174                         // Okay, main node found!
175                         $methodName = 'setImage' . $this->convertToClassName($element);
176                 } elseif (in_array($element, $this->subNodes)) {
177                         // Sub node found
178                         $methodName = 'setImageProperty' . $this->convertToClassName($element);
179                 } elseif ($element != 'image') {
180                         // Invalid node name found
181                         throw new InvalidXmlNodeException(array($this, $element, $attributes), XmlParser::EXCEPTION_XML_NODE_UNKNOWN);
182                 }
183
184                 // Call method
185                 //* DEBUG: */ echo "call: ".$methodName."<br />\n";
186                 call_user_func_array(array($this, $methodName), $attributes);
187         }
188
189         /**
190          * Ends the main or sub node by sending out the gathered data
191          *
192          * @param       $resource       An XML resource pointer (currently ignored)
193          * @param       $nodeName       Name of the node we want to finish
194          * @return      void
195          * @throws      XmlNodeMismatchException        If current main node mismatches the closing one
196          */
197         public function endElement ($resource, $nodeName) {
198                 // Make all lower-case
199                 $nodeName = strtolower($nodeName);
200
201                 // Does this match with current main node?
202                 //* DEBUG: */ echo "END: &gt;".$nodeName."&lt;<br />\n";
203                 if (($nodeName != $this->getCurrMainNode()) && (in_array($nodeName, $this->getMainNodes()))) {
204                         // Did not match!
205                         throw new XmlNodeMismatchException (array($this, $nodeName, $this->getCurrMainNode()), XmlParser::EXCEPTION_XML_NODE_MISMATCH);
206                 } elseif (in_array($nodeName, $this->getSubNodes())) {
207                         // Silently ignore sub nodes
208                         return;
209                 }
210
211                 // Construct method name
212                 $methodName = 'finish' . $this->convertToClassName($nodeName);
213
214                 // Call the corresponding method
215                 call_user_func_array(array($this->getImageInstance(), $methodName), array());
216         }
217
218         /**
219          * Currently not used
220          *
221          * @param       $resource               XML parser resource (currently ignored)
222          * @param       $characters             Characters to handle
223          * @return      void
224          * @todo        Find something usefull with this!
225          */
226         public function characterHandler ($resource, $characters) {
227                 // Trim all spaces away
228                 $characters = trim($characters);
229
230                 // Is this string empty?
231                 if (empty($characters)) {
232                         // Then skip it silently
233                         return false;
234                 } // END - if
235
236                 // Unfinished work!
237                 $this->partialStub("Handling extra characters is not yet supported!");
238         }
239
240         /**
241          * Intializes the image
242          *
243          * @return      void
244          * @todo        Add cache creation here
245          */
246         private function initImage () {
247                 // Unfinished work!
248         }
249
250         /**
251          * Set the image type
252          *
253          * @param       $imageType      Code fragment or direct value holding the image type
254          * @return      void
255          */
256         private function setImageType ($imageType) {
257                 // Set group to general
258                 $this->setVariableGroup('general');
259
260                 // Try to compile it first to get the value from variable stack
261                 $imageType = $this->compileRawCode($imageType);
262
263                 // Now make a class name of it
264                 $className = $this->convertToClassName($imageType.'_image');
265
266                 // And try to initiate it
267                 $this->setImageInstance(ObjectFactory::createObjectByName($className, array($this)));
268
269                 // Set current main node to type
270                 $this->currMainNode = 'type';
271         }
272
273         /**
274          * "Setter" for resolution, we first need to collect the resolution from the
275          * sub-nodes. So first, this method will prepare an array for it
276          *
277          * @return      void
278          */
279         private function setImageResolution () {
280                 // Call the image class
281                 $this->getImageInstance()->initResolution();
282
283                 // Current main node is resolution
284                 $this->currMainNode = 'resolution';
285         }
286
287         /**
288          * "Setter" for base information. For more details see above method!
289          *
290          * @return      void
291          * @see         ImageTemplateEngine::setImageResolution
292          */
293         private function setImageBase () {
294                 // Call the image class
295                 $this->getImageInstance()->initBase();
296
297                 // Current main node is resolution
298                 $this->currMainNode = 'base';
299         }
300
301         /**
302          * "Setter" for background-color. For more details see above method!
303          *
304          * @return      void
305          * @see         ImageTemplateEngine::setImageResolution
306          */
307         private function setImageBackgroundColor () {
308                 // Call the image class
309                 $this->getImageInstance()->initBackgroundColor();
310
311                 // Current main node is background-color
312                 $this->currMainNode = 'background-color';
313         }
314
315         /**
316          * "Setter" for foreground-color. For more details see above method!
317          *
318          * @return      void
319          * @see         ImageTemplateEngine::setImageResolution
320          */
321         private function setImageForegroundColor () {
322                 // Call the image class
323                 $this->getImageInstance()->initForegroundColor();
324
325                 // Current main node is foreground-color
326                 $this->currMainNode = 'foreground-color';
327         }
328
329         /**
330          * "Setter" for image-string. For more details see above method!
331          *
332          * @param       $groupable      Wether this image string is groupable
333          * @return      void
334          * @see         ImageTemplateEngine::setImageResolution
335          */
336         private function setImageImageString ($groupable = 'single') {
337                 // Call the image class
338                 $this->getImageInstance()->initImageString($groupable);
339
340                 // Current main node is foreground-color
341                 $this->currMainNode = 'image-string';
342         }
343
344         /**
345          * Setter for image name
346          *
347          * @param       $imageName      Name of the image
348          * @return      void
349          */
350         private function setImagePropertyName ($imageName) {
351                 // Call the image class
352                 $this->getImageInstance()->setImageName($imageName);
353         }
354
355         /**
356          * Setter for image width
357          *
358          * @param       $width  Width of the image or variable
359          * @return      void
360          */
361         private function setImagePropertyWidth ($width) {
362                 // Call the image class
363                 $this->getImageInstance()->setWidth($width);
364         }
365
366         /**
367          * Setter for image height
368          *
369          * @param       $height Height of the image or variable
370          * @return      void
371          */
372         private function setImagePropertyHeight ($height) {
373                 // Call the image class
374                 $this->getImageInstance()->setHeight($height);
375         }
376
377         /**
378          * Setter for image red color
379          *
380          * @param       $red    Red color value
381          * @return      void
382          */
383         private function setImagePropertyRed ($red) {
384                 // Call the image class
385                 $this->getImageInstance()->setRed($red);
386         }
387
388         /**
389          * Setter for image green color
390          *
391          * @param       $green  Green color value
392          * @return      void
393          */
394         private function setImagePropertyGreen ($green) {
395                 // Call the image class
396                 $this->getImageInstance()->setGreen($green);
397         }
398
399         /**
400          * Setter for image blue color
401          *
402          * @param       $blue   Blue color value
403          * @return      void
404          */
405         private function setImagePropertyBlue ($blue) {
406                 // Call the image class
407                 $this->getImageInstance()->setBlue($blue);
408         }
409
410         /**
411          * Setter for string name (identifier)
412          *
413          * @param       $stringName             String name (identifier)
414          * @return      void
415          */
416         private function setImagePropertyStringName ($stringName) {
417                 // Call the image class
418                 $this->getImageInstance()->setStringName($stringName);
419         }
420
421         /**
422          * Setter for font size
423          *
424          * @param       $fontSize       Size of the font
425          * @return      void
426          */
427         private function setImagePropertyFontSize ($fontSize) {
428                 // Call the image class
429                 $this->getImageInstance()->setFontSize($fontSize);
430         }
431
432         /**
433          * Setter for image string
434          *
435          * @param       $imageString    Image string to set
436          * @return      void
437          */
438         private function setImagePropertyText ($imageString) {
439                 // Call the image class
440                 $this->getImageInstance()->setString($imageString);
441         }
442
443         /**
444          * Setter for X coordinate
445          *
446          * @param       $x      X coordinate
447          * @return      void
448          */
449         private function setImagePropertyX ($x) {
450                 // Call the image class
451                 $this->getImageInstance()->setX($x);
452         }
453
454         /**
455          * Setter for Y coordinate
456          *
457          * @param       $y      Y coordinate
458          * @return      void
459          */
460         private function setImagePropertyY ($y) {
461                 // Call the image class
462                 $this->getImageInstance()->setY($y);
463         }
464
465         /**
466          * Getter for image cache file (FQFN)
467          *
468          * @return      $fqfn   Full-qualified file name of the image cache
469          */
470         public function getImageCacheFqfn () {
471                 // Get the FQFN ready
472                 $fqfn = sprintf("%s%s%s/%s.%s",
473                         $this->getConfigInstance()->getConfigEntry('base_path'),
474                         $this->getGenericBasePath(),
475                         'images/_cache',
476                         md5(
477                                 $this->getImageInstance()->getImageName() . ':' . $this->__toString() . ':' . $this->getImageInstance()->__toString()
478                         ),
479                         $this->getImageInstance()->getImageType()
480                 );
481
482                 // Return it
483                 return $fqfn;
484         }
485
486         /**
487          * Outputs the image to the world
488          *
489          * @param       $responseInstance       An instance of a Responseable class
490          * @return      void
491          */
492         public function transferToResponse (Responseable $responseInstance) {
493                 // Set the image instance
494                 $responseInstance->setImageInstance($this->getImageInstance());
495         }
496
497         /**
498          * Load a specified image template into the engine
499          *
500          * @param       $template       The image template we shall load which is
501          *                                              located in 'image' by default
502          * @return      void
503          */
504         public function loadImageTemplate ($template) {
505                 // Set template type
506                 $this->setTemplateType($this->getConfigInstance()->getConfigEntry('image_template_type'));
507
508                 // Load the special template
509                 $this->loadTemplate($template);
510         }
511 }
512
513 // [EOF]
514 ?>