Typos fixed and special command resolver are now possible
[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          * Instance to an application helper class
28          */
29         private static $applicationInstance = null;
30
31         /**
32          * The language instance for the template loader
33          */
34         private static $langInstance = null;
35
36         /**
37          * Debug instance
38          */
39         private static $debugInstance = null;
40
41         /**
42          * Instance of a request class
43          */
44         private $requestInstance = null;
45
46         /**
47          * Instance of a response class
48          */
49         private $responseInstance = null;
50
51         /**
52          * Search criteria instance
53          */
54         private $searchInstance = null;
55
56         /**
57          * The file I/O instance for the template loader
58          */
59         private $fileIoInstance = null;
60
61         /**
62          * Resolver instance
63          */
64         private $resolverInstance = null;
65
66         /**
67          * Template engine instance
68          */
69         private $templateInstance = null;
70
71         /**
72          * Database result instance
73          */
74         private $resultInstance = null;
75
76         /**
77          * Instance for user class
78          */
79         private $userInstance = null;
80
81         /**
82          * The real class name
83          */
84         private $realClass      = "FrameworkSystem";
85
86         /**
87          * Thousands seperator
88          */
89         private $thousands = "."; // German
90
91         /**
92          * Decimal seperator
93          */
94         private $decimals  = ","; // German
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_HEADERS_ALREADY_SENT         = 0x031;
149         const EXCEPTION_DEFAULT_CONTROLLER_GONE      = 0x032;
150         const EXCEPTION_CLASS_NOT_FOUND              = 0x033;
151         const EXCEPTION_REQUIRED_INTERFACE_MISSING   = 0x034;
152         const EXCEPTION_FATAL_ERROR                  = 0x035;
153         const EXCEPTION_FILE_NOT_FOUND               = 0x036;
154         const EXCEPTION_ASSERTION_FAILED             = 0x037;
155         const EXCEPTION_FILE_CANNOT_BE_READ          = 0x038;
156         const EXCEPTION_DATABASE_UPDATED_NOT_ALLOWED = 0x039;
157
158         /**
159          * In the super constructor these system classes shall be ignored or else
160          * we would get an endless calling loop.
161          *
162          *---------------------------------------------------------------------*
163          * ATTENTION: IF YOU REMOVE ONE OF THEM YOU WILL RUN YOUR SERVER IN AN *
164          * ENDLESS LOOP !!!                                                    *
165          *---------------------------------------------------------------------*
166          */
167         private $systemClasses = array(
168                 "DebugMiddleware",                              // Debug middleware output sub-system
169                 "Registry",                                             // Object registry
170                 "ObjectFactory",                                // Object factory
171                 "DebugWebOutput",                               // Debug web output sub-system
172                 "WebOutput",                                    // Web output sub-system
173                 "CompressorChannel",                    // Compressor sub-system
174                 "DebugConsoleOutput",                   // Debug console output sub-system
175                 "DebugErrorLogOutput",                  // Debug error_log() output sub-system
176                 "FrameworkDirectoryPointer",    // Directory handler sub-system
177                 "NullCompressor",                               // Null compressor
178                 "Bzip2Compressor",                              // BZIP2 compressor
179                 "GzipCompressor",                               // GZIP compressor
180         );
181
182         /* No longer used:
183         */
184
185         /**
186          * Private super constructor
187          *
188          * @param       $className      Name of the class
189          * @return      void
190          */
191         protected function __construct ($className) {
192                 // Set real class
193                 $this->setRealClass($className);
194
195                 // Initialize the class if class Registry is there
196                 if ((class_exists('Registry')) && (Registry::isInitialized() === false)) {
197                         // Initialize the registry automatically
198                         $this->initInstance();
199                 } // END - if
200         }
201
202         /**
203          * Destructor reached...
204          *
205          * @return      void
206          * @todo        This is old code. Do we still need this old lost code?
207          */
208         public function __destruct() {
209                 // Is this object already destroyed?
210                 if ($this->__toString() != 'DestructedObject') {
211                         // Destroy all informations about this class but keep some text about it alive
212                         $this->setRealClass('DestructedObject');
213                 } elseif ((defined('DEBUG_DESTRUCTOR')) && (is_object($this->getDebugInstance()))) {
214                         // Already destructed object
215                         $this->debugOutput(sprintf("[%s:] The object <span class=\"object_name\">%s</span> is already destroyed.",
216                                 __CLASS__, $this->__toString()
217                         ));
218                 }
219         }
220
221         /**
222          * The call method where all non-implemented methods end up
223          *
224          * @return      void
225          */
226         public final function __call ($methodName, $args) {
227                 // Implode all given arguments
228                 $argsString = "";
229                 if (empty($args)) {
230                         // No arguments
231                         $argsString = "NULL";
232                 } elseif (is_array($args)) {
233                         // Some arguments are there
234                         foreach ($args as $arg) {
235                                 // Add the type
236                                 $argsString .= $arg." (".gettype($arg);
237
238                                 // Add length if type is string
239                                 if (gettype($arg) == 'string') $argsString .= ", ".strlen($arg);
240
241                                 // Closing bracket
242                                 $argsString .= "), ";
243                         } // END - foreach
244
245                         // Remove last comma
246                         if (substr($argsString, -2, 1) === ",") {
247                                 $argsString = substr($argsString, 0, -2);
248                         } // END - if
249                 } else {
250                         // Invalid arguments!
251                         $argsString = sprintf("!INVALID:%s!", $args);
252                 }
253
254                 // Output stub message
255                 $this->debugOutput(sprintf("[%s-&gt;%s] Stub! Args: %s",
256                         $this->__toString(),
257                         $methodName,
258                         $argsString
259                 ));
260
261                 // Return nothing
262                 return null;
263         }
264
265         /**
266          * Private initializer for this class
267          *
268          * @return      void
269          */
270         private final function initInstance () {
271                 // Is this a system class?
272                 if (!in_array($this->__toString(), $this->systemClasses)) {
273                         // Set configuration instance
274                         $this->setConfigInstance(FrameworkConfiguration::getInstance());
275
276                         // Add application helper to our class
277                         $this->systemclasses[] = $this->getConfigInstance()->readConfig('app_helper_class');
278
279                         // Set debug instance
280                         $this->setDebugInstance(DebugMiddleware::createDebugMiddleware($this->getConfigInstance()->readConfig('debug_class')));
281
282                         // Get output instance and set it
283                         $outputInstance = ObjectFactory::createObjectByConfiguredName('web_engine', array($this->getConfigInstance()->readConfig('web_content_type')));
284                         $this->setWebOutputInstance($outputInstance);
285
286                         // Set the compressor channel
287                         $this->setCompressorChannel(CompressorChannel::createCompressorChannel(sprintf("%s%s",
288                                 $this->getConfigInstance()->readConfig('base_path'),
289                                 $this->getConfigInstance()->readConfig('compressor_base_path')
290                         )));
291
292                         // Initialization done! :D
293                         Registry::isInitialized('OK');
294                 } elseif ($this->__toString() == 'DebugMiddleware') {
295                         // Set configuration instance
296                         $this->setConfigInstance(FrameworkConfiguration::getInstance());
297                 }
298         }
299
300         /**
301          * Setter for database result instance
302          *
303          * @param       $resultInstance         An instance of a database result class
304          * @return      void
305          * @todo        SearchableResult and UpdateableResult shall have a super interface to use here
306          */
307         protected final function setResultInstance (SearchableResult $resultInstance) {
308                 $this->resultInstance =  $resultInstance;
309         }
310
311         /**
312          * Getter for database result instance
313          *
314          * @return      $resultInstance         An instance of a database result class
315          */
316         public final function getResultInstance () {
317                 return $this->resultInstance;
318         }
319
320         /**
321          * Setter for template engine instances
322          *
323          * @param       $templateInstance       An instance of a template engine class
324          * @return      void
325          */
326         protected final function setTemplateInstance (CompileableTemplate $templateInstance) {
327                 $this->templateInstance = $templateInstance;
328         }
329
330         /**
331          * Getter for template engine instances
332          *
333          * @return      $templateInstance       An instance of a template engine class
334          */
335         protected final function getTemplateInstance () {
336                 return $this->templateInstance;
337         }
338
339         /**
340          * Setter for search instance
341          *
342          * @param       $searchInstance         Searchable criteria instance
343          * @return      void
344          */
345         public final function setSearchInstance (LocalSearchCriteria $searchInstance) {
346                 $this->searchInstance = $searchInstance;
347         }
348
349         /**
350          * Getter for search instance
351          *
352          * @return      $searchInstance         Searchable criteria instance
353          */
354         public final function getSearchInstance () {
355                 return $this->searchInstance;
356         }
357
358         /**
359          * Setter for resolver instance
360          *
361          * @param       $resolverInstance               Instance of a command resolver class
362          * @return      void
363          */
364         public final function setResolverInstance (Resolver $resolverInstance) {
365                 $this->resolverInstance = $resolverInstance;
366         }
367
368         /**
369          * Getter for resolver instance
370          *
371          * @return      $resolverInstance               Instance of a command resolver class
372          */
373         public final function getResolverInstance () {
374                 return $this->resolverInstance;
375         }
376
377         /**
378          * Setter for language instance
379          *
380          * @param       $configInstance         The configuration instance which shall
381          *                                                              be FrameworkConfiguration
382          * @return      void
383          */
384         public final function setConfigInstance (FrameworkConfiguration $configInstance) {
385                 Registry::getRegistry()->addInstance('config', $configInstance);
386         }
387
388         /**
389          * Getter for configuration instance
390          *
391          * @return      $cfgInstance    Configuration instance
392          */
393         public final function getConfigInstance () {
394                 $cfgInstance = Registry::getRegistry()->getInstance('config');
395                 return $cfgInstance;
396         }
397
398         /**
399          * Setter for debug instance
400          *
401          * @param       $debugInstance  The instance for debug output class
402          * @return      void
403          */
404         public final function setDebugInstance (DebugMiddleware $debugInstance) {
405                 self::$debugInstance = $debugInstance;
406         }
407
408         /**
409          * Getter for debug instance
410          *
411          * @return      $debugInstance  Instance to class DebugConsoleOutput or DebugWebOutput
412          */
413         public final function getDebugInstance () {
414                 return self::$debugInstance;
415         }
416
417         /**
418          * Setter for web output instance
419          *
420          * @param               $webInstance    The instance for web output class
421          * @return      void
422          */
423         public final function setWebOutputInstance (OutputStreamer $webInstance) {
424                 Registry::getRegistry()->addInstance('web_output', $webInstance);
425         }
426
427         /**
428          * Getter for web output instance
429          *
430          * @return      $webOutput - Instance to class WebOutput
431          */
432         public final function getWebOutputInstance () {
433                 return Registry::getRegistry()->getInstance('web_output');
434         }
435
436         /**
437          * Setter for database instance
438          *
439          * @param               $dbInstance     The instance for the database connection
440          *                                      (forced DatabaseConnection)
441          * @return      void
442          */
443         public final function setDatabaseInstance (DatabaseConnection $dbInstance) {
444                 Registry::getRegistry()->addInstance('dbInstance', $dbInstance);
445         }
446
447         /**
448          * Getter for database layer
449          *
450          * @return      $dbInstance     The database layer instance
451          */
452         public final function getDatabaseInstance () {
453                 // Default is invalid db instance
454                 $dbInstance = null;
455
456                 // Is the registry there and initialized?
457                 if ((class_exists('Registry')) && (Registry::isInitialized() === true)) {
458                         $dbInstance = Registry::getRegistry()->getInstance('dbInstance');
459                 } // END - if
460
461                 // Return instance
462                 return $dbInstance;
463         }
464
465         /**
466          * Setter for compressor channel
467          *
468          * @param               $compressorChannel      An instance of CompressorChannel
469          * @return      void
470          */
471         public final function setCompressorChannel (CompressorChannel $compressorChannel) {
472                 Registry::getRegistry()->addInstance('compressor', $compressorChannel);
473         }
474
475         /**
476          * Getter for compressor channel
477          *
478          * @return      $compressor     The compressor channel
479          */
480         public final function getCompressorChannel () {
481                 return Registry::getRegistry()->getInstance('compressor');
482         }
483
484         /**
485          * Protected getter for a manageable application helper class
486          *
487          * @return      $applicationInstance    An instance of a manageable application helper class
488          */
489         protected final function getApplicationInstance () {
490                 return self::$applicationInstance;
491         }
492
493         /**
494          * Setter for a manageable application helper class
495          *
496          * @param       $applicationInstance    An instance of a manageable application helper class
497          * @return      void
498          */
499         public final function setApplicationInstance (ManageableApplication $applicationInstance) {
500                 self::$applicationInstance = $applicationInstance;
501         }
502
503         /**
504          * Setter for request instance
505          *
506          * @param       $requestInstance        An instance of a Requestable class
507          * @return      void
508          */
509         public final function setRequestInstance (Requestable $requestInstance) {
510                 $this->requestInstance = $requestInstance;
511         }
512
513         /**
514          * Getter for request instance
515          *
516          * @return      $requestInstance        An instance of a Requestable class
517          */
518         public final function getRequestInstance () {
519                 return $this->requestInstance;
520         }
521
522         /**
523          * Setter for response instance
524          *
525          * @param       $responseInstance       An instance of a Responseable class
526          * @return      void
527          */
528         public final function setResponseInstance (Responseable $responseInstance) {
529                 $this->responseInstance = $responseInstance;
530         }
531
532         /**
533          * Getter for response instance
534          *
535          * @return      $responseInstance       An instance of a Responseable class
536          */
537         public final function getResponseInstance () {
538                 return $this->responseInstance;
539         }
540
541         /**
542          * Getter for $realClass
543          *
544          * @return      $realClass The name of the real class (not BaseFrameworkSystem)
545          */
546         public final function __toString () {
547                 return $this->realClass;
548         }
549
550         /**
551          * Setter for the real class name
552          *
553          * @param               $realClass      Class name (string)
554          * @return      void
555          */
556         public final function setRealClass ($realClass) {
557                 // Cast to string
558                 $realClass = (string) $realClass;
559
560                 // Set real class
561                 $this->realClass = $realClass;
562         }
563
564         /**
565          * Compare class name of this and given class name
566          *
567          * @param               $className      The class name as string from the other class
568          * @return      boolean The result of comparing both class names
569          */
570         public final function isClass ($className) {
571                 return ($this->__toString() == $className);
572         }
573
574         /**
575          * Stub method (only real cabins shall override it)
576          *
577          * @return      boolean false = is no cabin, true = is a cabin
578          * @deprecated
579          */
580         public function isCabin () {
581                 return false;
582         }
583
584         /**
585          * Stub method for tradeable objects
586          *
587          * @return      boolean false = is not tradeable by the Merchant class,
588          *                                      true  = is a tradeable object
589          * @deprecated
590          */
591         public function isTradeable () {
592                 return false;
593         }
594
595         /**
596          * Formats computer generated price values into human-understandable formats
597          * with thousand and decimal seperators.
598          *
599          * @param       $value          The in computer format value for a price
600          * @param       $currency       The currency symbol (use HTML-valid characters!)
601          * @param       $decNum         Number of decimals after commata
602          * @return      $price          The for the current language formated price string
603          * @throws      MissingDecimalsThousandsSeperatorException      If decimals or
604          *                                                                                              thousands seperator
605          *                                                                                              is missing
606          */
607         public function formatCurrency ($value, $currency = "&euro;", $decNum = 2) {
608                 // Are all required attriutes set?
609                 if ((!isset($this->decimals)) || (!isset($this->thousands))) {
610                         // Throw an exception
611                         throw new MissingDecimalsThousandsSeperatorException($this, self::EXCEPTION_ATTRIBUTES_ARE_MISSING);
612                 }
613
614                 // Cast the number
615                 $value = (float) $value;
616
617                 // Reformat the US number
618                 $price = sprintf("%s %s",
619                         number_format($value, $decNum, $this->decimals, $this->thousands),
620                         $currency
621                 );
622
623                 // Return as string...
624                 return $price;
625         }
626
627         /**
628          * Removes number formating characters
629          *
630          * @return      void
631          */
632         public final function removeNumberFormaters () {
633                 unset($this->thousands);
634                 unset($this->decimals);
635         }
636
637         /**
638          * Private getter for language instance
639          *
640          * @return      $langInstance   An instance to the language sub-system
641          */
642         protected final function getLanguageInstance () {
643                 return self::$langInstance;
644         }
645
646         /**
647          * Setter for language instance
648          *
649          * @param       $langInstance   An instance to the language sub-system
650          * @return      void
651          * @see         LanguageSystem
652          */
653         public final function setLanguageInstance (ManageableLanguage $langInstance) {
654                 self::$langInstance = $langInstance;
655         }
656
657         /**
658          * Remove the $systemClasses array from memory
659          *
660          * @return      void
661          */
662         public final function removeSystemArray () {
663                 unset($this->systemClasses);
664         }
665
666         /**
667          * Appends a trailing slash to a string
668          *
669          * @param       $str            A string (maybe) without trailing slash
670          * @return      $str            A string with an auto-appended trailing slash
671          */
672         public final function addMissingTrailingSlash ($str) {
673                 // Is there a trailing slash?
674                 if (substr($str, -1, 1) != "/") $str .= "/";
675                 return $str;
676         }
677
678         /**
679          * Private getter for file IO instance
680          *
681          * @return      $fileIoInstance An instance to the file I/O sub-system
682          */
683         protected final function getFileIoInstance () {
684                 return $this->fileIoInstance;
685         }
686
687         /**
688          * Setter for file I/O instance
689          *
690          * @param       $fileIoInstance An instance to the file I/O sub-system
691          * @return      void
692          */
693         public final function setFileIoInstance (FileIoHandler $fileIoInstance) {
694                 $this->fileIoInstance = $fileIoInstance;
695         }
696
697         /**
698          * Prepare the template engine (WebTemplateEngine by default) for a given
699          * application helper instance (ApplicationHelper by default).
700          *
701          * @param               $appInstance                    An application helper instance or
702          *                                                                              null if we shall use the default
703          * @return              $templateInstance                               The template engine instance
704          * @throws              NullPointerException    If the template engine could not
705          *                                                                              be initialized
706          * @throws              UnsupportedTemplateEngineException      If $templateInstance is an
707          *                                                                              unsupported template engine
708          * @throws              MissingLanguageHandlerException If the language sub-system
709          *                                                                              is not yet initialized
710          * @throws              NullPointerException    If the discovered application
711          *                                                                              instance is still null
712          */
713         protected function prepareTemplateInstance (BaseFrameworkSystem $appInstance=null) {
714                 // Is the application instance set?
715                 if (is_null($appInstance)) {
716                         // Get the current instance
717                         $appInstance = $this->getApplicationInstance();
718
719                         // Still null?
720                         if (is_null($appInstance)) {
721                                 // Thrown an exception
722                                 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
723                         } // END - if
724                 } // END - if
725
726                 // Generate FQFN for all application templates
727                 $fqfn = sprintf("%s%s/%s",
728                         $this->getConfigInstance()->readConfig('application_path'),
729                         strtolower($appInstance->getAppShortName()),
730                         $this->getConfigInstance()->readConfig('tpl_base_path')
731                 );
732
733                 // Are both instances set?
734                 if ($appInstance->getLanguageInstance() === null) {
735                         // Invalid language instance
736                         throw new MissingLanguageHandlerException($appInstance, self::EXCEPTION_MISSING_LANGUAGE_HANDLER);
737                 } elseif ($appInstance->getFileIoInstance() === null) {
738                         // Invalid language instance
739                         throw new MissingFileIoHandlerException($appInstance, self::EXCEPTION_MISSING_FILE_IO_HANDLER);
740                 }
741
742                 // Initialize the template engine
743                 $templateInstance = ObjectFactory::createObjectByConfiguredName('template_class', array($fqfn, $appInstance->getLanguageInstance(), $appInstance->getFileIoInstance()));
744
745                 // Return the prepared instance
746                 return $templateInstance;
747         }
748
749         /**
750          * Debugs this instance by putting out it's full content
751          *
752          * @param       $message        Optional message to show in debug output
753          * @return      void
754          */
755         public final function debugInstance ($message = "") {
756                 // Restore the error handler to avoid trouble with missing array elements or undeclared variables
757                 restore_error_handler();
758
759                 // Init content
760                 $content = "";
761
762                 // Is a message set?
763                 if (!empty($message)) {
764                         // Construct message
765                         $content = sprintf("<div class=\"debug_message\">Message: %s</div>\n", $message);
766                 } // END - if
767
768                 // Generate the output
769                 $content .= sprintf("<pre>%s</pre>",
770                         trim(
771                                 htmlentities(
772                                         print_r($this, true)
773                                 )
774                         )
775                 );
776
777                 // Output it
778                 ApplicationEntryPoint::app_die(sprintf("<div class=\"debug_header\">%s debug output:</div><div class=\"debug_content\">%s</div>\nLoaded includes: <div class=\"debug_include_list\">%s</div>",
779                         $this->__toString(),
780                         $content,
781                         ClassLoader::getInstance()->getPrintableIncludeList()
782                 ));
783         }
784
785         /**
786          * Output a partial stub message for the caller method
787          *
788          * @param       $message        An optional message to display
789          * @return      void
790          */
791         protected function partialStub ($message = "") {
792                 // Get the backtrace
793                 $backtrace = debug_backtrace();
794
795                 // Generate the class::method string
796                 $methodName = "UnknownClass-&gt;unknownMethod";
797                 if ((isset($backtrace[1]['class'])) && (isset($backtrace[1]['function']))) {
798                         $methodName = $backtrace[1]['class']."-&gt;".$backtrace[1]['function'];
799                 } // END - if
800
801                 // Construct the full message
802                 $stubMessage = sprintf("[%s:] Partial stub!",
803                         $methodName
804                 );
805
806                 // Is the extra message given?
807                 if (!empty($message)) {
808                         // Then add it as well
809                         $stubMessage .= sprintf(" Message: <span id=\"stub_message\">%s</span>", $message);
810                 } // END - if
811
812                 // Debug instance is there?
813                 if (!is_null($this->getDebugInstance())) {
814                         // Output stub message
815                         $this->debugOutput($stubMessage);
816                 } else {
817                         // Trigger an error
818                         trigger_error($stubMessage."<br />\n");
819                 }
820         }
821
822         /**
823          * Outputs a debug backtrace and stops further script execution
824          *
825          * @return      void
826          */
827         public function debugBackTrace () {
828                 // Sorry, there is no other way getting this nice backtrace
829                 print("<pre>\n");
830                 debug_print_backtrace();
831                 print("</pre>");
832                 exit;
833         }
834
835         /**
836          * Outputs a debug message wether to debug instance (should be set!) or dies with or pints the message
837          *
838          * @param       $message        Message we shall send out...
839          * @param       $doPrint        Wether we shall print or die here which first is the default
840          * @return      void
841          */
842         public function debugOutput ($message, $doPrint = true) {
843                 // Get debug instance
844                 $debugInstance = $this->getDebugInstance();
845
846                 // Is the debug instance there?
847                 if (is_object($debugInstance)) {
848                         // Use debug output handler
849                         $debugInstance->output($message);
850                         if ($doPrint === false) die(); // Die here if not printed
851                 } else {
852                         // Put directly out
853                         if ($doPrint) {
854                                 print($message);
855                         } else {
856                                 // DO NOT REWRITE THIS TO app_die() !!!
857                                 die($message);
858                         }
859                 }
860         }
861
862         /**
863          * Converts e.g. a command from URL to a valid class by keeping out bad characters
864          *
865          * @param       $str            The string, what ever it is needs to be converted
866          * @return      $className      Generated class name
867          */
868         public function convertToClassName ($str) {
869                 // Init class name
870                 $className = "";
871
872                 // Convert all dashes in underscores
873                 $str = str_replace("-", "_", $str);
874
875                 // Now use that underscores to get classname parts for hungarian style
876                 foreach (explode("_", $str) as $strPart) {
877                         // Make the class name part lower case and first upper case
878                         $className .= ucfirst(strtolower($strPart));
879                 } // END - foreach
880
881                 // Return class name
882                 return $className;
883         }
884
885         /**
886          * Marks up the code by adding e.g. line numbers
887          *
888          * @param       $phpCode                Unmarked PHP code
889          * @return      $markedCode             Marked PHP code
890          */
891         public function markupCode ($phpCode) {
892                 // Init marked code
893                 $markedCode = "";
894
895                 // Get last error
896                 $errorArray = error_get_last();
897
898                 // Init the code with error message
899                 if (is_array($errorArray)) {
900                         // Get error infos
901                         $markedCode = sprintf("<div id=\"error_header\">File: <span id=\"error_data\">%s</span>, Line: <span id=\"error_data\">%s</span>, Message: <span id=\"error_data\">%s</span>, Type: <span id=\"error_data\">%s</span></div>",
902                                 basename($errorArray['file']),
903                                 $errorArray['line'],
904                                 $errorArray['message'],
905                                 $errorArray['type']
906                         );
907                 } // END - if
908
909                 // Add line number to the code
910                 foreach (explode("\n", $phpCode) as $lineNo => $code) {
911                         // Add line numbers
912                         $markedCode .= sprintf("<span id=\"code_line\">%s</span>: %s\n",
913                                 ($lineNo + 1),
914                                 htmlentities($code, ENT_QUOTES)
915                         );
916                 } // END - foreach
917
918                 // Return the code
919                 return $markedCode;
920         }
921
922         /**
923          * Filter a given GMT timestamp (non Uni* stamp!) to make it look more
924          * beatiful for web-based front-ends. If null is given a message id
925          * null_timestamp will be resolved and returned.
926          *
927          * @param       $timestamp      Timestamp to prepare (filter) for display
928          * @return      $readable       A readable timestamp
929          */
930         public function doFilterFormatTimestamp ($timestamp) {
931                 // Default value to return
932                 $readable = "???";
933
934                 // Is the timestamp null?
935                 if (is_null($timestamp)) {
936                         // Get a message string
937                         $readable = $this->getLanguageInstance()->getMessage('null_timestamp');
938                 } else {
939                         switch ($this->getLanguageInstance()->getLanguageCode()) {
940                                 case "de": // German format is a bit different to default
941                                         // Split the GMT stamp up
942                                         $dateTime = explode(" ", $timestamp);
943                                         $dateArray = explode("-", $dateTime[0]);
944                                         $timeArray = explode(":", $dateTime[1]);
945
946                                         // Construct the timestamp
947                                         $readable = sprintf($this->getConfigInstance()->readConfig('german_date_time'),
948                                                 $dateArray[0],
949                                                 $dateArray[1],
950                                                 $dateArray[2],
951                                                 $timeArray[0],
952                                                 $timeArray[1],
953                                                 $timeArray[2]
954                                         );
955                                         break;
956
957                                 default: // Default is pass-through
958                                         $readable = $timestamp;
959                                         break;
960                         }
961                 }
962
963                 // Return the stamp
964                 return $readable;
965         }
966
967         /**
968          * "Getter" for databse entry
969          *
970          * @return      $entry  An array with database entries
971          * @throws      NullPointerException    If the database result is not found
972          * @throws      InvalidDatabaseResultException  If the database result is invalid
973          */
974         protected final function getDatabaseEntry () {
975                 // Is there an instance?
976                 if (is_null($this->getResultInstance())) {
977                         // Throw an exception here
978                         throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
979                 } // END - if
980
981                 // Rewind it
982                 $this->getResultInstance()->rewind();
983
984                 // Do we have an entry?
985                 if ($this->getResultInstance()->valid() === false) {
986                         throw new InvalidDatabaseResultException(array($this, $this->getResultInstance()), DatabaseResult::EXCEPTION_INVALID_DATABASE_RESULT);
987                 } // END - if
988
989                 // Get next entry
990                 $this->getResultInstance()->next();
991
992                 // Fetch it
993                 $entry = $this->getResultInstance()->current();
994
995                 // And return it
996                 return $entry;
997         }
998
999         /**
1000          * Getter for field name
1001          *
1002          * @param       $fieldName              Field name which we shall get
1003          * @return      $fieldValue             Field value from the user
1004          * @throws      NullPointerException    If the result instance is null
1005          */
1006         public final function getField ($fieldName) {
1007                 // Default field value
1008                 $fieldValue = null;
1009
1010                 // Get result instance
1011                 $resultInstance = $this->getResultInstance();
1012
1013                 // Is this instance null?
1014                 if (is_null($resultInstance)) {
1015                         // Then the user instance is no longer valid (expired cookies?)
1016                         throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
1017                 } // END - if
1018
1019                 // Get current array
1020                 $fieldArray = $resultInstance->current();
1021
1022                 // Does the field exist?
1023                 if (isset($fieldArray[$fieldName])) {
1024                         // Get it
1025                         $fieldValue = $fieldArray[$fieldName];
1026                 } // END - if
1027
1028                 // Return it
1029                 return $fieldValue;
1030         }
1031
1032         /**
1033          * Protected setter for user instance
1034          *
1035          * @param       $userInstance   An instance of a user class
1036          * @return      void
1037          */
1038         protected final function setUserInstance (ManageableAccount $userInstance) {
1039                 $this->userInstance = $userInstance;
1040         }
1041
1042         /**
1043          * Getter for user instance
1044          *
1045          * @return      $userInstance   An instance of a user class
1046          */
1047         public final function getUserInstance () {
1048                 return $this->userInstance;
1049         }
1050 }
1051
1052 // [EOF]
1053 ?>