More patterns added, part description changed to object description
[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.3.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.mxchange.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          * The instance to the debug output handler (should be DebugConsoleOutput or DebugWebOutput)
28          *
29          * @see         DebugConsoleOutput
30          * @see         DebugWebOutput
31          */
32         private static $debug       = null;
33
34         /**
35          * The instance to the web output handler (should be WebOutput)
36          *
37          * @see         WebOutput
38          */
39         private static $webOutput   = null;
40
41         /**
42          * The instance to the compression layer which should be CompressorChannel
43          */
44         private static $compressor  = null;
45
46         /**
47          * The configuration instance which shall be FrameworkConfiguration
48          */
49         private static $cfgInstance = null;
50
51         /**
52          * The instance to the database layer which should be DatabaseConnection
53          */
54         private $dbInstance  = null;
55
56         /**
57          * The real class name
58          */
59         private $realClass      = "FrameworkSystem";
60
61         /**
62          * A human-readable description for this simulator part
63          */
64         private $objectDescription      = "Namenlose Framework-Einheit";
65
66         /**
67          * The unique ID string for identifying all type of classes
68          */
69         private $uniqueID = "";
70
71         /**
72          * Thousands seperator
73          */
74         private $thousands = "."; // German
75
76         /**
77          * Decimal seperator
78          */
79         private $decimals  = ","; // German
80
81         /**
82          * The language instance for the template loader
83          */
84         private $langInstance = null;
85
86         /**
87          * The file I/O instance for the template loader
88          */
89         private $fileIOInstance = null;
90
91         /***********************
92          * Exception codes.... *
93          ***********************/
94
95         const EXCEPTION_IS_NULL_POINTER              = 0x001;
96         const EXCEPTION_IS_NO_OBJECT                 = 0x002;
97         const EXCEPTION_IS_NO_ARRAY                  = 0x003;
98         const EXCEPTION_MISSING_METHOD               = 0x004;
99         const EXCEPTION_CLASSES_NOT_MATCHING         = 0x005;
100         const EXCEPTION_INDEX_OUT_OF_BOUNDS          = 0x006;
101         const EXCEPTION_DIMENSION_ARRAY_INVALID      = 0x007;
102         const EXCEPTION_ITEM_NOT_TRADEABLE           = 0x008;
103         const EXCEPTION_ITEM_NOT_IN_PRICE_LIST       = 0x009;
104         const EXCEPTION_GENDER_IS_WRONG              = 0x00a;
105         const EXCEPTION_BIRTH_DATE_IS_INVALID        = 0x00b;
106         const EXCEPTION_EMPTY_STRUCTURES_ARRAY       = 0x00c;
107         const EXCEPTION_HAS_ALREADY_PERSONELL_LIST   = 0x00d;
108         const EXCEPTION_NOT_ENOUGTH_UNEMPLOYEES      = 0x00e;
109         const EXCEPTION_TOTAL_PRICE_NOT_CALCULATED   = 0x00f;
110         const EXCEPTION_HARBOR_HAS_NO_SHIPYARDS      = 0x010;
111         const EXCEPTION_CONTRACT_PARTNER_INVALID     = 0x011;
112         const EXCEPTION_CONTRACT_PARTNER_MISMATCH    = 0x012;
113         const EXCEPTION_CONTRACT_ALREADY_SIGNED      = 0x013;
114         const EXCEPTION_UNEXPECTED_EMPTY_STRING      = 0x014;
115         const EXCEPTION_PATH_NOT_FOUND               = 0x015;
116         const EXCEPTION_INVALID_PATH_NAME            = 0x016;
117         const EXCEPTION_READ_PROTECED_PATH           = 0x017;
118         const EXCEPTION_WRITE_PROTECED_PATH          = 0x018;
119         const EXCEPTION_DIR_POINTER_INVALID          = 0x019;
120         const EXCEPTION_FILE_POINTER_INVALID         = 0x01a;
121         const EXCEPTION_INVALID_DIRECTORY_POINTER    = 0x01b;
122         const EXCEPTION_UNEXPECTED_OBJECT            = 0x01c;
123         const EXCEPTION_LIMIT_ELEMENT_IS_UNSUPPORTED = 0x01d;
124         const EXCEPTION_GETTER_IS_MISSING            = 0x01e;
125         const EXCEPTION_ARRAY_EXPECTED               = 0x01f;
126         const EXCEPTION_ARRAY_HAS_INVALID_COUNT      = 0x020;
127         const EXCEPTION_ID_IS_INVALID_FORMAT         = 0x021;
128         const EXCEPTION_MD5_CHECKSUMS_MISMATCH       = 0x022;
129         const EXCEPTION_UNEXPECTED_STRING_SIZE       = 0x023;
130         const EXCEPTION_SIMULATOR_ID_INVALID         = 0x024;
131         const EXCEPTION_MISMATCHING_COMPRESSORS      = 0x025;
132         const EXCEPTION_CONTAINER_ITEM_IS_NULL       = 0x026;
133         const EXCEPTION_ITEM_IS_NO_ARRAY             = 0x027;
134         const EXCEPTION_CONTAINER_MAYBE_DAMAGED      = 0x028;
135         const EXCEPTION_INVALID_STRING               = 0x029;
136         const EXCEPTION_VARIABLE_NOT_SET             = 0x02a;
137         const EXCEPTION_ATTRIBUTES_ARE_MISSING       = 0x02b;
138         const EXCEPTION_ARRAY_ELEMENTS_MISSING       = 0x02c;
139         const EXCEPTION_TEMPLATE_ENGINE_UNSUPPORTED  = 0x02d;
140         const EXCEPTION_MISSING_LANGUAGE_HANDLER     = 0x02e;
141         const EXCEPTION_MISSING_FILE_IO_HANDLER      = 0x02f;
142         const EXCEPTION_MISSING_ELEMENT              = 0x030;
143
144         /**
145          * In the super constructor these system classes shall be ignored or else
146          * we would get an endless calling loop.
147          *
148          *--------------------------------------------------------------------*
149          * ATTENTION: IF YOU REMOVE ONE OF THEM YOU WILL SHOOT YOUR SERVER!!! *
150          *--------------------------------------------------------------------*
151          */
152         private $systemClasses = array(
153                 "DebugMiddleware",                      // Debug middleware output sub-system
154                 "DebugWebOutput",                       // Debug web output sub-system
155                 "DebugConsoleOutput",           // Debug console output sub-system
156                 "DebugErrorLogOutput",          // Debug error_log() output sub-system
157                 "CompressorChannel",            // Compressor sub-system
158                 "FrameworkDirectoryPointer",    // Directory handler sub-system
159                 "NullCompressor",                       // Null compressor
160                 "Bzip2Compressor",                      // BZIP2 compressor
161                 "GzipCompressor",                       // GZIP compressor
162                 "WebOutput",                            // Web output sub-system
163         );
164
165         /**
166          * Private super constructor
167          *
168          * @return      void
169          */
170         private function __construct ($class) {
171                 // Set real class
172                 $this->setRealClass($class);
173         }
174
175         /**
176          * Destructor reached...
177          *
178          * @return      void
179          */
180         public function __destruct() {
181                 // Is this object already destroyed?
182                 if ($this->__toString() != "DestructedObject") {
183                         // Debug message
184                         if ((defined('DEBUG_DESTRUCTOR')) && (is_object($this->getDebugInstance()))) {
185                                 $this->getDebugInstance()->output(sprintf("[%s:] Das Objekt <strong>%s</strong> wird zerst&ouml;rt.<br />\n",
186                                         __CLASS__, $this->__toString()
187                                 ));
188                         }
189
190                         // Destroy all informations about this class but keep some text about it alive
191                         $this->setObjectDescription(sprintf("Entferntes Objekt <em>%s</em>", $this->__toString()));
192                         $this->setRealClass("DestructedObject");
193                         $this->resetUniqueID();
194                 } elseif ((defined('DEBUG_DESTRUCTOR')) && (is_object($this->getDebugInstance()))) {
195                         // Already destructed object
196                         $this->getDebugInstance()->output(sprintf("[%s:] Das Objekt <strong>%s</strong> wurde bereits zerst&ouml;rt.<br />\n",
197                                 __CLASS__, $this->__toString()
198                         ));
199                 }
200         }
201
202         /**
203          * The call method where all non-implemented methods end up
204          *
205          * @return      void
206          */
207         public final function __call ($methodName, $args) {
208                 // Implode all given arguments
209                 $argsString = implode("|", $args);
210                 if (empty($argsString)) $argsString = "NULL";
211
212                 $this->getDebugInstance()->output(sprintf("[%s::%s] Stub! Args: %s",
213                         $this->__toString(),
214                         $methodName,
215                         $argsString
216                 ));
217
218                 // Return nothing
219                 return null;
220         }
221
222         /**
223          * Public constructor (for initializing things, etc.)
224          *
225          * @return      void
226          */
227         public function constructor ($class) {
228                 // Call constructor
229                 $this->__construct($class);
230
231                 // Get the current (singleton) configuration instance
232                 $this->setConfigInstance(FrameworkConfiguration::createFrameworkConfiguration());
233
234                 // Is the class weather debug nor compressor channel?
235                 if (!in_array($class, $this->systemClasses)) {
236                         // Initialize debug instance
237                         if (is_null($this->getDebugInstance())) {
238                                 // Set the debug output system if it is not debug class ;)
239                                 $this->setDebugInstance(DebugMiddleware::createDebugMiddleware($this->getConfigInstance()->readConfig("debug_engine")));
240                         }
241
242                         // Initialize web instance
243                         if (is_null($this->getWebOutputInstance())) {
244                                 // Generate the eval() command
245                                 $eval = sprintf("\$this->setWebOutputInstance(%s::create%s(\"%s\"));",
246                                         $this->getConfigInstance()->readConfig("web_engine"),
247                                         $this->getConfigInstance()->readConfig("web_engine"),
248                                         $this->getConfigInstance()->readConfig("web_content_type")
249                                 );
250
251                                 // Debug message
252                                 if ((defined('DEBUG_EVAL')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:] Konstruierte PHP-Anweisung: <pre><em>%s</em></pre><br />\n",
253                                         $this->__toString(),
254                                         htmlentities($eval)
255                                 ));
256
257                                 // Run the command
258                                 eval($eval);
259                         }
260
261                         // Initialize compressor channel
262                         if (is_null($this->getCompressorChannel())) {
263                                 // Set the compressor channel
264                                 $this->setCompressorChannel(CompressorChannel::createCompressorChannel(sprintf("%s%s",
265                                         PATH,
266                                         $this->getConfigInstance()->readConfig("compressor_base_path")
267                                 )));
268                         }
269
270                         // Initialize database middleware
271                         if (is_null($this->getDatabaseInstance())) {
272                                 // Get the middleware instance
273                                 $db = DatabaseConnection::getInstance();
274                                 if (is_object($db)) {
275                                         // Set the database middleware
276                                         $this->setDatabaseInstance($db);
277                                 }
278                         }
279
280                         // Debug output
281                         if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] Alle Sub-Systeme sind initialisiert.<br />\n",
282                                 $this->__toString()
283                         ));
284                 }
285         }
286
287         /**
288          * Setter for language instance
289          *
290          * @param               $configInstance The configuration instance which shall
291          *                                                      be FrameworkConfiguration
292          * @return      void
293          */
294         public final function setConfigInstance (FrameworkConfiguration $configInstance) {
295                 $this->cfgInstance = $configInstance;
296                 if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] Konfigurations-Handler auf <strong>%s</strong> gesetzt.<br />\n",
297                         $this->__toString(),
298                         $configInstance->__toString()
299                 ));
300         }
301
302         /**
303          * Getter for configuration instance
304          *
305          * @return      $cfhInstance - Configuration instance
306          */
307         public final function getConfigInstance () {
308                 if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] Konfigurations-Handler <strong>%s</strong> angefordert.<br />\n",
309                         $this->__toString(),
310                         $this->cfgInstance->__toString()
311                 ));
312                 return $this->cfgInstance;
313         }
314
315         /**
316          * Setter for debug instance
317          *
318          * @param               $debugInstance  The instance for debug output class
319          * @return      void
320          */
321         public final function setDebugInstance (DebugMiddleware $debugInstance) {
322                 self::$debug = $debugInstance;
323                 if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] Debug-Handler auf <strong>%s</strong> gesetzt.<br />\n",
324                         $this->__toString(),
325                         $this->getDebugInstance()->__toString()
326                 ));
327         }
328
329         /**
330          * Getter for debug instance
331          *
332          * @return      $debug - Instance to class DebugConsoleOutput or DebugWebOutput
333          */
334         public final function getDebugInstance () {
335                 return self::$debug;
336         }
337
338         /**
339          * Setter for web output instance
340          *
341          * @param               $webInstance    The instance for web output class
342          * @return      void
343          */
344         public final function setWebOutputInstance (OutputStreamer $webInstance) {
345                 self::$webOutput = $webInstance;
346                 if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] Web-Handler auf <strong>%s</strong> gesetzt.<br />\n",
347                         $this->__toString(),
348                         $this->getWebOutputInstance()->__toString()
349                 ));
350         }
351
352         /**
353          * Getter for web output instance
354          *
355          * @return      $webOutput - Instance to class WebOutput
356          */
357         public final function getWebOutputInstance () {
358                 return self::$webOutput;
359         }
360
361         /**
362          * Static setter for database instance
363          *
364          * @param               $dbInstance     The instance for the database connection
365          *                                      (forced DatabaseConnection)
366          * @return      void
367          */
368         public final function setDatabaseInstance (DatabaseConnection $dbInstance) {
369                 if ((defined('DEBUG_SYSTEM')) && (is_object($dbInstance->getDebugInstance()))) $dbInstance->getDebugInstance()->output(sprintf("[%s:] Datenbankschicht gesetzt.<br />\n",
370                         $dbInstance->__toString()
371                 ));
372                 $this->dbInstance = $dbInstance;
373         }
374
375         /**
376          * Getter for $realClass
377          *
378          * @return      $realClass The name of the real class (not BaseFrameworkSystem)
379          */
380         public final function __toString () {
381                 if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] __toString() erreicht.<br />\n",
382                         $this->realClass
383                 ));
384                 return $this->realClass;
385         }
386
387         /**
388          * Setter for the real class name
389          *
390          * @param               $realClass      Class name (string)
391          * @return      void
392          */
393         public final function setRealClass ($realClass) {
394                 // Cast to string
395                 $realClass = (string) $realClass;
396
397                 // Set real class
398                 $this->realClass = $realClass;
399         }
400
401         /**
402          * Generate unique ID from a lot entropy
403          *
404          * @return      void
405          */
406         public final function createUniqueID () {
407                 if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] createUniqueID aufgerufen.<br />\n",
408                         $this->__toString()
409                 ));
410
411                 // Existiert noch keine?
412                 if (empty($this->uniqueID)) {
413                         if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] createUniqueID erzeugt neue Unique-ID.<br />\n",
414                                 $this->__toString()
415                         ));
416
417                         // Correct missing class name
418                         $corrected = false;
419                         if ($this->__toString() == "") {
420                                 $this->setRealClass(__CLASS__);
421                                 $corrected = true;
422                         }
423
424                         // Neue ID erstellen
425                         $tempID = false;
426                         while (true) {
427                                 // Generate a unique ID number
428                                 $tempID = $this->generateIdNumber();
429                                 $isUsed = false;
430
431                                 // Try to figure out if the ID number is not yet used
432                                 try {
433                                         if (is_object($this->getDatabaseInstance())) {
434                                                 $isUsed = $this->getDatabaseInstance()->isUniqueIdUsed($tempID, true);
435                                         }
436                                 } catch (FrameworkException $e) {
437                                         // Catches all and ignores all ;-)
438                                 }
439
440                                 if (
441                                         (
442                                                 $tempID !== false
443                                         ) && (
444                                                 (
445                                                         $this->getDatabaseInstance() === null
446                                                 ) || (
447                                                         (
448                                                                 is_object($this->getDatabaseInstance())
449                                                         ) && (
450                                                                 !$isUsed
451                                                         )
452                                                 )
453                                         )
454                                 ) {
455                                         // Abort the loop
456                                         break;
457                                 }
458                         }
459
460                         // Debug message
461                         if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] uniqueID ist auf <strong>%s</strong> gesetzt.<br />\n",
462                                 $this->__toString(),
463                                 $tempID
464                         ));
465
466                         // Apply the new ID
467                         $this->setUniqueID($tempID);
468
469                         // Revert maybe corrected class name
470                         if ($corrected) {
471                                 $this->setRealClass("");
472                         }
473
474                         // Remove system classes if we are in a system class
475                         if ((isset($this->systemClasses)) && (in_array($this->__toString(), $this->systemClasses))) {
476                                 // This may save some RAM...
477                                 $this->removeSystemArray();
478                         }
479                 }
480         }
481
482         /**
483          * Generates a new ID number for classes based from the class' real name,
484          * the description and some random data
485          *
486          * @return      $tempID The new (temporary) ID number
487          */
488         private final function generateIdNumber () {
489                 return sprintf("%s@%s",
490                         $this->__toString(),
491                         md5(sprintf("%s:%s:%s:%s:%s:%s",
492                                 $this->__toString(),
493                                 $this->getObjectDescription(),
494                                 time(),
495                                 getenv('REMOTE_ADDR'),
496                                 getenv('SERVER_ADDR'),
497                                 mt_rand()
498                         ))
499                 );
500         }
501
502         /**
503          * Setter for unique ID
504          *
505          * @param               $uniqueID               The newly generated unique ID number
506          * @return      void
507          */
508         private final function setUniqueID ($uniqueID) {
509                 // Cast to string
510                 $uniqueID = (string) $uniqueID;
511
512                 // Debug message
513                 if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] Unique-ID gesetzt auf <u>%s</u>.<br />\n",
514                         $this->__toString(),
515                         $uniqueID
516                 ));
517
518                 // Set the ID number
519                 $this->uniqueID = $uniqueID;
520         }
521
522         /**
523          * Getter for unique ID
524          *
525          * @return      $uniqueID               The unique ID of this class
526          */
527         public final function getUniqueID () {
528                 if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] Unique-ID angefordert.<br />\n",
529                         $this->__toString()
530                 ));
531                 return $this->uniqueID;
532         }
533
534         /**
535          * Resets or recreates the unique ID number
536          *
537          * @return      void
538          */
539         public final function resetUniqueID() {
540                 // Sweet and simple... ;-)
541                 $newUniqueID = $this->generateIdNumber();
542                 if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] Unique-ID zur&uuml;ckgesetzt auf <u>%s</u>.<br />\n",
543                         $this->__toString(),
544                         $newUniqueID
545                 ));
546                 $this->setUniqueID($newUniqueID);
547         }
548
549         /**
550          * Getter for simulator description
551          *
552          * @return      $objectDescription      The description of this simulation part
553          */
554         public final function getObjectDescription () {
555                 if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] getObjectDescription erreicht.<br />\n",
556                         $this->__toString()
557                 ));
558                 if (isset($this->objectDescription)) {
559                         return $this->objectDescription;
560                 } else {
561                         return null;
562                 }
563         }
564
565         /**
566          * Setter for simulation part description
567          *
568          * @param               $objectDescription      The description as string for this simulation part
569          * @return      void
570          */
571         public final function setObjectDescription ($objectDescription) {
572                 $this->objectDescription = (String) $objectDescription;
573                 if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] Teilbeschreibung wird auf <strong>%s</strong> gesetzt.<br />\n",
574                         $this->__toString(),
575                         $this->objectDescription
576                 ));
577         }
578
579         /**
580          * Validate if given object is the same as current
581          *
582          * @param               $object An object instance for comparison with this class
583          * @return      boolean The result of comparing both's unique ID
584          */
585         public final function equals ($object) {
586                 return ($this->getUniqueID() == $object->getUniqueID());
587         }
588
589         /**
590          * Compare if both simulation part description and class name matches
591          * (shall be enougth)
592          *
593          * @param               $itemInstance   An object instance to an other class
594          * @return      boolean         The result of comparing class name simulation part description
595          */
596         public function itemMatches ($itemInstance) {
597                 return (
598                         (
599                                 $this->__toString()   == $itemInstance->__toString()
600                         ) && (
601                                 $this->getObjectDescription() == $itemInstance->getObjectDescription()
602                         )
603                 );
604         }
605
606         /**
607          * Compare class name of this and given class name
608          *
609          * @param               $class  The class name as string from the other class
610          * @return      boolean The result of comparing both class names
611          */
612         public final function isClass ($class) {
613                 if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] <strong>%s</strong>=<strong>%s</strong>?<br />\n",
614                         $this->__toString(),
615                         $this->__toString(),
616                         $class
617                 ));
618                 return ($this->__toString() == $class);
619         }
620
621         /**
622          * Stub method (only real cabins shall override it)
623          *
624          * @return      boolean false = is no cabin, true = is a cabin
625          */
626         public function isCabin () {
627                 return false;
628         }
629
630         /**
631          * Stub method for tradeable objects
632          *
633          * @return      boolean false = is not tradeable by the Merchant class,
634          *                                      true  = is a tradeable object
635          */
636         public function isTradeable () {
637                 return false;
638         }
639
640         /**
641          * Formats computer generated price values into human-understandable formats
642          * with thousand and decimal seperators.
643          *
644          * @param               $value  The in computer format value for a price
645          * @param               $currency       The currency symbol (use HTML-valid characters!)
646          * @param               $decNum Number of decimals after commata
647          * @return      $price  The for the current language formated price string
648          * @throws      MissingDecimalsThousandsSeperatorException      If decimals or
649          *                                                                                              thousands seperator
650          *                                                                                              is missing
651          */
652         public function formatCurrency ($value, $currency = "&euro;", $decNum = 2) {
653                 // Are all required attriutes set?
654                 if ((!isset($this->decimals)) || (!isset($this->thousands))) {
655                         // Throw an exception
656                         throw new MissingDecimalsThousandsSeperatorException($this, self::EXCEPTION_ATTRIBUTES_ARE_MISSING);
657                 }
658
659                 // Cast the number
660                 $value = (float) $value;
661                 if (defined('DEBUG_CORE') && is_object($this->getDebugInstance())) $this->getDebugInstance()->output(sprintf("[%s:] <strong>%d</strong> wird umformatiert.<br />\n",
662                         $this->__toString(),
663                         $value
664                 ));
665
666                 // Reformat the US number
667                 $price = sprintf("%s %s",
668                         number_format($value, $decNum, $this->decimals, $this->thousands),
669                         $currency
670                 );
671
672                 // Return as string...
673                 return $price;
674         }
675
676         /**
677          * Removes number formating characters
678          *
679          * @return      void
680          */
681         public final function removeNumberFormaters () {
682                 if (defined('DEBUG_CORE') && is_object($this->getDebugInstance())) $this->getDebugInstance()->output(sprintf("[%s:] Zahlenumformatierungszeichen werden entfernt.<br />\n",
683                         $this->__toString()
684                 ));
685                 unset($this->thousands);
686                 unset($this->decimals);
687         }
688
689         /**
690          * Getter for database layer
691          *
692          * @return      $dbInstance     The database layer instance
693          */
694         public final function getDatabaseInstance () {
695                 if (defined('DEBUG_CORE') && is_object($this->getDebugInstance())) $this->getDebugInstance()->output(sprintf("[%s:] Datenbank-Instanz <u>%s</u> angefordert.<br />\n",
696                         $this->__toString(),
697                         $this->dbInstance
698                 ));
699                 return $this->dbInstance;
700         }
701
702         /**
703          * Setter for compressor channel
704          *
705          * @param               $compressorChannel      An instance of CompressorChannel
706          * @return      void
707          */
708         public final function setCompressorChannel (CompressorChannel $compressorChannel) {
709                 self::$compressor = $compressorChannel;
710         }
711
712         /**
713          * Getter for compressor channel
714          *
715          * @return      $compressor     The compressor channel
716          */
717         public final function getCompressorChannel () {
718                 return self::$compressor;
719         }
720
721         /**
722          * Remove the $systemClasses array from memory
723          *
724          * @return      void
725          */
726         public final function removeSystemArray () {
727                 unset($this->systemClasses);
728         }
729
730         /**
731          * Create a file name and path name from the object's unique ID number.
732          * The left part of the ID shall always be a valid class name and the
733          * right part an ID number.
734          *
735          * @return      $pfn            The file name with a prepended path name
736          * @throws      NoArrayCreatedException If explode() fails to create an array
737          * @throws      InvalidArrayCountException      If the array contains less or
738          *                                                                      more than two elements
739          */
740         public final function getPathFileNameFromObject () {
741                 // Get the main object's unique ID. We use this as a path/filename combination
742                 $pathFile = $this->getUniqueID();
743
744                 // Split it up in path and file name
745                 $pathFile = explode("@", $pathFile);
746
747                 // Are there two elements? Index 0 is the path, 1 the file name + global extension
748                 if (!is_array($pathFile)) {
749                         // No array found
750                         throw new NoArrayCreatedException(array($this, "pathFile"), self::EXCEPTION_ARRAY_EXPECTED);
751                 } elseif (count($pathFile) != 2) {
752                         // Invalid ID returned!
753                         throw new InvalidArrayCountException(array($this, "pathFile", count($pathFile), 2), self::EXCEPTION_ARRAY_HAS_INVALID_COUNT);
754                 }
755
756                 // Auto-append missing trailing slash
757                 $pathFile[0] = $this->addMissingTrailingSlash($pathFile[0]);
758
759                 // Create the file name and return it
760                 $pfn = ($pathFile[0] . $pathFile[1]);
761                 return $pfn;
762         }
763
764         /**
765          * Appends a trailing slash to a string
766          *
767          * @param       $str            A string (maybe) without trailing slash
768          * @return      $str            A string with an auto-appended trailing slash
769          */
770         public final function addMissingTrailingSlash ($str) {
771                 // Is there a trailing slash?
772                 if (substr($str, -1, 1) != "/") $str .= "/";
773                 return $str;
774         }
775
776         /**
777          * Private getter for language instance
778          *
779          * @return      $langInstance   An instance to the language sub-system
780          */
781         protected final function getLanguageInstance () {
782                 return $this->langInstance;
783         }
784
785         /**
786          * Setter for language instance
787          *
788          * @param       $langInstance   An instance to the language sub-system
789          * @return      void
790          * @see         LanguageSystem
791          */
792         public final function setLanguageInstance (ManageableLanguage $langInstance) {
793                 $this->langInstance = $langInstance;
794         }
795
796         /**
797          * Private getter for file IO instance
798          *
799          * @return      $fileIOInstance An instance to the file I/O sub-system
800          */
801         protected final function getFileIOInstance () {
802                 return $this->fileIOInstance;
803         }
804
805         /**
806          * Setter for file I/O instance
807          *
808          * @param       $fileIOInstance An instance to the file I/O sub-system
809          * @return      void
810          */
811         public final function setFileIOInstance (FileIOHandler $fileIOInstance) {
812                 $this->fileIOInstance = $fileIOInstance;
813         }
814
815         /**
816          * Prepare the template engine (TemplateEngine by default) for a given
817          * application helper instance (ApplicationHelper by default).
818          *
819          * @param               $appInstance                    An application helper instance
820          * @return              $tplEngine                              The template engine instance
821          * @throws              NullPointerException    If the template engine could not
822          *                                                                              be initialized
823          * @throws              UnsupportedTemplateEngineException      If $tplEngine is an
824          *                                                                              unsupported template engine
825          * @throws              MissingLanguageHandlerException If the language sub-system
826          *                                                                              is not yet initialized
827          */
828         protected function prepareTemplateEngine (BaseFrameworkSystem $appInstance) {
829                 // Generate FQFN for all application templates
830                 $fqfn = sprintf("%s%s/%s/%s",
831                         PATH,
832                         $this->getConfigInstance()->readConfig("application_path"),
833                         strtolower($appInstance->getAppShortName()),
834                         $this->getConfigInstance()->readConfig("tpl_base_path")
835                 );
836
837                 // Are both instances set?
838                 if ($appInstance->getLanguageInstance() === null) {
839                         // Invalid language instance
840                         throw new MissingLanguageHandlerException($appInstance, self::EXCEPTION_MISSING_LANGUAGE_HANDLER);
841                 } elseif ($appInstance->getFileIOInstance() === null) {
842                         // Invalid language instance
843                         throw new MissingFileIoHandlerException($appInstance, self::EXCEPTION_MISSING_FILE_IO_HANDLER);
844                 }
845
846                 // Initialize the template engine
847                 $tplEngine = null;
848                 $eval = sprintf("\$tplEngine = %s::create%s(
849         \"%s\",
850         \$appInstance->getLanguageInstance(),
851         \$appInstance->getFileIOInstance()
852 );",
853                         $this->getConfigInstance()->readConfig("tpl_engine"),
854                         $this->getConfigInstance()->readConfig("tpl_engine"),
855                         $fqfn
856                 );
857
858                 // Debug message
859                 if ((!is_null($this->getDebugInstance())) && (defined('DEBUG_EVAL'))) {
860                         $this->getDebugInstance()->output(sprintf("[%s:] Konstruierte PHP-Anweisung: <pre><em>%s</em></pre><br />\n",
861                                 $this->__toString(),
862                                 htmlentities($eval)
863                         ));
864                 }
865
866                 // Run the command
867                 eval($eval);
868
869                 // Is it a valid instance?
870                 if (is_null($tplEngine)) {
871                         // No class returned
872                         throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
873                 } elseif (!$tplEngine instanceof CompileableTemplate) {
874                         // Not an object! ;-(
875                         throw new UnsupportedTemplateEngineException($tplEngine, self::EXCEPTION_TEMPLATE_ENGINE_UNSUPPORTED);
876                 }
877
878                 // Return the prepared instance
879                 return $tplEngine;
880         }
881 }
882
883 // [EOF]
884 ?>