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