]> git.mxchange.org Git - shipsimu.git/blob - inc/classes/main/class_BaseFrameworkSystem.php
getConfigInstance() is now protected, factories added
[shipsimu.git] / inc / classes / main / class_BaseFrameworkSystem.php
1 <?php
2 /**
3  * The simulator system class is the super class of all other classes. This
4  * class handles saving of games etc.
5  *
6  * @author              Roland Haeder <webmaster@ship-simu.org>
7  * @version             0.0.0
8  * @copyright   Copyright(c) 2007, 2008 Roland Haeder, this is free software
9  * @license             GNU GPL 3.0 or any newer version
10  * @link                http://www.ship-simu.org
11  *
12  * This program is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation, either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24  */
25 class BaseFrameworkSystem extends stdClass implements FrameworkInterface {
26         /**
27          * The instance to the debug output handler (should be DebugConsoleOutput or DebugWebOutput)
28          *
29          * @see         DebugConsoleOutput
30          * @see         DebugWebOutput
31          */
32         private static $debug       = null;
33
34         /**
35          * The instance to the web output handler (should be WebOutput)
36          *
37          * @see         WebOutput
38          */
39         private static $webOutput   = null;
40
41         /**
42          * The instance to the compression layer which should be CompressorChannel
43          */
44         private static $compressor  = null;
45
46         /**
47          * The configuration instance which shall be FrameworkConfiguration
48          */
49         private static $cfgInstance = null;
50
51         /**
52          * The instance to the database layer which should be DatabaseConnection
53          */
54         private $dbInstance  = null;
55
56         /**
57          * Instance to an application helper class
58          */
59         private $applicationInstance = null;
60
61         /**
62          * The real class name
63          */
64         private $realClass      = "FrameworkSystem";
65
66         /**
67          * A human-readable description for this simulator part
68          */
69         private $objectDescription      = "Namenlose Framework-Einheit";
70
71         /**
72          * The unique ID string for identifying all type of classes
73          */
74         private $uniqueID = "";
75
76         /**
77          * Thousands seperator
78          */
79         private $thousands = "."; // German
80
81         /**
82          * Decimal seperator
83          */
84         private $decimals  = ","; // German
85
86         /**
87          * The language instance for the template loader
88          */
89         private $langInstance = null;
90
91         /**
92          * The file I/O instance for the template loader
93          */
94         private $fileIOInstance = null;
95
96         /***********************
97          * Exception codes.... *
98          ***********************/
99
100         const EXCEPTION_IS_NULL_POINTER              = 0x001;
101         const EXCEPTION_IS_NO_OBJECT                 = 0x002;
102         const EXCEPTION_IS_NO_ARRAY                  = 0x003;
103         const EXCEPTION_MISSING_METHOD               = 0x004;
104         const EXCEPTION_CLASSES_NOT_MATCHING         = 0x005;
105         const EXCEPTION_INDEX_OUT_OF_BOUNDS          = 0x006;
106         const EXCEPTION_DIMENSION_ARRAY_INVALID      = 0x007;
107         const EXCEPTION_ITEM_NOT_TRADEABLE           = 0x008;
108         const EXCEPTION_ITEM_NOT_IN_PRICE_LIST       = 0x009;
109         const EXCEPTION_GENDER_IS_WRONG              = 0x00a;
110         const EXCEPTION_BIRTH_DATE_IS_INVALID        = 0x00b;
111         const EXCEPTION_EMPTY_STRUCTURES_ARRAY       = 0x00c;
112         const EXCEPTION_HAS_ALREADY_PERSONELL_LIST   = 0x00d;
113         const EXCEPTION_NOT_ENOUGTH_UNEMPLOYEES      = 0x00e;
114         const EXCEPTION_TOTAL_PRICE_NOT_CALCULATED   = 0x00f;
115         const EXCEPTION_HARBOR_HAS_NO_SHIPYARDS      = 0x010;
116         const EXCEPTION_CONTRACT_PARTNER_INVALID     = 0x011;
117         const EXCEPTION_CONTRACT_PARTNER_MISMATCH    = 0x012;
118         const EXCEPTION_CONTRACT_ALREADY_SIGNED      = 0x013;
119         const EXCEPTION_UNEXPECTED_EMPTY_STRING      = 0x014;
120         const EXCEPTION_PATH_NOT_FOUND               = 0x015;
121         const EXCEPTION_INVALID_PATH_NAME            = 0x016;
122         const EXCEPTION_READ_PROTECED_PATH           = 0x017;
123         const EXCEPTION_WRITE_PROTECED_PATH          = 0x018;
124         const EXCEPTION_DIR_POINTER_INVALID          = 0x019;
125         const EXCEPTION_FILE_POINTER_INVALID         = 0x01a;
126         const EXCEPTION_INVALID_DIRECTORY_POINTER    = 0x01b;
127         const EXCEPTION_UNEXPECTED_OBJECT            = 0x01c;
128         const EXCEPTION_LIMIT_ELEMENT_IS_UNSUPPORTED = 0x01d;
129         const EXCEPTION_GETTER_IS_MISSING            = 0x01e;
130         const EXCEPTION_ARRAY_EXPECTED               = 0x01f;
131         const EXCEPTION_ARRAY_HAS_INVALID_COUNT      = 0x020;
132         const EXCEPTION_ID_IS_INVALID_FORMAT         = 0x021;
133         const EXCEPTION_MD5_CHECKSUMS_MISMATCH       = 0x022;
134         const EXCEPTION_UNEXPECTED_STRING_SIZE       = 0x023;
135         const EXCEPTION_SIMULATOR_ID_INVALID         = 0x024;
136         const EXCEPTION_MISMATCHING_COMPRESSORS      = 0x025;
137         const EXCEPTION_CONTAINER_ITEM_IS_NULL       = 0x026;
138         const EXCEPTION_ITEM_IS_NO_ARRAY             = 0x027;
139         const EXCEPTION_CONTAINER_MAYBE_DAMAGED      = 0x028;
140         const EXCEPTION_INVALID_STRING               = 0x029;
141         const EXCEPTION_VARIABLE_NOT_SET             = 0x02a;
142         const EXCEPTION_ATTRIBUTES_ARE_MISSING       = 0x02b;
143         const EXCEPTION_ARRAY_ELEMENTS_MISSING       = 0x02c;
144         const EXCEPTION_TEMPLATE_ENGINE_UNSUPPORTED  = 0x02d;
145         const EXCEPTION_MISSING_LANGUAGE_HANDLER     = 0x02e;
146         const EXCEPTION_MISSING_FILE_IO_HANDLER      = 0x02f;
147         const EXCEPTION_MISSING_ELEMENT              = 0x030;
148         const EXCEPTION_INVALID_COMMAND              = 0x031;
149         const EXCEPTION_INVALID_CONTROLLER           = 0x032;
150         const EXCEPTION_HEADERS_ALREADY_SENT         = 0x033;
151         const EXCEPTION_DEFAUL_CONTROLLER_GONE       = 0x034;
152
153         /**
154          * In the super constructor these system classes shall be ignored or else
155          * we would get an endless calling loop.
156          *
157          *--------------------------------------------------------------------*
158          * ATTENTION: IF YOU REMOVE ONE OF THEM YOU WILL SHOOT YOUR SERVER!!! *
159          *--------------------------------------------------------------------*
160          */
161         private $systemClasses = array(
162                 "DebugMiddleware",                              // Debug middleware output sub-system
163                 "DebugWebOutput",                               // Debug web output sub-system
164                 "DebugConsoleOutput",                   // Debug console output sub-system
165                 "DebugErrorLogOutput",                  // Debug error_log() output sub-system
166                 "CompressorChannel",                    // Compressor sub-system
167                 "FrameworkDirectoryPointer",    // Directory handler sub-system
168                 "NullCompressor",                               // Null compressor
169                 "Bzip2Compressor",                              // BZIP2 compressor
170                 "GzipCompressor",                               // GZIP compressor
171                 "WebOutput",                                    // Web output sub-system
172         );
173
174         /**
175          * Private super constructor
176          *
177          * @return      void
178          */
179         protected function __construct ($class) {
180                 // Set real class
181                 $this->setRealClass($class);
182
183                 // Init this instance
184                 $this->initInstance($class);
185         }
186
187         /**
188          * Destructor reached...
189          *
190          * @return      void
191          */
192         public function __destruct() {
193                 // Is this object already destroyed?
194                 if ($this->__toString() != "DestructedObject") {
195                         // Debug message
196                         if ((defined('DEBUG_DESTRUCTOR')) && (is_object($this->getDebugInstance()))) {
197                                 $this->getDebugInstance()->output(sprintf("[%s:] Das Objekt <strong>%s</strong> wird zerst&ouml;rt.<br />\n",
198                                         __CLASS__, $this->__toString()
199                                 ));
200                         }
201
202                         // Destroy all informations about this class but keep some text about it alive
203                         $this->setObjectDescription(sprintf("Entferntes Objekt <em>%s</em>", $this->__toString()));
204                         $this->setRealClass("DestructedObject");
205                         $this->resetUniqueID();
206                 } elseif ((defined('DEBUG_DESTRUCTOR')) && (is_object($this->getDebugInstance()))) {
207                         // Already destructed object
208                         $this->getDebugInstance()->output(sprintf("[%s:] Das Objekt <strong>%s</strong> wurde bereits zerst&ouml;rt.<br />\n",
209                                 __CLASS__, $this->__toString()
210                         ));
211                 }
212         }
213
214         /**
215          * The call method where all non-implemented methods end up
216          *
217          * @return      void
218          */
219         public final function __call ($methodName, $args) {
220                 // Implode all given arguments
221                 $argsString = implode("|", $args);
222                 if (empty($argsString)) $argsString = "NULL";
223
224                 $this->getDebugInstance()->output(sprintf("[%s::%s] Stub! Args: %s",
225                         $this->__toString(),
226                         $methodName,
227                         $argsString
228                 ));
229
230                 // Return nothing
231                 return null;
232         }
233
234         /**
235          * Initializes the instance
236          *
237          * @return      void
238          */
239         public function initInstance ($class) {
240                 // Get the current (singleton) configuration instance
241                 $this->setConfigInstance(FrameworkConfiguration::createFrameworkConfiguration());
242
243                 // Is the class weather debug nor compressor channel?
244                 if (!in_array($class, $this->systemClasses)) {
245                         // Initialize debug instance
246                         if (is_null($this->getDebugInstance())) {
247                                 // Set the debug output system if it is not debug class ;)
248                                 $this->setDebugInstance(DebugMiddleware::createDebugMiddleware($this->getConfigInstance()->readConfig("debug_engine")));
249                         }
250
251                         // Initialize web instance
252                         if (is_null($this->getWebOutputInstance())) {
253                                 // Generate the eval() command
254                                 $eval = sprintf("\$this->setWebOutputInstance(%s::create%s(\"%s\"));",
255                                         $this->getConfigInstance()->readConfig("web_engine"),
256                                         $this->getConfigInstance()->readConfig("web_engine"),
257                                         $this->getConfigInstance()->readConfig("web_content_type")
258                                 );
259
260                                 // Debug message
261                                 if (defined('DEBUG_EVAL')) $this->getDebugInstance()->output(sprintf("[%s:] Constructed PHP command: <pre><em>%s</em></pre><br />\n",
262                                         $this->__toString(),
263                                         htmlentities($eval)
264                                 ));
265
266                                 // Run the command
267                                 eval($eval);
268                         }
269
270                         // Initialize compressor channel
271                         if (is_null($this->getCompressorChannel())) {
272                                 // Set the compressor channel
273                                 $this->setCompressorChannel(CompressorChannel::createCompressorChannel(sprintf("%s%s",
274                                         PATH,
275                                         $this->getConfigInstance()->readConfig("compressor_base_path")
276                                 )));
277                         }
278
279                         // Initialize database middleware
280                         if (is_null($this->getDatabaseInstance())) {
281                                 // Get the middleware instance
282                                 $db = DatabaseConnection::getInstance();
283                                 if (is_object($db)) {
284                                         // Set the database middleware
285                                         $this->setDatabaseInstance($db);
286                                 }
287                         }
288                 }
289         }
290
291         /**
292          * Setter for language instance
293          *
294          * @param       $configInstance The configuration instance which shall
295          *                                                      be FrameworkConfiguration
296          * @return      void
297          */
298         public final function setConfigInstance (FrameworkConfiguration $configInstance) {
299                 self::$cfgInstance = $configInstance;
300         }
301
302         /**
303          * Getter for configuration instance
304          *
305          * @return      $cfhInstance - Configuration instance
306          */
307         protected final function getConfigInstance () {
308                 return self::$cfgInstance;
309         }
310
311         /**
312          * Setter for debug instance
313          *
314          * @param               $debugInstance  The instance for debug output class
315          * @return      void
316          */
317         public final function setDebugInstance (DebugMiddleware $debugInstance) {
318                 self::$debug = $debugInstance;
319         }
320
321         /**
322          * Getter for debug instance
323          *
324          * @return      $debug - Instance to class DebugConsoleOutput or DebugWebOutput
325          */
326         public final function getDebugInstance () {
327                 return self::$debug;
328         }
329
330         /**
331          * Setter for web output instance
332          *
333          * @param               $webInstance    The instance for web output class
334          * @return      void
335          */
336         public final function setWebOutputInstance (OutputStreamer $webInstance) {
337                 self::$webOutput = $webInstance;
338         }
339
340         /**
341          * Getter for web output instance
342          *
343          * @return      $webOutput - Instance to class WebOutput
344          */
345         public final function getWebOutputInstance () {
346                 return self::$webOutput;
347         }
348
349         /**
350          * Static setter for database instance
351          *
352          * @param               $dbInstance     The instance for the database connection
353          *                                      (forced DatabaseConnection)
354          * @return      void
355          */
356         public final function setDatabaseInstance (DatabaseConnection $dbInstance) {
357                 $this->dbInstance = $dbInstance;
358         }
359
360         /**
361          * Getter for $realClass
362          *
363          * @return      $realClass The name of the real class (not BaseFrameworkSystem)
364          */
365         public final function __toString () {
366                 return $this->realClass;
367         }
368
369         /**
370          * Setter for the real class name
371          *
372          * @param               $realClass      Class name (string)
373          * @return      void
374          */
375         public final function setRealClass ($realClass) {
376                 // Cast to string
377                 $realClass = (string) $realClass;
378
379                 // Set real class
380                 $this->realClass = $realClass;
381         }
382
383         /**
384          * Generate unique ID from a lot entropy
385          *
386          * @return      void
387          */
388         public final function createUniqueID () {
389                 // Existiert noch keine?
390                 if (empty($this->uniqueID)) {
391
392                         // Correct missing class name
393                         $corrected = false;
394                         if ($this->__toString() == "") {
395                                 $this->setRealClass(__CLASS__);
396                                 $corrected = true;
397                         }
398
399                         // Neue ID erstellen
400                         $tempID = false;
401                         while (true) {
402                                 // Generate a unique ID number
403                                 $tempID = $this->generateIdNumber();
404                                 $isUsed = false;
405
406                                 // Try to figure out if the ID number is not yet used
407                                 try {
408                                         if (is_object($this->getDatabaseInstance())) {
409                                                 $isUsed = $this->getDatabaseInstance()->isUniqueIdUsed($tempID, true);
410                                         }
411                                 } catch (FrameworkException $e) {
412                                         // Catches all and ignores all ;-)
413                                 }
414
415                                 if (
416                                         (
417                                                 $tempID !== false
418                                         ) && (
419                                                 (
420                                                         $this->getDatabaseInstance() === null
421                                                 ) || (
422                                                         (
423                                                                 is_object($this->getDatabaseInstance())
424                                                         ) && (
425                                                                 !$isUsed
426                                                         )
427                                                 )
428                                         )
429                                 ) {
430                                         // Abort the loop
431                                         break;
432                                 }
433                         } // END - while
434
435                         // Apply the new ID
436                         $this->setUniqueID($tempID);
437
438                         // Revert maybe corrected class name
439                         if ($corrected) {
440                                 $this->setRealClass("");
441                         }
442
443                         // Remove system classes if we are in a system class
444                         if ((isset($this->systemClasses)) && (in_array($this->__toString(), $this->systemClasses))) {
445                                 // This may save some RAM...
446                                 $this->removeSystemArray();
447                         }
448                 }
449         }
450
451         /**
452          * Generates a new ID number for classes based from the class' real name,
453          * the description and some random data
454          *
455          * @return      $tempID The new (temporary) ID number
456          */
457         private final function generateIdNumber () {
458                 return sprintf("%s@%s",
459                         $this->__toString(),
460                         md5(sprintf("%s:%s:%s:%s:%s:%s",
461                                 $this->__toString(),
462                                 $this->getObjectDescription(),
463                                 time(),
464                                 getenv('REMOTE_ADDR'),
465                                 getenv('SERVER_ADDR'),
466                                 mt_rand()
467                         ))
468                 );
469         }
470
471         /**
472          * Setter for unique ID
473          *
474          * @param               $uniqueID               The newly generated unique ID number
475          * @return      void
476          */
477         private final function setUniqueID ($uniqueID) {
478                 // Cast to string
479                 $uniqueID = (string) $uniqueID;
480
481                 // Set the ID number
482                 $this->uniqueID = $uniqueID;
483         }
484
485         /**
486          * Getter for unique ID
487          *
488          * @return      $uniqueID               The unique ID of this class
489          */
490         public final function getUniqueID () {
491                 return $this->uniqueID;
492         }
493
494         /**
495          * Resets or recreates the unique ID number
496          *
497          * @return      void
498          */
499         public final function resetUniqueID() {
500                 // Sweet and simple... ;-)
501                 $newUniqueID = $this->generateIdNumber();
502                 $this->setUniqueID($newUniqueID);
503         }
504
505         /**
506          * Getter for simulator description
507          *
508          * @return      $objectDescription      The description of this simulation part
509          */
510         public final function getObjectDescription () {
511                 if (isset($this->objectDescription)) {
512                         return $this->objectDescription;
513                 } else {
514                         return null;
515                 }
516         }
517
518         /**
519          * Setter for simulation part description
520          *
521          * @param               $objectDescription      The description as string for this simulation part
522          * @return      void
523          */
524         public final function setObjectDescription ($objectDescription) {
525                 $this->objectDescription = (String) $objectDescription;
526         }
527
528         /**
529          * Validate if given object is the same as current
530          *
531          * @param               $object An object instance for comparison with this class
532          * @return      boolean The result of comparing both's unique ID
533          */
534         public final function equals ($object) {
535                 return ($this->getUniqueID() == $object->getUniqueID());
536         }
537
538         /**
539          * Compare if both simulation part description and class name matches
540          * (shall be enougth)
541          *
542          * @param               $itemInstance   An object instance to an other class
543          * @return      boolean         The result of comparing class name simulation part description
544          */
545         public function itemMatches ($itemInstance) {
546                 return (
547                         (
548                                 $this->__toString()   == $itemInstance->__toString()
549                         ) && (
550                                 $this->getObjectDescription() == $itemInstance->getObjectDescription()
551                         )
552                 );
553         }
554
555         /**
556          * Compare class name of this and given class name
557          *
558          * @param               $class  The class name as string from the other class
559          * @return      boolean The result of comparing both class names
560          */
561         public final function isClass ($class) {
562                 return ($this->__toString() == $class);
563         }
564
565         /**
566          * Stub method (only real cabins shall override it)
567          *
568          * @return      boolean false = is no cabin, true = is a cabin
569          */
570         public function isCabin () {
571                 return false;
572         }
573
574         /**
575          * Stub method for tradeable objects
576          *
577          * @return      boolean false = is not tradeable by the Merchant class,
578          *                                      true  = is a tradeable object
579          */
580         public function isTradeable () {
581                 return false;
582         }
583
584         /**
585          * Formats computer generated price values into human-understandable formats
586          * with thousand and decimal seperators.
587          *
588          * @param               $value  The in computer format value for a price
589          * @param               $currency       The currency symbol (use HTML-valid characters!)
590          * @param               $decNum Number of decimals after commata
591          * @return      $price  The for the current language formated price string
592          * @throws      MissingDecimalsThousandsSeperatorException      If decimals or
593          *                                                                                              thousands seperator
594          *                                                                                              is missing
595          */
596         public function formatCurrency ($value, $currency = "&euro;", $decNum = 2) {
597                 // Are all required attriutes set?
598                 if ((!isset($this->decimals)) || (!isset($this->thousands))) {
599                         // Throw an exception
600                         throw new MissingDecimalsThousandsSeperatorException($this, self::EXCEPTION_ATTRIBUTES_ARE_MISSING);
601                 }
602
603                 // Cast the number
604                 $value = (float) $value;
605
606                 // Reformat the US number
607                 $price = sprintf("%s %s",
608                         number_format($value, $decNum, $this->decimals, $this->thousands),
609                         $currency
610                 );
611
612                 // Return as string...
613                 return $price;
614         }
615
616         /**
617          * Removes number formating characters
618          *
619          * @return      void
620          */
621         public final function removeNumberFormaters () {
622                 unset($this->thousands);
623                 unset($this->decimals);
624         }
625
626         /**
627          * Getter for database layer
628          *
629          * @return      $dbInstance     The database layer instance
630          */
631         public final function getDatabaseInstance () {
632                 return $this->dbInstance;
633         }
634
635         /**
636          * Setter for compressor channel
637          *
638          * @param               $compressorChannel      An instance of CompressorChannel
639          * @return      void
640          */
641         public final function setCompressorChannel (CompressorChannel $compressorChannel) {
642                 self::$compressor = $compressorChannel;
643         }
644
645         /**
646          * Getter for compressor channel
647          *
648          * @return      $compressor     The compressor channel
649          */
650         public final function getCompressorChannel () {
651                 return self::$compressor;
652         }
653
654         /**
655          * Remove the $systemClasses array from memory
656          *
657          * @return      void
658          */
659         public final function removeSystemArray () {
660                 unset($this->systemClasses);
661         }
662
663         /**
664          * Create a file name and path name from the object's unique ID number.
665          * The left part of the ID shall always be a valid class name and the
666          * right part an ID number.
667          *
668          * @return      $pfn            The file name with a prepended path name
669          * @throws      NoArrayCreatedException If explode() fails to create an array
670          * @throws      InvalidArrayCountException      If the array contains less or
671          *                                                                      more than two elements
672          */
673         public final function getPathFileNameFromObject () {
674                 // Get the main object's unique ID. We use this as a path/filename combination
675                 $pathFile = $this->getUniqueID();
676
677                 // Split it up in path and file name
678                 $pathFile = explode("@", $pathFile);
679
680                 // Are there two elements? Index 0 is the path, 1 the file name + global extension
681                 if (!is_array($pathFile)) {
682                         // No array found
683                         throw new NoArrayCreatedException(array($this, "pathFile"), self::EXCEPTION_ARRAY_EXPECTED);
684                 } elseif (count($pathFile) != 2) {
685                         // Invalid ID returned!
686                         throw new InvalidArrayCountException(array($this, "pathFile", count($pathFile), 2), self::EXCEPTION_ARRAY_HAS_INVALID_COUNT);
687                 }
688
689                 // Auto-append missing trailing slash
690                 $pathFile[0] = $this->addMissingTrailingSlash($pathFile[0]);
691
692                 // Create the file name and return it
693                 $pfn = ($pathFile[0] . $pathFile[1]);
694                 return $pfn;
695         }
696
697         /**
698          * Appends a trailing slash to a string
699          *
700          * @param       $str            A string (maybe) without trailing slash
701          * @return      $str            A string with an auto-appended trailing slash
702          */
703         public final function addMissingTrailingSlash ($str) {
704                 // Is there a trailing slash?
705                 if (substr($str, -1, 1) != "/") $str .= "/";
706                 return $str;
707         }
708
709         /**
710          * Private getter for language instance
711          *
712          * @return      $langInstance   An instance to the language sub-system
713          */
714         protected final function getLanguageInstance () {
715                 return $this->langInstance;
716         }
717
718         /**
719          * Setter for language instance
720          *
721          * @param       $langInstance   An instance to the language sub-system
722          * @return      void
723          * @see         LanguageSystem
724          */
725         public final function setLanguageInstance (ManageableLanguage $langInstance) {
726                 $this->langInstance = $langInstance;
727         }
728
729         /**
730          * Private getter for file IO instance
731          *
732          * @return      $fileIOInstance An instance to the file I/O sub-system
733          */
734         protected final function getFileIOInstance () {
735                 return $this->fileIOInstance;
736         }
737
738         /**
739          * Setter for file I/O instance
740          *
741          * @param       $fileIOInstance An instance to the file I/O sub-system
742          * @return      void
743          */
744         public final function setFileIOInstance (FileIOHandler $fileIOInstance) {
745                 $this->fileIOInstance = $fileIOInstance;
746         }
747
748         /**
749          * Protected getter for a manageable application helper class
750          *
751          * @return      $applicationInstance    An instance of a manageable application helper class
752          */
753         protected final function getApplicationInstance () {
754                 return $this->applicationInstance;
755         }
756
757         /**
758          * Setter for a manageable application helper class
759          *
760          * @param       $applicationInstance    An instance of a manageable application helper class
761          * @return      void
762          */
763         public final function setApplicationInstance (ManageableApplication $applicationInstance) {
764                 $this->applicationInstance = $applicationInstance;
765         }
766
767         /**
768          * Prepare the template engine (TemplateEngine by default) for a given
769          * application helper instance (ApplicationHelper by default).
770          *
771          * @param               $appInstance                    An application helper instance or
772          *                                                                              null if we shall use the default
773          * @return              $tplEngine                              The template engine instance
774          * @throws              NullPointerException    If the template engine could not
775          *                                                                              be initialized
776          * @throws              UnsupportedTemplateEngineException      If $tplEngine is an
777          *                                                                              unsupported template engine
778          * @throws              MissingLanguageHandlerException If the language sub-system
779          *                                                                              is not yet initialized
780          * @throws              NullPointerException    If the discovered application
781          *                                                                              instance is still null
782          */
783         protected function prepareTemplateEngine (BaseFrameworkSystem $appInstance=null) {
784                 // Is the application instance set?
785                 if (is_null($appInstance)) {
786                         // Get the current instance
787                         $appInstance = $this->getApplicationInstance();
788
789                         // Still null?
790                         if (is_null($appInstance)) {
791                                 // Thrown an exception
792                                 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
793                         }
794                 }
795
796                 // Generate FQFN for all application templates
797                 $fqfn = sprintf("%s%s/%s/%s",
798                         PATH,
799                         $this->getConfigInstance()->readConfig("application_path"),
800                         strtolower($appInstance->getAppShortName()),
801                         $this->getConfigInstance()->readConfig("tpl_base_path")
802                 );
803
804                 // Are both instances set?
805                 if ($appInstance->getLanguageInstance() === null) {
806                         // Invalid language instance
807                         throw new MissingLanguageHandlerException($appInstance, self::EXCEPTION_MISSING_LANGUAGE_HANDLER);
808                 } elseif ($appInstance->getFileIOInstance() === null) {
809                         // Invalid language instance
810                         throw new MissingFileIoHandlerException($appInstance, self::EXCEPTION_MISSING_FILE_IO_HANDLER);
811                 }
812
813                 // Initialize the template engine
814                 $tplEngine = null;
815                 $eval = sprintf("\$tplEngine = %s::create%s(
816         \"%s\",
817         \$appInstance->getLanguageInstance(),
818         \$appInstance->getFileIOInstance()
819 );",
820                         $this->getConfigInstance()->readConfig("tpl_engine"),
821                         $this->getConfigInstance()->readConfig("tpl_engine"),
822                         $fqfn
823                 );
824
825                 // Debug message
826                 if ((!is_null($this->getDebugInstance())) && (defined('DEBUG_EVAL'))) {
827                         $this->getDebugInstance()->output(sprintf("[%s:] Constructed PHP command: <pre><em>%s</em></pre><br />\n",
828                                 $this->__toString(),
829                                 htmlentities($eval)
830                         ));
831                 }
832
833                 // Run the command
834                 eval($eval);
835
836                 // Is it a valid instance?
837                 if (is_null($tplEngine)) {
838                         // No class returned
839                         throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
840                 } elseif (!$tplEngine instanceof CompileableTemplate) {
841                         // Not an object! ;-(
842                         throw new UnsupportedTemplateEngineException($tplEngine, self::EXCEPTION_TEMPLATE_ENGINE_UNSUPPORTED);
843                 }
844
845                 // Return the prepared instance
846                 return $tplEngine;
847         }
848
849         /**
850          * Debugs this instance by putting out it's full content
851          *
852          * @return      void
853          */
854         public final function debugInstance () {
855                 // Generate the output
856                 $content = "<pre>".trim(print_r($this, true))."</pre>";
857
858                 // Output it
859                 ApplicationEntryPoint::app_die("<strong>Debug output:</strong>".$content);
860         }
861 }
862
863 // [EOF]
864 ?>