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