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