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