SocketRegistry basicly finished:
[core.git] / inc / classes / main / class_BaseFrameworkSystem.php
1 <?php
2 /**
3  * The simulator system class is the super class of all other classes. This
4  * class handles saving of games etc.
5  *
6  * @author              Roland Haeder <webmaster@ship-simu.org>
7  * @version             0.0.0
8  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009, 2010 Core Developer Team
9  * @license             GNU GPL 3.0 or any newer version
10  * @link                http://www.ship-simu.org
11  *
12  * This program is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation, either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24  */
25 class BaseFrameworkSystem extends stdClass implements FrameworkInterface {
26         /**
27          * Instance of a request class
28          */
29         private $requestInstance = null;
30
31         /**
32          * Instance of a response class
33          */
34         private $responseInstance = null;
35
36         /**
37          * Search criteria instance
38          */
39         private $searchInstance = null;
40
41         /**
42          * Update criteria instance
43          */
44         private $updateInstance = null;
45
46         /**
47          * The file I/O instance for the template loader
48          */
49         private $fileIoInstance = null;
50
51         /**
52          * Resolver instance
53          */
54         private $resolverInstance = null;
55
56         /**
57          * Template engine instance
58          */
59         private $templateInstance = null;
60
61         /**
62          * Database result instance
63          */
64         private $resultInstance = null;
65
66         /**
67          * Instance for user class
68          */
69         private $userInstance = null;
70
71         /**
72          * A controller instance
73          */
74         private $controllerInstance = null;
75
76         /**
77          * Instance of a RNG
78          */
79         private $rngInstance = null;
80
81         /**
82          * Instance of an Iterator class
83          */
84         private $iteratorInstance = null;
85
86         /**
87          * Instance of the list
88          */
89         private $listInstance = null;
90
91         /**
92          * Instance of a menu
93          */
94         private $menuInstance = null;
95
96         /**
97          * Instance of the image
98          */
99         private $imageInstance = null;
100
101         /**
102          * Instance of the stacker
103          */
104         private $stackerInstance = null;
105
106         /**
107          * A Compressor instance
108          */
109         private $compressorInstance = null;
110
111         /**
112          * A Parseable instance
113          */
114         private $parserInstance = null;
115
116         /**
117          * The real class name
118          */
119         private $realClass      = 'BaseFrameworkSystem';
120
121         /**
122          * Thousands seperator
123          */
124         private $thousands = '.'; // German
125
126         /**
127          * Decimal seperator
128          */
129         private $decimals  = ','; // German
130
131         /**
132          * Socket resource
133          */
134         private $socketResource = false;
135
136         /***********************
137          * Exception codes.... *
138          ***********************/
139         // @todo Try to clean these constants up
140         const EXCEPTION_IS_NULL_POINTER              = 0x001;
141         const EXCEPTION_IS_NO_OBJECT                 = 0x002;
142         const EXCEPTION_IS_NO_ARRAY                  = 0x003;
143         const EXCEPTION_MISSING_METHOD               = 0x004;
144         const EXCEPTION_CLASSES_NOT_MATCHING         = 0x005;
145         const EXCEPTION_INDEX_OUT_OF_BOUNDS          = 0x006;
146         const EXCEPTION_DIMENSION_ARRAY_INVALID      = 0x007;
147         const EXCEPTION_ITEM_NOT_TRADEABLE           = 0x008;
148         const EXCEPTION_ITEM_NOT_IN_PRICE_LIST       = 0x009;
149         const EXCEPTION_GENDER_IS_WRONG              = 0x00a;
150         const EXCEPTION_BIRTH_DATE_IS_INVALID        = 0x00b;
151         const EXCEPTION_EMPTY_STRUCTURES_ARRAY       = 0x00c;
152         const EXCEPTION_HAS_ALREADY_PERSONELL_LIST   = 0x00d;
153         const EXCEPTION_NOT_ENOUGTH_UNEMPLOYEES      = 0x00e;
154         const EXCEPTION_TOTAL_PRICE_NOT_CALCULATED   = 0x00f;
155         const EXCEPTION_HARBOR_HAS_NO_SHIPYARDS      = 0x010;
156         const EXCEPTION_CONTRACT_PARTNER_INVALID     = 0x011;
157         const EXCEPTION_CONTRACT_PARTNER_MISMATCH    = 0x012;
158         const EXCEPTION_CONTRACT_ALREADY_SIGNED      = 0x013;
159         const EXCEPTION_UNEXPECTED_EMPTY_STRING      = 0x014;
160         const EXCEPTION_PATH_NOT_FOUND               = 0x015;
161         const EXCEPTION_INVALID_PATH_NAME            = 0x016;
162         const EXCEPTION_READ_PROTECED_PATH           = 0x017;
163         const EXCEPTION_WRITE_PROTECED_PATH          = 0x018;
164         const EXCEPTION_DIR_POINTER_INVALID          = 0x019;
165         const EXCEPTION_FILE_POINTER_INVALID         = 0x01a;
166         const EXCEPTION_INVALID_RESOURCE             = 0x01b;
167         const EXCEPTION_UNEXPECTED_OBJECT            = 0x01c;
168         const EXCEPTION_LIMIT_ELEMENT_IS_UNSUPPORTED = 0x01d;
169         const EXCEPTION_GETTER_IS_MISSING            = 0x01e;
170         const EXCEPTION_ARRAY_EXPECTED               = 0x01f;
171         const EXCEPTION_ARRAY_HAS_INVALID_COUNT      = 0x020;
172         const EXCEPTION_ID_IS_INVALID_FORMAT         = 0x021;
173         const EXCEPTION_MD5_CHECKSUMS_MISMATCH       = 0x022;
174         const EXCEPTION_UNEXPECTED_STRING_SIZE       = 0x023;
175         const EXCEPTION_SIMULATOR_ID_INVALID         = 0x024;
176         const EXCEPTION_MISMATCHING_COMPRESSORS      = 0x025;
177         const EXCEPTION_CONTAINER_ITEM_IS_NULL       = 0x026;
178         const EXCEPTION_ITEM_IS_NO_ARRAY             = 0x027;
179         const EXCEPTION_CONTAINER_MAYBE_DAMAGED      = 0x028;
180         const EXCEPTION_INVALID_STRING               = 0x029;
181         const EXCEPTION_VARIABLE_NOT_SET             = 0x02a;
182         const EXCEPTION_ATTRIBUTES_ARE_MISSING       = 0x02b;
183         const EXCEPTION_ARRAY_ELEMENTS_MISSING       = 0x02c;
184         const EXCEPTION_TEMPLATE_ENGINE_UNSUPPORTED  = 0x02d;
185         const EXCEPTION_MISSING_LANGUAGE_HANDLER     = 0x02e;
186         const EXCEPTION_MISSING_FILE_IO_HANDLER      = 0x02f;
187         const EXCEPTION_MISSING_ELEMENT              = 0x030;
188         const EXCEPTION_HEADERS_ALREADY_SENT         = 0x031;
189         const EXCEPTION_DEFAULT_CONTROLLER_GONE      = 0x032;
190         const EXCEPTION_CLASS_NOT_FOUND              = 0x033;
191         const EXCEPTION_REQUIRED_INTERFACE_MISSING   = 0x034;
192         const EXCEPTION_FATAL_ERROR                  = 0x035;
193         const EXCEPTION_FILE_NOT_FOUND               = 0x036;
194         const EXCEPTION_ASSERTION_FAILED             = 0x037;
195         const EXCEPTION_FILE_CANNOT_BE_READ          = 0x038;
196         const EXCEPTION_DATABASE_UPDATED_NOT_ALLOWED = 0x039;
197         const EXCEPTION_FILTER_CHAIN_INTERCEPTED     = 0x040;
198
199         /**
200          * Protected super constructor
201          *
202          * @param       $className      Name of the class
203          * @return      void
204          */
205         protected function __construct ($className) {
206                 // Set real class
207                 $this->setRealClass($className);
208
209                 // Set configuration instance if no registry
210                 if (!$this instanceof Register) {
211                         // Because registries doesn't need to be configured
212                         $this->setConfigInstance(FrameworkConfiguration::getInstance());
213                 } // END - if
214         }
215
216         /**
217          * Destructor reached...
218          *
219          * @return      void
220          * @todo        This is old code. Do we still need this old lost code?
221          */
222         public function __destruct() {
223                 // Flush any updated entries to the database
224                 $this->flushPendingUpdates();
225
226                 // Is this object already destroyed?
227                 if ($this->__toString() != 'DestructedObject') {
228                         // Destroy all informations about this class but keep some text about it alive
229                         $this->setRealClass('DestructedObject');
230                 } elseif ((defined('DEBUG_DESTRUCTOR')) && (is_object($this->getDebugInstance()))) {
231                         // Already destructed object
232                         $this->debugOutput(sprintf("[%s:] The object <span class=\"object_name\">%s</span> is already destroyed.",
233                                 __CLASS__,
234                                 $this->__toString()
235                         ));
236                 }
237         }
238
239         /**
240          * The call method where all non-implemented methods end up
241          *
242          * @return      void
243          */
244         public final function __call ($methodName, $args) {
245                 // Implode all given arguments
246                 $argsString = '';
247                 if (empty($args)) {
248                         // No arguments
249                         $argsString = 'NULL';
250                 } elseif (is_array($args)) {
251                         // Some arguments are there
252                         foreach ($args as $arg) {
253                                 // Add the type
254                                 $argsString .= $this->replaceControlCharacters($arg) . ' (' . gettype($arg);
255
256                                 // Add length if type is string
257                                 if (gettype($arg) == 'string') $argsString .= ', '.strlen($arg);
258
259                                 // Closing bracket
260                                 $argsString .= '), ';
261                         } // END - foreach
262
263                         // Remove last comma
264                         if (substr($argsString, -2, 1) == ',') {
265                                 $argsString = substr($argsString, 0, -2);
266                         } // END - if
267                 } else {
268                         // Invalid arguments!
269                         $argsString = '!INVALID:' . gettype($args) . '!';
270                 }
271
272                 // Output stub message
273                 $this->debugOutput(sprintf("[%s-&gt;%s] Stub! Args: %s",
274                         $this->__toString(),
275                         $methodName,
276                         $argsString
277                 ));
278
279                 // Return nothing
280                 return null;
281         }
282
283         /**
284          * Setter for database result instance
285          *
286          * @param       $resultInstance         An instance of a database result class
287          * @return      void
288          * @todo        SearchableResult and UpdateableResult shall have a super interface to use here
289          */
290         protected final function setResultInstance (SearchableResult $resultInstance) {
291                 $this->resultInstance =  $resultInstance;
292         }
293
294         /**
295          * Getter for database result instance
296          *
297          * @return      $resultInstance         An instance of a database result class
298          */
299         public final function getResultInstance () {
300                 return $this->resultInstance;
301         }
302
303         /**
304          * Setter for template engine instances
305          *
306          * @param       $templateInstance       An instance of a template engine class
307          * @return      void
308          */
309         protected final function setTemplateInstance (CompileableTemplate $templateInstance) {
310                 $this->templateInstance = $templateInstance;
311         }
312
313         /**
314          * Getter for template engine instances
315          *
316          * @return      $templateInstance       An instance of a template engine class
317          */
318         protected final function getTemplateInstance () {
319                 return $this->templateInstance;
320         }
321
322         /**
323          * Setter for search instance
324          *
325          * @param       $searchInstance         Searchable criteria instance
326          * @return      void
327          */
328         public final function setSearchInstance (LocalSearchCriteria $searchInstance) {
329                 $this->searchInstance = $searchInstance;
330         }
331
332         /**
333          * Getter for search instance
334          *
335          * @return      $searchInstance         Searchable criteria instance
336          */
337         public final function getSearchInstance () {
338                 return $this->searchInstance;
339         }
340
341         /**
342          * Setter for update instance
343          *
344          * @param       $updateInstance         Searchable criteria instance
345          * @return      void
346          */
347         public final function setUpdateInstance (LocalUpdateCriteria $updateInstance) {
348                 $this->updateInstance = $updateInstance;
349         }
350
351         /**
352          * Getter for update instance
353          *
354          * @return      $updateInstance         Updateable criteria instance
355          */
356         public final function getUpdateInstance () {
357                 return $this->updateInstance;
358         }
359
360         /**
361          * Setter for resolver instance
362          *
363          * @param       $resolverInstance               Instance of a command resolver class
364          * @return      void
365          */
366         public final function setResolverInstance (Resolver $resolverInstance) {
367                 $this->resolverInstance = $resolverInstance;
368         }
369
370         /**
371          * Getter for resolver instance
372          *
373          * @return      $resolverInstance               Instance of a command resolver class
374          */
375         public final function getResolverInstance () {
376                 return $this->resolverInstance;
377         }
378
379         /**
380          * Setter for language instance
381          *
382          * @param       $configInstance         The configuration instance which shall
383          *                                                              be FrameworkConfiguration
384          * @return      void
385          */
386         public final function setConfigInstance (FrameworkConfiguration $configInstance) {
387                 Registry::getRegistry()->addInstance('config', $configInstance);
388         }
389
390         /**
391          * Getter for configuration instance
392          *
393          * @return      $configInstance         Configuration instance
394          */
395         public final function getConfigInstance () {
396                 $configInstance = Registry::getRegistry()->getInstance('config');
397                 return $configInstance;
398         }
399
400         /**
401          * Setter for debug instance
402          *
403          * @param       $debugInstance  The instance for debug output class
404          * @return      void
405          */
406         public final function setDebugInstance (DebugMiddleware $debugInstance) {
407                 Registry::getRegistry()->addInstance('debug', $debugInstance);
408         }
409
410         /**
411          * Getter for debug instance
412          *
413          * @return      $debugInstance  Instance to class DebugConsoleOutput or DebugWebOutput
414          */
415         public final function getDebugInstance () {
416                 // Get debug instance
417                 $debugInstance = Registry::getRegistry()->getInstance('debug');
418
419                 // Return it
420                 return $debugInstance;
421         }
422
423         /**
424          * Setter for web output instance
425          *
426          * @param               $webInstance    The instance for web output class
427          * @return      void
428          */
429         public final function setWebOutputInstance (OutputStreamer $webInstance) {
430                 Registry::getRegistry()->addInstance('web_output', $webInstance);
431         }
432
433         /**
434          * Getter for web output instance
435          *
436          * @return      $webOutputInstance - Instance to class WebOutput
437          */
438         public final function getWebOutputInstance () {
439                 $webOutputInstance = Registry::getRegistry()->getInstance('web_output');
440                 return $webOutputInstance;
441         }
442
443         /**
444          * Setter for database instance
445          *
446          * @param               $dbInstance     The instance for the database connection
447          *                                      (forced DatabaseConnection)
448          * @return      void
449          */
450         public final function setDatabaseInstance (DatabaseConnection $dbInstance) {
451                 Registry::getRegistry()->addInstance('db_instance', $dbInstance);
452         }
453
454         /**
455          * Getter for database layer
456          *
457          * @return      $dbInstance     The database layer instance
458          */
459         public final function getDatabaseInstance () {
460                 // Get instance
461                 $dbInstance = Registry::getRegistry()->getInstance('db_instance');
462
463                 // Return instance
464                 return $dbInstance;
465         }
466
467         /**
468          * Setter for compressor channel
469          *
470          * @param               $compressorInstance             An instance of CompressorChannel
471          * @return      void
472          */
473         public final function setCompressorChannel (CompressorChannel $compressorInstance) {
474                 Registry::getRegistry()->addInstance('compressor', $compressorInstance);
475         }
476
477         /**
478          * Getter for compressor channel
479          *
480          * @return      $compressorInstance             The compressor channel
481          */
482         public final function getCompressorChannel () {
483                 $compressorInstance = Registry::getRegistry()->getInstance('compressor');
484                 return $compressorInstance;
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                 $applicationInstance = Registry::getRegistry()->getInstance('application');
494                 return $applicationInstance;
495         }
496
497         /**
498          * Setter for a manageable application helper class
499          *
500          * @param       $applicationInstance    An instance of a manageable application helper class
501          * @return      void
502          */
503         public final function setApplicationInstance (ManageableApplication $applicationInstance) {
504                 Registry::getRegistry()->addInstance('application', $applicationInstance);
505         }
506
507         /**
508          * Setter for request instance
509          *
510          * @param       $requestInstance        An instance of a Requestable class
511          * @return      void
512          */
513         public final function setRequestInstance (Requestable $requestInstance) {
514                 $this->requestInstance = $requestInstance;
515         }
516
517         /**
518          * Getter for request instance
519          *
520          * @return      $requestInstance        An instance of a Requestable class
521          */
522         public final function getRequestInstance () {
523                 return $this->requestInstance;
524         }
525
526         /**
527          * Setter for response instance
528          *
529          * @param       $responseInstance       An instance of a Responseable class
530          * @return      void
531          */
532         public final function setResponseInstance (Responseable $responseInstance) {
533                 $this->responseInstance = $responseInstance;
534         }
535
536         /**
537          * Getter for response instance
538          *
539          * @return      $responseInstance       An instance of a Responseable class
540          */
541         public final function getResponseInstance () {
542                 return $this->responseInstance;
543         }
544
545         /**
546          * Getter for $realClass
547          *
548          * @return      $realClass The name of the real class (not BaseFrameworkSystem)
549          */
550         public final function __toString () {
551                 return $this->realClass;
552         }
553
554         /**
555          * Setter for the real class name
556          *
557          * @param               $realClass      Class name (string)
558          * @return      void
559          */
560         public final function setRealClass ($realClass) {
561                 // Cast to string
562                 $realClass = (string) $realClass;
563
564                 // Set real class
565                 $this->realClass = $realClass;
566         }
567
568         /**
569          * Checks wether an object equals this object. You should overwrite this
570          * method to implement own equality checks
571          *
572          * @param       $objectInstance         An instance of a FrameworkInterface object
573          * @return      $equals                         Wether both objects equals
574          */
575         public function equals (FrameworkInterface $objectInstance) {
576                 // Now test it
577                 $equals = ((
578                         $this->__toString() == $objectInstance->__toString()
579                 ) && (
580                         $this->hashCode() == $objectInstance->hashCode()
581                 ));
582
583                 // Return the result
584                 return $result;
585         }
586
587         /**
588          * Formats computer generated price values into human-understandable formats
589          * with thousand and decimal seperators.
590          *
591          * @param       $value          The in computer format value for a price
592          * @param       $currency       The currency symbol (use HTML-valid characters!)
593          * @param       $decNum         Number of decimals after commata
594          * @return      $price          The for the current language formated price string
595          * @throws      MissingDecimalsThousandsSeperatorException      If decimals or
596          *                                                                                              thousands seperator
597          *                                                                                              is missing
598          */
599         public function formatCurrency ($value, $currency = '&euro;', $decNum = 2) {
600                 // Are all required attriutes set?
601                 if ((!isset($this->decimals)) || (!isset($this->thousands))) {
602                         // Throw an exception
603                         throw new MissingDecimalsThousandsSeperatorException($this, self::EXCEPTION_ATTRIBUTES_ARE_MISSING);
604                 }
605
606                 // Cast the number
607                 $value = (float) $value;
608
609                 // Reformat the US number
610                 $price = number_format($value, $decNum, $this->decimals, $this->thousands) . $currency;
611
612                 // Return as string...
613                 return $price;
614         }
615
616         /**
617          * Private getter for language instance
618          *
619          * @return      $langInstance   An instance to the language sub-system
620          */
621         protected final function getLanguageInstance () {
622                 $langInstance = Registry::getRegistry()->getInstance('language');
623                 return $langInstance;
624         }
625
626         /**
627          * Setter for language instance
628          *
629          * @param       $langInstance   An instance to the language sub-system
630          * @return      void
631          * @see         LanguageSystem
632          */
633         public final function setLanguageInstance (ManageableLanguage $langInstance) {
634                 Registry::getRegistry()->addInstance('language', $langInstance);
635         }
636
637         /**
638          * Appends a trailing slash to a string
639          *
640          * @param       $str            A string (maybe) without trailing slash
641          * @return      $str            A string with an auto-appended trailing slash
642          */
643         public final function addMissingTrailingSlash ($str) {
644                 // Is there a trailing slash?
645                 if (substr($str, -1, 1) != '/') $str .= '/';
646                 return $str;
647         }
648
649         /**
650          * Private getter for file IO instance
651          *
652          * @return      $fileIoInstance An instance to the file I/O sub-system
653          */
654         protected final function getFileIoInstance () {
655                 return $this->fileIoInstance;
656         }
657
658         /**
659          * Setter for file I/O instance
660          *
661          * @param       $fileIoInstance An instance to the file I/O sub-system
662          * @return      void
663          */
664         public final function setFileIoInstance (FileIoHandler $fileIoInstance) {
665                 $this->fileIoInstance = $fileIoInstance;
666         }
667
668         /**
669          * Prepare the template engine (WebTemplateEngine by default) for a given
670          * application helper instance (ApplicationHelper by default).
671          *
672          * @param               $appInstance                    An application helper instance or
673          *                                                                              null if we shall use the default
674          * @return              $templateInstance                               The template engine instance
675          * @throws              NullPointerException    If the template engine could not
676          *                                                                              be initialized
677          * @throws              UnsupportedTemplateEngineException      If $templateInstance is an
678          *                                                                              unsupported template engine
679          * @throws              MissingLanguageHandlerException If the language sub-system
680          *                                                                              is not yet initialized
681          * @throws              NullPointerException    If the discovered application
682          *                                                                              instance is still null
683          */
684         protected function prepareTemplateInstance (FrameworkInterface $appInstance=null) {
685                 // Is the application instance set?
686                 if (is_null($appInstance)) {
687                         // Get the current instance
688                         $appInstance = $this->getApplicationInstance();
689
690                         // Still null?
691                         if (is_null($appInstance)) {
692                                 // Thrown an exception
693                                 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
694                         } // END - if
695                 } // END - if
696
697                 // Are both instances set?
698                 if ($appInstance->getLanguageInstance() === null) {
699                         // Invalid language instance
700                         throw new MissingLanguageHandlerException($appInstance, self::EXCEPTION_MISSING_LANGUAGE_HANDLER);
701                 } elseif ($appInstance->getFileIoInstance() === null) {
702                         // Invalid language instance
703                         throw new MissingFileIoHandlerException($appInstance, self::EXCEPTION_MISSING_FILE_IO_HANDLER);
704                 }
705
706                 // Initialize the template engine
707                 $templateInstance = ObjectFactory::createObjectByConfiguredName('web_template_class', array($appInstance));
708
709                 // Return the prepared instance
710                 return $templateInstance;
711         }
712
713         /**
714          * Debugs this instance by putting out it's full content
715          *
716          * @param       $message        Optional message to show in debug output
717          * @return      void
718          */
719         public final function debugInstance ($message = '') {
720                 // Restore the error handler to avoid trouble with missing array elements or undeclared variables
721                 restore_error_handler();
722
723                 // Init content
724                 $content = '';
725
726                 // Is a message set?
727                 if (!empty($message)) {
728                         // Construct message
729                         $content = sprintf("<div class=\"debug_message\">Message: %s</div>\n", $message);
730                 } // END - if
731
732                 // Generate the output
733                 $content .= sprintf("<pre>%s</pre>",
734                         trim(
735                                 htmlentities(
736                                         print_r($this, true)
737                                 )
738                         )
739                 );
740
741                 // Output it
742                 ApplicationEntryPoint::app_die(sprintf("<div class=\"debug_header\">%s debug output:</div><div class=\"debug_content\">%s</div>\nLoaded includes: <div class=\"debug_include_list\">%s</div>",
743                         $this->__toString(),
744                         $content,
745                         ClassLoader::getInstance()->getPrintableIncludeList()
746                 ));
747         }
748
749         /**
750          * Replaces control characters with printable output
751          *
752          * @param       $str    String with control characters
753          * @return      $str    Replaced string
754          */
755         protected function replaceControlCharacters ($str) {
756                 // Replace them
757                 $str = str_replace(
758                         "\r", '[r]', str_replace(
759                         "\n", '[n]', str_replace(
760                         "\t", '[t]',
761                         $str
762                 )));
763
764                 // Return it
765                 return $str;
766         }
767
768         /**
769          * Output a partial stub message for the caller method
770          *
771          * @param       $message        An optional message to display
772          * @return      void
773          */
774         protected function partialStub ($message = '') {
775                 // Get the backtrace
776                 $backtrace = debug_backtrace();
777
778                 // Generate the class::method string
779                 $methodName = 'UnknownClass-&gt;unknownMethod';
780                 if ((isset($backtrace[1]['class'])) && (isset($backtrace[1]['function']))) {
781                         $methodName = $backtrace[1]['class']."-&gt;".$backtrace[1]['function'];
782                 } // END - if
783
784                 // Construct the full message
785                 $stubMessage = sprintf("[%s:] Partial stub!",
786                         $methodName
787                 );
788
789                 // Is the extra message given?
790                 if (!empty($message)) {
791                         // Then add it as well
792                         $stubMessage .= sprintf(" Message: <span id=\"stub_message\">%s</span>", $message);
793                 } // END - if
794
795                 // Debug instance is there?
796                 if (!is_null($this->getDebugInstance())) {
797                         // Output stub message
798                         $this->debugOutput($stubMessage);
799                 } else {
800                         // Trigger an error
801                         trigger_error($stubMessage."<br />\n");
802                 }
803         }
804
805         /**
806          * Outputs a debug backtrace and stops further script execution
807          *
808          * @return      void
809          */
810         public function debugBackTrace () {
811                 // Sorry, there is no other way getting this nice backtrace
812                 print("<pre>\n");
813                 debug_print_backtrace();
814                 print("</pre>");
815                 exit();
816         }
817
818         /**
819          * Outputs a debug message wether to debug instance (should be set!) or dies with or pints the message
820          *
821          * @param       $message        Message we shall send out...
822          * @param       $doPrint        Wether we shall print or die here which first is the default
823          * @return      void
824          */
825         public function debugOutput ($message, $doPrint = true) {
826                 // Get debug instance
827                 $debugInstance = $this->getDebugInstance();
828
829                 // Is the debug instance there?
830                 if (is_object($debugInstance)) {
831                         // Use debug output handler
832                         $debugInstance->output($message);
833                         if ($doPrint === false) die(); // Die here if not printed
834                 } else {
835                         // Put directly out
836                         if ($doPrint === true) {
837                                 print($message);
838                         } else {
839                                 // DO NOT REWRITE THIS TO app_die() !!!
840                                 die($message);
841                         }
842                 }
843         }
844
845         /**
846          * Converts e.g. a command from URL to a valid class by keeping out bad characters
847          *
848          * @param       $str            The string, what ever it is needs to be converted
849          * @return      $className      Generated class name
850          */
851         public function convertToClassName ($str) {
852                 // Init class name
853                 $className = '';
854
855                 // Convert all dashes in underscores
856                 $str = $this->convertDashesToUnderscores($str);
857
858                 // Now use that underscores to get classname parts for hungarian style
859                 foreach (explode('_', $str) as $strPart) {
860                         // Make the class name part lower case and first upper case
861                         $className .= ucfirst(strtolower($strPart));
862                 } // END - foreach
863
864                 // Return class name
865                 return $className;
866         }
867
868         /**
869          * Converts dashes to underscores, e.g. useable for configuration entries
870          *
871          * @param       $str    The string with maybe dashes inside
872          * @return      $str    The converted string with no dashed, but underscores
873          */
874         public final function convertDashesToUnderscores ($str) {
875                 // Convert them all
876                 $str = str_replace('-', '_', $str);
877
878                 // Return converted string
879                 return $str;
880         }
881
882         /**
883          * Marks up the code by adding e.g. line numbers
884          *
885          * @param       $phpCode                Unmarked PHP code
886          * @return      $markedCode             Marked PHP code
887          */
888         public function markupCode ($phpCode) {
889                 // Init marked code
890                 $markedCode = '';
891
892                 // Get last error
893                 $errorArray = error_get_last();
894
895                 // Init the code with error message
896                 if (is_array($errorArray)) {
897                         // Get error infos
898                         $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>",
899                                 basename($errorArray['file']),
900                                 $errorArray['line'],
901                                 $errorArray['message'],
902                                 $errorArray['type']
903                         );
904                 } // END - if
905
906                 // Add line number to the code
907                 foreach (explode("\n", $phpCode) as $lineNo => $code) {
908                         // Add line numbers
909                         $markedCode .= sprintf("<span id=\"code_line\">%s</span>: %s\n",
910                                 ($lineNo + 1),
911                                 htmlentities($code, ENT_QUOTES)
912                         );
913                 } // END - foreach
914
915                 // Return the code
916                 return $markedCode;
917         }
918
919         /**
920          * Filter a given GMT timestamp (non Uni* stamp!) to make it look more
921          * beatiful for web-based front-ends. If null is given a message id
922          * null_timestamp will be resolved and returned.
923          *
924          * @param       $timestamp      Timestamp to prepare (filter) for display
925          * @return      $readable       A readable timestamp
926          */
927         public function doFilterFormatTimestamp ($timestamp) {
928                 // Default value to return
929                 $readable = '???';
930
931                 // Is the timestamp null?
932                 if (is_null($timestamp)) {
933                         // Get a message string
934                         $readable = $this->getLanguageInstance()->getMessage('null_timestamp');
935                 } else {
936                         switch ($this->getLanguageInstance()->getLanguageCode()) {
937                                 case 'de': // German format is a bit different to default
938                                         // Split the GMT stamp up
939                                         $dateTime  = explode(' ', $timestamp  );
940                                         $dateArray = explode('-', $dateTime[0]);
941                                         $timeArray = explode(':', $dateTime[1]);
942
943                                         // Construct the timestamp
944                                         $readable = sprintf($this->getConfigInstance()->getConfigEntry('german_date_time'),
945                                                 $dateArray[0],
946                                                 $dateArray[1],
947                                                 $dateArray[2],
948                                                 $timeArray[0],
949                                                 $timeArray[1],
950                                                 $timeArray[2]
951                                         );
952                                         break;
953
954                                 default: // Default is pass-through
955                                         $readable = $timestamp;
956                                         break;
957                         } // END - switch
958                 }
959
960                 // Return the stamp
961                 return $readable;
962         }
963
964         /**
965          * Filter a given number into a localized number
966          *
967          * @param       $value          The raw value from e.g. database
968          * @return      $localized      Localized value
969          */
970         public function doFilterFormatNumber ($value) {
971                 // Generate it from config and localize dependencies
972                 switch ($this->getLanguageInstance()->getLanguageCode()) {
973                         case 'de': // German format is a bit different to default
974                                 $localized = number_format($value, $this->getConfigInstance()->getConfigEntry('decimals'), ',', '.');
975                                 break;
976
977                         default: // US, etc.
978                                 $localized = number_format($value, $this->getConfigInstance()->getConfigEntry('decimals'), '.', ',');
979                                 break;
980                 } // END - switch
981
982                 // Return it
983                 return $localized;
984         }
985
986         /**
987          * "Getter" for databse entry
988          *
989          * @return      $entry  An array with database entries
990          * @throws      NullPointerException    If the database result is not found
991          * @throws      InvalidDatabaseResultException  If the database result is invalid
992          */
993         protected final function getDatabaseEntry () {
994                 // Is there an instance?
995                 if (is_null($this->getResultInstance())) {
996                         // Throw an exception here
997                         throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
998                 } // END - if
999
1000                 // Rewind it
1001                 $this->getResultInstance()->rewind();
1002
1003                 // Do we have an entry?
1004                 if ($this->getResultInstance()->valid() === false) {
1005                         throw new InvalidDatabaseResultException(array($this, $this->getResultInstance()), DatabaseResult::EXCEPTION_INVALID_DATABASE_RESULT);
1006                 } // END - if
1007
1008                 // Get next entry
1009                 $this->getResultInstance()->next();
1010
1011                 // Fetch it
1012                 $entry = $this->getResultInstance()->current();
1013
1014                 // And return it
1015                 return $entry;
1016         }
1017
1018         /**
1019          * Getter for field name
1020          *
1021          * @param       $fieldName              Field name which we shall get
1022          * @return      $fieldValue             Field value from the user
1023          * @throws      NullPointerException    If the result instance is null
1024          */
1025         public final function getField ($fieldName) {
1026                 // Default field value
1027                 $fieldValue = null;
1028
1029                 // Get result instance
1030                 $resultInstance = $this->getResultInstance();
1031
1032                 // Is this instance null?
1033                 if (is_null($resultInstance)) {
1034                         // Then the user instance is no longer valid (expired cookies?)
1035                         throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
1036                 } // END - if
1037
1038                 // Get current array
1039                 $fieldArray = $resultInstance->current();
1040                 //* DEBUG: */ $this->debugOutput($fieldName.':<pre>'.print_r($fieldArray, true).'</pre>');
1041
1042                 // Does the field exist?
1043                 if (isset($fieldArray[$fieldName])) {
1044                         // Get it
1045                         $fieldValue = $fieldArray[$fieldName];
1046                 } // END - if
1047
1048                 // Return it
1049                 return $fieldValue;
1050         }
1051
1052         /**
1053          * Protected setter for user instance
1054          *
1055          * @param       $userInstance   An instance of a user class
1056          * @return      void
1057          */
1058         protected final function setUserInstance (ManageableAccount $userInstance) {
1059                 $this->userInstance = $userInstance;
1060         }
1061
1062         /**
1063          * Getter for user instance
1064          *
1065          * @return      $userInstance   An instance of a user class
1066          */
1067         public final function getUserInstance () {
1068                 return $this->userInstance;
1069         }
1070
1071         /**
1072          * Setter for controller instance (this surely breaks a bit the MVC patterm)
1073          *
1074          * @param       $controllerInstance             An instance of the controller
1075          * @return      void
1076          */
1077         public final function setControllerInstance (Controller $controllerInstance) {
1078                 $this->controllerInstance = $controllerInstance;
1079         }
1080
1081         /**
1082          * Getter for controller instance (this surely breaks a bit the MVC patterm)
1083          *
1084          * @return      $controllerInstance             An instance of the controller
1085          */
1086         public final function getControllerInstance () {
1087                 return $this->controllerInstance;
1088         }
1089
1090         /**
1091          * Flushs all pending updates to the database layer
1092          *
1093          * @return      void
1094          */
1095         public function flushPendingUpdates () {
1096                 // Get result instance
1097                 $resultInstance = $this->getResultInstance();
1098
1099                 // Do we have data to update?
1100                 if ((is_object($resultInstance)) && ($resultInstance->ifDataNeedsFlush())) {
1101                         // Get wrapper class name config entry
1102                         $configEntry = $resultInstance->getUpdateInstance()->getWrapperConfigEntry();
1103
1104                         // Create object instance
1105                         $wrapperInstance = ObjectFactory::createObjectByConfiguredName($configEntry);
1106
1107                         // Yes, then send the whole result to the database layer
1108                         $wrapperInstance->doUpdateByResult($this->getResultInstance());
1109                 } // END - if
1110         }
1111
1112         /**
1113          * Outputs a deprecation warning to the developer.
1114          *
1115          * @param       $message        The message we shall output to the developer
1116          * @return      void
1117          * @todo        Write a logging mechanism for productive mode
1118          */
1119         public function deprecationWarning ($message) {
1120                 // Is developer mode active?
1121                 if (defined('DEVELOPER')) {
1122                         // Debug instance is there?
1123                         if (!is_null($this->getDebugInstance())) {
1124                                 // Output stub message
1125                                 $this->debugOutput($message);
1126                         } else {
1127                                 // Trigger an error
1128                                 trigger_error($message."<br />\n");
1129                         }
1130                 } else {
1131                         // @TODO Finish this part!
1132                         $this->partialStub('Developer mode inactive. Message:' . $message);
1133                 }
1134         }
1135
1136         /**
1137          * Generates a generic hash code of this class. You should really overwrite
1138          * this method with your own hash code generator code. But keep KISS in mind.
1139          *
1140          * @return      $hashCode       A generic hash code respresenting this whole class
1141          */
1142         public function hashCode () {
1143                 // Simple hash code
1144                 return crc32($this->__toString());
1145         }
1146
1147         /**
1148          * Checks wether the given PHP extension is loaded
1149          *
1150          * @param       $phpExtension   The PHP extension we shall check
1151          * @return      $isLoaded       Wether the PHP extension is loaded
1152          */
1153         public final function isPhpExtensionLoaded ($phpExtension) {
1154                 // Is it loaded?
1155                 $isLoaded = in_array($phpExtension, get_loaded_extensions());
1156
1157                 // Return result
1158                 return $isLoaded;
1159         }
1160
1161         /**
1162          * Setter for RNG instance
1163          *
1164          * @param       $rngInstance    An instance of a random number generator (RNG)
1165          * @return      void
1166          */
1167         protected final function setRngInstance (RandomNumberGenerator $rngInstance) {
1168                 $this->rngInstance = $rngInstance;
1169         }
1170
1171         /**
1172          * Getter for RNG instance
1173          *
1174          * @return      $rngInstance    An instance of a random number generator (RNG)
1175          */
1176         public final function getRngInstance () {
1177                 return $this->rngInstance;
1178         }
1179
1180         /**
1181          * Setter for Iterator instance
1182          *
1183          * @param       $iteratorInstance       An instance of an Iterator
1184          * @return      void
1185          */
1186         protected final function setIteratorInstance (Iterator $iteratorInstance) {
1187                 $this->iteratorInstance = $iteratorInstance;
1188         }
1189
1190         /**
1191          * Getter for Iterator instance
1192          *
1193          * @return      $iteratorInstance       An instance of an Iterator
1194          */
1195         public final function getIteratorInstance () {
1196                 return $this->iteratorInstance;
1197         }
1198
1199         /**
1200          * "Getter" as a time() replacement but with milliseconds. You should use this
1201          * method instead of the encapsulated getimeofday() function.
1202          *
1203          * @return      $milliTime      Timestamp with milliseconds
1204          */
1205         public function getMilliTime () {
1206                 // Get the time of day as float
1207                 $milliTime = gettimeofday(true);
1208
1209                 // Return it
1210                 return $milliTime;
1211         }
1212
1213         /**
1214          * Idles (sleeps) for given milliseconds
1215          *
1216          * @return      $hasSlept       Wether it goes fine
1217          */
1218         public function idle ($milliSeconds) {
1219                 // Sleep is fine by default
1220                 $hasSlept = true;
1221
1222                 // Idle so long with found function
1223                 if (function_exists('time_sleep_until')) {
1224                         // Get current time and add idle time
1225                         $sleepUntil = $this->getMilliTime() + abs($milliSeconds) / 1000;
1226
1227                         // New PHP 5.1.0 function found
1228                         $hasSlept = time_sleep_until($sleepUntil);
1229                 } else {
1230                         // My Sun Station doesn't have that function even with latest PHP
1231                         // package. :(
1232                         usleep($milliSeconds * 1000);
1233                 }
1234
1235                 // Return result
1236                 return $hasSlept;
1237         }
1238
1239         /**
1240          * Setter for the list instance
1241          *
1242          * @param       $listInstance   A list of Listable
1243          * @return      void
1244          */
1245         protected final function setListInstance (Listable $listInstance) {
1246                 $this->listInstance = $listInstance;
1247         }
1248
1249         /**
1250          * Getter for the list instance
1251          *
1252          * @return      $listInstance   A list of Listable
1253          */
1254         protected final function getListInstance () {
1255                 return $this->listInstance;
1256         }
1257
1258         /**
1259          * Setter for the menu instance
1260          *
1261          * @param       $menuInstance   A RenderableMenu instance
1262          * @return      void
1263          */
1264         protected final function setMenuInstance (RenderableMenu $menuInstance) {
1265                 $this->menuInstance = $menuInstance;
1266         }
1267
1268         /**
1269          * Getter for the menu instance
1270          *
1271          * @return      $menuInstance   A RenderableMenu instance
1272          */
1273         protected final function getMenuInstance () {
1274                 return $this->menuInstance;
1275         }
1276
1277         /**
1278          * Setter for image instance
1279          *
1280          * @param       $imageInstance  An instance of an image
1281          * @return      void
1282          */
1283         public final function setImageInstance (BaseImage $imageInstance) {
1284                 $this->imageInstance = $imageInstance;
1285         }
1286
1287         /**
1288          * Getter for image instance
1289          *
1290          * @return      $imageInstance  An instance of an image
1291          */
1292         public final function getImageInstance () {
1293                 return $this->imageInstance;
1294         }
1295
1296         /**
1297          * Setter for stacker instance
1298          *
1299          * @param       $stackerInstance        An instance of an stacker
1300          * @return      void
1301          */
1302         public final function setStackerInstance (Stackable $stackerInstance) {
1303                 $this->stackerInstance = $stackerInstance;
1304         }
1305
1306         /**
1307          * Getter for stacker instance
1308          *
1309          * @return      $stackerInstance        An instance of an stacker
1310          */
1311         public final function getStackerInstance () {
1312                 return $this->stackerInstance;
1313         }
1314
1315         /**
1316          * Setter for compressor instance
1317          *
1318          * @param       $compressorInstance     An instance of an compressor
1319          * @return      void
1320          */
1321         public final function setCompressorInstance (Compressor $compressorInstance) {
1322                 $this->compressorInstance = $compressorInstance;
1323         }
1324
1325         /**
1326          * Getter for compressor instance
1327          *
1328          * @return      $compressorInstance     An instance of an compressor
1329          */
1330         public final function getCompressorInstance () {
1331                 return $this->compressorInstance;
1332         }
1333
1334         /**
1335          * Setter for Parseable instance
1336          *
1337          * @param       $parserInstance An instance of an Parseable
1338          * @return      void
1339          */
1340         public final function setParserInstance (Parseable $parserInstance) {
1341                 $this->parserInstance = $parserInstance;
1342         }
1343
1344         /**
1345          * Getter for Parseable instance
1346          *
1347          * @return      $parserInstance An instance of an Parseable
1348          */
1349         public final function getParserInstance () {
1350                 return $this->parserInstance;
1351         }
1352
1353         /**
1354          * Setter for socket resource
1355          *
1356          * @param       $socketResource         A valid socket resource
1357          * @return      void
1358          */
1359         public final function setSocketResource ($socketResource) {
1360                 $this->socketResource = $socketResource;
1361         }
1362
1363         /**
1364          * Getter for socket resource
1365          *
1366          * @return      $socketResource         A valid socket resource
1367          */
1368         public function getSocketResource () {
1369                 return $this->socketResource;
1370         }
1371 }
1372
1373 // [EOF]
1374 ?>