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