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