]> git.mxchange.org Git - core.git/blob - framework/main/classes/class_BaseFrameworkSystem.php
41287ab05db2d2bc6cf107e5ae8a63004a440bab
[core.git] / framework / main / classes / class_BaseFrameworkSystem.php
1 <?php
2 // Own namespace
3 namespace CoreFramework\Object;
4
5 // Import framework stuff
6 use CoreFramework\Compressor\Compressor;
7 use CoreFramework\Configuration\FrameworkConfiguration;
8 use CoreFramework\Connection\Database\DatabaseConnection;
9 use CoreFramework\Controller\Controller;
10 use CoreFramework\Criteria\Criteria;
11 use CoreFramework\Criteria\Local\LocalSearchCriteria;
12 use CoreFramework\Criteria\Local\LocalUpdateCriteria;
13 use CoreFramework\Factory\Database\Wrapper\DatabaseWrapperFactory;
14 use CoreFramework\Factory\ObjectFactory;
15 use CoreFramework\Filesystem\Block;
16 use CoreFramework\Filesystem\FilePointer;
17 use CoreFramework\Filesystem\FrameworkDirectory;
18 use CoreFramework\Generic\FrameworkInterface;
19 use CoreFramework\Generic\NullPointerException;
20 use CoreFramework\Handler\Stream\IoHandler;
21 use CoreFramework\Loader\ClassLoader;
22 use CoreFramework\Manager\ManageableApplication;
23 use CoreFramework\Middleware\Compressor\CompressorChannel;
24 use CoreFramework\Middleware\Debug\DebugMiddleware;
25 use CoreFramework\Parser\Parseable;
26 use CoreFramework\Registry\Register;
27 use CoreFramework\Registry\Registry;
28 use CoreFramework\Request\Requestable;
29 use CoreFramework\Resolver\Resolver;
30 use CoreFramework\Result\Database\CachedDatabaseResult;
31 use CoreFramework\Result\Search\SearchableResult;
32 use CoreFramework\Response\Responseable;
33 use CoreFramework\Stream\Output\OutputStreamer;
34 use CoreFramework\Template\CompileableTemplate;
35 use CoreFramework\User\ManageableAccount;
36 use CoreFramework\Wrapper\Database\DatabaseWrapper;
37
38 // Import SPL stuff
39 use \stdClass;
40 use \ReflectionClass;
41
42 /**
43  * The simulator system class is the super class of all other classes. This
44  * class handles saving of games etc.
45  *
46  * @author              Roland Haeder <webmaster@shipsimu.org>
47  * @version             0.0.0
48  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Core Developer Team
49  * @license             GNU GPL 3.0 or any newer version
50  * @link                http://www.shipsimu.org
51  *
52  * This program is free software: you can redistribute it and/or modify
53  * it under the terms of the GNU General Public License as published by
54  * the Free Software Foundation, either version 3 of the License, or
55  * (at your option) any later version.
56  *
57  * This program is distributed in the hope that it will be useful,
58  * but WITHOUT ANY WARRANTY; without even the implied warranty of
59  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
60  * GNU General Public License for more details.
61  *
62  * You should have received a copy of the GNU General Public License
63  * along with this program. If not, see <http://www.gnu.org/licenses/>.
64  */
65 class BaseFrameworkSystem extends stdClass implements FrameworkInterface {
66         /**
67          * Length of output from hash()
68          */
69         private static $hashLength = NULL;
70
71         /**
72          * The real class name
73          */
74         private $realClass = 'BaseFrameworkSystem';
75
76         /**
77          * Instance of a Requestable class
78          */
79         private $requestInstance = NULL;
80
81         /**
82          * Instance of a Responseable class
83          */
84         private $responseInstance = NULL;
85
86         /**
87          * Search criteria instance
88          */
89         private $searchInstance = NULL;
90
91         /**
92          * Update criteria instance
93          */
94         private $updateInstance = NULL;
95
96         /**
97          * The file I/O instance for the template loader
98          */
99         private $fileIoInstance = NULL;
100
101         /**
102          * Resolver instance
103          */
104         private $resolverInstance = NULL;
105
106         /**
107          * Template engine instance
108          */
109         private $templateInstance = NULL;
110
111         /**
112          * Database result instance
113          */
114         private $resultInstance = NULL;
115
116         /**
117          * Instance for user class
118          */
119         private $userInstance = NULL;
120
121         /**
122          * A controller instance
123          */
124         private $controllerInstance = NULL;
125
126         /**
127          * Instance of a RNG
128          */
129         private $rngInstance = NULL;
130
131         /**
132          * Instance of a crypto helper
133          */
134         private $cryptoInstance = NULL;
135
136         /**
137          * Instance of an Iterator class
138          */
139         private $iteratorInstance = NULL;
140
141         /**
142          * Instance of the list
143          */
144         private $listInstance = NULL;
145
146         /**
147          * Instance of a menu
148          */
149         private $menuInstance = NULL;
150
151         /**
152          * Instance of the image
153          */
154         private $imageInstance = NULL;
155
156         /**
157          * Instance of the stacker
158          */
159         private $stackInstance = NULL;
160
161         /**
162          * A Compressor instance
163          */
164         private $compressorInstance = NULL;
165
166         /**
167          * A Parseable instance
168          */
169         private $parserInstance = NULL;
170
171         /**
172          * A HandleableProtocol instance
173          */
174         private $protocolInstance = NULL;
175
176         /**
177          * A database wrapper instance
178          */
179         private $databaseInstance = NULL;
180
181         /**
182          * A helper instance for the form
183          */
184         private $helperInstance = NULL;
185
186         /**
187          * An instance of a Source class
188          */
189         private $sourceInstance = NULL;
190
191         /**
192          * An instance of a UrlSource class
193          */
194         private $urlSourceInstance = NULL;
195
196         /**
197          * An instance of a InputStream class
198          */
199         private $inputStreamInstance = NULL;
200
201         /**
202          * An instance of a OutputStream class
203          */
204         private $outputStreamInstance = NULL;
205
206         /**
207          * Networkable handler instance
208          */
209         private $handlerInstance = NULL;
210
211         /**
212          * Visitor handler instance
213          */
214         private $visitorInstance = NULL;
215
216         /**
217          * DHT instance
218          */
219         private $dhtInstance = NULL;
220
221         /**
222          * An instance of a database wrapper class
223          */
224         private $wrapperInstance = NULL;
225
226         /**
227          * An instance of a file I/O pointer class (not handler)
228          */
229         private $pointerInstance = NULL;
230
231         /**
232          * An instance of an Indexable class
233          */
234         private $indexInstance = NULL;
235
236         /**
237          * An instance of a Block class
238          */
239         private $blockInstance = NULL;
240
241         /**
242          * A Minable instance
243          */
244         private $minableInstance = NULL;
245
246         /**
247          * A FrameworkDirectory instance
248          */
249         private $directoryInstance = NULL;
250
251         /**
252          * Listener instance
253          */
254         private $listenerInstance = NULL;
255
256         /**
257          * An instance of a communicator
258          */
259         private $communicatorInstance = NULL;
260
261         /**
262          * The concrete output instance
263          */
264         private $outputInstance = NULL;
265
266         /**
267          * State instance
268          */
269         private $stateInstance = NULL;
270
271         /**
272          * Thousands separator
273          */
274         private $thousands = '.'; // German
275
276         /**
277          * Decimal separator
278          */
279         private $decimals  = ','; // German
280
281         /**
282          * Socket resource
283          */
284         private $socketResource = FALSE;
285
286         /**
287          * Regular expression to use for validation
288          */
289         private $regularExpression = '';
290
291         /**
292          * Package data
293          */
294         private $packageData = array();
295
296         /**
297          * Generic array
298          */
299         private $genericArray = array();
300
301         /**
302          * Command name
303          */
304         private $commandName = '';
305
306         /**
307          * Controller name
308          */
309         private $controllerName = '';
310
311         /**
312          * Name of used protocol
313          */
314         private $protocolName = 'invalid';
315
316         /**
317          * Array with bitmasks and such for pack/unpack methods to support both
318          * 32-bit and 64-bit systems
319          */
320         private $packingData = array(
321                 32 => array(
322                         'step'   => 3,
323                         'left'   => 0xffff0000,
324                         'right'  => 0x0000ffff,
325                         'factor' => 16,
326                         'format' => 'II',
327                 ),
328                 64 => array(
329                         'step'   => 7,
330                         'left'   => 0xffffffff00000000,
331                         'right'  => 0x00000000ffffffff,
332                         'factor' => 32,
333                         'format' => 'NN'
334                 )
335         );
336
337         /**
338          * Simple 64-bit check, thanks to "Salman A" from stackoverflow.com:
339          *
340          * The integer size is 4 bytes on 32-bit and 8 bytes on a 64-bit system.
341          */
342         private $archArrayElement = FALSE;
343
344         /***********************
345          * Exception codes.... *
346          ***********************/
347
348         // @todo Try to clean these constants up
349         const EXCEPTION_IS_NULL_POINTER              = 0x001;
350         const EXCEPTION_IS_NO_OBJECT                 = 0x002;
351         const EXCEPTION_IS_NO_ARRAY                  = 0x003;
352         const EXCEPTION_MISSING_METHOD               = 0x004;
353         const EXCEPTION_CLASSES_NOT_MATCHING         = 0x005;
354         const EXCEPTION_INDEX_OUT_OF_BOUNDS          = 0x006;
355         const EXCEPTION_DIMENSION_ARRAY_INVALID      = 0x007;
356         const EXCEPTION_ITEM_NOT_TRADEABLE           = 0x008;
357         const EXCEPTION_ITEM_NOT_IN_PRICE_LIST       = 0x009;
358         const EXCEPTION_GENDER_IS_WRONG              = 0x00a;
359         const EXCEPTION_BIRTH_DATE_IS_INVALID        = 0x00b;
360         const EXCEPTION_EMPTY_STRUCTURES_ARRAY       = 0x00c;
361         const EXCEPTION_HAS_ALREADY_PERSONELL_LIST   = 0x00d;
362         const EXCEPTION_NOT_ENOUGTH_UNEMPLOYEES      = 0x00e;
363         const EXCEPTION_TOTAL_PRICE_NOT_CALCULATED   = 0x00f;
364         const EXCEPTION_HARBOR_HAS_NO_SHIPYARDS      = 0x010;
365         const EXCEPTION_CONTRACT_PARTNER_INVALID     = 0x011;
366         const EXCEPTION_CONTRACT_PARTNER_MISMATCH    = 0x012;
367         const EXCEPTION_CONTRACT_ALREADY_SIGNED      = 0x013;
368         const EXCEPTION_UNEXPECTED_EMPTY_STRING      = 0x014;
369         const EXCEPTION_PATH_NOT_FOUND               = 0x015;
370         const EXCEPTION_INVALID_PATH_NAME            = 0x016;
371         const EXCEPTION_READ_PROTECED_PATH           = 0x017;
372         const EXCEPTION_WRITE_PROTECED_PATH          = 0x018;
373         const EXCEPTION_DIR_POINTER_INVALID          = 0x019;
374         const EXCEPTION_FILE_POINTER_INVALID         = 0x01a;
375         const EXCEPTION_INVALID_RESOURCE             = 0x01b;
376         const EXCEPTION_UNEXPECTED_OBJECT            = 0x01c;
377         const EXCEPTION_LIMIT_ELEMENT_IS_UNSUPPORTED = 0x01d;
378         const EXCEPTION_GETTER_IS_MISSING            = 0x01e;
379         const EXCEPTION_ARRAY_EXPECTED               = 0x01f;
380         const EXCEPTION_ARRAY_HAS_INVALID_COUNT      = 0x020;
381         const EXCEPTION_ID_IS_INVALID_FORMAT         = 0x021;
382         const EXCEPTION_MD5_CHECKSUMS_MISMATCH       = 0x022;
383         const EXCEPTION_UNEXPECTED_STRING_SIZE       = 0x023;
384         const EXCEPTION_SIMULATOR_ID_INVALID         = 0x024;
385         const EXCEPTION_MISMATCHING_COMPRESSORS      = 0x025;
386         const EXCEPTION_CONTAINER_ITEM_IS_NULL       = 0x026;
387         const EXCEPTION_ITEM_IS_NO_ARRAY             = 0x027;
388         const EXCEPTION_CONTAINER_MAYBE_DAMAGED      = 0x028;
389         const EXCEPTION_INVALID_STRING               = 0x029;
390         const EXCEPTION_VARIABLE_NOT_SET             = 0x02a;
391         const EXCEPTION_ATTRIBUTES_ARE_MISSING       = 0x02b;
392         const EXCEPTION_ARRAY_ELEMENTS_MISSING       = 0x02c;
393         const EXCEPTION_TEMPLATE_ENGINE_UNSUPPORTED  = 0x02d;
394         const EXCEPTION_UNSPPORTED_OPERATION         = 0x02e;
395         const EXCEPTION_FACTORY_REQUIRE_PARAMETER    = 0x02f;
396         const EXCEPTION_MISSING_ELEMENT              = 0x030;
397         const EXCEPTION_HEADERS_ALREADY_SENT         = 0x031;
398         const EXCEPTION_DEFAULT_CONTROLLER_GONE      = 0x032;
399         const EXCEPTION_CLASS_NOT_FOUND              = 0x033;
400         const EXCEPTION_REQUIRED_INTERFACE_MISSING   = 0x034;
401         const EXCEPTION_FATAL_ERROR                  = 0x035;
402         const EXCEPTION_FILE_NOT_FOUND               = 0x036;
403         const EXCEPTION_ASSERTION_FAILED             = 0x037;
404         const EXCEPTION_FILE_NOT_REACHABLE           = 0x038;
405         const EXCEPTION_FILE_CANNOT_BE_READ          = 0x039;
406         const EXCEPTION_FILE_CANNOT_BE_WRITTEN       = 0x03a;
407         const EXCEPTION_PATH_CANNOT_BE_WRITTEN       = 0x03b;
408         const EXCEPTION_DATABASE_UPDATED_NOT_ALLOWED = 0x03c;
409         const EXCEPTION_FILTER_CHAIN_INTERCEPTED     = 0x03d;
410
411         /**
412          * Hexadecimal->Decimal translation array
413          */
414         private static $hexdec = array(
415                 '0' => 0,
416                 '1' => 1,
417                 '2' => 2,
418                 '3' => 3,
419                 '4' => 4,
420                 '5' => 5,
421                 '6' => 6,
422                 '7' => 7,
423                 '8' => 8,
424                 '9' => 9,
425                 'a' => 10,
426                 'b' => 11,
427                 'c' => 12,
428                 'd' => 13,
429                 'e' => 14,
430                 'f' => 15
431         );
432
433         /**
434          * Decimal->hexadecimal translation array
435          */
436         private static $dechex = array(
437                  0 => '0',
438                  1 => '1',
439                  2 => '2',
440                  3 => '3',
441                  4 => '4',
442                  5 => '5',
443                  6 => '6',
444                  7 => '7',
445                  8 => '8',
446                  9 => '9',
447                 10 => 'a',
448                 11 => 'b',
449                 12 => 'c',
450                 13 => 'd',
451                 14 => 'e',
452                 15 => 'f'
453         );
454
455         /**
456          * Startup time in miliseconds
457          */
458         private static $startupTime = 0;
459
460         /**
461          * Protected super constructor
462          *
463          * @param       $className      Name of the class
464          * @return      void
465          */
466         protected function __construct ($className) {
467                 // Set real class
468                 $this->setRealClass($className);
469
470                 // Set configuration instance if no registry ...
471                 if (!$this instanceof Register) {
472                         // ... because registries doesn't need to be configured
473                         $this->setConfigInstance(FrameworkConfiguration::getSelfInstance());
474                 } // END - if
475
476                 // Is the startup time set? (0 cannot be TRUE anymore)
477                 if (self::$startupTime == 0) {
478                         // Then set it
479                         self::$startupTime = microtime(TRUE);
480                 } // END - if
481
482                 // Set array element
483                 $this->archArrayElement = (PHP_INT_SIZE === 8 ? 64 : 32);
484         }
485
486         /**
487          * Destructor for all classes. You should not call this method on your own.
488          *
489          * @return      void
490          */
491         public function __destruct () {
492                 // Flush any updated entries to the database
493                 $this->flushPendingUpdates();
494
495                 // Is this object already destroyed?
496                 if ($this->__toString() != 'DestructedObject') {
497                         // Destroy all informations about this class but keep some text about it alive
498                         $this->setRealClass('DestructedObject');
499                 } elseif ((defined('DEBUG_DESTRUCTOR')) && (is_object($this->getDebugInstance()))) {
500                         // Already destructed object
501                         self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:] The object <span class="object_name">%s</span> is already destroyed.',
502                                 __CLASS__,
503                                 $this->__toString()
504                         ));
505                 } else {
506                         // Do not call this twice
507                         trigger_error(__METHOD__ . ': Called twice.');
508                         exit;
509                 }
510         }
511
512         /**
513          * The __call() method where all non-implemented methods end up
514          *
515          * @param       $methodName             Name of the missing method
516          * @args        $args                   Arguments passed to the method
517          * @return      void
518          */
519         public final function __call ($methodName, $args) {
520                 return self::__callStatic($methodName, $args);
521         }
522
523         /**
524          * The __callStatic() method where all non-implemented static methods end up
525          *
526          * @param       $methodName             Name of the missing method
527          * @args        $args                   Arguments passed to the method
528          * @return      void
529          */
530         public static final function __callStatic ($methodName, $args) {
531                 // Trace message
532                 //* PRINT-DEBUG: */ printf('[%s:%d]: methodName=%s,args[]=%s - CALLED!' . PHP_EOL, __METHOD__, __LINE__, $methodName, gettype($args));
533
534                 // Init argument string
535                 $argsString = '';
536
537                 // Is it NULL, empty or an array?
538                 if (is_null($args)) {
539                         // No arguments
540                         $argsString = 'NULL';
541                 } elseif (is_array($args)) {
542                         // Start braces
543                         $argsString = '(';
544
545                         // Some arguments are there
546                         foreach ($args as $arg) {
547                                 // Add data about the argument
548                                 $argsString .= gettype($arg) . ':';
549
550                                 if (is_null($arg)) {
551                                         // Found a NULL argument
552                                         $argsString .= 'NULL';
553                                 } elseif (is_string($arg)) {
554                                         // Add length for strings
555                                         $argsString .= strlen($arg);
556                                 } elseif ((is_int($arg)) || (is_float($arg))) {
557                                         // ... integer/float
558                                         $argsString .= $arg;
559                                 } elseif (is_array($arg)) {
560                                         // .. or size if array
561                                         $argsString .= count($arg);
562                                 } elseif (is_object($arg)) {
563                                         // Get reflection
564                                         $reflection = new ReflectionClass($arg);
565
566                                         // Is an other object, maybe no __toString() available
567                                         $argsString .= $reflection->getName();
568                                 } elseif ($arg === TRUE) {
569                                         // ... is boolean 'TRUE'
570                                         $argsString .= 'TRUE';
571                                 } elseif ($arg === FALSE) {
572                                         // ... is boolean 'FALSE'
573                                         $argsString .= 'FALSE';
574                                 }
575
576                                 // Comma for next one
577                                 $argsString .= ', ';
578                         } // END - foreach
579
580                         // Remove last comma
581                         if (substr($argsString, -2, 1) == ',') {
582                                 $argsString = substr($argsString, 0, -2);
583                         } // END - if
584
585                         // Close braces
586                         $argsString .= ')';
587                 } else {
588                         // Invalid arguments!
589                         $argsString = '!INVALID:' . gettype($args) . '!';
590                 }
591
592                 // Output stub message
593                 // @TODO __CLASS__ does always return BaseFrameworkSystem but not the extending (=child) class
594                 self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[unknown::%s:] Stub! Args: %s',
595                         $methodName,
596                         $argsString
597                 ));
598
599                 // Return nothing
600                 return NULL;
601         }
602
603         /**
604          * Getter for $realClass
605          *
606          * @return      $realClass The name of the real class (not BaseFrameworkSystem)
607          */
608         public function __toString () {
609                 return $this->realClass;
610         }
611
612         /**
613          * Magic method to catch setting of missing but set class fields/attributes
614          *
615          * @param       $name   Name of the field/attribute
616          * @param       $value  Value to store
617          * @return      void
618          */
619         public final function __set ($name, $value) {
620                 $this->debugBackTrace(sprintf('Tried to set a missing field. name=%s, value[%s]=%s',
621                         $name,
622                         gettype($value),
623                         print_r($value, TRUE)
624                 ));
625         }
626
627         /**
628          * Magic method to catch getting of missing fields/attributes
629          *
630          * @param       $name   Name of the field/attribute
631          * @return      void
632          */
633         public final function __get ($name) {
634                 $this->debugBackTrace(sprintf('Tried to get a missing field. name=%s',
635                         $name
636                 ));
637         }
638
639         /**
640          * Magic method to catch unsetting of missing fields/attributes
641          *
642          * @param       $name   Name of the field/attribute
643          * @return      void
644          */
645         public final function __unset ($name) {
646                 $this->debugBackTrace(sprintf('Tried to unset a missing field. name=%s',
647                         $name
648                 ));
649         }
650
651         /**
652          * Magic method to catch object serialization
653          *
654          * @return      $unsupported    Unsupported method
655          * @throws      UnsupportedOperationException   Objects of this framework cannot be serialized
656          */
657         public final function __sleep () {
658                 throw new UnsupportedOperationException(array($this, __FUNCTION__), self::EXCEPTION_UNSPPORTED_OPERATION);
659         }
660
661         /**
662          * Magic method to catch object deserialization
663          *
664          * @return      $unsupported    Unsupported method
665          * @throws      UnsupportedOperationException   Objects of this framework cannot be serialized
666          */
667         public final function __wakeup () {
668                 throw new UnsupportedOperationException(array($this, __FUNCTION__), self::EXCEPTION_UNSPPORTED_OPERATION);
669         }
670
671         /**
672          * Magic method to catch calls when an object instance is called
673          *
674          * @return      $unsupported    Unsupported method
675          * @throws      UnsupportedOperationException   Objects of this framework cannot be serialized
676          */
677         public final function __invoke () {
678                 throw new UnsupportedOperationException(array($this, __FUNCTION__), self::EXCEPTION_UNSPPORTED_OPERATION);
679         }
680
681         /**
682          * Setter for the real class name
683          *
684          * @param       $realClass      Class name (string)
685          * @return      void
686          */
687         public final function setRealClass ($realClass) {
688                 // Set real class
689                 $this->realClass = (string) $realClass;
690         }
691
692         /**
693          * Setter for database result instance
694          *
695          * @param       $resultInstance         An instance of a database result class
696          * @return      void
697          * @todo        SearchableResult and UpdateableResult shall have a super interface to use here
698          */
699         protected final function setResultInstance (SearchableResult $resultInstance) {
700                 $this->resultInstance =  $resultInstance;
701         }
702
703         /**
704          * Getter for database result instance
705          *
706          * @return      $resultInstance         An instance of a database result class
707          */
708         public final function getResultInstance () {
709                 return $this->resultInstance;
710         }
711
712         /**
713          * Setter for template engine instances
714          *
715          * @param       $templateInstance       An instance of a template engine class
716          * @return      void
717          */
718         protected final function setTemplateInstance (CompileableTemplate $templateInstance) {
719                 $this->templateInstance = $templateInstance;
720         }
721
722         /**
723          * Getter for template engine instances
724          *
725          * @return      $templateInstance       An instance of a template engine class
726          */
727         protected final function getTemplateInstance () {
728                 return $this->templateInstance;
729         }
730
731         /**
732          * Setter for search instance
733          *
734          * @param       $searchInstance         Searchable criteria instance
735          * @return      void
736          */
737         public final function setSearchInstance (LocalSearchCriteria $searchInstance) {
738                 $this->searchInstance = $searchInstance;
739         }
740
741         /**
742          * Getter for search instance
743          *
744          * @return      $searchInstance         Searchable criteria instance
745          */
746         public final function getSearchInstance () {
747                 return $this->searchInstance;
748         }
749
750         /**
751          * Setter for update instance
752          *
753          * @param       $updateInstance         An instance of a LocalUpdateCriteria clase
754          * @return      void
755          */
756         public final function setUpdateInstance (LocalUpdateCriteria $updateInstance) {
757                 $this->updateInstance = $updateInstance;
758         }
759
760         /**
761          * Getter for update instance
762          *
763          * @return      $updateInstance         Updateable criteria instance
764          */
765         public final function getUpdateInstance () {
766                 return $this->updateInstance;
767         }
768
769         /**
770          * Setter for resolver instance
771          *
772          * @param       $resolverInstance       Instance of a command resolver class
773          * @return      void
774          */
775         public final function setResolverInstance (Resolver $resolverInstance) {
776                 $this->resolverInstance = $resolverInstance;
777         }
778
779         /**
780          * Getter for resolver instance
781          *
782          * @return      $resolverInstance       Instance of a command resolver class
783          */
784         public final function getResolverInstance () {
785                 return $this->resolverInstance;
786         }
787
788         /**
789          * Setter for language instance
790          *
791          * @param       $configInstance         The configuration instance which shall
792          *                                                              be FrameworkConfiguration
793          * @return      void
794          */
795         public final function setConfigInstance (FrameworkConfiguration $configInstance) {
796                 Registry::getRegistry()->addInstance('config', $configInstance);
797         }
798
799         /**
800          * Getter for configuration instance
801          *
802          * @return      $configInstance         Configuration instance
803          */
804         public final function getConfigInstance () {
805                 $configInstance = Registry::getRegistry()->getInstance('config');
806                 return $configInstance;
807         }
808
809         /**
810          * Setter for debug instance
811          *
812          * @param       $debugInstance  The instance for debug output class
813          * @return      void
814          */
815         public final function setDebugInstance (DebugMiddleware $debugInstance) {
816                 Registry::getRegistry()->addInstance('debug', $debugInstance);
817         }
818
819         /**
820          * Getter for debug instance
821          *
822          * @return      $debugInstance  Instance to class DebugConsoleOutput or DebugWebOutput
823          */
824         public final function getDebugInstance () {
825                 // Get debug instance
826                 $debugInstance = Registry::getRegistry()->getInstance('debug');
827
828                 // Return it
829                 return $debugInstance;
830         }
831
832         /**
833          * Setter for web output instance
834          *
835          * @param       $webInstance    The instance for web output class
836          * @return      void
837          */
838         public final function setWebOutputInstance (OutputStreamer $webInstance) {
839                 Registry::getRegistry()->addInstance('web_output', $webInstance);
840         }
841
842         /**
843          * Getter for web output instance
844          *
845          * @return      $webOutputInstance - Instance to class WebOutput
846          */
847         public final function getWebOutputInstance () {
848                 $webOutputInstance = Registry::getRegistry()->getInstance('web_output');
849                 return $webOutputInstance;
850         }
851
852         /**
853          * Setter for database instance
854          *
855          * @param       $databaseInstance       The instance for the database connection (forced DatabaseConnection)
856          * @return      void
857          */
858         public final function setDatabaseInstance (DatabaseConnection $databaseInstance) {
859                 Registry::getRegistry()->addInstance('db_instance', $databaseInstance);
860         }
861
862         /**
863          * Getter for database layer
864          *
865          * @return      $databaseInstance       The database layer instance
866          */
867         public final function getDatabaseInstance () {
868                 // Get instance
869                 $databaseInstance = Registry::getRegistry()->getInstance('db_instance');
870
871                 // Return instance
872                 return $databaseInstance;
873         }
874
875         /**
876          * Setter for compressor channel
877          *
878          * @param       $compressorInstance             An instance of CompressorChannel
879          * @return      void
880          */
881         public final function setCompressorChannel (CompressorChannel $compressorInstance) {
882                 Registry::getRegistry()->addInstance('compressor', $compressorInstance);
883         }
884
885         /**
886          * Getter for compressor channel
887          *
888          * @return      $compressorInstance             The compressor channel
889          */
890         public final function getCompressorChannel () {
891                 $compressorInstance = Registry::getRegistry()->getInstance('compressor');
892                 return $compressorInstance;
893         }
894
895         /**
896          * Protected getter for a manageable application helper class
897          *
898          * @return      $applicationInstance    An instance of a manageable application helper class
899          */
900         protected final function getApplicationInstance () {
901                 $applicationInstance = Registry::getRegistry()->getInstance('application');
902                 return $applicationInstance;
903         }
904
905         /**
906          * Setter for a manageable application helper class
907          *
908          * @param       $applicationInstance    An instance of a manageable application helper class
909          * @return      void
910          */
911         public final function setApplicationInstance (ManageableApplication $applicationInstance) {
912                 Registry::getRegistry()->addInstance('application', $applicationInstance);
913         }
914
915         /**
916          * Setter for request instance
917          *
918          * @param       $requestInstance        An instance of a Requestable class
919          * @return      void
920          */
921         public final function setRequestInstance (Requestable $requestInstance) {
922                 $this->requestInstance = $requestInstance;
923         }
924
925         /**
926          * Getter for request instance
927          *
928          * @return      $requestInstance        An instance of a Requestable class
929          */
930         public final function getRequestInstance () {
931                 return $this->requestInstance;
932         }
933
934         /**
935          * Setter for response instance
936          *
937          * @param       $responseInstance       An instance of a Responseable class
938          * @return      void
939          */
940         public final function setResponseInstance (Responseable $responseInstance) {
941                 $this->responseInstance = $responseInstance;
942         }
943
944         /**
945          * Getter for response instance
946          *
947          * @return      $responseInstance       An instance of a Responseable class
948          */
949         public final function getResponseInstance () {
950                 return $this->responseInstance;
951         }
952
953         /**
954          * Private getter for language instance
955          *
956          * @return      $langInstance   An instance to the language sub-system
957          */
958         protected final function getLanguageInstance () {
959                 $langInstance = Registry::getRegistry()->getInstance('language');
960                 return $langInstance;
961         }
962
963         /**
964          * Setter for language instance
965          *
966          * @param       $langInstance   An instance to the language sub-system
967          * @return      void
968          * @see         LanguageSystem
969          */
970         public final function setLanguageInstance (ManageableLanguage $langInstance) {
971                 Registry::getRegistry()->addInstance('language', $langInstance);
972         }
973
974         /**
975          * Private getter for file IO instance
976          *
977          * @return      $fileIoInstance         An instance to the file I/O sub-system
978          */
979         protected final function getFileIoInstance () {
980                 return $this->fileIoInstance;
981         }
982
983         /**
984          * Setter for file I/O instance
985          *
986          * @param       $fileIoInstance         An instance to the file I/O sub-system
987          * @return      void
988          */
989         public final function setFileIoInstance (IoHandler $fileIoInstance) {
990                 $this->fileIoInstance = $fileIoInstance;
991         }
992
993         /**
994          * Protected setter for user instance
995          *
996          * @param       $userInstance   An instance of a user class
997          * @return      void
998          */
999         protected final function setUserInstance (ManageableAccount $userInstance) {
1000                 $this->userInstance = $userInstance;
1001         }
1002
1003         /**
1004          * Getter for user instance
1005          *
1006          * @return      $userInstance   An instance of a user class
1007          */
1008         public final function getUserInstance () {
1009                 return $this->userInstance;
1010         }
1011
1012         /**
1013          * Setter for controller instance (this surely breaks a bit the MVC patterm)
1014          *
1015          * @param       $controllerInstance             An instance of the controller
1016          * @return      void
1017          */
1018         public final function setControllerInstance (Controller $controllerInstance) {
1019                 $this->controllerInstance = $controllerInstance;
1020         }
1021
1022         /**
1023          * Getter for controller instance (this surely breaks a bit the MVC patterm)
1024          *
1025          * @return      $controllerInstance             An instance of the controller
1026          */
1027         public final function getControllerInstance () {
1028                 return $this->controllerInstance;
1029         }
1030
1031         /**
1032          * Setter for RNG instance
1033          *
1034          * @param       $rngInstance    An instance of a random number generator (RNG)
1035          * @return      void
1036          */
1037         protected final function setRngInstance (RandomNumberGenerator $rngInstance) {
1038                 $this->rngInstance = $rngInstance;
1039         }
1040
1041         /**
1042          * Getter for RNG instance
1043          *
1044          * @return      $rngInstance    An instance of a random number generator (RNG)
1045          */
1046         public final function getRngInstance () {
1047                 return $this->rngInstance;
1048         }
1049
1050         /**
1051          * Setter for Cryptable instance
1052          *
1053          * @param       $cryptoInstance An instance of a Cryptable class
1054          * @return      void
1055          */
1056         protected final function setCryptoInstance (Cryptable $cryptoInstance) {
1057                 $this->cryptoInstance = $cryptoInstance;
1058         }
1059
1060         /**
1061          * Getter for Cryptable instance
1062          *
1063          * @return      $cryptoInstance An instance of a Cryptable class
1064          */
1065         public final function getCryptoInstance () {
1066                 return $this->cryptoInstance;
1067         }
1068
1069         /**
1070          * Setter for the list instance
1071          *
1072          * @param       $listInstance   A list of Listable
1073          * @return      void
1074          */
1075         protected final function setListInstance (Listable $listInstance) {
1076                 $this->listInstance = $listInstance;
1077         }
1078
1079         /**
1080          * Getter for the list instance
1081          *
1082          * @return      $listInstance   A list of Listable
1083          */
1084         protected final function getListInstance () {
1085                 return $this->listInstance;
1086         }
1087
1088         /**
1089          * Setter for the menu instance
1090          *
1091          * @param       $menuInstance   A RenderableMenu instance
1092          * @return      void
1093          */
1094         protected final function setMenuInstance (RenderableMenu $menuInstance) {
1095                 $this->menuInstance = $menuInstance;
1096         }
1097
1098         /**
1099          * Getter for the menu instance
1100          *
1101          * @return      $menuInstance   A RenderableMenu instance
1102          */
1103         protected final function getMenuInstance () {
1104                 return $this->menuInstance;
1105         }
1106
1107         /**
1108          * Setter for image instance
1109          *
1110          * @param       $imageInstance  An instance of an image
1111          * @return      void
1112          */
1113         public final function setImageInstance (BaseImage $imageInstance) {
1114                 $this->imageInstance = $imageInstance;
1115         }
1116
1117         /**
1118          * Getter for image instance
1119          *
1120          * @return      $imageInstance  An instance of an image
1121          */
1122         public final function getImageInstance () {
1123                 return $this->imageInstance;
1124         }
1125
1126         /**
1127          * Setter for stacker instance
1128          *
1129          * @param       $stackInstance  An instance of an stacker
1130          * @return      void
1131          */
1132         public final function setStackInstance (Stackable $stackInstance) {
1133                 $this->stackInstance = $stackInstance;
1134         }
1135
1136         /**
1137          * Getter for stacker instance
1138          *
1139          * @return      $stackInstance  An instance of an stacker
1140          */
1141         public final function getStackInstance () {
1142                 return $this->stackInstance;
1143         }
1144
1145         /**
1146          * Setter for compressor instance
1147          *
1148          * @param       $compressorInstance     An instance of an compressor
1149          * @return      void
1150          */
1151         public final function setCompressorInstance (Compressor $compressorInstance) {
1152                 $this->compressorInstance = $compressorInstance;
1153         }
1154
1155         /**
1156          * Getter for compressor instance
1157          *
1158          * @return      $compressorInstance     An instance of an compressor
1159          */
1160         public final function getCompressorInstance () {
1161                 return $this->compressorInstance;
1162         }
1163
1164         /**
1165          * Setter for Parseable instance
1166          *
1167          * @param       $parserInstance An instance of an Parseable
1168          * @return      void
1169          */
1170         public final function setParserInstance (Parseable $parserInstance) {
1171                 $this->parserInstance = $parserInstance;
1172         }
1173
1174         /**
1175          * Getter for Parseable instance
1176          *
1177          * @return      $parserInstance An instance of an Parseable
1178          */
1179         public final function getParserInstance () {
1180                 return $this->parserInstance;
1181         }
1182
1183         /**
1184          * Setter for HandleableProtocol instance
1185          *
1186          * @param       $protocolInstance       An instance of an HandleableProtocol
1187          * @return      void
1188          */
1189         public final function setProtocolInstance (HandleableProtocol $protocolInstance) {
1190                 $this->protocolInstance = $protocolInstance;
1191         }
1192
1193         /**
1194          * Getter for HandleableProtocol instance
1195          *
1196          * @return      $protocolInstance       An instance of an HandleableProtocol
1197          */
1198         public final function getProtocolInstance () {
1199                 return $this->protocolInstance;
1200         }
1201
1202         /**
1203          * Setter for DatabaseWrapper instance
1204          *
1205          * @param       $wrapperInstance        An instance of an DatabaseWrapper
1206          * @return      void
1207          */
1208         public final function setWrapperInstance (DatabaseWrapper $wrapperInstance) {
1209                 $this->wrapperInstance = $wrapperInstance;
1210         }
1211
1212         /**
1213          * Getter for DatabaseWrapper instance
1214          *
1215          * @return      $wrapperInstance        An instance of an DatabaseWrapper
1216          */
1217         public final function getWrapperInstance () {
1218                 return $this->wrapperInstance;
1219         }
1220
1221         /**
1222          * Setter for socket resource
1223          *
1224          * @param       $socketResource         A valid socket resource
1225          * @return      void
1226          */
1227         public final function setSocketResource ($socketResource) {
1228                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($this->__toString() . '::' . __FUNCTION__ . ': socketResource=' . $socketResource . ',previous[' . gettype($this->socketResource) . ']=' . $this->socketResource);
1229                 $this->socketResource = $socketResource;
1230         }
1231
1232         /**
1233          * Getter for socket resource
1234          *
1235          * @return      $socketResource         A valid socket resource
1236          */
1237         public final function getSocketResource () {
1238                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($this->__toString() . '::' . __FUNCTION__ . ': socketResource[' . gettype($this->socketResource) . ']=' . $this->socketResource);
1239                 return $this->socketResource;
1240         }
1241
1242         /**
1243          * Setter for regular expression
1244          *
1245          * @param       $regularExpression      A valid regular expression
1246          * @return      void
1247          */
1248         public final function setRegularExpression ($regularExpression) {
1249                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($this->__toString() . '::' . __FUNCTION__ . ': regularExpression=' . $regularExpression . ',previous[' . gettype($this->regularExpression) . ']=' . $this->regularExpression);
1250                 $this->regularExpression = $regularExpression;
1251         }
1252
1253         /**
1254          * Getter for regular expression
1255          *
1256          * @return      $regularExpression      A valid regular expression
1257          */
1258         public final function getRegularExpression () {
1259                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($this->__toString() . '::' . __FUNCTION__ . ': regularExpression[' . gettype($this->regularExpression) . ']=' . $this->regularExpression);
1260                 return $this->regularExpression;
1261         }
1262
1263         /**
1264          * Setter for helper instance
1265          *
1266          * @param       $helperInstance         An instance of a helper class
1267          * @return      void
1268          */
1269         protected final function setHelperInstance (Helper $helperInstance) {
1270                 $this->helperInstance = $helperInstance;
1271         }
1272
1273         /**
1274          * Getter for helper instance
1275          *
1276          * @return      $helperInstance         An instance of a helper class
1277          */
1278         public final function getHelperInstance () {
1279                 return $this->helperInstance;
1280         }
1281
1282         /**
1283          * Setter for a Source instance
1284          *
1285          * @param       $sourceInstance         An instance of a Source class
1286          * @return      void
1287          */
1288         protected final function setSourceInstance (Source $sourceInstance) {
1289                 $this->sourceInstance = $sourceInstance;
1290         }
1291
1292         /**
1293          * Getter for a Source instance
1294          *
1295          * @return      $sourceInstance         An instance of a Source class
1296          */
1297         protected final function getSourceInstance () {
1298                 return $this->sourceInstance;
1299         }
1300
1301         /**
1302          * Setter for a UrlSource instance
1303          *
1304          * @param       $sourceInstance         An instance of a UrlSource class
1305          * @return      void
1306          */
1307         protected final function setUrlSourceInstance (UrlSource $urlSourceInstance) {
1308                 $this->urlSourceInstance = $urlSourceInstance;
1309         }
1310
1311         /**
1312          * Getter for a UrlSource instance
1313          *
1314          * @return      $urlSourceInstance              An instance of a UrlSource class
1315          */
1316         protected final function getUrlSourceInstance () {
1317                 return $this->urlSourceInstance;
1318         }
1319
1320         /**
1321          * Getter for a InputStream instance
1322          *
1323          * @param       $inputStreamInstance    The InputStream instance
1324          */
1325         protected final function getInputStreamInstance () {
1326                 return $this->inputStreamInstance;
1327         }
1328
1329         /**
1330          * Setter for a InputStream instance
1331          *
1332          * @param       $inputStreamInstance    The InputStream instance
1333          * @return      void
1334          */
1335         protected final function setInputStreamInstance (InputStream $inputStreamInstance) {
1336                 $this->inputStreamInstance = $inputStreamInstance;
1337         }
1338
1339         /**
1340          * Getter for a OutputStream instance
1341          *
1342          * @param       $outputStreamInstance   The OutputStream instance
1343          */
1344         protected final function getOutputStreamInstance () {
1345                 return $this->outputStreamInstance;
1346         }
1347
1348         /**
1349          * Setter for a OutputStream instance
1350          *
1351          * @param       $outputStreamInstance   The OutputStream instance
1352          * @return      void
1353          */
1354         protected final function setOutputStreamInstance (OutputStream $outputStreamInstance) {
1355                 $this->outputStreamInstance = $outputStreamInstance;
1356         }
1357
1358         /**
1359          * Setter for handler instance
1360          *
1361          * @param       $handlerInstance        An instance of a Handleable class
1362          * @return      void
1363          */
1364         protected final function setHandlerInstance (Handleable $handlerInstance) {
1365                 $this->handlerInstance = $handlerInstance;
1366         }
1367
1368         /**
1369          * Getter for handler instance
1370          *
1371          * @return      $handlerInstance        A Networkable instance
1372          */
1373         protected final function getHandlerInstance () {
1374                 return $this->handlerInstance;
1375         }
1376
1377         /**
1378          * Setter for visitor instance
1379          *
1380          * @param       $visitorInstance        A Visitor instance
1381          * @return      void
1382          */
1383         protected final function setVisitorInstance (Visitor $visitorInstance) {
1384                 $this->visitorInstance = $visitorInstance;
1385         }
1386
1387         /**
1388          * Getter for visitor instance
1389          *
1390          * @return      $visitorInstance        A Visitor instance
1391          */
1392         protected final function getVisitorInstance () {
1393                 return $this->visitorInstance;
1394         }
1395
1396         /**
1397          * Setter for DHT instance
1398          *
1399          * @param       $dhtInstance    A Distributable instance
1400          * @return      void
1401          */
1402         protected final function setDhtInstance (Distributable $dhtInstance) {
1403                 $this->dhtInstance = $dhtInstance;
1404         }
1405
1406         /**
1407          * Getter for DHT instance
1408          *
1409          * @return      $dhtInstance    A Distributable instance
1410          */
1411         protected final function getDhtInstance () {
1412                 return $this->dhtInstance;
1413         }
1414
1415         /**
1416          * Setter for raw package Data
1417          *
1418          * @param       $packageData    Raw package Data
1419          * @return      void
1420          */
1421         public final function setPackageData (array $packageData) {
1422                 $this->packageData = $packageData;
1423         }
1424
1425         /**
1426          * Getter for raw package Data
1427          *
1428          * @return      $packageData    Raw package Data
1429          */
1430         public function getPackageData () {
1431                 return $this->packageData;
1432         }
1433
1434
1435         /**
1436          * Setter for Iterator instance
1437          *
1438          * @param       $iteratorInstance       An instance of an Iterator
1439          * @return      void
1440          */
1441         protected final function setIteratorInstance (Iterator $iteratorInstance) {
1442                 $this->iteratorInstance = $iteratorInstance;
1443         }
1444
1445         /**
1446          * Getter for Iterator instance
1447          *
1448          * @return      $iteratorInstance       An instance of an Iterator
1449          */
1450         public final function getIteratorInstance () {
1451                 return $this->iteratorInstance;
1452         }
1453
1454         /**
1455          * Setter for FilePointer instance
1456          *
1457          * @param       $pointerInstance        An instance of an FilePointer class
1458          * @return      void
1459          */
1460         protected final function setPointerInstance (FilePointer $pointerInstance) {
1461                 $this->pointerInstance = $pointerInstance;
1462         }
1463
1464         /**
1465          * Getter for FilePointer instance
1466          *
1467          * @return      $pointerInstance        An instance of an FilePointer class
1468          */
1469         public final function getPointerInstance () {
1470                 return $this->pointerInstance;
1471         }
1472
1473         /**
1474          * Unsets pointer instance which triggers a call of __destruct() if the
1475          * instance is still there. This is surely not fatal on already "closed"
1476          * file pointer instances.
1477          *
1478          * I don't want to mess around with above setter by giving it a default
1479          * value NULL as setter should always explicitly only set (existing) object
1480          * instances and NULL is NULL.
1481          *
1482          * @return      void
1483          */
1484         protected final function unsetPointerInstance () {
1485                 // Simply it to NULL
1486                 $this->pointerInstance = NULL;
1487         }
1488
1489         /**
1490          * Setter for Indexable instance
1491          *
1492          * @param       $indexInstance  An instance of an Indexable class
1493          * @return      void
1494          */
1495         protected final function setIndexInstance (Indexable $indexInstance) {
1496                 $this->indexInstance = $indexInstance;
1497         }
1498
1499         /**
1500          * Getter for Indexable instance
1501          *
1502          * @return      $indexInstance  An instance of an Indexable class
1503          */
1504         public final function getIndexInstance () {
1505                 return $this->indexInstance;
1506         }
1507
1508         /**
1509          * Setter for Block instance
1510          *
1511          * @param       $blockInstance  An instance of an Block class
1512          * @return      void
1513          */
1514         protected final function setBlockInstance (Block $blockInstance) {
1515                 $this->blockInstance = $blockInstance;
1516         }
1517
1518         /**
1519          * Getter for Block instance
1520          *
1521          * @return      $blockInstance  An instance of an Block class
1522          */
1523         public final function getBlockInstance () {
1524                 return $this->blockInstance;
1525         }
1526
1527         /**
1528          * Setter for Minable instance
1529          *
1530          * @param       $minableInstance        A Minable instance
1531          * @return      void
1532          */
1533         protected final function setMinableInstance (Minable $minableInstance) {
1534                 $this->minableInstance = $minableInstance;
1535         }
1536
1537         /**
1538          * Getter for minable instance
1539          *
1540          * @return      $minableInstance        A Minable instance
1541          */
1542         protected final function getMinableInstance () {
1543                 return $this->minableInstance;
1544         }
1545
1546         /**
1547          * Setter for FrameworkDirectory instance
1548          *
1549          * @param       $directoryInstance      A FrameworkDirectory instance
1550          * @return      void
1551          */
1552         protected final function setDirectoryInstance (FrameworkDirectory $directoryInstance) {
1553                 $this->directoryInstance = $directoryInstance;
1554         }
1555
1556         /**
1557          * Getter for FrameworkDirectory instance
1558          *
1559          * @return      $directoryInstance      A FrameworkDirectory instance
1560          */
1561         protected final function getDirectoryInstance () {
1562                 return $this->directoryInstance;
1563         }
1564
1565         /**
1566          * Setter for listener instance
1567          *
1568          * @param       $listenerInstance       A Listenable instance
1569          * @return      void
1570          */
1571         protected final function setListenerInstance (Listenable $listenerInstance) {
1572                 $this->listenerInstance = $listenerInstance;
1573         }
1574
1575         /**
1576          * Getter for listener instance
1577          *
1578          * @return      $listenerInstance       A Listenable instance
1579          */
1580         protected final function getListenerInstance () {
1581                 return $this->listenerInstance;
1582         }
1583
1584         /**
1585          * Getter for communicator instance
1586          *
1587          * @return      $communicatorInstance   An instance of a Communicator class
1588          */
1589         public final function getCommunicatorInstance () {
1590                 return $this->communicatorInstance;
1591         }
1592
1593         /**
1594          * Setter for communicator instance
1595          *
1596          * @param       $communicatorInstance   An instance of a Communicator class
1597          * @return      void
1598          */
1599         protected final function setCommunicatorInstance (Communicator $communicatorInstance) {
1600                 $this->communicatorInstance = $communicatorInstance;
1601         }
1602
1603         /**
1604          * Setter for state instance
1605          *
1606          * @param       $stateInstance  A Stateable instance
1607          * @return      void
1608          */
1609         public final function setStateInstance (Stateable $stateInstance) {
1610                 $this->stateInstance = $stateInstance;
1611         }
1612
1613         /**
1614          * Getter for state instance
1615          *
1616          * @return      $stateInstance  A Stateable instance
1617          */
1618         public final function getStateInstance () {
1619                 return $this->stateInstance;
1620         }
1621
1622         /**
1623          * Setter for output instance
1624          *
1625          * @param       $outputInstance The debug output instance
1626          * @return      void
1627          */
1628         public final function setOutputInstance (OutputStreamer $outputInstance) {
1629                 $this->outputInstance = $outputInstance;
1630         }
1631
1632         /**
1633          * Getter for output instance
1634          *
1635          * @return      $outputInstance The debug output instance
1636          */
1637         public final function getOutputInstance () {
1638                 return $this->outputInstance;
1639         }
1640
1641         /**
1642          * Setter for command name
1643          *
1644          * @param       $commandName    Last validated command name
1645          * @return      void
1646          */
1647         protected final function setCommandName ($commandName) {
1648                 $this->commandName = $commandName;
1649         }
1650
1651         /**
1652          * Getter for command name
1653          *
1654          * @return      $commandName    Last validated command name
1655          */
1656         protected final function getCommandName () {
1657                 return $this->commandName;
1658         }
1659
1660         /**
1661          * Setter for controller name
1662          *
1663          * @param       $controllerName Last validated controller name
1664          * @return      void
1665          */
1666         protected final function setControllerName ($controllerName) {
1667                 $this->controllerName = $controllerName;
1668         }
1669
1670         /**
1671          * Getter for controller name
1672          *
1673          * @return      $controllerName Last validated controller name
1674          */
1675         protected final function getControllerName () {
1676                 return $this->controllerName;
1677         }
1678
1679         /**
1680          * Getter for protocol name
1681          *
1682          * @return      $protocolName   Name of used protocol
1683          */
1684         public final function getProtocolName () {
1685                 return $this->protocolName;
1686         }
1687
1688         /**
1689          * Setter for protocol name
1690          *
1691          * @param       $protocolName   Name of used protocol
1692          * @return      void
1693          */
1694         protected final function setProtocolName ($protocolName) {
1695                 $this->protocolName = $protocolName;
1696         }
1697
1698         /**
1699          * Checks whether an object equals this object. You should overwrite this
1700          * method to implement own equality checks
1701          *
1702          * @param       $objectInstance         An instance of a FrameworkInterface object
1703          * @return      $equals                         Whether both objects equals
1704          */
1705         public function equals (FrameworkInterface $objectInstance) {
1706                 // Now test it
1707                 $equals = ((
1708                         $this->__toString() == $objectInstance->__toString()
1709                 ) && (
1710                         $this->hashCode() == $objectInstance->hashCode()
1711                 ));
1712
1713                 // Return the result
1714                 return $equals;
1715         }
1716
1717         /**
1718          * Generates a generic hash code of this class. You should really overwrite
1719          * this method with your own hash code generator code. But keep KISS in mind.
1720          *
1721          * @return      $hashCode       A generic hash code respresenting this whole class
1722          */
1723         public function hashCode () {
1724                 // Simple hash code
1725                 return crc32($this->__toString());
1726         }
1727
1728         /**
1729          * Formats computer generated price values into human-understandable formats
1730          * with thousand and decimal separators.
1731          *
1732          * @param       $value          The in computer format value for a price
1733          * @param       $currency       The currency symbol (use HTML-valid characters!)
1734          * @param       $decNum         Number of decimals after commata
1735          * @return      $price          The for the current language formated price string
1736          * @throws      MissingDecimalsThousandsSeparatorException      If decimals or
1737          *                                                                                              thousands separator
1738          *                                                                                              is missing
1739          */
1740         public function formatCurrency ($value, $currency = '&euro;', $decNum = 2) {
1741                 // Are all required attriutes set?
1742                 if ((!isset($this->decimals)) || (!isset($this->thousands))) {
1743                         // Throw an exception
1744                         throw new MissingDecimalsThousandsSeparatorException($this, self::EXCEPTION_ATTRIBUTES_ARE_MISSING);
1745                 } // END - if
1746
1747                 // Cast the number
1748                 $value = (float) $value;
1749
1750                 // Reformat the US number
1751                 $price = number_format($value, $decNum, $this->decimals, $this->thousands) . $currency;
1752
1753                 // Return as string...
1754                 return $price;
1755         }
1756
1757         /**
1758          * Appends a trailing slash to a string
1759          *
1760          * @param       $str    A string (maybe) without trailing slash
1761          * @return      $str    A string with an auto-appended trailing slash
1762          */
1763         public final function addMissingTrailingSlash ($str) {
1764                 // Is there a trailing slash?
1765                 if (substr($str, -1, 1) != '/') {
1766                         $str .= '/';
1767                 } // END - if
1768
1769                 // Return string with trailing slash
1770                 return $str;
1771         }
1772
1773         /**
1774          * Prepare the template engine (HtmlTemplateEngine by default) for a given
1775          * application helper instance (ApplicationHelper by default).
1776          *
1777          * @param               $applicationInstance    An application helper instance or
1778          *                                                                              null if we shall use the default
1779          * @return              $templateInstance               The template engine instance
1780          * @throws              NullPointerException    If the discovered application
1781          *                                                                              instance is still null
1782          */
1783         protected function prepareTemplateInstance (ManageableApplication $applicationInstance = NULL) {
1784                 // Is the application instance set?
1785                 if (is_null($applicationInstance)) {
1786                         // Get the current instance
1787                         $applicationInstance = $this->getApplicationInstance();
1788
1789                         // Still null?
1790                         if (is_null($applicationInstance)) {
1791                                 // Thrown an exception
1792                                 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
1793                         } // END - if
1794                 } // END - if
1795
1796                 // Initialize the template engine
1797                 $templateInstance = ObjectFactory::createObjectByConfiguredName('html_template_class');
1798
1799                 // Return the prepared instance
1800                 return $templateInstance;
1801         }
1802
1803         /**
1804          * Debugs this instance by putting out it's full content
1805          *
1806          * @param       $message        Optional message to show in debug output
1807          * @return      void
1808          */
1809         public final function debugInstance ($message = '') {
1810                 // Restore the error handler to avoid trouble with missing array elements or undeclared variables
1811                 restore_error_handler();
1812
1813                 // Init content
1814                 $content = '';
1815
1816                 // Is a message set?
1817                 if (!empty($message)) {
1818                         // Construct message
1819                         $content = sprintf('<div class="debug_message">Message: %s</div>' . PHP_EOL, $message);
1820                 } // END - if
1821
1822                 // Generate the output
1823                 $content .= sprintf('<pre>%s</pre>',
1824                         trim(
1825                                 htmlentities(
1826                                         print_r($this, TRUE)
1827                                 )
1828                         )
1829                 );
1830
1831                 // Output it
1832                 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>',
1833                         $this->__toString(),
1834                         $content,
1835                         ClassLoader::getSelfInstance()->getPrintableIncludeList()
1836                 ));
1837         }
1838
1839         /**
1840          * Replaces control characters with printable output
1841          *
1842          * @param       $str    String with control characters
1843          * @return      $str    Replaced string
1844          */
1845         protected function replaceControlCharacters ($str) {
1846                 // Replace them
1847                 $str = str_replace(
1848                         chr(13), '[r]', str_replace(
1849                         chr(10), '[n]', str_replace(
1850                         chr(9) , '[t]',
1851                         $str
1852                 )));
1853
1854                 // Return it
1855                 return $str;
1856         }
1857
1858         /**
1859          * Output a partial stub message for the caller method
1860          *
1861          * @param       $message        An optional message to display
1862          * @return      void
1863          */
1864         protected function partialStub ($message = '') {
1865                 // Get the backtrace
1866                 $backtrace = debug_backtrace();
1867
1868                 // Generate the class::method string
1869                 $methodName = 'UnknownClass-&gt;unknownMethod';
1870                 if ((isset($backtrace[1]['class'])) && (isset($backtrace[1]['function']))) {
1871                         $methodName = $backtrace[1]['class'] . '-&gt;' . $backtrace[1]['function'];
1872                 } // END - if
1873
1874                 // Construct the full message
1875                 $stubMessage = sprintf('[%s:] Partial stub!',
1876                         $methodName
1877                 );
1878
1879                 // Is the extra message given?
1880                 if (!empty($message)) {
1881                         // Then add it as well
1882                         $stubMessage .= ' Message: ' . $message;
1883                 } // END - if
1884
1885                 // Debug instance is there?
1886                 if (!is_null($this->getDebugInstance())) {
1887                         // Output stub message
1888                         self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($stubMessage);
1889                 } else {
1890                         // Trigger an error
1891                         trigger_error($stubMessage);
1892                         exit;
1893                 }
1894         }
1895
1896         /**
1897          * Outputs a debug backtrace and stops further script execution
1898          *
1899          * @param       $message        An optional message to output
1900          * @param       $doExit         Whether exit the program (TRUE is default)
1901          * @return      void
1902          */
1903         public function debugBackTrace ($message = '', $doExit = TRUE) {
1904                 // Sorry, there is no other way getting this nice backtrace
1905                 if (!empty($message)) {
1906                         // Output message
1907                         printf('Message: %s<br />' . PHP_EOL, $message);
1908                 } // END - if
1909
1910                 print('<pre>');
1911                 debug_print_backtrace();
1912                 print('</pre>');
1913
1914                 // Exit program?
1915                 if ($doExit === TRUE) {
1916                         exit();
1917                 } // END - if
1918         }
1919
1920         /**
1921          * Creates an instance of a debugger instance
1922          *
1923          * @param       $className              Name of the class (currently unsupported)
1924          * @param       $lineNumber             Line number where the call was made
1925          * @return      $debugInstance  An instance of a debugger class
1926          * @deprecated  Not fully, as the new Logger facilities are not finished yet.
1927          */
1928         public final static function createDebugInstance ($className, $lineNumber = NULL) {
1929                 // Is the instance set?
1930                 if (!Registry::getRegistry()->instanceExists('debug')) {
1931                         // Init debug instance
1932                         $debugInstance = NULL;
1933
1934                         // Try it
1935                         try {
1936                                 // Get a debugger instance
1937                                 $debugInstance = DebugMiddleware::createDebugMiddleware(FrameworkConfiguration::getSelfInstance()->getConfigEntry('debug_' . self::getResponseTypeFromSystem() . '_class'), $className);
1938                         } catch (NullPointerException $e) {
1939                                 // Didn't work, no instance there
1940                                 exit(sprintf('Cannot create debugInstance! Exception=%s,message=%s,className=%s,lineNumber=%d' . PHP_EOL, $e->__toString(), $e->getMessage(), $className, $lineNumber));
1941                         }
1942
1943                         // Empty string should be ignored and used for testing the middleware
1944                         DebugMiddleware::getSelfInstance()->output('');
1945
1946                         // Set it in its own class. This will set it in the registry
1947                         $debugInstance->setDebugInstance($debugInstance);
1948                 } else {
1949                         // Get instance from registry
1950                         $debugInstance = Registry::getRegistry()->getDebugInstance();
1951                 }
1952
1953                 // Return it
1954                 return $debugInstance;
1955         }
1956
1957         /**
1958          * Simple output of a message with line-break
1959          *
1960          * @param       $message        Message to output
1961          * @return      void
1962          */
1963         public function outputLine ($message) {
1964                 // Simply output it
1965                 print($message . PHP_EOL);
1966         }
1967
1968         /**
1969          * Outputs a debug message whether to debug instance (should be set!) or
1970          * dies with or ptints the message. Do NEVER EVER rewrite the exit() call to
1971          * ApplicationEntryPoint::app_exit(), this would cause an endless loop.
1972          *
1973          * @param       $message        Message we shall send out...
1974          * @param       $doPrint        Whether print or die here (default: print)
1975          * @paran       $stripTags      Whether to strip tags (default: FALSE)
1976          * @return      void
1977          */
1978         public function debugOutput ($message, $doPrint = TRUE, $stripTags = FALSE) {
1979                 // Set debug instance to NULL
1980                 $debugInstance = NULL;
1981
1982                 // Try it:
1983                 try {
1984                         // Get debug instance
1985                         $debugInstance = $this->getDebugInstance();
1986                 } catch (NullPointerException $e) {
1987                         // The debug instance is not set (yet)
1988                 }
1989
1990                 // Is the debug instance there?
1991                 if (is_object($debugInstance)) {
1992                         // Use debug output handler
1993                         $debugInstance->output($message, $stripTags);
1994
1995                         if ($doPrint === FALSE) {
1996                                 // Die here if not printed
1997                                 exit();
1998                         } // END - if
1999                 } else {
2000                         // Are debug times enabled?
2001                         if ($this->getConfigInstance()->getConfigEntry('debug_' . self::getResponseTypeFromSystem() . '_output_timings') == 'Y') {
2002                                 // Prepent it
2003                                 $message = $this->getPrintableExecutionTime() . $message;
2004                         } // END - if
2005
2006                         // Put directly out
2007                         if ($doPrint === TRUE) {
2008                                 // Print message
2009                                 $this->outputLine($message);
2010                         } else {
2011                                 // Die here
2012                                 exit($message);
2013                         }
2014                 }
2015         }
2016
2017         /**
2018          * Converts e.g. a command from URL to a valid class by keeping out bad characters
2019          *
2020          * @param       $str            The string, what ever it is needs to be converted
2021          * @return      $className      Generated class name
2022          */
2023         public static final function convertToClassName ($str) {
2024                 // Init class name
2025                 $className = '';
2026
2027                 // Convert all dashes in underscores
2028                 $str = self::convertDashesToUnderscores($str);
2029
2030                 // Now use that underscores to get classname parts for hungarian style
2031                 foreach (explode('_', $str) as $strPart) {
2032                         // Make the class name part lower case and first upper case
2033                         $className .= ucfirst(strtolower($strPart));
2034                 } // END - foreach
2035
2036                 // Return class name
2037                 return $className;
2038         }
2039
2040         /**
2041          * Converts dashes to underscores, e.g. useable for configuration entries
2042          *
2043          * @param       $str    The string with maybe dashes inside
2044          * @return      $str    The converted string with no dashed, but underscores
2045          */
2046         public static final function convertDashesToUnderscores ($str) {
2047                 // Convert them all
2048                 $str = str_replace('-', '_', $str);
2049
2050                 // Return converted string
2051                 return $str;
2052         }
2053
2054         /**
2055          * Marks up the code by adding e.g. line numbers
2056          *
2057          * @param       $phpCode                Unmarked PHP code
2058          * @return      $markedCode             Marked PHP code
2059          */
2060         public function markupCode ($phpCode) {
2061                 // Init marked code
2062                 $markedCode = '';
2063
2064                 // Get last error
2065                 $errorArray = error_get_last();
2066
2067                 // Init the code with error message
2068                 if (is_array($errorArray)) {
2069                         // Get error infos
2070                         $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>',
2071                                 basename($errorArray['file']),
2072                                 $errorArray['line'],
2073                                 $errorArray['message'],
2074                                 $errorArray['type']
2075                         );
2076                 } // END - if
2077
2078                 // Add line number to the code
2079                 foreach (explode(chr(10), $phpCode) as $lineNo => $code) {
2080                         // Add line numbers
2081                         $markedCode .= sprintf('<span id="code_line">%s</span>: %s' . PHP_EOL,
2082                                 ($lineNo + 1),
2083                                 htmlentities($code, ENT_QUOTES)
2084                         );
2085                 } // END - foreach
2086
2087                 // Return the code
2088                 return $markedCode;
2089         }
2090
2091         /**
2092          * Filter a given GMT timestamp (non Uni* stamp!) to make it look more
2093          * beatiful for web-based front-ends. If null is given a message id
2094          * null_timestamp will be resolved and returned.
2095          *
2096          * @param       $timestamp      Timestamp to prepare (filter) for display
2097          * @return      $readable       A readable timestamp
2098          */
2099         public function doFilterFormatTimestamp ($timestamp) {
2100                 // Default value to return
2101                 $readable = '???';
2102
2103                 // Is the timestamp null?
2104                 if (is_null($timestamp)) {
2105                         // Get a message string
2106                         $readable = $this->getLanguageInstance()->getMessage('null_timestamp');
2107                 } else {
2108                         switch ($this->getLanguageInstance()->getLanguageCode()) {
2109                                 case 'de': // German format is a bit different to default
2110                                         // Split the GMT stamp up
2111                                         $dateTime  = explode(' ', $timestamp  );
2112                                         $dateArray = explode('-', $dateTime[0]);
2113                                         $timeArray = explode(':', $dateTime[1]);
2114
2115                                         // Construct the timestamp
2116                                         $readable = sprintf($this->getConfigInstance()->getConfigEntry('german_date_time'),
2117                                                 $dateArray[0],
2118                                                 $dateArray[1],
2119                                                 $dateArray[2],
2120                                                 $timeArray[0],
2121                                                 $timeArray[1],
2122                                                 $timeArray[2]
2123                                         );
2124                                         break;
2125
2126                                 default: // Default is pass-through
2127                                         $readable = $timestamp;
2128                                         break;
2129                         } // END - switch
2130                 }
2131
2132                 // Return the stamp
2133                 return $readable;
2134         }
2135
2136         /**
2137          * Filter a given number into a localized number
2138          *
2139          * @param       $value          The raw value from e.g. database
2140          * @return      $localized      Localized value
2141          */
2142         public function doFilterFormatNumber ($value) {
2143                 // Generate it from config and localize dependencies
2144                 switch ($this->getLanguageInstance()->getLanguageCode()) {
2145                         case 'de': // German format is a bit different to default
2146                                 $localized = number_format($value, $this->getConfigInstance()->getConfigEntry('decimals'), ',', '.');
2147                                 break;
2148
2149                         default: // US, etc.
2150                                 $localized = number_format($value, $this->getConfigInstance()->getConfigEntry('decimals'), '.', ',');
2151                                 break;
2152                 } // END - switch
2153
2154                 // Return it
2155                 return $localized;
2156         }
2157
2158         /**
2159          * "Getter" for databse entry
2160          *
2161          * @return      $entry  An array with database entries
2162          * @throws      NullPointerException    If the database result is not found
2163          * @throws      InvalidDatabaseResultException  If the database result is invalid
2164          */
2165         protected final function getDatabaseEntry () {
2166                 // Is there an instance?
2167                 if (!$this->getResultInstance() instanceof SearchableResult) {
2168                         // Throw an exception here
2169                         throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
2170                 } // END - if
2171
2172                 // Rewind it
2173                 $this->getResultInstance()->rewind();
2174
2175                 // Do we have an entry?
2176                 if ($this->getResultInstance()->valid() === FALSE) {
2177                         // @TODO Move the constant to e.g. BaseDatabaseResult when there is a non-cached database result available
2178                         throw new InvalidDatabaseResultException(array($this, $this->getResultInstance()), CachedDatabaseResult::EXCEPTION_INVALID_DATABASE_RESULT);
2179                 } // END - if
2180
2181                 // Get next entry
2182                 $this->getResultInstance()->next();
2183
2184                 // Fetch it
2185                 $entry = $this->getResultInstance()->current();
2186
2187                 // And return it
2188                 return $entry;
2189         }
2190
2191         /**
2192          * Getter for field name
2193          *
2194          * @param       $fieldName              Field name which we shall get
2195          * @return      $fieldValue             Field value from the user
2196          * @throws      NullPointerException    If the result instance is null
2197          */
2198         public final function getField ($fieldName) {
2199                 // Default field value
2200                 $fieldValue = NULL;
2201
2202                 // Get result instance
2203                 $resultInstance = $this->getResultInstance();
2204
2205                 // Is this instance null?
2206                 if (is_null($resultInstance)) {
2207                         // Then the user instance is no longer valid (expired cookies?)
2208                         throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
2209                 } // END - if
2210
2211                 // Get current array
2212                 $fieldArray = $resultInstance->current();
2213                 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($fieldName.':<pre>'.print_r($fieldArray, TRUE).'</pre>');
2214
2215                 // Convert dashes to underscore
2216                 $fieldName2 = self::convertDashesToUnderscores($fieldName);
2217
2218                 // Does the field exist?
2219                 if ($this->isFieldSet($fieldName)) {
2220                         // Get it
2221                         $fieldValue = $fieldArray[$fieldName2];
2222                 } elseif (defined('DEVELOPER')) {
2223                         // Missing field entry, may require debugging
2224                         self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ']:fieldArray<pre>=' . print_r($fieldArray, TRUE) . '</pre>,fieldName=' . $fieldName . ' not found!');
2225                 } else {
2226                         // Missing field entry, may require debugging
2227                         self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ']:fieldName=' . $fieldName . ' not found!');
2228                 }
2229
2230                 // Return it
2231                 return $fieldValue;
2232         }
2233
2234         /**
2235          * Checks if given field is set
2236          *
2237          * @param       $fieldName      Field name to check
2238          * @return      $isSet          Whether the given field name is set
2239          * @throws      NullPointerException    If the result instance is null
2240          */
2241         public function isFieldSet ($fieldName) {
2242                 // Get result instance
2243                 $resultInstance = $this->getResultInstance();
2244
2245                 // Is this instance null?
2246                 if (is_null($resultInstance)) {
2247                         // Then the user instance is no longer valid (expired cookies?)
2248                         throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
2249                 } // END - if
2250
2251                 // Get current array
2252                 $fieldArray = $resultInstance->current();
2253                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('[' . $this->__toString() . ':' . __LINE__ . '] fieldName=' . $fieldName . ',fieldArray=<pre>'.print_r($fieldArray, TRUE).'</pre>');
2254
2255                 // Convert dashes to underscore
2256                 $fieldName = self::convertDashesToUnderscores($fieldName);
2257
2258                 // Determine it
2259                 $isSet = isset($fieldArray[$fieldName]);
2260
2261                 // Return result
2262                 return $isSet;
2263         }
2264
2265         /**
2266          * Flushs all pending updates to the database layer
2267          *
2268          * @return      void
2269          */
2270         public function flushPendingUpdates () {
2271                 // Get result instance
2272                 $resultInstance = $this->getResultInstance();
2273
2274                 // Do we have data to update?
2275                 if ((is_object($resultInstance)) && ($resultInstance->ifDataNeedsFlush())) {
2276                         // Get wrapper class name config entry
2277                         $configEntry = $resultInstance->getUpdateInstance()->getWrapperConfigEntry();
2278
2279                         // Create object instance
2280                         $wrapperInstance = DatabaseWrapperFactory::createWrapperByConfiguredName($configEntry);
2281
2282                         // Yes, then send the whole result to the database layer
2283                         $wrapperInstance->doUpdateByResult($this->getResultInstance());
2284                 } // END - if
2285         }
2286
2287         /**
2288          * Outputs a deprecation warning to the developer.
2289          *
2290          * @param       $message        The message we shall output to the developer
2291          * @return      void
2292          * @todo        Write a logging mechanism for productive mode
2293          */
2294         public function deprecationWarning ($message) {
2295                 // Is developer mode active?
2296                 if (defined('DEVELOPER')) {
2297                         // Debug instance is there?
2298                         if (!is_null($this->getDebugInstance())) {
2299                                 // Output stub message
2300                                 self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($message);
2301                         } else {
2302                                 // Trigger an error
2303                                 trigger_error($message . "<br />\n");
2304                                 exit;
2305                         }
2306                 } else {
2307                         // @TODO Finish this part!
2308                         $this->partialStub('Developer mode inactive. Message:' . $message);
2309                 }
2310         }
2311
2312         /**
2313          * Checks whether the given PHP extension is loaded
2314          *
2315          * @param       $phpExtension   The PHP extension we shall check
2316          * @return      $isLoaded       Whether the PHP extension is loaded
2317          */
2318         public final function isPhpExtensionLoaded ($phpExtension) {
2319                 // Is it loaded?
2320                 $isLoaded = in_array($phpExtension, get_loaded_extensions());
2321
2322                 // Return result
2323                 return $isLoaded;
2324         }
2325
2326         /**
2327          * "Getter" as a time() replacement but with milliseconds. You should use this
2328          * method instead of the encapsulated getimeofday() function.
2329          *
2330          * @return      $milliTime      Timestamp with milliseconds
2331          */
2332         public function getMilliTime () {
2333                 // Get the time of day as float
2334                 $milliTime = gettimeofday(TRUE);
2335
2336                 // Return it
2337                 return $milliTime;
2338         }
2339
2340         /**
2341          * Idles (sleeps) for given milliseconds
2342          *
2343          * @return      $hasSlept       Whether it goes fine
2344          */
2345         public function idle ($milliSeconds) {
2346                 // Sleep is fine by default
2347                 $hasSlept = TRUE;
2348
2349                 // Idle so long with found function
2350                 if (function_exists('time_sleep_until')) {
2351                         // Get current time and add idle time
2352                         $sleepUntil = $this->getMilliTime() + abs($milliSeconds) / 1000;
2353
2354                         // New PHP 5.1.0 function found, ignore errors
2355                         $hasSlept = @time_sleep_until($sleepUntil);
2356                 } else {
2357                         /*
2358                          * My Sun station doesn't have that function even with latest PHP
2359                          * package. :(
2360                          */
2361                         usleep($milliSeconds * 1000);
2362                 }
2363
2364                 // Return result
2365                 return $hasSlept;
2366         }
2367         /**
2368          * Converts a hexadecimal string, even with negative sign as first string to
2369          * a decimal number using BC functions.
2370          *
2371          * This work is based on comment #86673 on php.net documentation page at:
2372          * <http://de.php.net/manual/en/function.dechex.php#86673>
2373          *
2374          * @param       $hex    Hexadecimal string
2375          * @return      $dec    Decimal number
2376          */
2377         protected function hex2dec ($hex) {
2378                 // Convert to all lower-case
2379                 $hex = strtolower($hex);
2380
2381                 // Detect sign (negative/positive numbers)
2382                 $sign = '';
2383                 if (substr($hex, 0, 1) == '-') {
2384                         $sign = '-';
2385                         $hex = substr($hex, 1);
2386                 } // END - if
2387
2388                 // Decode the hexadecimal string into a decimal number
2389                 $dec = 0;
2390                 for ($i = strlen($hex) - 1, $e = 1; $i >= 0; $i--, $e = bcmul($e, 16)) {
2391                         $factor = self::$hexdec[substr($hex, $i, 1)];
2392                         $dec = bcadd($dec, bcmul($factor, $e));
2393                 } // END - for
2394
2395                 // Return the decimal number
2396                 return $sign . $dec;
2397         }
2398
2399         /**
2400          * Converts even very large decimal numbers, also signed, to a hexadecimal
2401          * string.
2402          *
2403          * This work is based on comment #97756 on php.net documentation page at:
2404          * <http://de.php.net/manual/en/function.hexdec.php#97756>
2405          *
2406          * @param       $dec            Decimal number, even with negative sign
2407          * @param       $maxLength      Optional maximum length of the string
2408          * @return      $hex    Hexadecimal string
2409          */
2410         protected function dec2hex ($dec, $maxLength = 0) {
2411                 // maxLength can be zero or devideable by 2
2412                 assert(($maxLength == 0) || (($maxLength % 2) == 0));
2413
2414                 // Detect sign (negative/positive numbers)
2415                 $sign = '';
2416                 if ($dec < 0) {
2417                         $sign = '-';
2418                         $dec = abs($dec);
2419                 } // END - if
2420
2421                 // Encode the decimal number into a hexadecimal string
2422                 $hex = '';
2423                 do {
2424                         $hex = self::$dechex[($dec % (2 ^ 4))] . $hex;
2425                         $dec /= (2 ^ 4);
2426                 } while ($dec >= 1);
2427
2428                 /*
2429                  * Leading zeros are required for hex-decimal "numbers". In some
2430                  * situations more leading zeros are wanted, so check for both
2431                  * conditions.
2432                  */
2433                 if ($maxLength > 0) {
2434                         // Prepend more zeros
2435                         $hex = str_pad($hex, $maxLength, '0', STR_PAD_LEFT);
2436                 } elseif ((strlen($hex) % 2) != 0) {
2437                         // Only make string's length dividable by 2
2438                         $hex = '0' . $hex;
2439                 }
2440
2441                 // Return the hexadecimal string
2442                 return $sign . $hex;
2443         }
2444
2445         /**
2446          * Converts a ASCII string (0 to 255) into a decimal number.
2447          *
2448          * @param       $asc    The ASCII string to be converted
2449          * @return      $dec    Decimal number
2450          */
2451         protected function asc2dec ($asc) {
2452                 // Convert it into a hexadecimal number
2453                 $hex = bin2hex($asc);
2454
2455                 // And back into a decimal number
2456                 $dec = $this->hex2dec($hex);
2457
2458                 // Return it
2459                 return $dec;
2460         }
2461
2462         /**
2463          * Converts a decimal number into an ASCII string.
2464          *
2465          * @param       $dec            Decimal number
2466          * @return      $asc    An ASCII string
2467          */
2468         protected function dec2asc ($dec) {
2469                 // First convert the number into a hexadecimal string
2470                 $hex = $this->dec2hex($dec);
2471
2472                 // Then convert it into the ASCII string
2473                 $asc = $this->hex2asc($hex);
2474
2475                 // Return it
2476                 return $asc;
2477         }
2478
2479         /**
2480          * Converts a hexadecimal number into an ASCII string. Negative numbers
2481          * are not allowed.
2482          *
2483          * @param       $hex    Hexadecimal string
2484          * @return      $asc    An ASCII string
2485          */
2486         protected function hex2asc ($hex) {
2487                 // Check for length, it must be devideable by 2
2488                 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('hex='.$hex);
2489                 assert((strlen($hex) % 2) == 0);
2490
2491                 // Walk the string
2492                 $asc = '';
2493                 for ($idx = 0; $idx < strlen($hex); $idx+=2) {
2494                         // Get the decimal number of the chunk
2495                         $part = hexdec(substr($hex, $idx, 2));
2496
2497                         // Add it to the final string
2498                         $asc .= chr($part);
2499                 } // END - for
2500
2501                 // Return the final string
2502                 return $asc;
2503         }
2504
2505         /**
2506          * Checks whether the given encoded data was encoded with Base64
2507          *
2508          * @param       $encodedData    Encoded data we shall check
2509          * @return      $isBase64               Whether the encoded data is Base64
2510          */
2511         protected function isBase64Encoded ($encodedData) {
2512                 // Determine it
2513                 $isBase64 = (@base64_decode($encodedData, TRUE) !== FALSE);
2514
2515                 // Return it
2516                 return $isBase64;
2517         }
2518
2519         /**
2520          * "Getter" to get response/request type from analysis of the system.
2521          *
2522          * @return      $responseType   Analyzed response type
2523          */
2524         protected static function getResponseTypeFromSystem () {
2525                 // Default is console
2526                 $responseType = 'console';
2527
2528                 // Is 'HTTP_HOST' set?
2529                 if (isset($_SERVER['HTTP_HOST'])) {
2530                         /*
2531                          * Then it is a HTML response/request as RSS and so on may be
2532                          * transfered over HTTP as well.
2533                          */
2534                         $responseType = 'html';
2535                 } // END - if
2536
2537                 // Return it
2538                 return $responseType;
2539         }
2540
2541         /**
2542          * Gets a cache key from Criteria instance
2543          *
2544          * @param       $criteriaInstance       An instance of a Criteria class
2545          * @param       $onlyKeys                       Only use these keys for a cache key
2546          * @return      $cacheKey                       A cache key suitable for lookup/storage purposes
2547          */
2548         protected function getCacheKeyByCriteria (Criteria $criteriaInstance, array $onlyKeys = array()) {
2549                 // Generate it
2550                 $cacheKey = sprintf('%s@%s',
2551                         $this->__toString(),
2552                         $criteriaInstance->getCacheKey($onlyKeys)
2553                 );
2554
2555                 // And return it
2556                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($this->__toString() . ': cacheKey=' . $cacheKey);
2557                 return $cacheKey;
2558         }
2559
2560         /**
2561          * Getter for startup time in miliseconds
2562          *
2563          * @return      $startupTime    Startup time in miliseconds
2564          */
2565         protected function getStartupTime () {
2566                 return self::$startupTime;
2567         }
2568
2569         /**
2570          * "Getter" for a printable currently execution time in nice braces
2571          *
2572          * @return      $executionTime  Current execution time in nice braces
2573          */
2574         protected function getPrintableExecutionTime () {
2575                 // Caculate the execution time
2576                 $executionTime = microtime(TRUE) - $this->getStartupTime();
2577
2578                 // Pack it in nice braces
2579                 $executionTime = sprintf('[ %01.5f ] ', $executionTime);
2580
2581                 // And return it
2582                 return $executionTime;
2583         }
2584
2585         /**
2586          * Hashes a given string with a simple but stronger hash function (no salt)
2587          * and hex-encode it.
2588          *
2589          * @param       $str    The string to be hashed
2590          * @return      $hash   The hash from string $str
2591          */
2592         public static final function hash ($str) {
2593                 // Hash given string with (better secure) hasher
2594                 $hash = bin2hex(mhash(MHASH_SHA256, $str));
2595
2596                 // Return it
2597                 return $hash;
2598         }
2599
2600         /**
2601          * "Getter" for length of hash() output. This will be "cached" to speed up
2602          * things.
2603          *
2604          * @return      $length         Length of hash() output
2605          */
2606         public static final function getHashLength () {
2607                 // Is it cashed?
2608                 if (is_null(self::$hashLength)) {
2609                         // No, then hash a string and save its length.
2610                         self::$hashLength = strlen(self::hash('abc123'));
2611                 } // END - if
2612
2613                 // Return it
2614                 return self::$hashLength;
2615         }
2616
2617         /**
2618          * Checks whether the given number is really a number (only chars 0-9).
2619          *
2620          * @param       $num            A string consisting only chars between 0 and 9
2621          * @param       $castValue      Whether to cast the value to double. Do only use this to secure numbers from Requestable classes.
2622          * @param       $assertMismatch         Whether to assert mismatches
2623          * @return      $ret            The (hopefully) secured numbered value
2624          */
2625         public function bigintval ($num, $castValue = TRUE, $assertMismatch = FALSE) {
2626                 // Filter all numbers out
2627                 $ret = preg_replace('/[^0123456789]/', '', $num);
2628
2629                 // Shall we cast?
2630                 if ($castValue === TRUE) {
2631                         // Cast to biggest numeric type
2632                         $ret = (double) $ret;
2633                 } // END - if
2634
2635                 // Assert only if requested
2636                 if ($assertMismatch === TRUE) {
2637                         // Has the whole value changed?
2638                         assert(('' . $ret . '' != '' . $num . '') && (!is_null($num)));
2639                 } // END - if
2640
2641                 // Return result
2642                 return $ret;
2643         }
2644
2645         /**
2646          * Checks whether the given hexadecimal number is really a hex-number (only chars 0-9,a-f).
2647          *
2648          * @param       $num    A string consisting only chars between 0 and 9
2649          * @param       $assertMismatch         Whether to assert mismatches
2650          * @return      $ret    The (hopefully) secured hext-numbered value
2651          */
2652         public function hexval ($num, $assertMismatch = FALSE) {
2653                 // Filter all numbers out
2654                 $ret = preg_replace('/[^0123456789abcdefABCDEF]/', '', $num);
2655
2656                 // Assert only if requested
2657                 if ($assertMismatch === TRUE) {
2658                         // Has the whole value changed?
2659                         assert(('' . $ret . '' != '' . $num . '') && (!is_null($num)));
2660                 } // END - if
2661
2662                 // Return result
2663                 return $ret;
2664         }
2665
2666         /**
2667          * Checks whether start/end marker are set
2668          *
2669          * @param       $data   Data to be checked
2670          * @return      $isset  Whether start/end marker are set
2671          */
2672         public final function ifStartEndMarkersSet ($data) {
2673                 // Determine it
2674                 $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));
2675
2676                 // ... and return it
2677                 return $isset;
2678         }
2679
2680         /**
2681          * Determines if an element is set in the generic array
2682          *
2683          * @param       $keyGroup       Main group for the key
2684          * @param       $subGroup       Sub group for the key
2685          * @param       $key            Key to check
2686          * @param       $element        Element to check
2687          * @return      $isset          Whether the given key is set
2688          */
2689         protected final function isGenericArrayElementSet ($keyGroup, $subGroup, $key, $element) {
2690                 // Debug message
2691                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element);
2692
2693                 // Is it there?
2694                 $isset = isset($this->genericArray[$keyGroup][$subGroup][$key][$element]);
2695
2696                 // Return it
2697                 return $isset;
2698         }
2699         /**
2700          * Determines if a key is set in the generic array
2701          *
2702          * @param       $keyGroup       Main group for the key
2703          * @param       $subGroup       Sub group for the key
2704          * @param       $key            Key to check
2705          * @return      $isset          Whether the given key is set
2706          */
2707         protected final function isGenericArrayKeySet ($keyGroup, $subGroup, $key) {
2708                 // Debug message
2709                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2710
2711                 // Is it there?
2712                 $isset = isset($this->genericArray[$keyGroup][$subGroup][$key]);
2713
2714                 // Return it
2715                 return $isset;
2716         }
2717
2718
2719         /**
2720          * Determines if a group is set in the generic array
2721          *
2722          * @param       $keyGroup       Main group
2723          * @param       $subGroup       Sub group
2724          * @return      $isset          Whether the given group is set
2725          */
2726         protected final function isGenericArrayGroupSet ($keyGroup, $subGroup) {
2727                 // Debug message
2728                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup);
2729
2730                 // Is it there?
2731                 $isset = isset($this->genericArray[$keyGroup][$subGroup]);
2732
2733                 // Return it
2734                 return $isset;
2735         }
2736
2737         /**
2738          * Getter for sub key group
2739          *
2740          * @param       $keyGroup       Main key group
2741          * @param       $subGroup       Sub key group
2742          * @return      $array          An array with all array elements
2743          */
2744         protected final function getGenericSubArray ($keyGroup, $subGroup) {
2745                 // Is it there?
2746                 if (!$this->isGenericArrayGroupSet($keyGroup, $subGroup)) {
2747                         // No, then abort here
2748                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' not found.');
2749                         exit;
2750                 } // END - if
2751
2752                 // Debug message
2753                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',value=' . print_r($this->genericArray[$keyGroup][$subGroup], TRUE));
2754
2755                 // Return it
2756                 return $this->genericArray[$keyGroup][$subGroup];
2757         }
2758
2759         /**
2760          * Unsets a given key in generic array
2761          *
2762          * @param       $keyGroup       Main group for the key
2763          * @param       $subGroup       Sub group for the key
2764          * @param       $key            Key to unset
2765          * @return      void
2766          */
2767         protected final function unsetGenericArrayKey ($keyGroup, $subGroup, $key) {
2768                 // Debug message
2769                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2770
2771                 // Remove it
2772                 unset($this->genericArray[$keyGroup][$subGroup][$key]);
2773         }
2774
2775         /**
2776          * Unsets a given element in generic array
2777          *
2778          * @param       $keyGroup       Main group for the key
2779          * @param       $subGroup       Sub group for the key
2780          * @param       $key            Key to unset
2781          * @param       $element        Element to unset
2782          * @return      void
2783          */
2784         protected final function unsetGenericArrayElement ($keyGroup, $subGroup, $key, $element) {
2785                 // Debug message
2786                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element);
2787
2788                 // Remove it
2789                 unset($this->genericArray[$keyGroup][$subGroup][$key][$element]);
2790         }
2791
2792         /**
2793          * Append a string to a given generic array key
2794          *
2795          * @param       $keyGroup       Main group for the key
2796          * @param       $subGroup       Sub group for the key
2797          * @param       $key            Key to unset
2798          * @param       $value          Value to add/append
2799          * @return      void
2800          */
2801         protected final function appendStringToGenericArrayKey ($keyGroup, $subGroup, $key, $value, $appendGlue = '') {
2802                 // Debug message
2803                 //* 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);
2804
2805                 // Is it already there?
2806                 if ($this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
2807                         // Append it
2808                         $this->genericArray[$keyGroup][$subGroup][$key] .= $appendGlue . (string) $value;
2809                 } else {
2810                         // Add it
2811                         $this->genericArray[$keyGroup][$subGroup][$key] = (string) $value;
2812                 }
2813         }
2814
2815         /**
2816          * Append a string to a given generic array element
2817          *
2818          * @param       $keyGroup       Main group for the key
2819          * @param       $subGroup       Sub group for the key
2820          * @param       $key            Key to unset
2821          * @param       $element        Element to check
2822          * @param       $value          Value to add/append
2823          * @return      void
2824          */
2825         protected final function appendStringToGenericArrayElement ($keyGroup, $subGroup, $key, $element, $value, $appendGlue = '') {
2826                 // Debug message
2827                 //* 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);
2828
2829                 // Is it already there?
2830                 if ($this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element)) {
2831                         // Append it
2832                         $this->genericArray[$keyGroup][$subGroup][$key][$element] .= $appendGlue . (string) $value;
2833                 } else {
2834                         // Add it
2835                         $this->setStringGenericArrayElement($keyGroup, $subGroup, $key, $element, $value);
2836                 }
2837         }
2838
2839         /**
2840          * Sets a string in a given generic array element
2841          *
2842          * @param       $keyGroup       Main group for the key
2843          * @param       $subGroup       Sub group for the key
2844          * @param       $key            Key to unset
2845          * @param       $element        Element to check
2846          * @param       $value          Value to add/append
2847          * @return      void
2848          */
2849         protected final function setStringGenericArrayElement ($keyGroup, $subGroup, $key, $element, $value, $appendGlue = '') {
2850                 // Debug message
2851                 //* 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);
2852
2853                 // Set it
2854                 $this->genericArray[$keyGroup][$subGroup][$key][$element] = (string) $value;
2855         }
2856
2857         /**
2858          * Initializes given generic array group
2859          *
2860          * @param       $keyGroup       Main group for the key
2861          * @param       $subGroup       Sub group for the key
2862          * @param       $key            Key to use
2863          * @param       $forceInit      Optionally force initialization
2864          * @return      void
2865          */
2866         protected final function initGenericArrayGroup ($keyGroup, $subGroup, $forceInit = FALSE) {
2867                 // Debug message
2868                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',forceInit=' . intval($forceInit));
2869
2870                 // Is it already set?
2871                 if (($forceInit === FALSE) && ($this->isGenericArrayGroupSet($keyGroup, $subGroup))) {
2872                         // Already initialized
2873                         trigger_error(__METHOD__ . ':keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' already initialized.');
2874                         exit;
2875                 } // END - if
2876
2877                 // Initialize it
2878                 $this->genericArray[$keyGroup][$subGroup] = array();
2879         }
2880
2881         /**
2882          * Initializes given generic array key
2883          *
2884          * @param       $keyGroup       Main group for the key
2885          * @param       $subGroup       Sub group for the key
2886          * @param       $key            Key to use
2887          * @param       $forceInit      Optionally force initialization
2888          * @return      void
2889          */
2890         protected final function initGenericArrayKey ($keyGroup, $subGroup, $key, $forceInit = FALSE) {
2891                 // Debug message
2892                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',forceInit=' . intval($forceInit));
2893
2894                 // Is it already set?
2895                 if (($forceInit === FALSE) && ($this->isGenericArrayKeySet($keyGroup, $subGroup, $key))) {
2896                         // Already initialized
2897                         trigger_error(__METHOD__ . ':keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' already initialized.');
2898                         exit;
2899                 } // END - if
2900
2901                 // Initialize it
2902                 $this->genericArray[$keyGroup][$subGroup][$key] = array();
2903         }
2904
2905         /**
2906          * Initializes given generic array element
2907          *
2908          * @param       $keyGroup       Main group for the key
2909          * @param       $subGroup       Sub group for the key
2910          * @param       $key            Key to use
2911          * @param       $element        Element to use
2912          * @param       $forceInit      Optionally force initialization
2913          * @return      void
2914          */
2915         protected final function initGenericArrayElement ($keyGroup, $subGroup, $key, $element, $forceInit = FALSE) {
2916                 // Debug message
2917                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ',forceInit=' . intval($forceInit));
2918
2919                 // Is it already set?
2920                 if (($forceInit === FALSE) && ($this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element))) {
2921                         // Already initialized
2922                         trigger_error(__METHOD__ . ':keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ' already initialized.');
2923                         exit;
2924                 } // END - if
2925
2926                 // Initialize it
2927                 $this->genericArray[$keyGroup][$subGroup][$key][$element] = array();
2928         }
2929
2930         /**
2931          * Pushes an element to a generic key
2932          *
2933          * @param       $keyGroup       Main group for the key
2934          * @param       $subGroup       Sub group for the key
2935          * @param       $key            Key to use
2936          * @param       $value          Value to add/append
2937          * @return      $count          Number of array elements
2938          */
2939         protected final function pushValueToGenericArrayKey ($keyGroup, $subGroup, $key, $value) {
2940                 // Debug message
2941                 //* NOISY-DEBUG: */ if (!is_object($value)) $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',value[' . gettype($value) . ']=' . print_r($value, TRUE));
2942
2943                 // Is it set?
2944                 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
2945                         // Initialize array
2946                         $this->initGenericArrayKey($keyGroup, $subGroup, $key);
2947                 } // END - if
2948
2949                 // Then push it
2950                 $count = array_push($this->genericArray[$keyGroup][$subGroup][$key], $value);
2951
2952                 // Return count
2953                 //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], TRUE));
2954                 //* DEBUG: */ print(__METHOD__ . ': count=' . $count . PHP_EOL);
2955                 return $count;
2956         }
2957
2958         /**
2959          * Pushes an element to a generic array element
2960          *
2961          * @param       $keyGroup       Main group for the key
2962          * @param       $subGroup       Sub group for the key
2963          * @param       $key            Key to use
2964          * @param       $element        Element to check
2965          * @param       $value          Value to add/append
2966          * @return      $count          Number of array elements
2967          */
2968         protected final function pushValueToGenericArrayElement ($keyGroup, $subGroup, $key, $element, $value) {
2969                 // Debug message
2970                 //* 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));
2971
2972                 // Is it set?
2973                 if (!$this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element)) {
2974                         // Initialize array
2975                         $this->initGenericArrayElement($keyGroup, $subGroup, $key, $element);
2976                 } // END - if
2977
2978                 // Then push it
2979                 $count = array_push($this->genericArray[$keyGroup][$subGroup][$key][$element], $value);
2980
2981                 // Return count
2982                 //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], TRUE));
2983                 //* DEBUG: */ print(__METHOD__ . ': count=' . $count . PHP_EOL);
2984                 return $count;
2985         }
2986
2987         /**
2988          * Pops an element from  a generic group
2989          *
2990          * @param       $keyGroup       Main group for the key
2991          * @param       $subGroup       Sub group for the key
2992          * @param       $key            Key to unset
2993          * @return      $value          Last "popped" value
2994          */
2995         protected final function popGenericArrayElement ($keyGroup, $subGroup, $key) {
2996                 // Debug message
2997                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2998
2999                 // Is it set?
3000                 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
3001                         // Not found
3002                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' not found.');
3003                         exit;
3004                 } // END - if
3005
3006                 // Then "pop" it
3007                 $value = array_pop($this->genericArray[$keyGroup][$subGroup][$key]);
3008
3009                 // Return value
3010                 //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], TRUE));
3011                 //* DEBUG: */ print(__METHOD__ . ': value[' . gettype($value) . ']=' . print_r($value, TRUE) . PHP_EOL);
3012                 return $value;
3013         }
3014
3015         /**
3016          * Shifts an element from  a generic group
3017          *
3018          * @param       $keyGroup       Main group for the key
3019          * @param       $subGroup       Sub group for the key
3020          * @param       $key            Key to unset
3021          * @return      $value          Last "popped" value
3022          */
3023         protected final function shiftGenericArrayElement ($keyGroup, $subGroup, $key) {
3024                 // Debug message
3025                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
3026
3027                 // Is it set?
3028                 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
3029                         // Not found
3030                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' not found.');
3031                         exit;
3032                 } // END - if
3033
3034                 // Then "shift" it
3035                 $value = array_shift($this->genericArray[$keyGroup][$subGroup][$key]);
3036
3037                 // Return value
3038                 //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], TRUE));
3039                 //* DEBUG: */ print(__METHOD__ . ': value[' . gettype($value) . ']=' . print_r($value, TRUE) . PHP_EOL);
3040                 return $value;
3041         }
3042
3043         /**
3044          * Count generic array group
3045          *
3046          * @param       $keyGroup       Main group for the key
3047          * @return      $count          Count of given group
3048          */
3049         protected final function countGenericArray ($keyGroup) {
3050                 // Debug message
3051                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup);
3052
3053                 // Is it there?
3054                 if (!isset($this->genericArray[$keyGroup])) {
3055                         // Abort here
3056                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ' not found.');
3057                         exit;
3058                 } // END - if
3059
3060                 // Then count it
3061                 $count = count($this->genericArray[$keyGroup]);
3062
3063                 // Debug message
3064                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',count=' . $count);
3065
3066                 // Return it
3067                 return $count;
3068         }
3069
3070         /**
3071          * Count generic array sub group
3072          *
3073          * @param       $keyGroup       Main group for the key
3074          * @param       $subGroup       Sub group for the key
3075          * @return      $count          Count of given group
3076          */
3077         protected final function countGenericArrayGroup ($keyGroup, $subGroup) {
3078                 // Debug message
3079                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup);
3080
3081                 // Is it there?
3082                 if (!$this->isGenericArrayGroupSet($keyGroup, $subGroup)) {
3083                         // Abort here
3084                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' not found.');
3085                         exit;
3086                 } // END - if
3087
3088                 // Then count it
3089                 $count = count($this->genericArray[$keyGroup][$subGroup]);
3090
3091                 // Debug message
3092                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',count=' . $count);
3093
3094                 // Return it
3095                 return $count;
3096         }
3097
3098         /**
3099          * Count generic array elements
3100          *
3101          * @param       $keyGroup       Main group for the key
3102          * @param       $subGroup       Sub group for the key
3103          * @para        $key            Key to count
3104          * @return      $count          Count of given key
3105          */
3106         protected final function countGenericArrayElements ($keyGroup, $subGroup, $key) {
3107                 // Debug message
3108                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
3109
3110                 // Is it there?
3111                 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
3112                         // Abort here
3113                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' not found.');
3114                         exit;
3115                 } elseif (!$this->isValidGenericArrayGroup($keyGroup, $subGroup)) {
3116                         // Not valid
3117                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' is not an array.');
3118                         exit;
3119                 }
3120
3121                 // Then count it
3122                 $count = count($this->genericArray[$keyGroup][$subGroup][$key]);
3123
3124                 // Debug message
3125                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',count=' . $count);
3126
3127                 // Return it
3128                 return $count;
3129         }
3130
3131         /**
3132          * Getter for whole generic group array
3133          *
3134          * @param       $keyGroup       Key group to get
3135          * @return      $array          Whole generic array group
3136          */
3137         protected final function getGenericArray ($keyGroup) {
3138                 // Debug message
3139                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup);
3140
3141                 // Is it there?
3142                 if (!isset($this->genericArray[$keyGroup])) {
3143                         // Then abort here
3144                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ' does not exist.');
3145                         exit;
3146                 } // END - if
3147
3148                 // Return it
3149                 return $this->genericArray[$keyGroup];
3150         }
3151
3152         /**
3153          * Setter for generic array key
3154          *
3155          * @param       $keyGroup       Key group to get
3156          * @param       $subGroup       Sub group for the key
3157          * @param       $key            Key to unset
3158          * @param       $value          Mixed value from generic array element
3159          * @return      void
3160          */
3161         protected final function setGenericArrayKey ($keyGroup, $subGroup, $key, $value) {
3162                 // Debug message
3163                 //* NOISY-DEBUG: */ if (!is_object($value)) $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',value[' . gettype($value) . ']=' . print_r($value, TRUE));
3164
3165                 // Set value here
3166                 $this->genericArray[$keyGroup][$subGroup][$key] = $value;
3167         }
3168
3169         /**
3170          * Getter for generic array key
3171          *
3172          * @param       $keyGroup       Key group to get
3173          * @param       $subGroup       Sub group for the key
3174          * @param       $key            Key to unset
3175          * @return      $value          Mixed value from generic array element
3176          */
3177         protected final function getGenericArrayKey ($keyGroup, $subGroup, $key) {
3178                 // Debug message
3179                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
3180
3181                 // Is it there?
3182                 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
3183                         // Then abort here
3184                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' does not exist.');
3185                         exit;
3186                 } // END - if
3187
3188                 // Return it
3189                 return $this->genericArray[$keyGroup][$subGroup][$key];
3190         }
3191
3192         /**
3193          * Sets a value in given generic array key/element
3194          *
3195          * @param       $keyGroup       Main group for the key
3196          * @param       $subGroup       Sub group for the key
3197          * @param       $key            Key to set
3198          * @param       $element        Element to set
3199          * @param       $value          Value to set
3200          * @return      void
3201          */
3202         protected final function setGenericArrayElement ($keyGroup, $subGroup, $key, $element, $value) {
3203                 // Debug message
3204                 //* 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));
3205
3206                 // Then set it
3207                 $this->genericArray[$keyGroup][$subGroup][$key][$element] = $value;
3208         }
3209
3210         /**
3211          * Getter for generic array element
3212          *
3213          * @param       $keyGroup       Key group to get
3214          * @param       $subGroup       Sub group for the key
3215          * @param       $key            Key to look for
3216          * @param       $element        Element to look for
3217          * @return      $value          Mixed value from generic array element
3218          */
3219         protected final function getGenericArrayElement ($keyGroup, $subGroup, $key, $element) {
3220                 // Debug message
3221                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element);
3222
3223                 // Is it there?
3224                 if (!$this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element)) {
3225                         // Then abort here
3226                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ' does not exist.');
3227                         exit;
3228                 } // END - if
3229
3230                 // Return it
3231                 return $this->genericArray[$keyGroup][$subGroup][$key][$element];
3232         }
3233
3234         /**
3235          * Checks if a given sub group is valid (array)
3236          *
3237          * @param       $keyGroup       Key group to get
3238          * @param       $subGroup       Sub group for the key
3239          * @return      $isValid        Whether given sub group is valid
3240          */
3241         protected final function isValidGenericArrayGroup ($keyGroup, $subGroup) {
3242                 // Debug message
3243                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup);
3244
3245                 // Determine it
3246                 $isValid = (($this->isGenericArrayGroupSet($keyGroup, $subGroup)) && (is_array($this->getGenericSubArray($keyGroup, $subGroup))));
3247
3248                 // Return it
3249                 return $isValid;
3250         }
3251
3252         /**
3253          * Checks if a given key is valid (array)
3254          *
3255          * @param       $keyGroup       Key group to get
3256          * @param       $subGroup       Sub group for the key
3257          * @param       $key            Key to check
3258          * @return      $isValid        Whether given sub group is valid
3259          */
3260         protected final function isValidGenericArrayKey ($keyGroup, $subGroup, $key) {
3261                 // Debug message
3262                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
3263
3264                 // Determine it
3265                 $isValid = (($this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) && (is_array($this->getGenericArrayKey($keyGroup, $subGroup, $key))));
3266
3267                 // Return it
3268                 return $isValid;
3269         }
3270
3271         /**
3272          * Initializes the web output instance
3273          *
3274          * @return      void
3275          */
3276         protected function initWebOutputInstance () {
3277                 // Get application instance
3278                 $applicationInstance = Registry::getRegistry()->getInstance('app');
3279
3280                 // Is this a response instance?
3281                 if ($this instanceof Responseable) {
3282                         // Then set it in application instance
3283                         $applicationInstance->setResponseInstance($this);
3284                 } // END - if
3285
3286                 // Init web output instance
3287                 $outputInstance = ObjectFactory::createObjectByConfiguredName('output_class', array($applicationInstance));
3288
3289                 // Set it locally
3290                 $this->setWebOutputInstance($outputInstance);
3291         }
3292
3293         /**
3294          * Translates boolean TRUE to 'Y' and FALSE to 'N'
3295          *
3296          * @param       $boolean                Boolean value
3297          * @return      $translated             Translated boolean value
3298          */
3299         public static final function translateBooleanToYesNo ($boolean) {
3300                 // Make sure it is really boolean
3301                 assert(is_bool($boolean));
3302
3303                 // "Translate" it
3304                 $translated = ($boolean === TRUE) ? 'Y' : 'N';
3305
3306                 // ... and return it
3307                 return $translated;
3308         }
3309
3310         /**
3311          * Encodes raw data (almost any type) by "serializing" it and then pack it
3312          * into a "binary format".
3313          *
3314          * @param       $rawData        Raw data (almost any type)
3315          * @return      $encoded        Encoded data
3316          */
3317         protected function encodeData ($rawData) {
3318                 // Make sure no objects or resources pass through
3319                 assert(!is_object($rawData));
3320                 assert(!is_resource($rawData));
3321
3322                 // First "serialize" it (json_encode() is faster than serialize())
3323                 $encoded = $this->packString(json_encode($rawData));
3324
3325                 // And return it
3326                 return $encoded;
3327         }
3328
3329         /**
3330          * Pack a string into a "binary format". Please execuse me that this is
3331          * widely undocumented. :-(
3332          *
3333          * @param       $str            Unpacked string
3334          * @return      $packed         Packed string
3335          * @todo        Improve documentation
3336          */
3337         protected function packString ($str) {
3338                 // Debug message
3339                 //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('str=' . $str . ' - CALLED!');
3340
3341                 // First compress the string (gzcompress is okay)
3342                 $str = gzcompress($str);
3343
3344                 // Init variable
3345                 $packed = '';
3346
3347                 // And start the "encoding" loop
3348                 for ($idx = 0; $idx < strlen($str); $idx += $this->packingData[$this->archArrayElement]['step']) {
3349                         $big = 0;
3350                         for ($i = 0; $i < $this->packingData[$this->archArrayElement]['step']; $i++) {
3351                                 $factor = ($this->packingData[$this->archArrayElement]['step'] - 1 - $i);
3352
3353                                 if (($idx + $i) <= strlen($str)) {
3354                                         $ord = ord(substr($str, ($idx + $i), 1));
3355
3356                                         $add = $ord * pow(256, $factor);
3357
3358                                         $big += $add;
3359
3360                                         //print 'idx=' . $idx . ',i=' . $i . ',ord=' . $ord . ',factor=' . $factor . ',add=' . $add . ',big=' . $big . PHP_EOL;
3361                                 } // END - if
3362                         } // END - for
3363
3364                         $l = ($big & $this->packingData[$this->archArrayElement]['left']) >>$this->packingData[$this->archArrayElement]['factor'];
3365                         $r = $big & $this->packingData[$this->archArrayElement]['right'];
3366
3367                         $chunk = str_pad(pack($this->packingData[$this->archArrayElement]['format'], $l, $r), 8, '0', STR_PAD_LEFT);
3368                         //* NOISY-DEBUG */ print 'big=' . $big . ',chunk('.strlen($chunk) . ')='.md5($chunk).PHP_EOL;
3369
3370                         $packed .= $chunk;
3371                 } // END - for
3372
3373                 // Return it
3374                 //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('packed=' . $packed . ' - EXIT!');
3375                 return $packed;
3376         }
3377
3378         /**
3379          * Checks whether the given file/path is in open_basedir(). This does not
3380          * gurantee that the file is actually readable and/or writeable. If you need
3381          * such gurantee then please use isReadableFile() instead.
3382          *
3383          * @param       $filePathName   Name of the file/path to be checked
3384          * @return      $isReachable    Whether it is within open_basedir()
3385          */
3386         protected static function isReachableFilePath ($filePathName) {
3387                 // Is not reachable by default
3388                 $isReachable = FALSE;
3389
3390                 // Get open_basedir parameter
3391                 $openBaseDir = ini_get('open_basedir');
3392
3393                 // Is it set?
3394                 if (!empty($openBaseDir)) {
3395                         // Check all entries
3396                         foreach (explode(PATH_SEPARATOR, $openBaseDir) as $dir) {
3397                                 // Check on existence
3398                                 if (substr($filePathName, 0, strlen($dir)) == $dir) {
3399                                         // Is reachable
3400                                         $isReachable = TRUE;
3401                                 } // END - if
3402                         } // END - foreach
3403                 } else {
3404                         // If open_basedir is not set, all is allowed
3405                         $isReachable = TRUE;
3406                 }
3407
3408                 // Return status
3409                 return $isReachable;
3410         }
3411
3412         /**
3413          * Checks whether the give file is within open_basedir() (done by
3414          * isReachableFilePath()), is actually a file and is readable.
3415          *
3416          * @param       $fileName               Name of the file to be checked
3417          * @return      $isReadable             Whether the file is readable (and therefor exists)
3418          */
3419         public static function isReadableFile ($fileName) {
3420                 // Default is not readable
3421                 $isReadable = FALSE;
3422
3423                 // Is within parameters, so check if it is a file and readable
3424                 $isReadable = ((self::isReachableFilePath($fileName)) && (file_exists($fileName)) && (is_file($fileName)) && (is_readable($fileName)));
3425
3426                 // Return status
3427                 return $isReadable;
3428         }
3429
3430         /**
3431          * Creates a full-qualified file name (FQFN) for given file name by adding
3432          * a configured temporary file path to it.
3433          *
3434          * @param       $fileName       Name for temporary file
3435          * @return      $fqfn   Full-qualified file name
3436          * @throw       PathWriteProtectedException If the path in 'temp_file_path' is write-protected
3437          * @throws      FileIoException If the file cannot be written
3438          */
3439          protected static function createTempPathForFile ($fileName) {
3440                 // Get config entry
3441                 $basePath = FrameworkConfiguration::getSelfInstance()->getConfigEntry('temp_file_path');
3442
3443                 // Is the path writeable?
3444                 if (!is_writable($basePath)) {
3445                         // Path is write-protected
3446                         throw new PathWriteProtectedException($fileName, self::EXCEPTION_PATH_CANNOT_BE_WRITTEN);
3447                 } // END - if
3448
3449                 // Add it
3450                 $fqfn = $basePath . '/' . $fileName;
3451
3452                 // Is it reachable?
3453                 if (!self::isReachableFilePath($fqfn)) {
3454                         // Not reachable
3455                         throw new FileIoException($fqfn, self::EXCEPTION_FILE_NOT_REACHABLE);
3456                 } // END - if
3457
3458                 // Return it
3459                 return $fqfn;
3460          }
3461
3462         /**
3463          * "Getter" for a printable state name
3464          *
3465          * @return      $stateName      Name of the node's state in a printable format
3466          */
3467         public final function getPrintableState () {
3468                 // Default is 'null'
3469                 $stateName = 'null';
3470
3471                 // Get the state instance
3472                 $stateInstance = $this->getStateInstance();
3473
3474                 // Is it an instance of Stateable?
3475                 if ($stateInstance instanceof Stateable) {
3476                         // Then use that state name
3477                         $stateName = $stateInstance->getStateName();
3478                 } // END - if
3479
3480                 // Return result
3481                 return $stateName;
3482         }
3483
3484         /**
3485          * Handles socket error for given socket resource and peer data. This method
3486          * validates $socketResource if it is a valid resource (see is_resource())
3487          * but assumes valid data in array $recipientData, except that
3488          * count($recipientData) is always 2.
3489          *
3490          * @param       $method                         Value of __METHOD__ from calling method
3491          * @param       $line                           Value of __LINE__ from calling method
3492          * @param       $socketResource         A valid socket resource
3493          * @param       $socketData                     A valid socket data array (0 = IP/file name, 1 = port)
3494          * @return      void
3495          * @throws      InvalidSocketException  If $socketResource is no socket resource
3496          * @throws      NoSocketErrorDetectedException  If socket_last_error() gives zero back
3497          * @todo        Move all this socket-related stuff into own class, most of it resides in BaseListener
3498          */
3499         protected final function handleSocketError ($method, $line, $socketResource, array $socketData) {
3500                 // This method handles only socket resources
3501                 if (!is_resource($socketResource)) {
3502                         // No resource, abort here
3503                         throw new InvalidSocketException(array($this, $socketResource), BaseListener::EXCEPTION_INVALID_SOCKET);
3504                 } // END - if
3505
3506                 // Check socket array, 1st element is mostly IP address (or file name), 2nd is port number
3507                 //* DEBUG-DIE: */ die(__METHOD__ . ':socketData=' . print_r($socketData, TRUE));
3508                 assert(isset($socketData[0]));
3509                 assert(isset($socketData[1]));
3510
3511                 // Get error code for first validation (0 is not an error)
3512                 $errorCode = socket_last_error($socketResource);
3513
3514                 // If the error code is zero, someone called this method without an error
3515                 if ($errorCode == 0) {
3516                         // No error detected (or previously cleared outside this method)
3517                         throw new NoSocketErrorDetectedException(array($this, $socketResource), BaseListener::EXCEPTION_NO_SOCKET_ERROR);
3518                 } // END - if
3519
3520                 // Get handler (method) name
3521                 $handlerName = $this->getSocketErrorHandlerFromCode($errorCode);
3522
3523                 // Call-back the error handler method
3524                 call_user_func_array(array($this, $handlerName), array($socketResource, $socketData));
3525
3526                 // Finally clear the error because it has been handled
3527                 socket_clear_error($socketResource);
3528         }
3529
3530 }