Added exit; after all trigger_error() calls.
[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@shipsimu.org>
7  * @version             0.0.0
8  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2013 Core Developer Team
9  * @license             GNU GPL 3.0 or any newer version
10  * @link                http://www.shipsimu.org
11  *
12  * This program is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation, either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24  */
25 class BaseFrameworkSystem extends stdClass implements FrameworkInterface {
26         /**
27          * The real class name
28          */
29         private $realClass = 'BaseFrameworkSystem';
30
31         /**
32          * Instance of a request class
33          */
34         private $requestInstance = NULL;
35
36         /**
37          * Instance of a response class
38          */
39         private $responseInstance = NULL;
40
41         /**
42          * Search criteria instance
43          */
44         private $searchInstance = NULL;
45
46         /**
47          * Update criteria instance
48          */
49         private $updateInstance = NULL;
50
51         /**
52          * The file I/O instance for the template loader
53          */
54         private $fileIoInstance = NULL;
55
56         /**
57          * Resolver instance
58          */
59         private $resolverInstance = NULL;
60
61         /**
62          * Template engine instance
63          */
64         private $templateInstance = NULL;
65
66         /**
67          * Database result instance
68          */
69         private $resultInstance = NULL;
70
71         /**
72          * Instance for user class
73          */
74         private $userInstance = NULL;
75
76         /**
77          * A controller instance
78          */
79         private $controllerInstance = NULL;
80
81         /**
82          * Instance of a RNG
83          */
84         private $rngInstance = NULL;
85
86         /**
87          * Instance of a crypto helper
88          */
89         private $cryptoInstance = NULL;
90
91         /**
92          * Instance of an Iterator class
93          */
94         private $iteratorInstance = NULL;
95
96         /**
97          * Instance of the list
98          */
99         private $listInstance = NULL;
100
101         /**
102          * Instance of a menu
103          */
104         private $menuInstance = NULL;
105
106         /**
107          * Instance of the image
108          */
109         private $imageInstance = NULL;
110
111         /**
112          * Instance of the stacker
113          */
114         private $stackerInstance = NULL;
115
116         /**
117          * A Compressor instance
118          */
119         private $compressorInstance = NULL;
120
121         /**
122          * A Parseable instance
123          */
124         private $parserInstance = NULL;
125
126         /**
127          * A ProtocolHandler instance
128          */
129         private $protocolInstance = NULL;
130
131         /**
132          * A database wrapper instance
133          */
134         private $databaseInstance = NULL;
135
136         /**
137          * A helper instance for the form
138          */
139         private $helperInstance = NULL;
140
141         /**
142          * An instance of a Sourceable class
143          */
144         private $sourceInstance = NULL;
145
146         /**
147          * An instance of a InputStreamable class
148          */
149         private $inputStreamInstance = NULL;
150
151         /**
152          * An instance of a OutputStreamable class
153          */
154         private $outputStreamInstance = NULL;
155
156         /**
157          * Networkable handler instance
158          */
159         private $handlerInstance = NULL;
160
161         /**
162          * Visitor handler instance
163          */
164         private $visitorInstance = NULL;
165
166         /**
167          * DHT instance
168          */
169         private $dhtInstance = NULL;
170
171         /**
172          * An instance of a database wrapper class
173          */
174         private $wrapperInstance = NULL;
175
176         /**
177          * Thousands separator
178          */
179         private $thousands = '.'; // German
180
181         /**
182          * Decimal separator
183          */
184         private $decimals  = ','; // German
185
186         /**
187          * Socket resource
188          */
189         private $socketResource = FALSE;
190
191         /**
192          * Package data
193          */
194         private $packageData = array();
195
196         /**
197          * Generic array
198          */
199         private $genericArray = array();
200
201         /***********************
202          * Exception codes.... *
203          ***********************/
204
205         // @todo Try to clean these constants up
206         const EXCEPTION_IS_NULL_POINTER              = 0x001;
207         const EXCEPTION_IS_NO_OBJECT                 = 0x002;
208         const EXCEPTION_IS_NO_ARRAY                  = 0x003;
209         const EXCEPTION_MISSING_METHOD               = 0x004;
210         const EXCEPTION_CLASSES_NOT_MATCHING         = 0x005;
211         const EXCEPTION_INDEX_OUT_OF_BOUNDS          = 0x006;
212         const EXCEPTION_DIMENSION_ARRAY_INVALID      = 0x007;
213         const EXCEPTION_ITEM_NOT_TRADEABLE           = 0x008;
214         const EXCEPTION_ITEM_NOT_IN_PRICE_LIST       = 0x009;
215         const EXCEPTION_GENDER_IS_WRONG              = 0x00a;
216         const EXCEPTION_BIRTH_DATE_IS_INVALID        = 0x00b;
217         const EXCEPTION_EMPTY_STRUCTURES_ARRAY       = 0x00c;
218         const EXCEPTION_HAS_ALREADY_PERSONELL_LIST   = 0x00d;
219         const EXCEPTION_NOT_ENOUGTH_UNEMPLOYEES      = 0x00e;
220         const EXCEPTION_TOTAL_PRICE_NOT_CALCULATED   = 0x00f;
221         const EXCEPTION_HARBOR_HAS_NO_SHIPYARDS      = 0x010;
222         const EXCEPTION_CONTRACT_PARTNER_INVALID     = 0x011;
223         const EXCEPTION_CONTRACT_PARTNER_MISMATCH    = 0x012;
224         const EXCEPTION_CONTRACT_ALREADY_SIGNED      = 0x013;
225         const EXCEPTION_UNEXPECTED_EMPTY_STRING      = 0x014;
226         const EXCEPTION_PATH_NOT_FOUND               = 0x015;
227         const EXCEPTION_INVALID_PATH_NAME            = 0x016;
228         const EXCEPTION_READ_PROTECED_PATH           = 0x017;
229         const EXCEPTION_WRITE_PROTECED_PATH          = 0x018;
230         const EXCEPTION_DIR_POINTER_INVALID          = 0x019;
231         const EXCEPTION_FILE_POINTER_INVALID         = 0x01a;
232         const EXCEPTION_INVALID_RESOURCE             = 0x01b;
233         const EXCEPTION_UNEXPECTED_OBJECT            = 0x01c;
234         const EXCEPTION_LIMIT_ELEMENT_IS_UNSUPPORTED = 0x01d;
235         const EXCEPTION_GETTER_IS_MISSING            = 0x01e;
236         const EXCEPTION_ARRAY_EXPECTED               = 0x01f;
237         const EXCEPTION_ARRAY_HAS_INVALID_COUNT      = 0x020;
238         const EXCEPTION_ID_IS_INVALID_FORMAT         = 0x021;
239         const EXCEPTION_MD5_CHECKSUMS_MISMATCH       = 0x022;
240         const EXCEPTION_UNEXPECTED_STRING_SIZE       = 0x023;
241         const EXCEPTION_SIMULATOR_ID_INVALID         = 0x024;
242         const EXCEPTION_MISMATCHING_COMPRESSORS      = 0x025;
243         const EXCEPTION_CONTAINER_ITEM_IS_NULL       = 0x026;
244         const EXCEPTION_ITEM_IS_NO_ARRAY             = 0x027;
245         const EXCEPTION_CONTAINER_MAYBE_DAMAGED      = 0x028;
246         const EXCEPTION_INVALID_STRING               = 0x029;
247         const EXCEPTION_VARIABLE_NOT_SET             = 0x02a;
248         const EXCEPTION_ATTRIBUTES_ARE_MISSING       = 0x02b;
249         const EXCEPTION_ARRAY_ELEMENTS_MISSING       = 0x02c;
250         const EXCEPTION_TEMPLATE_ENGINE_UNSUPPORTED  = 0x02d;
251         const EXCEPTION_UNSPPORTED_OPERATION         = 0x02e;
252         const EXCEPTION_MISSING_ELEMENT              = 0x030;
253         const EXCEPTION_HEADERS_ALREADY_SENT         = 0x031;
254         const EXCEPTION_DEFAULT_CONTROLLER_GONE      = 0x032;
255         const EXCEPTION_CLASS_NOT_FOUND              = 0x033;
256         const EXCEPTION_REQUIRED_INTERFACE_MISSING   = 0x034;
257         const EXCEPTION_FATAL_ERROR                  = 0x035;
258         const EXCEPTION_FILE_NOT_FOUND               = 0x036;
259         const EXCEPTION_ASSERTION_FAILED             = 0x037;
260         const EXCEPTION_FILE_CANNOT_BE_READ          = 0x038;
261         const EXCEPTION_DATABASE_UPDATED_NOT_ALLOWED = 0x039;
262         const EXCEPTION_FILTER_CHAIN_INTERCEPTED     = 0x040;
263
264         /**
265          * Hexadecimal->Decimal translation array
266          */
267         private static $hexdec = array(
268                 '0' => 0,
269                 '1' => 1,
270                 '2' => 2,
271                 '3' => 3,
272                 '4' => 4,
273                 '5' => 5,
274                 '6' => 6,
275                 '7' => 7,
276                 '8' => 8,
277                 '9' => 9,
278                 'a' => 10,
279                 'b' => 11,
280                 'c' => 12,
281                 'd' => 13,
282                 'e' => 14,
283                 'f' => 15
284         );
285
286         /**
287          * Decimal->hexadecimal translation array
288          */
289         private static $dechex = array(
290                  0 => '0',
291                  1 => '1',
292                  2 => '2',
293                  3 => '3',
294                  4 => '4',
295                  5 => '5',
296                  6 => '6',
297                  7 => '7',
298                  8 => '8',
299                  9 => '9',
300                 10 => 'a',
301                 11 => 'b',
302                 12 => 'c',
303                 13 => 'd',
304                 14 => 'e',
305                 15 => 'f'
306         );
307
308         /**
309          * Startup time in miliseconds
310          */
311         private static $startupTime = 0;
312
313         /**
314          * Protected super constructor
315          *
316          * @param       $className      Name of the class
317          * @return      void
318          */
319         protected function __construct ($className) {
320                 // Set real class
321                 $this->setRealClass($className);
322
323                 // Set configuration instance if no registry ...
324                 if (!$this instanceof Register) {
325                         // ... because registries doesn't need to be configured
326                         $this->setConfigInstance(FrameworkConfiguration::getSelfInstance());
327                 } // END - if
328
329                 // Is the startup time set? (0 cannot be TRUE anymore)
330                 if (self::$startupTime == 0) {
331                         // Then set it
332                         self::$startupTime = microtime(TRUE);
333                 } // END - if
334         }
335
336         /**
337          * Destructor for all classes
338          *
339          * @return      void
340          */
341         public function __destruct () {
342                 // Flush any updated entries to the database
343                 $this->flushPendingUpdates();
344
345                 // Is this object already destroyed?
346                 if ($this->__toString() != 'DestructedObject') {
347                         // Destroy all informations about this class but keep some text about it alive
348                         $this->setRealClass('DestructedObject');
349                 } elseif ((defined('DEBUG_DESTRUCTOR')) && (is_object($this->getDebugInstance()))) {
350                         // Already destructed object
351                         self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:] The object <span class="object_name">%s</span> is already destroyed.',
352                                 __CLASS__,
353                                 $this->__toString()
354                         ));
355                 } else {
356                         // Do not call this twice
357                         trigger_error(__METHOD__ . ': Called twice.');
358                         exit;
359                 }
360         }
361
362         /**
363          * The __call() method where all non-implemented methods end up
364          *
365          * @param       $methodName             Name of the missing method
366          * @args        $args                   Arguments passed to the method
367          * @return      void
368          */
369         public final function __call ($methodName, $args) {
370                 return self::__callStatic($methodName, $args);
371         }
372
373         /**
374          * The __callStatic() method where all non-implemented static methods end up
375          *
376          * @param       $methodName             Name of the missing method
377          * @args        $args                   Arguments passed to the method
378          * @return      void
379          */
380         public static final function __callStatic ($methodName, $args) {
381                 // Init argument string
382                 $argsString = '';
383
384                 // Is it empty or an array?
385                 if (empty($args)) {
386                         // No arguments
387                         $argsString = 'NULL';
388                 } elseif (is_array($args)) {
389                         // Some arguments are there
390                         foreach ($args as $arg) {
391                                 // Add the value itself if not array. This prevents 'array to string conversion' message
392                                 if (is_array($arg)) {
393                                         $argsString .= 'Array';
394                                 } else {
395                                         $argsString .= $arg;
396                                 }
397
398                                 // Add data about the argument
399                                 $argsString .= ' (' . gettype($arg);
400
401                                 if (is_string($arg)) {
402                                         // Add length for strings
403                                         $argsString .= ', ' . strlen($arg);
404                                 } elseif (is_array($arg)) {
405                                         // .. or size if array
406                                         $argsString .= ', ' . count($arg);
407                                 } elseif ($arg === TRUE) {
408                                         // ... is boolean 'TRUE'
409                                         $argsString .= ', TRUE';
410                                 } elseif ($arg === FALSE) {
411                                         // ... is boolean 'FALSE'
412                                         $argsString .= ', FALSE';
413                                 }
414
415                                 // Closing bracket
416                                 $argsString .= '), ';
417                         } // END - foreach
418
419                         // Remove last comma
420                         if (substr($argsString, -2, 1) == ',') {
421                                 $argsString = substr($argsString, 0, -2);
422                         } // END - if
423                 } else {
424                         // Invalid arguments!
425                         $argsString = '!INVALID:' . gettype($args) . '!';
426                 }
427
428                 // Output stub message
429                 // @TODO __CLASS__ does always return BaseFrameworkSystem but not the extending (=child) class
430                 self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[unknown::%s:] Stub! Args: %s',
431                         $methodName,
432                         $argsString
433                 ));
434
435                 // Return nothing
436                 return NULL;
437         }
438
439         /**
440          * Getter for $realClass
441          *
442          * @return      $realClass The name of the real class (not BaseFrameworkSystem)
443          */
444         public function __toString () {
445                 return $this->realClass;
446         }
447
448         /**
449          * Magic function to catch setting of missing but set class fields/attributes
450          *
451          * @param       $name   Name of the field/attribute
452          * @param       $value  Value to store
453          * @return      void
454          */
455         public final function __set ($name, $value) {
456                 $this->debugBackTrace(sprintf('Tried to set a missing field. name=%s, value[%s]=%s',
457                         $name,
458                         gettype($value),
459                         $value
460                 ));
461         }
462
463         /**
464          * Magic function to catch getting of missing fields/attributes
465          *
466          * @param       $name   Name of the field/attribute
467          * @return      void
468          */
469         public final function __get ($name) {
470                 $this->debugBackTrace(sprintf('Tried to get a missing field. name=%s',
471                         $name
472                 ));
473         }
474
475         /**
476          * Magic function to catch unsetting of missing fields/attributes
477          *
478          * @param       $name   Name of the field/attribute
479          * @return      void
480          */
481         public final function __unset ($name) {
482                 $this->debugBackTrace(sprintf('Tried to unset a missing field. name=%s',
483                         $name
484                 ));
485         }
486
487         /**
488          * Setter for the real class name
489          *
490          * @param       $realClass      Class name (string)
491          * @return      void
492          */
493         public final function setRealClass ($realClass) {
494                 // Set real class
495                 $this->realClass = (string) $realClass;
496         }
497
498         /**
499          * Setter for database result instance
500          *
501          * @param       $resultInstance         An instance of a database result class
502          * @return      void
503          * @todo        SearchableResult and UpdateableResult shall have a super interface to use here
504          */
505         protected final function setResultInstance (SearchableResult $resultInstance) {
506                 $this->resultInstance =  $resultInstance;
507         }
508
509         /**
510          * Getter for database result instance
511          *
512          * @return      $resultInstance         An instance of a database result class
513          */
514         public final function getResultInstance () {
515                 return $this->resultInstance;
516         }
517
518         /**
519          * Setter for template engine instances
520          *
521          * @param       $templateInstance       An instance of a template engine class
522          * @return      void
523          */
524         protected final function setTemplateInstance (CompileableTemplate $templateInstance) {
525                 $this->templateInstance = $templateInstance;
526         }
527
528         /**
529          * Getter for template engine instances
530          *
531          * @return      $templateInstance       An instance of a template engine class
532          */
533         protected final function getTemplateInstance () {
534                 return $this->templateInstance;
535         }
536
537         /**
538          * Setter for search instance
539          *
540          * @param       $searchInstance         Searchable criteria instance
541          * @return      void
542          */
543         public final function setSearchInstance (LocalSearchCriteria $searchInstance) {
544                 $this->searchInstance = $searchInstance;
545         }
546
547         /**
548          * Getter for search instance
549          *
550          * @return      $searchInstance         Searchable criteria instance
551          */
552         public final function getSearchInstance () {
553                 return $this->searchInstance;
554         }
555
556         /**
557          * Setter for update instance
558          *
559          * @param       $updateInstance         Searchable criteria instance
560          * @return      void
561          */
562         public final function setUpdateInstance (LocalUpdateCriteria $updateInstance) {
563                 $this->updateInstance = $updateInstance;
564         }
565
566         /**
567          * Getter for update instance
568          *
569          * @return      $updateInstance         Updateable criteria instance
570          */
571         public final function getUpdateInstance () {
572                 return $this->updateInstance;
573         }
574
575         /**
576          * Setter for resolver instance
577          *
578          * @param       $resolverInstance       Instance of a command resolver class
579          * @return      void
580          */
581         public final function setResolverInstance (Resolver $resolverInstance) {
582                 $this->resolverInstance = $resolverInstance;
583         }
584
585         /**
586          * Getter for resolver instance
587          *
588          * @return      $resolverInstance       Instance of a command resolver class
589          */
590         public final function getResolverInstance () {
591                 return $this->resolverInstance;
592         }
593
594         /**
595          * Setter for language instance
596          *
597          * @param       $configInstance         The configuration instance which shall
598          *                                                              be FrameworkConfiguration
599          * @return      void
600          */
601         public final function setConfigInstance (FrameworkConfiguration $configInstance) {
602                 Registry::getRegistry()->addInstance('config', $configInstance);
603         }
604
605         /**
606          * Getter for configuration instance
607          *
608          * @return      $configInstance         Configuration instance
609          */
610         public final function getConfigInstance () {
611                 $configInstance = Registry::getRegistry()->getInstance('config');
612                 return $configInstance;
613         }
614
615         /**
616          * Setter for debug instance
617          *
618          * @param       $debugInstance  The instance for debug output class
619          * @return      void
620          */
621         public final function setDebugInstance (DebugMiddleware $debugInstance) {
622                 Registry::getRegistry()->addInstance('debug', $debugInstance);
623         }
624
625         /**
626          * Getter for debug instance
627          *
628          * @return      $debugInstance  Instance to class DebugConsoleOutput or DebugWebOutput
629          */
630         public final function getDebugInstance () {
631                 // Get debug instance
632                 $debugInstance = Registry::getRegistry()->getInstance('debug');
633
634                 // Return it
635                 return $debugInstance;
636         }
637
638         /**
639          * Setter for web output instance
640          *
641          * @param       $webInstance    The instance for web output class
642          * @return      void
643          */
644         public final function setWebOutputInstance (OutputStreamer $webInstance) {
645                 Registry::getRegistry()->addInstance('web_output', $webInstance);
646         }
647
648         /**
649          * Getter for web output instance
650          *
651          * @return      $webOutputInstance - Instance to class WebOutput
652          */
653         public final function getWebOutputInstance () {
654                 $webOutputInstance = Registry::getRegistry()->getInstance('web_output');
655                 return $webOutputInstance;
656         }
657
658         /**
659          * Setter for database instance
660          *
661          * @param       $databaseInstance       The instance for the database connection (forced DatabaseConnection)
662          * @return      void
663          */
664         public final function setDatabaseInstance (DatabaseConnection $databaseInstance) {
665                 Registry::getRegistry()->addInstance('db_instance', $databaseInstance);
666         }
667
668         /**
669          * Getter for database layer
670          *
671          * @return      $databaseInstance       The database layer instance
672          */
673         public final function getDatabaseInstance () {
674                 // Get instance
675                 $databaseInstance = Registry::getRegistry()->getInstance('db_instance');
676
677                 // Return instance
678                 return $databaseInstance;
679         }
680
681         /**
682          * Setter for compressor channel
683          *
684          * @param       $compressorInstance             An instance of CompressorChannel
685          * @return      void
686          */
687         public final function setCompressorChannel (CompressorChannel $compressorInstance) {
688                 Registry::getRegistry()->addInstance('compressor', $compressorInstance);
689         }
690
691         /**
692          * Getter for compressor channel
693          *
694          * @return      $compressorInstance             The compressor channel
695          */
696         public final function getCompressorChannel () {
697                 $compressorInstance = Registry::getRegistry()->getInstance('compressor');
698                 return $compressorInstance;
699         }
700
701         /**
702          * Protected getter for a manageable application helper class
703          *
704          * @return      $applicationInstance    An instance of a manageable application helper class
705          */
706         protected final function getApplicationInstance () {
707                 $applicationInstance = Registry::getRegistry()->getInstance('application');
708                 return $applicationInstance;
709         }
710
711         /**
712          * Setter for a manageable application helper class
713          *
714          * @param       $applicationInstance    An instance of a manageable application helper class
715          * @return      void
716          */
717         public final function setApplicationInstance (ManageableApplication $applicationInstance) {
718                 Registry::getRegistry()->addInstance('application', $applicationInstance);
719         }
720
721         /**
722          * Setter for request instance
723          *
724          * @param       $requestInstance        An instance of a Requestable class
725          * @return      void
726          */
727         public final function setRequestInstance (Requestable $requestInstance) {
728                 $this->requestInstance = $requestInstance;
729         }
730
731         /**
732          * Getter for request instance
733          *
734          * @return      $requestInstance        An instance of a Requestable class
735          */
736         public final function getRequestInstance () {
737                 return $this->requestInstance;
738         }
739
740         /**
741          * Setter for response instance
742          *
743          * @param       $responseInstance       An instance of a Responseable class
744          * @return      void
745          */
746         public final function setResponseInstance (Responseable $responseInstance) {
747                 $this->responseInstance = $responseInstance;
748         }
749
750         /**
751          * Getter for response instance
752          *
753          * @return      $responseInstance       An instance of a Responseable class
754          */
755         public final function getResponseInstance () {
756                 return $this->responseInstance;
757         }
758
759         /**
760          * Private getter for language instance
761          *
762          * @return      $langInstance   An instance to the language sub-system
763          */
764         protected final function getLanguageInstance () {
765                 $langInstance = Registry::getRegistry()->getInstance('language');
766                 return $langInstance;
767         }
768
769         /**
770          * Setter for language instance
771          *
772          * @param       $langInstance   An instance to the language sub-system
773          * @return      void
774          * @see         LanguageSystem
775          */
776         public final function setLanguageInstance (ManageableLanguage $langInstance) {
777                 Registry::getRegistry()->addInstance('language', $langInstance);
778         }
779
780         /**
781          * Private getter for file IO instance
782          *
783          * @return      $fileIoInstance         An instance to the file I/O sub-system
784          */
785         protected final function getFileIoInstance () {
786                 return $this->fileIoInstance;
787         }
788
789         /**
790          * Setter for file I/O instance
791          *
792          * @param       $fileIoInstance         An instance to the file I/O sub-system
793          * @return      void
794          */
795         public final function setFileIoInstance (IoHandler $fileIoInstance) {
796                 $this->fileIoInstance = $fileIoInstance;
797         }
798
799         /**
800          * Protected setter for user instance
801          *
802          * @param       $userInstance   An instance of a user class
803          * @return      void
804          */
805         protected final function setUserInstance (ManageableAccount $userInstance) {
806                 $this->userInstance = $userInstance;
807         }
808
809         /**
810          * Getter for user instance
811          *
812          * @return      $userInstance   An instance of a user class
813          */
814         public final function getUserInstance () {
815                 return $this->userInstance;
816         }
817
818         /**
819          * Setter for controller instance (this surely breaks a bit the MVC patterm)
820          *
821          * @param       $controllerInstance             An instance of the controller
822          * @return      void
823          */
824         public final function setControllerInstance (Controller $controllerInstance) {
825                 $this->controllerInstance = $controllerInstance;
826         }
827
828         /**
829          * Getter for controller instance (this surely breaks a bit the MVC patterm)
830          *
831          * @return      $controllerInstance             An instance of the controller
832          */
833         public final function getControllerInstance () {
834                 return $this->controllerInstance;
835         }
836
837         /**
838          * Setter for RNG instance
839          *
840          * @param       $rngInstance    An instance of a random number generator (RNG)
841          * @return      void
842          */
843         protected final function setRngInstance (RandomNumberGenerator $rngInstance) {
844                 $this->rngInstance = $rngInstance;
845         }
846
847         /**
848          * Getter for RNG instance
849          *
850          * @return      $rngInstance    An instance of a random number generator (RNG)
851          */
852         public final function getRngInstance () {
853                 return $this->rngInstance;
854         }
855
856         /**
857          * Setter for Cryptable instance
858          *
859          * @param       $cryptoInstance An instance of a Cryptable class
860          * @return      void
861          */
862         protected final function setCryptoInstance (Cryptable $cryptoInstance) {
863                 $this->cryptoInstance = $cryptoInstance;
864         }
865
866         /**
867          * Getter for Cryptable instance
868          *
869          * @return      $cryptoInstance An instance of a Cryptable class
870          */
871         public final function getCryptoInstance () {
872                 return $this->cryptoInstance;
873         }
874
875         /**
876          * Setter for the list instance
877          *
878          * @param       $listInstance   A list of Listable
879          * @return      void
880          */
881         protected final function setListInstance (Listable $listInstance) {
882                 $this->listInstance = $listInstance;
883         }
884
885         /**
886          * Getter for the list instance
887          *
888          * @return      $listInstance   A list of Listable
889          */
890         protected final function getListInstance () {
891                 return $this->listInstance;
892         }
893
894         /**
895          * Setter for the menu instance
896          *
897          * @param       $menuInstance   A RenderableMenu instance
898          * @return      void
899          */
900         protected final function setMenuInstance (RenderableMenu $menuInstance) {
901                 $this->menuInstance = $menuInstance;
902         }
903
904         /**
905          * Getter for the menu instance
906          *
907          * @return      $menuInstance   A RenderableMenu instance
908          */
909         protected final function getMenuInstance () {
910                 return $this->menuInstance;
911         }
912
913         /**
914          * Setter for image instance
915          *
916          * @param       $imageInstance  An instance of an image
917          * @return      void
918          */
919         public final function setImageInstance (BaseImage $imageInstance) {
920                 $this->imageInstance = $imageInstance;
921         }
922
923         /**
924          * Getter for image instance
925          *
926          * @return      $imageInstance  An instance of an image
927          */
928         public final function getImageInstance () {
929                 return $this->imageInstance;
930         }
931
932         /**
933          * Setter for stacker instance
934          *
935          * @param       $stackerInstance        An instance of an stacker
936          * @return      void
937          */
938         public final function setStackerInstance (Stackable $stackerInstance) {
939                 $this->stackerInstance = $stackerInstance;
940         }
941
942         /**
943          * Getter for stacker instance
944          *
945          * @return      $stackerInstance        An instance of an stacker
946          */
947         public final function getStackerInstance () {
948                 return $this->stackerInstance;
949         }
950
951         /**
952          * Setter for compressor instance
953          *
954          * @param       $compressorInstance     An instance of an compressor
955          * @return      void
956          */
957         public final function setCompressorInstance (Compressor $compressorInstance) {
958                 $this->compressorInstance = $compressorInstance;
959         }
960
961         /**
962          * Getter for compressor instance
963          *
964          * @return      $compressorInstance     An instance of an compressor
965          */
966         public final function getCompressorInstance () {
967                 return $this->compressorInstance;
968         }
969
970         /**
971          * Setter for Parseable instance
972          *
973          * @param       $parserInstance An instance of an Parseable
974          * @return      void
975          */
976         public final function setParserInstance (Parseable $parserInstance) {
977                 $this->parserInstance = $parserInstance;
978         }
979
980         /**
981          * Getter for Parseable instance
982          *
983          * @return      $parserInstance An instance of an Parseable
984          */
985         public final function getParserInstance () {
986                 return $this->parserInstance;
987         }
988
989         /**
990          * Setter for ProtocolHandler instance
991          *
992          * @param       $protocolInstance       An instance of an ProtocolHandler
993          * @return      void
994          */
995         public final function setProtocolInstance (ProtocolHandler $protocolInstance = NULL) {
996                 $this->protocolInstance = $protocolInstance;
997         }
998
999         /**
1000          * Getter for ProtocolHandler instance
1001          *
1002          * @return      $protocolInstance       An instance of an ProtocolHandler
1003          */
1004         public final function getProtocolInstance () {
1005                 return $this->protocolInstance;
1006         }
1007
1008         /**
1009          * Setter for DatabaseWrapper instance
1010          *
1011          * @param       $wrapperInstance        An instance of an DatabaseWrapper
1012          * @return      void
1013          */
1014         public final function setWrapperInstance (DatabaseWrapper $wrapperInstance) {
1015                 $this->wrapperInstance = $wrapperInstance;
1016         }
1017
1018         /**
1019          * Getter for DatabaseWrapper instance
1020          *
1021          * @return      $wrapperInstance        An instance of an DatabaseWrapper
1022          */
1023         public final function getWrapperInstance () {
1024                 return $this->wrapperInstance;
1025         }
1026
1027         /**
1028          * Setter for socket resource
1029          *
1030          * @param       $socketResource         A valid socket resource
1031          * @return      void
1032          */
1033         public final function setSocketResource ($socketResource) {
1034                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput($this->__toString() . '::' . __FUNCTION__ . ': socketResource=' . $socketResource . ',previous[' . gettype($this->socketResource) . ']=' . $this->socketResource);
1035                 $this->socketResource = $socketResource;
1036         }
1037
1038         /**
1039          * Getter for socket resource
1040          *
1041          * @return      $socketResource         A valid socket resource
1042          */
1043         public final function getSocketResource () {
1044                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput($this->__toString() . '::' . __FUNCTION__ . ': socketResource[' . gettype($this->socketResource) . ']=' . $this->socketResource);
1045                 return $this->socketResource;
1046         }
1047
1048         /**
1049          * Setter for helper instance
1050          *
1051          * @param       $helperInstance         An instance of a helper class
1052          * @return      void
1053          */
1054         protected final function setHelperInstance (Helper $helperInstance) {
1055                 $this->helperInstance = $helperInstance;
1056         }
1057
1058         /**
1059          * Getter for helper instance
1060          *
1061          * @return      $helperInstance         An instance of a helper class
1062          */
1063         public final function getHelperInstance () {
1064                 return $this->helperInstance;
1065         }
1066
1067         /**
1068          * Setter for a Sourceable instance
1069          *
1070          * @param       $sourceInstance The Sourceable instance
1071          * @return      void
1072          */
1073         protected final function setSourceInstance (Sourceable $sourceInstance) {
1074                 $this->sourceInstance = $sourceInstance;
1075         }
1076
1077         /**
1078          * Getter for a Sourceable instance
1079          *
1080          * @return      $sourceInstance The Sourceable instance
1081          */
1082         protected final function getSourceInstance () {
1083                 return $this->sourceInstance;
1084         }
1085
1086         /**
1087          * Getter for a InputStreamable instance
1088          *
1089          * @param       $inputStreamInstance    The InputStreamable instance
1090          */
1091         protected final function getInputStreamInstance () {
1092                 return $this->inputStreamInstance;
1093         }
1094
1095         /**
1096          * Setter for a InputStreamable instance
1097          *
1098          * @param       $inputStreamInstance    The InputStreamable instance
1099          * @return      void
1100          */
1101         protected final function setInputStreamInstance (InputStreamable $inputStreamInstance) {
1102                 $this->inputStreamInstance = $inputStreamInstance;
1103         }
1104
1105         /**
1106          * Getter for a OutputStreamable instance
1107          *
1108          * @param       $outputStreamInstance   The OutputStreamable instance
1109          */
1110         protected final function getOutputStreamInstance () {
1111                 return $this->outputStreamInstance;
1112         }
1113
1114         /**
1115          * Setter for a OutputStreamable instance
1116          *
1117          * @param       $outputStreamInstance   The OutputStreamable instance
1118          * @return      void
1119          */
1120         protected final function setOutputStreamInstance (OutputStreamable $outputStreamInstance) {
1121                 $this->outputStreamInstance = $outputStreamInstance;
1122         }
1123
1124         /**
1125          * Setter for handler instance
1126          *
1127          * @param       $handlerInstance        An instance of a Handleable class
1128          * @return      void
1129          */
1130         protected final function setHandlerInstance (Handleable $handlerInstance) {
1131                 $this->handlerInstance = $handlerInstance;
1132         }
1133
1134         /**
1135          * Getter for handler instance
1136          *
1137          * @return      $handlerInstance        A Networkable instance
1138          */
1139         protected final function getHandlerInstance () {
1140                 return $this->handlerInstance;
1141         }
1142
1143         /**
1144          * Setter for visitor instance
1145          *
1146          * @param       $visitorInstance        A Visitor instance
1147          * @return      void
1148          */
1149         protected final function setVisitorInstance (Visitor $visitorInstance) {
1150                 $this->visitorInstance = $visitorInstance;
1151         }
1152
1153         /**
1154          * Getter for visitor instance
1155          *
1156          * @return      $visitorInstance        A Visitor instance
1157          */
1158         protected final function getVisitorInstance () {
1159                 return $this->visitorInstance;
1160         }
1161
1162         /**
1163          * Setter for DHT instance
1164          *
1165          * @param       $dhtInstance    A Distributable instance
1166          * @return      void
1167          */
1168         protected final function setDhtInstance (Distributable $dhtInstance) {
1169                 $this->dhtInstance = $dhtInstance;
1170         }
1171
1172         /**
1173          * Getter for DHT instance
1174          *
1175          * @return      $dhtInstance    A Distributable instance
1176          */
1177         protected final function getDhtInstance () {
1178                 return $this->dhtInstance;
1179         }
1180
1181         /**
1182          * Setter for raw package Data
1183          *
1184          * @param       $packageData    Raw package Data
1185          * @return      void
1186          */
1187         public final function setPackageData (array $packageData) {
1188                 $this->packageData = $packageData;
1189         }
1190
1191         /**
1192          * Getter for raw package Data
1193          *
1194          * @return      $packageData    Raw package Data
1195          */
1196         public function getPackageData () {
1197                 return $this->packageData;
1198         }
1199
1200
1201         /**
1202          * Setter for Iterator instance
1203          *
1204          * @param       $iteratorInstance       An instance of an Iterator
1205          * @return      void
1206          */
1207         protected final function setIteratorInstance (Iterator $iteratorInstance) {
1208                 $this->iteratorInstance = $iteratorInstance;
1209         }
1210
1211         /**
1212          * Getter for Iterator instance
1213          *
1214          * @return      $iteratorInstance       An instance of an Iterator
1215          */
1216         public final function getIteratorInstance () {
1217                 return $this->iteratorInstance;
1218         }
1219
1220         /**
1221          * Checks whether an object equals this object. You should overwrite this
1222          * method to implement own equality checks
1223          *
1224          * @param       $objectInstance         An instance of a FrameworkInterface object
1225          * @return      $equals                         Whether both objects equals
1226          */
1227         public function equals (FrameworkInterface $objectInstance) {
1228                 // Now test it
1229                 $equals = ((
1230                         $this->__toString() == $objectInstance->__toString()
1231                 ) && (
1232                         $this->hashCode() == $objectInstance->hashCode()
1233                 ));
1234
1235                 // Return the result
1236                 return $equals;
1237         }
1238
1239         /**
1240          * Generates a generic hash code of this class. You should really overwrite
1241          * this method with your own hash code generator code. But keep KISS in mind.
1242          *
1243          * @return      $hashCode       A generic hash code respresenting this whole class
1244          */
1245         public function hashCode () {
1246                 // Simple hash code
1247                 return crc32($this->__toString());
1248         }
1249
1250         /**
1251          * Formats computer generated price values into human-understandable formats
1252          * with thousand and decimal separators.
1253          *
1254          * @param       $value          The in computer format value for a price
1255          * @param       $currency       The currency symbol (use HTML-valid characters!)
1256          * @param       $decNum         Number of decimals after commata
1257          * @return      $price          The for the current language formated price string
1258          * @throws      MissingDecimalsThousandsSeparatorException      If decimals or
1259          *                                                                                              thousands separator
1260          *                                                                                              is missing
1261          */
1262         public function formatCurrency ($value, $currency = '&euro;', $decNum = 2) {
1263                 // Are all required attriutes set?
1264                 if ((!isset($this->decimals)) || (!isset($this->thousands))) {
1265                         // Throw an exception
1266                         throw new MissingDecimalsThousandsSeparatorException($this, self::EXCEPTION_ATTRIBUTES_ARE_MISSING);
1267                 } // END - if
1268
1269                 // Cast the number
1270                 $value = (float) $value;
1271
1272                 // Reformat the US number
1273                 $price = number_format($value, $decNum, $this->decimals, $this->thousands) . $currency;
1274
1275                 // Return as string...
1276                 return $price;
1277         }
1278
1279         /**
1280          * Appends a trailing slash to a string
1281          *
1282          * @param       $str    A string (maybe) without trailing slash
1283          * @return      $str    A string with an auto-appended trailing slash
1284          */
1285         public final function addMissingTrailingSlash ($str) {
1286                 // Is there a trailing slash?
1287                 if (substr($str, -1, 1) != '/') {
1288                         $str .= '/';
1289                 } // END - if
1290
1291                 // Return string with trailing slash
1292                 return $str;
1293         }
1294
1295         /**
1296          * Prepare the template engine (WebTemplateEngine by default) for a given
1297          * application helper instance (ApplicationHelper by default).
1298          *
1299          * @param               $applicationInstance    An application helper instance or
1300          *                                                                              null if we shall use the default
1301          * @return              $templateInstance               The template engine instance
1302          * @throws              NullPointerException    If the discovered application
1303          *                                                                              instance is still null
1304          */
1305         protected function prepareTemplateInstance (ManageableApplication $applicationInstance = NULL) {
1306                 // Is the application instance set?
1307                 if (is_null($applicationInstance)) {
1308                         // Get the current instance
1309                         $applicationInstance = $this->getApplicationInstance();
1310
1311                         // Still null?
1312                         if (is_null($applicationInstance)) {
1313                                 // Thrown an exception
1314                                 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
1315                         } // END - if
1316                 } // END - if
1317
1318                 // Initialize the template engine
1319                 $templateInstance = ObjectFactory::createObjectByConfiguredName('web_template_class');
1320
1321                 // Return the prepared instance
1322                 return $templateInstance;
1323         }
1324
1325         /**
1326          * Debugs this instance by putting out it's full content
1327          *
1328          * @param       $message        Optional message to show in debug output
1329          * @return      void
1330          */
1331         public final function debugInstance ($message = '') {
1332                 // Restore the error handler to avoid trouble with missing array elements or undeclared variables
1333                 restore_error_handler();
1334
1335                 // Init content
1336                 $content = '';
1337
1338                 // Is a message set?
1339                 if (!empty($message)) {
1340                         // Construct message
1341                         $content = sprintf('<div class="debug_message">Message: %s</div>' . PHP_EOL, $message);
1342                 } // END - if
1343
1344                 // Generate the output
1345                 $content .= sprintf('<pre>%s</pre>',
1346                         trim(
1347                                 htmlentities(
1348                                         print_r($this, TRUE)
1349                                 )
1350                         )
1351                 );
1352
1353                 // Output it
1354                 ApplicationEntryPoint::app_exit(sprintf('<div class="debug_header">%s debug output:</div><div class="debug_content">%s</div>Loaded includes: <div class="debug_include_list">%s</div>',
1355                         $this->__toString(),
1356                         $content,
1357                         ClassLoader::getSelfInstance()->getPrintableIncludeList()
1358                 ));
1359         }
1360
1361         /**
1362          * Replaces control characters with printable output
1363          *
1364          * @param       $str    String with control characters
1365          * @return      $str    Replaced string
1366          */
1367         protected function replaceControlCharacters ($str) {
1368                 // Replace them
1369                 $str = str_replace(
1370                         chr(13), '[r]', str_replace(
1371                         chr(10), '[n]', str_replace(
1372                         chr(9) , '[t]',
1373                         $str
1374                 )));
1375
1376                 // Return it
1377                 return $str;
1378         }
1379
1380         /**
1381          * Output a partial stub message for the caller method
1382          *
1383          * @param       $message        An optional message to display
1384          * @return      void
1385          */
1386         protected function partialStub ($message = '') {
1387                 // Get the backtrace
1388                 $backtrace = debug_backtrace();
1389
1390                 // Generate the class::method string
1391                 $methodName = 'UnknownClass-&gt;unknownMethod';
1392                 if ((isset($backtrace[1]['class'])) && (isset($backtrace[1]['function']))) {
1393                         $methodName = $backtrace[1]['class'] . '-&gt;' . $backtrace[1]['function'];
1394                 } // END - if
1395
1396                 // Construct the full message
1397                 $stubMessage = sprintf('[%s:] Partial stub!',
1398                         $methodName
1399                 );
1400
1401                 // Is the extra message given?
1402                 if (!empty($message)) {
1403                         // Then add it as well
1404                         $stubMessage .= ' Message: ' . $message;
1405                 } // END - if
1406
1407                 // Debug instance is there?
1408                 if (!is_null($this->getDebugInstance())) {
1409                         // Output stub message
1410                         self::createDebugInstance(__CLASS__)->debugOutput($stubMessage);
1411                 } else {
1412                         // Trigger an error
1413                         trigger_error($stubMessage);
1414                         exit;
1415                 }
1416         }
1417
1418         /**
1419          * Outputs a debug backtrace and stops further script execution
1420          *
1421          * @param       $message        An optional message to output
1422          * @param       $doExit         Whether exit the program (TRUE is default)
1423          * @return      void
1424          */
1425         public function debugBackTrace ($message = '', $doExit = TRUE) {
1426                 // Sorry, there is no other way getting this nice backtrace
1427                 if (!empty($message)) {
1428                         // Output message
1429                         printf('Message: %s<br />' . chr(10), $message);
1430                 } // END - if
1431
1432                 print('<pre>');
1433                 debug_print_backtrace();
1434                 print('</pre>');
1435
1436                 // Exit program?
1437                 if ($doExit === TRUE) {
1438                         exit();
1439                 } // END - if
1440         }
1441
1442         /**
1443          * Creates an instance of a debugger instance
1444          *
1445          * @param       $className              Name of the class (currently unsupported)
1446          * @return      $debugInstance  An instance of a debugger class
1447          */
1448         public final static function createDebugInstance ($className) {
1449                 // Init debug instance
1450                 $debugInstance = NULL;
1451
1452                 // Try it
1453                 try {
1454                         // Get a debugger instance
1455                         $debugInstance = DebugMiddleware::createDebugMiddleware(FrameworkConfiguration::getSelfInstance()->getConfigEntry('debug_class'));
1456                 } catch (NullPointerException $e) {
1457                         // Didn't work, no instance there
1458                         exit('Cannot create debugInstance! Exception=' . $e->__toString() . ', message=' . $e->getMessage());
1459                 }
1460
1461                 // Empty string should be ignored and used for testing the middleware
1462                 DebugMiddleware::getSelfInstance()->output('');
1463
1464                 // Return it
1465                 return $debugInstance;
1466         }
1467
1468         /**
1469          * Simple output of a message with line-break
1470          *
1471          * @param       $message        Message to output
1472          * @return      void
1473          */
1474         public function outputLine ($message) {
1475                 // Simply output it
1476                 print($message . PHP_EOL);
1477         }
1478
1479         /**
1480          * Outputs a debug message whether to debug instance (should be set!) or
1481          * dies with or ptints the message. Do NEVER EVER rewrite the exit() call to
1482          * ApplicationEntryPoint::app_exit(), this would cause an endless loop.
1483          *
1484          * @param       $message        Message we shall send out...
1485          * @param       $doPrint        Whether print or die here (default: print)
1486          * @paran       $stripTags      Whether to strip tags (default: FALSE)
1487          * @return      void
1488          */
1489         public function debugOutput ($message, $doPrint = TRUE, $stripTags = FALSE) {
1490                 // Set debug instance to NULL
1491                 $debugInstance = NULL;
1492
1493                 // Try it:
1494                 try {
1495                         // Get debug instance
1496                         $debugInstance = $this->getDebugInstance();
1497                 } catch (NullPointerException $e) {
1498                         // The debug instance is not set (yet)
1499                 }
1500
1501                 // Is the debug instance there?
1502                 if (is_object($debugInstance)) {
1503                         // Use debug output handler
1504                         $debugInstance->output($message, $stripTags);
1505
1506                         if ($doPrint === FALSE) {
1507                                 // Die here if not printed
1508                                 exit();
1509                         } // END - if
1510                 } else {
1511                         // Are debug times enabled?
1512                         if ($this->getConfigInstance()->getConfigEntry('debug_output_timings') == 'Y') {
1513                                 // Prepent it
1514                                 $message = $this->getPrintableExecutionTime() . $message;
1515                         } // END - if
1516
1517                         // Put directly out
1518                         if ($doPrint === TRUE) {
1519                                 // Print message
1520                                 $this->outputLine($message);
1521                         } else {
1522                                 // Die here
1523                                 exit($message);
1524                         }
1525                 }
1526         }
1527
1528         /**
1529          * Converts e.g. a command from URL to a valid class by keeping out bad characters
1530          *
1531          * @param       $str            The string, what ever it is needs to be converted
1532          * @return      $className      Generated class name
1533          */
1534         public function convertToClassName ($str) {
1535                 // Init class name
1536                 $className = '';
1537
1538                 // Convert all dashes in underscores
1539                 $str = $this->convertDashesToUnderscores($str);
1540
1541                 // Now use that underscores to get classname parts for hungarian style
1542                 foreach (explode('_', $str) as $strPart) {
1543                         // Make the class name part lower case and first upper case
1544                         $className .= ucfirst(strtolower($strPart));
1545                 } // END - foreach
1546
1547                 // Return class name
1548                 return $className;
1549         }
1550
1551         /**
1552          * Converts dashes to underscores, e.g. useable for configuration entries
1553          *
1554          * @param       $str    The string with maybe dashes inside
1555          * @return      $str    The converted string with no dashed, but underscores
1556          */
1557         public final function convertDashesToUnderscores ($str) {
1558                 // Convert them all
1559                 $str = str_replace('-', '_', $str);
1560
1561                 // Return converted string
1562                 return $str;
1563         }
1564
1565         /**
1566          * Marks up the code by adding e.g. line numbers
1567          *
1568          * @param       $phpCode                Unmarked PHP code
1569          * @return      $markedCode             Marked PHP code
1570          */
1571         public function markupCode ($phpCode) {
1572                 // Init marked code
1573                 $markedCode = '';
1574
1575                 // Get last error
1576                 $errorArray = error_get_last();
1577
1578                 // Init the code with error message
1579                 if (is_array($errorArray)) {
1580                         // Get error infos
1581                         $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>',
1582                                 basename($errorArray['file']),
1583                                 $errorArray['line'],
1584                                 $errorArray['message'],
1585                                 $errorArray['type']
1586                         );
1587                 } // END - if
1588
1589                 // Add line number to the code
1590                 foreach (explode(chr(10), $phpCode) as $lineNo => $code) {
1591                         // Add line numbers
1592                         $markedCode .= sprintf('<span id="code_line">%s</span>: %s' . chr(10),
1593                                 ($lineNo + 1),
1594                                 htmlentities($code, ENT_QUOTES)
1595                         );
1596                 } // END - foreach
1597
1598                 // Return the code
1599                 return $markedCode;
1600         }
1601
1602         /**
1603          * Filter a given GMT timestamp (non Uni* stamp!) to make it look more
1604          * beatiful for web-based front-ends. If null is given a message id
1605          * null_timestamp will be resolved and returned.
1606          *
1607          * @param       $timestamp      Timestamp to prepare (filter) for display
1608          * @return      $readable       A readable timestamp
1609          */
1610         public function doFilterFormatTimestamp ($timestamp) {
1611                 // Default value to return
1612                 $readable = '???';
1613
1614                 // Is the timestamp null?
1615                 if (is_null($timestamp)) {
1616                         // Get a message string
1617                         $readable = $this->getLanguageInstance()->getMessage('null_timestamp');
1618                 } else {
1619                         switch ($this->getLanguageInstance()->getLanguageCode()) {
1620                                 case 'de': // German format is a bit different to default
1621                                         // Split the GMT stamp up
1622                                         $dateTime  = explode(' ', $timestamp  );
1623                                         $dateArray = explode('-', $dateTime[0]);
1624                                         $timeArray = explode(':', $dateTime[1]);
1625
1626                                         // Construct the timestamp
1627                                         $readable = sprintf($this->getConfigInstance()->getConfigEntry('german_date_time'),
1628                                                 $dateArray[0],
1629                                                 $dateArray[1],
1630                                                 $dateArray[2],
1631                                                 $timeArray[0],
1632                                                 $timeArray[1],
1633                                                 $timeArray[2]
1634                                         );
1635                                         break;
1636
1637                                 default: // Default is pass-through
1638                                         $readable = $timestamp;
1639                                         break;
1640                         } // END - switch
1641                 }
1642
1643                 // Return the stamp
1644                 return $readable;
1645         }
1646
1647         /**
1648          * Filter a given number into a localized number
1649          *
1650          * @param       $value          The raw value from e.g. database
1651          * @return      $localized      Localized value
1652          */
1653         public function doFilterFormatNumber ($value) {
1654                 // Generate it from config and localize dependencies
1655                 switch ($this->getLanguageInstance()->getLanguageCode()) {
1656                         case 'de': // German format is a bit different to default
1657                                 $localized = number_format($value, $this->getConfigInstance()->getConfigEntry('decimals'), ',', '.');
1658                                 break;
1659
1660                         default: // US, etc.
1661                                 $localized = number_format($value, $this->getConfigInstance()->getConfigEntry('decimals'), '.', ',');
1662                                 break;
1663                 } // END - switch
1664
1665                 // Return it
1666                 return $localized;
1667         }
1668
1669         /**
1670          * "Getter" for databse entry
1671          *
1672          * @return      $entry  An array with database entries
1673          * @throws      NullPointerException    If the database result is not found
1674          * @throws      InvalidDatabaseResultException  If the database result is invalid
1675          */
1676         protected final function getDatabaseEntry () {
1677                 // Is there an instance?
1678                 if (is_null($this->getResultInstance())) {
1679                         // Throw an exception here
1680                         throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
1681                 } // END - if
1682
1683                 // Rewind it
1684                 $this->getResultInstance()->rewind();
1685
1686                 // Do we have an entry?
1687                 if ($this->getResultInstance()->valid() === FALSE) {
1688                         throw new InvalidDatabaseResultException(array($this, $this->getResultInstance()), DatabaseResult::EXCEPTION_INVALID_DATABASE_RESULT);
1689                 } // END - if
1690
1691                 // Get next entry
1692                 $this->getResultInstance()->next();
1693
1694                 // Fetch it
1695                 $entry = $this->getResultInstance()->current();
1696
1697                 // And return it
1698                 return $entry;
1699         }
1700
1701         /**
1702          * Getter for field name
1703          *
1704          * @param       $fieldName              Field name which we shall get
1705          * @return      $fieldValue             Field value from the user
1706          * @throws      NullPointerException    If the result instance is null
1707          */
1708         public final function getField ($fieldName) {
1709                 // Default field value
1710                 $fieldValue = NULL;
1711
1712                 // Get result instance
1713                 $resultInstance = $this->getResultInstance();
1714
1715                 // Is this instance null?
1716                 if (is_null($resultInstance)) {
1717                         // Then the user instance is no longer valid (expired cookies?)
1718                         throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
1719                 } // END - if
1720
1721                 // Get current array
1722                 $fieldArray = $resultInstance->current();
1723                 //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput($fieldName.':<pre>'.print_r($fieldArray, TRUE).'</pre>');
1724
1725                 // Convert dashes to underscore
1726                 $fieldName = $this->convertDashesToUnderscores($fieldName);
1727
1728                 // Does the field exist?
1729                 if (isset($fieldArray[$fieldName])) {
1730                         // Get it
1731                         $fieldValue = $fieldArray[$fieldName];
1732                 } else {
1733                         // Missing field entry, may require debugging
1734                         self::createDebugInstance(__CLASS__)->debugOutput($this->__toString() . ':fieldname=' . $fieldName . ' not found!');
1735                 }
1736
1737                 // Return it
1738                 return $fieldValue;
1739         }
1740
1741         /**
1742          * Flushs all pending updates to the database layer
1743          *
1744          * @return      void
1745          */
1746         public function flushPendingUpdates () {
1747                 // Get result instance
1748                 $resultInstance = $this->getResultInstance();
1749
1750                 // Do we have data to update?
1751                 if ((is_object($resultInstance)) && ($resultInstance->ifDataNeedsFlush())) {
1752                         // Get wrapper class name config entry
1753                         $configEntry = $resultInstance->getUpdateInstance()->getWrapperConfigEntry();
1754
1755                         // Create object instance
1756                         $wrapperInstance = ObjectFactory::createObjectByConfiguredName($configEntry);
1757
1758                         // Yes, then send the whole result to the database layer
1759                         $wrapperInstance->doUpdateByResult($this->getResultInstance());
1760                 } // END - if
1761         }
1762
1763         /**
1764          * Outputs a deprecation warning to the developer.
1765          *
1766          * @param       $message        The message we shall output to the developer
1767          * @return      void
1768          * @todo        Write a logging mechanism for productive mode
1769          */
1770         public function deprecationWarning ($message) {
1771                 // Is developer mode active?
1772                 if (defined('DEVELOPER')) {
1773                         // Debug instance is there?
1774                         if (!is_null($this->getDebugInstance())) {
1775                                 // Output stub message
1776                                 self::createDebugInstance(__CLASS__)->debugOutput($message);
1777                         } else {
1778                                 // Trigger an error
1779                                 trigger_error($message . "<br />\n");
1780                                 exit;
1781                         }
1782                 } else {
1783                         // @TODO Finish this part!
1784                         $this->partialStub('Developer mode inactive. Message:' . $message);
1785                 }
1786         }
1787
1788         /**
1789          * Checks whether the given PHP extension is loaded
1790          *
1791          * @param       $phpExtension   The PHP extension we shall check
1792          * @return      $isLoaded       Whether the PHP extension is loaded
1793          */
1794         public final function isPhpExtensionLoaded ($phpExtension) {
1795                 // Is it loaded?
1796                 $isLoaded = in_array($phpExtension, get_loaded_extensions());
1797
1798                 // Return result
1799                 return $isLoaded;
1800         }
1801
1802         /**
1803          * "Getter" as a time() replacement but with milliseconds. You should use this
1804          * method instead of the encapsulated getimeofday() function.
1805          *
1806          * @return      $milliTime      Timestamp with milliseconds
1807          */
1808         public function getMilliTime () {
1809                 // Get the time of day as float
1810                 $milliTime = gettimeofday(TRUE);
1811
1812                 // Return it
1813                 return $milliTime;
1814         }
1815
1816         /**
1817          * Idles (sleeps) for given milliseconds
1818          *
1819          * @return      $hasSlept       Whether it goes fine
1820          */
1821         public function idle ($milliSeconds) {
1822                 // Sleep is fine by default
1823                 $hasSlept = TRUE;
1824
1825                 // Idle so long with found function
1826                 if (function_exists('time_sleep_until')) {
1827                         // Get current time and add idle time
1828                         $sleepUntil = $this->getMilliTime() + abs($milliSeconds) / 1000;
1829
1830                         // New PHP 5.1.0 function found, ignore errors
1831                         $hasSlept = @time_sleep_until($sleepUntil);
1832                 } else {
1833                         /*
1834                          * My Sun station doesn't have that function even with latest PHP
1835                          * package. :(
1836                          */
1837                         usleep($milliSeconds * 1000);
1838                 }
1839
1840                 // Return result
1841                 return $hasSlept;
1842         }
1843         /**
1844          * Converts a hexadecimal string, even with negative sign as first string to
1845          * a decimal number using BC functions.
1846          *
1847          * This work is based on comment #86673 on php.net documentation page at:
1848          * <http://de.php.net/manual/en/function.dechex.php#86673>
1849          *
1850          * @param       $hex    Hexadecimal string
1851          * @return      $dec    Decimal number
1852          */
1853         protected function hex2dec ($hex) {
1854                 // Convert to all lower-case
1855                 $hex = strtolower($hex);
1856
1857                 // Detect sign (negative/positive numbers)
1858                 $sign = '';
1859                 if (substr($hex, 0, 1) == '-') {
1860                         $sign = '-';
1861                         $hex = substr($hex, 1);
1862                 } // END - if
1863
1864                 // Decode the hexadecimal string into a decimal number
1865                 $dec = 0;
1866                 for ($i = strlen($hex) - 1, $e = 1; $i >= 0; $i--, $e = bcmul($e, 16)) {
1867                         $factor = self::$hexdec[substr($hex, $i, 1)];
1868                         $dec = bcadd($dec, bcmul($factor, $e));
1869                 } // END - for
1870
1871                 // Return the decimal number
1872                 return $sign . $dec;
1873         }
1874
1875         /**
1876          * Converts even very large decimal numbers, also signed, to a hexadecimal
1877          * string.
1878          *
1879          * This work is based on comment #97756 on php.net documentation page at:
1880          * <http://de.php.net/manual/en/function.hexdec.php#97756>
1881          *
1882          * @param       $dec            Decimal number, even with negative sign
1883          * @param       $maxLength      Optional maximum length of the string
1884          * @return      $hex    Hexadecimal string
1885          */
1886         protected function dec2hex ($dec, $maxLength = 0) {
1887                 // maxLength can be zero or devideable by 2
1888                 assert(($maxLength == 0) || (($maxLength % 2) == 0));
1889
1890                 // Detect sign (negative/positive numbers)
1891                 $sign = '';
1892                 if ($dec < 0) {
1893                         $sign = '-';
1894                         $dec = abs($dec);
1895                 } // END - if
1896
1897                 // Encode the decimal number into a hexadecimal string
1898                 $hex = '';
1899                 do {
1900                         $hex = self::$dechex[($dec % (2 ^ 4))] . $hex;
1901                         $dec /= (2 ^ 4);
1902                 } while ($dec >= 1);
1903
1904                 /*
1905                  * Leading zeros are required for hex-decimal "numbers". In some
1906                  * situations more leading zeros are wanted, so check for both
1907                  * conditions.
1908                  */
1909                 if ($maxLength > 0) {
1910                         // Prepend more zeros
1911                         $hex = str_pad($hex, $maxLength, '0', STR_PAD_LEFT);
1912                 } elseif ((strlen($hex) % 2) != 0) {
1913                         // Only make string's length dividable by 2
1914                         $hex = '0' . $hex;
1915                 }
1916
1917                 // Return the hexadecimal string
1918                 return $sign . $hex;
1919         }
1920
1921         /**
1922          * Converts a ASCII string (0 to 255) into a decimal number.
1923          *
1924          * @param       $asc    The ASCII string to be converted
1925          * @return      $dec    Decimal number
1926          */
1927         protected function asc2dec ($asc) {
1928                 // Convert it into a hexadecimal number
1929                 $hex = bin2hex($asc);
1930
1931                 // And back into a decimal number
1932                 $dec = $this->hex2dec($hex);
1933
1934                 // Return it
1935                 return $dec;
1936         }
1937
1938         /**
1939          * Converts a decimal number into an ASCII string.
1940          *
1941          * @param       $dec            Decimal number
1942          * @return      $asc    An ASCII string
1943          */
1944         protected function dec2asc ($dec) {
1945                 // First convert the number into a hexadecimal string
1946                 $hex = $this->dec2hex($dec);
1947
1948                 // Then convert it into the ASCII string
1949                 $asc = $this->hex2asc($hex);
1950
1951                 // Return it
1952                 return $asc;
1953         }
1954
1955         /**
1956          * Converts a hexadecimal number into an ASCII string. Negative numbers
1957          * are not allowed.
1958          *
1959          * @param       $hex    Hexadecimal string
1960          * @return      $asc    An ASCII string
1961          */
1962         protected function hex2asc ($hex) {
1963                 // Check for length, it must be devideable by 2
1964                 //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('hex='.$hex);
1965                 assert((strlen($hex) % 2) == 0);
1966
1967                 // Walk the string
1968                 $asc = '';
1969                 for ($idx = 0; $idx < strlen($hex); $idx+=2) {
1970                         // Get the decimal number of the chunk
1971                         $part = hexdec(substr($hex, $idx, 2));
1972
1973                         // Add it to the final string
1974                         $asc .= chr($part);
1975                 } // END - for
1976
1977                 // Return the final string
1978                 return $asc;
1979         }
1980
1981         /**
1982          * Checks whether the given encoded data was encoded with Base64
1983          *
1984          * @param       $encodedData    Encoded data we shall check
1985          * @return      $isBase64               Whether the encoded data is Base64
1986          */
1987         protected function isBase64Encoded ($encodedData) {
1988                 // Determine it
1989                 $isBase64 = (@base64_decode($encodedData, TRUE) !== FALSE);
1990
1991                 // Return it
1992                 return $isBase64;
1993         }
1994
1995         /**
1996          * "Getter" to get response/request type from analysis of the system.
1997          *
1998          * @return      $responseType   Analyzed response type
1999          */
2000         protected function getResponseTypeFromSystem () {
2001                 // Default is console
2002                 $responseType = 'console';
2003
2004                 // Is 'HTTP_HOST' set?
2005                 if (isset($_SERVER['HTTP_HOST'])) {
2006                         // Then it is a HTTP response/request
2007                         $responseType = 'http';
2008                 } // END - if
2009
2010                 // Return it
2011                 return $responseType;
2012         }
2013
2014         /**
2015          * Gets a cache key from Criteria instance
2016          *
2017          * @param       $criteriaInstance       An instance of a Criteria class
2018          * @param       $onlyKeys                       Only use these keys for a cache key
2019          * @return      $cacheKey                       A cache key suitable for lookup/storage purposes
2020          */
2021         protected function getCacheKeyByCriteria (Criteria $criteriaInstance, array $onlyKeys = array()) {
2022                 // Generate it
2023                 $cacheKey = sprintf('%s@%s',
2024                         $this->__toString(),
2025                         $criteriaInstance->getCacheKey($onlyKeys)
2026                 );
2027
2028                 // And return it
2029                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput($this->__toString() . ': cacheKey=' . $cacheKey);
2030                 return $cacheKey;
2031         }
2032
2033         /**
2034          * Getter for startup time in miliseconds
2035          *
2036          * @return      $startupTime    Startup time in miliseconds
2037          */
2038         protected function getStartupTime () {
2039                 return self::$startupTime;
2040         }
2041
2042         /**
2043          * "Getter" for a printable currently execution time in nice braces
2044          *
2045          * @return      $executionTime  Current execution time in nice braces
2046          */
2047         protected function getPrintableExecutionTime () {
2048                 // Caculate the execution time
2049                 $executionTime = microtime(TRUE) - $this->getStartupTime();
2050
2051                 // Pack it in nice braces
2052                 $executionTime = sprintf('[ %01.5f ] ', $executionTime);
2053
2054                 // And return it
2055                 return $executionTime;
2056         }
2057
2058         /**
2059          * Hashes a given string with a simple but stronger hash function (no salts)
2060          *
2061          * @param       $str    The string to be hashed
2062          * @return      $hash   The hash from string $str
2063          */
2064         public function hashString ($str) {
2065                 // Hash given string with (better secure) hasher
2066                 $hash = mhash(MHASH_SHA256, $str);
2067
2068                 // Return it
2069                 return $hash;
2070         }
2071
2072         /**
2073          * Checks whether the given number is really a number (only chars 0-9).
2074          *
2075          * @param       $num            A string consisting only chars between 0 and 9
2076          * @param       $castValue      Whether to cast the value to double. Do only use this to secure numbers from Requestable classes.
2077          * @param       $assertMismatch         Whether to assert mismatches
2078          * @return      $ret            The (hopefully) secured numbered value
2079          */
2080         public function bigintval ($num, $castValue = TRUE, $assertMismatch = FALSE) {
2081                 // Filter all numbers out
2082                 $ret = preg_replace('/[^0123456789]/', '', $num);
2083
2084                 // Shall we cast?
2085                 if ($castValue === TRUE) {
2086                         // Cast to biggest numeric type
2087                         $ret = (double) $ret;
2088                 } // END - if
2089
2090                 // Assert only if requested
2091                 if ($assertMismatch === TRUE) {
2092                         // Has the whole value changed?
2093                         assert(('' . $ret . '' != '' . $num . '') && (!is_null($num)));
2094                 } // END - if
2095
2096                 // Return result
2097                 return $ret;
2098         }
2099
2100         /**
2101          * Checks whether the given hexadecimal number is really a hex-number (only chars 0-9,a-f).
2102          *
2103          * @param       $num    A string consisting only chars between 0 and 9
2104          * @param       $assertMismatch         Whether to assert mismatches
2105          * @return      $ret    The (hopefully) secured hext-numbered value
2106          */
2107         public function hexval ($num, $assertMismatch = FALSE) {
2108                 // Filter all numbers out
2109                 $ret = preg_replace('/[^0123456789abcdefABCDEF]/', '', $num);
2110
2111                 // Assert only if requested
2112                 if ($assertMismatch === TRUE) {
2113                         // Has the whole value changed?
2114                         assert(('' . $ret . '' != '' . $num . '') && (!is_null($num)));
2115                 } // END - if
2116
2117                 // Return result
2118                 return $ret;
2119         }
2120
2121         /**
2122          * Checks whether start/end marker are set
2123          *
2124          * @param       $data   Data to be checked
2125          * @return      $isset  Whether start/end marker are set
2126          */
2127         public final function ifStartEndMarkersSet ($data) {
2128                 // Determine it
2129                 $isset = ((substr($data, 0, strlen(BaseRawDataHandler::STREAM_START_MARKER)) == BaseRawDataHandler::STREAM_START_MARKER) && (substr($data, -1 * strlen(BaseRawDataHandler::STREAM_END_MARKER), strlen(BaseRawDataHandler::STREAM_END_MARKER)) == BaseRawDataHandler::STREAM_END_MARKER));
2130
2131                 // ... and return it
2132                 return $isset;
2133         }
2134
2135         /**
2136          * Determines if an element is set in the generic array
2137          *
2138          * @param       $keyGroup       Main group for the key
2139          * @param       $subGroup       Sub group for the key
2140          * @param       $key            Key to check
2141          * @param       $element        Element to check
2142          * @return      $isset          Whether the given key is set
2143          */
2144         protected final function isGenericArrayElementSet ($keyGroup, $subGroup, $key, $element) {
2145                 // Debug message
2146                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element);
2147
2148                 // Is it there?
2149                 $isset = isset($this->genericArray[$keyGroup][$subGroup][$key][$element]);
2150
2151                 // Return it
2152                 return $isset;
2153         }
2154         /**
2155          * Determines if a key is set in the generic array
2156          *
2157          * @param       $keyGroup       Main group for the key
2158          * @param       $subGroup       Sub group for the key
2159          * @param       $key            Key to check
2160          * @return      $isset          Whether the given key is set
2161          */
2162         protected final function isGenericArrayKeySet ($keyGroup, $subGroup, $key) {
2163                 // Debug message
2164                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2165
2166                 // Is it there?
2167                 $isset = isset($this->genericArray[$keyGroup][$subGroup][$key]);
2168
2169                 // Return it
2170                 return $isset;
2171         }
2172
2173
2174         /**
2175          * Determines if a group is set in the generic array
2176          *
2177          * @param       $keyGroup       Main group
2178          * @param       $subGroup       Sub group
2179          * @return      $isset          Whether the given group is set
2180          */
2181         protected final function isGenericArrayGroupSet ($keyGroup, $subGroup) {
2182                 // Debug message
2183                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup);
2184
2185                 // Is it there?
2186                 $isset = isset($this->genericArray[$keyGroup][$subGroup]);
2187
2188                 // Return it
2189                 return $isset;
2190         }
2191
2192         /**
2193          * Getter for sub key group
2194          *
2195          * @param       $keyGroup       Main key group
2196          * @param       $subGroup       Sub key group
2197          * @return      $array          An array with all array elements
2198          */
2199         protected final function getGenericSubArray ($keyGroup, $subGroup) {
2200                 // Is it there?
2201                 if (!$this->isGenericArrayGroupSet($keyGroup, $subGroup)) {
2202                         // No, then abort here
2203                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' not found.');
2204                         exit;
2205                 } // END - if
2206
2207                 // Debug message
2208                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',value=' . print_r($this->genericArray[$keyGroup][$subGroup], TRUE));
2209
2210                 // Return it
2211                 return $this->genericArray[$keyGroup][$subGroup];
2212         }
2213
2214         /**
2215          * Unsets a given key in generic array
2216          *
2217          * @param       $keyGroup       Main group for the key
2218          * @param       $subGroup       Sub group for the key
2219          * @param       $key            Key to unset
2220          * @return      void
2221          */
2222         protected final function unsetGenericArrayKey ($keyGroup, $subGroup, $key) {
2223                 // Debug message
2224                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2225
2226                 // Remove it
2227                 unset($this->genericArray[$keyGroup][$subGroup][$key]);
2228         }
2229
2230         /**
2231          * Unsets a given element in generic array
2232          *
2233          * @param       $keyGroup       Main group for the key
2234          * @param       $subGroup       Sub group for the key
2235          * @param       $key            Key to unset
2236          * @param       $element        Element to unset
2237          * @return      void
2238          */
2239         protected final function unsetGenericArrayElement ($keyGroup, $subGroup, $key, $element) {
2240                 // Debug message
2241                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element);
2242
2243                 // Remove it
2244                 unset($this->genericArray[$keyGroup][$subGroup][$key][$element]);
2245         }
2246
2247         /**
2248          * Append a string to a given generic array key
2249          *
2250          * @param       $keyGroup       Main group for the key
2251          * @param       $subGroup       Sub group for the key
2252          * @param       $key            Key to unset
2253          * @param       $value          Value to add/append
2254          * @return      void
2255          */
2256         protected final function appendStringToGenericArrayKey ($keyGroup, $subGroup, $key, $value, $appendGlue = '') {
2257                 // Debug message
2258                 //* NOISY-DEBUG: */ if (!is_object($value)) $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',value[' . gettype($value) . ']=' . print_r($value, TRUE) . ',appendGlue=' . $appendGlue);
2259
2260                 // Is it already there?
2261                 if ($this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
2262                         // Append it
2263                         $this->genericArray[$keyGroup][$subGroup][$key] .= $appendGlue . (string) $value;
2264                 } else {
2265                         // Add it
2266                         $this->genericArray[$keyGroup][$subGroup][$key] = (string) $value;
2267                 }
2268         }
2269
2270         /**
2271          * Append a string to a given generic array element
2272          *
2273          * @param       $keyGroup       Main group for the key
2274          * @param       $subGroup       Sub group for the key
2275          * @param       $key            Key to unset
2276          * @param       $element        Element to check
2277          * @param       $value          Value to add/append
2278          * @return      void
2279          */
2280         protected final function appendStringToGenericArrayElement ($keyGroup, $subGroup, $key, $element, $value, $appendGlue = '') {
2281                 // Debug message
2282                 //* NOISY-DEBUG: */ if (!is_object($value)) $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ',value[' . gettype($value) . ']=' . print_r($value, TRUE) . ',appendGlue=' . $appendGlue);
2283
2284                 // Is it already there?
2285                 if ($this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element)) {
2286                         // Append it
2287                         $this->genericArray[$keyGroup][$subGroup][$key][$element] .= $appendGlue . (string) $value;
2288                 } else {
2289                         // Add it
2290                         $this->genericArray[$keyGroup][$subGroup][$key][$element] = (string) $value;
2291                 }
2292         }
2293
2294         /**
2295          * Initializes given generic array group
2296          *
2297          * @param       $keyGroup       Main group for the key
2298          * @param       $subGroup       Sub group for the key
2299          * @param       $key            Key to use
2300          * @param       $forceInit      Optionally force initialization
2301          * @return      void
2302          */
2303         protected final function initGenericArrayGroup ($keyGroup, $subGroup, $forceInit = FALSE) {
2304                 // Debug message
2305                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',forceInit=' . intval($forceInit));
2306
2307                 // Is it already set?
2308                 if (($forceInit === FALSE) && ($this->isGenericArrayGroupSet($keyGroup, $subGroup))) {
2309                         // Already initialized
2310                         trigger_error(__METHOD__ . ':keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' already initialized.');
2311                         exit;
2312                 } // END - if
2313
2314                 // Initialize it
2315                 $this->genericArray[$keyGroup][$subGroup] = array();
2316         }
2317
2318         /**
2319          * Initializes given generic array key
2320          *
2321          * @param       $keyGroup       Main group for the key
2322          * @param       $subGroup       Sub group for the key
2323          * @param       $key            Key to use
2324          * @param       $forceInit      Optionally force initialization
2325          * @return      void
2326          */
2327         protected final function initGenericArrayKey ($keyGroup, $subGroup, $key, $forceInit = FALSE) {
2328                 // Debug message
2329                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',forceInit=' . intval($forceInit));
2330
2331                 // Is it already set?
2332                 if (($forceInit === FALSE) && ($this->isGenericArrayKeySet($keyGroup, $subGroup, $key))) {
2333                         // Already initialized
2334                         trigger_error(__METHOD__ . ':keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' already initialized.');
2335                         exit;
2336                 } // END - if
2337
2338                 // Initialize it
2339                 $this->genericArray[$keyGroup][$subGroup][$key] = array();
2340         }
2341
2342         /**
2343          * Initializes given generic array element
2344          *
2345          * @param       $keyGroup       Main group for the key
2346          * @param       $subGroup       Sub group for the key
2347          * @param       $key            Key to use
2348          * @param       $element        Element to use
2349          * @param       $forceInit      Optionally force initialization
2350          * @return      void
2351          */
2352         protected final function initGenericArrayElement ($keyGroup, $subGroup, $key, $element, $forceInit = FALSE) {
2353                 // Debug message
2354                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ',forceInit=' . intval($forceInit));
2355
2356                 // Is it already set?
2357                 if (($forceInit === FALSE) && ($this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element))) {
2358                         // Already initialized
2359                         trigger_error(__METHOD__ . ':keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ' already initialized.');
2360                         exit;
2361                 } // END - if
2362
2363                 // Initialize it
2364                 $this->genericArray[$keyGroup][$subGroup][$key][$element] = array();
2365         }
2366
2367         /**
2368          * Pushes an element to a generic key
2369          *
2370          * @param       $keyGroup       Main group for the key
2371          * @param       $subGroup       Sub group for the key
2372          * @param       $key            Key to use
2373          * @param       $value          Value to add/append
2374          * @return      $count          Number of array elements
2375          */
2376         protected final function pushValueToGenericArrayKey ($keyGroup, $subGroup, $key, $value) {
2377                 // Debug message
2378                 //* NOISY-DEBUG: */ if (!is_object($value)) $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',value[' . gettype($value) . ']=' . print_r($value, TRUE));
2379
2380                 // Is it set?
2381                 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
2382                         // Initialize array
2383                         $this->initGenericArrayKey($keyGroup, $subGroup, $key);
2384                 } // END - if
2385
2386                 // Then push it
2387                 $count = array_push($this->genericArray[$keyGroup][$subGroup][$key], $value);
2388
2389                 // Return count
2390                 //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], TRUE));
2391                 //* DEBUG: */ print(__METHOD__ . ': count=' . $count . PHP_EOL);
2392                 return $count;
2393         }
2394
2395         /**
2396          * Pushes an element to a generic array element
2397          *
2398          * @param       $keyGroup       Main group for the key
2399          * @param       $subGroup       Sub group for the key
2400          * @param       $key            Key to use
2401          * @param       $element        Element to check
2402          * @param       $value          Value to add/append
2403          * @return      $count          Number of array elements
2404          */
2405         protected final function pushValueToGenericArrayElement ($keyGroup, $subGroup, $key, $element, $value) {
2406                 // Debug message
2407                 //* NOISY-DEBUG: */ if (!is_object($value)) $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ',value[' . gettype($value) . ']=' . print_r($value, TRUE));
2408
2409                 // Is it set?
2410                 if (!$this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element)) {
2411                         // Initialize array
2412                         $this->initGenericArrayElement($keyGroup, $subGroup, $key, $element);
2413                 } // END - if
2414
2415                 // Then push it
2416                 $count = array_push($this->genericArray[$keyGroup][$subGroup][$key][$element], $value);
2417
2418                 // Return count
2419                 //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], TRUE));
2420                 //* DEBUG: */ print(__METHOD__ . ': count=' . $count . PHP_EOL);
2421                 return $count;
2422         }
2423
2424         /**
2425          * Pops an element from  a generic group
2426          *
2427          * @param       $keyGroup       Main group for the key
2428          * @param       $subGroup       Sub group for the key
2429          * @param       $key            Key to unset
2430          * @return      $value          Last "popped" value
2431          */
2432         protected final function popGenericArrayElement ($keyGroup, $subGroup, $key) {
2433                 // Debug message
2434                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2435
2436                 // Is it set?
2437                 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
2438                         // Not found
2439                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' not found.');
2440                         exit;
2441                 } // END - if
2442
2443                 // Then "pop" it
2444                 $value = array_pop($this->genericArray[$keyGroup][$subGroup][$key]);
2445
2446                 // Return value
2447                 //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], TRUE));
2448                 //* DEBUG: */ print(__METHOD__ . ': value[' . gettype($value) . ']=' . print_r($value, TRUE) . PHP_EOL);
2449                 return $value;
2450         }
2451
2452         /**
2453          * Shifts an element from  a generic group
2454          *
2455          * @param       $keyGroup       Main group for the key
2456          * @param       $subGroup       Sub group for the key
2457          * @param       $key            Key to unset
2458          * @return      $value          Last "popped" value
2459          */
2460         protected final function shiftGenericArrayElement ($keyGroup, $subGroup, $key) {
2461                 // Debug message
2462                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2463
2464                 // Is it set?
2465                 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
2466                         // Not found
2467                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' not found.');
2468                         exit;
2469                 } // END - if
2470
2471                 // Then "shift" it
2472                 $value = array_shift($this->genericArray[$keyGroup][$subGroup][$key]);
2473
2474                 // Return value
2475                 //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], TRUE));
2476                 //* DEBUG: */ print(__METHOD__ . ': value[' . gettype($value) . ']=' . print_r($value, TRUE) . PHP_EOL);
2477                 return $value;
2478         }
2479
2480         /**
2481          * Count generic array group
2482          *
2483          * @param       $keyGroup       Main group for the key
2484          * @return      $count          Count of given group
2485          */
2486         protected final function countGenericArray ($keyGroup) {
2487                 // Debug message
2488                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup);
2489
2490                 // Is it there?
2491                 if (!isset($this->genericArray[$keyGroup])) {
2492                         // Abort here
2493                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ' not found.');
2494                         exit;
2495                 } // END - if
2496
2497                 // Then count it
2498                 $count = count($this->genericArray[$keyGroup]);
2499
2500                 // Debug message
2501                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',count=' . $count);
2502
2503                 // Return it
2504                 return $count;
2505         }
2506
2507         /**
2508          * Count generic array sub group
2509          *
2510          * @param       $keyGroup       Main group for the key
2511          * @param       $subGroup       Sub group for the key
2512          * @return      $count          Count of given group
2513          */
2514         protected final function countGenericArrayGroup ($keyGroup, $subGroup) {
2515                 // Debug message
2516                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup);
2517
2518                 // Is it there?
2519                 if (!$this->isGenericArrayGroupSet($keyGroup, $subGroup)) {
2520                         // Abort here
2521                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' not found.');
2522                         exit;
2523                 } // END - if
2524
2525                 // Then count it
2526                 $count = count($this->genericArray[$keyGroup][$subGroup]);
2527
2528                 // Debug message
2529                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',count=' . $count);
2530
2531                 // Return it
2532                 return $count;
2533         }
2534
2535         /**
2536          * Count generic array elements
2537          *
2538          * @param       $keyGroup       Main group for the key
2539          * @param       $subGroup       Sub group for the key
2540          * @para        $key            Key to count
2541          * @return      $count          Count of given key
2542          */
2543         protected final function countGenericArrayElements ($keyGroup, $subGroup, $key) {
2544                 // Debug message
2545                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2546
2547                 // Is it there?
2548                 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
2549                         // Abort here
2550                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' not found.');
2551                         exit;
2552                 } elseif (!$this->isValidGenericArrayGroup($keyGroup, $subGroup)) {
2553                         // Not valid
2554                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' is not an array.');
2555                         exit;
2556                 }
2557
2558                 // Then count it
2559                 $count = count($this->genericArray[$keyGroup][$subGroup][$key]);
2560
2561                 // Debug message
2562                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',count=' . $count);
2563
2564                 // Return it
2565                 return $count;
2566         }
2567
2568         /**
2569          * Getter for whole generic group array
2570          *
2571          * @param       $keyGroup       Key group to get
2572          * @return      $array          Whole generic array group
2573          */
2574         protected final function getGenericArray ($keyGroup) {
2575                 // Debug message
2576                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup);
2577
2578                 // Is it there?
2579                 if (!isset($this->genericArray[$keyGroup])) {
2580                         // Then abort here
2581                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ' does not exist.');
2582                         exit;
2583                 } // END - if
2584
2585                 // Return it
2586                 return $this->genericArray[$keyGroup];
2587         }
2588
2589         /**
2590          * Setter for generic array key
2591          *
2592          * @param       $keyGroup       Key group to get
2593          * @param       $subGroup       Sub group for the key
2594          * @param       $key            Key to unset
2595          * @param       $value          Mixed value from generic array element
2596          * @return      void
2597          */
2598         protected final function setGenericArrayKey ($keyGroup, $subGroup, $key, $value) {
2599                 // Debug message
2600                 //* NOISY-DEBUG: */ if (!is_object($value)) $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',value[' . gettype($value) . ']=' . print_r($value, TRUE));
2601
2602                 // Set value here
2603                 $this->genericArray[$keyGroup][$subGroup][$key] = $value;
2604         }
2605
2606         /**
2607          * Getter for generic array key
2608          *
2609          * @param       $keyGroup       Key group to get
2610          * @param       $subGroup       Sub group for the key
2611          * @param       $key            Key to unset
2612          * @return      $value          Mixed value from generic array element
2613          */
2614         protected final function getGenericArrayKey ($keyGroup, $subGroup, $key) {
2615                 // Debug message
2616                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2617
2618                 // Is it there?
2619                 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
2620                         // Then abort here
2621                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' does not exist.');
2622                         exit;
2623                 } // END - if
2624
2625                 // Return it
2626                 return $this->genericArray[$keyGroup][$subGroup][$key];
2627         }
2628
2629         /**
2630          * Sets a value in given generic array key/element
2631          *
2632          * @param       $keyGroup       Main group for the key
2633          * @param       $subGroup       Sub group for the key
2634          * @param       $key            Key to set
2635          * @param       $element        Element to set
2636          * @param       $value          Value to set
2637          * @return      void
2638          */
2639         protected final function setGenericArrayElement ($keyGroup, $subGroup, $key, $element, $value) {
2640                 // Debug message
2641                 //* NOISY-DEBUG: */ if (!is_object($value)) $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ',value[' . gettype($value) . ']=' . print_r($value, TRUE));
2642
2643                 // Then set it
2644                 $this->genericArray[$keyGroup][$subGroup][$key][$element] = $value;
2645         }
2646
2647         /**
2648          * Getter for generic array element
2649          *
2650          * @param       $keyGroup       Key group to get
2651          * @param       $subGroup       Sub group for the key
2652          * @param       $key            Key to look for
2653          * @param       $element        Element to look for
2654          * @return      $value          Mixed value from generic array element
2655          */
2656         protected final function getGenericArrayElement ($keyGroup, $subGroup, $key, $element) {
2657                 // Debug message
2658                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element);
2659
2660                 // Is it there?
2661                 if (!$this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element)) {
2662                         // Then abort here
2663                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ' does not exist.');
2664                         exit;
2665                 } // END - if
2666
2667                 // Return it
2668                 return $this->genericArray[$keyGroup][$subGroup][$key][$element];
2669         }
2670
2671         /**
2672          * Checks if a given sub group is valid (array)
2673          *
2674          * @param       $keyGroup       Key group to get
2675          * @param       $subGroup       Sub group for the key
2676          * @return      $isValid        Whether given sub group is valid
2677          */
2678         protected final function isValidGenericArrayGroup ($keyGroup, $subGroup) {
2679                 // Debug message
2680                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup);
2681
2682                 // Determine it
2683                 $isValid = (($this->isGenericArrayGroupSet($keyGroup, $subGroup)) && (is_array($this->getGenericSubArray($keyGroup, $subGroup))));
2684
2685                 // Return it
2686                 return $isValid;
2687         }
2688
2689         /**
2690          * Checks if a given key is valid (array)
2691          *
2692          * @param       $keyGroup       Key group to get
2693          * @param       $subGroup       Sub group for the key
2694          * @param       $key            Key to check
2695          * @return      $isValid        Whether given sub group is valid
2696          */
2697         protected final function isValidGenericArrayKey ($keyGroup, $subGroup, $key) {
2698                 // Debug message
2699                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2700
2701                 // Determine it
2702                 $isValid = (($this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) && (is_array($this->getGenericArrayKey($keyGroup, $subGroup, $key))));
2703
2704                 // Return it
2705                 return $isValid;
2706         }
2707 }
2708
2709 // [EOF]
2710 ?>