3 namespace Org\Mxchange\CoreFramework\Object;
5 // Import framework stuff
6 use Org\Mxchange\CoreFramework\Bootstrap\FrameworkBootstrap;
7 use Org\Mxchange\CoreFramework\Criteria\Criteria;
8 use Org\Mxchange\CoreFramework\Criteria\Local\LocalSearchCriteria;
9 use Org\Mxchange\CoreFramework\Criteria\Local\LocalUpdateCriteria;
10 use Org\Mxchange\CoreFramework\Crypto\Cryptable;
11 use Org\Mxchange\CoreFramework\Crypto\RandomNumber\RandomNumberGenerator;
12 use Org\Mxchange\CoreFramework\Database\Frontend\DatabaseWrapper;
13 use Org\Mxchange\CoreFramework\EntryPoint\ApplicationEntryPoint;
14 use Org\Mxchange\CoreFramework\Factory\Database\Wrapper\DatabaseWrapperFactory;
15 use Org\Mxchange\CoreFramework\Factory\ObjectFactory;
16 use Org\Mxchange\CoreFramework\Filesystem\FilePointer;
17 use Org\Mxchange\CoreFramework\Filesystem\PathWriteProtectedException;
18 use Org\Mxchange\CoreFramework\Generic\FrameworkInterface;
19 use Org\Mxchange\CoreFramework\Generic\NullPointerException;
20 use Org\Mxchange\CoreFramework\Generic\UnsupportedOperationException;
21 use Org\Mxchange\CoreFramework\Handler\Handleable;
22 use Org\Mxchange\CoreFramework\Helper\Helper;
23 use Org\Mxchange\CoreFramework\Lists\Listable;
24 use Org\Mxchange\CoreFramework\Loader\ClassLoader;
25 use Org\Mxchange\CoreFramework\Localization\ManageableLanguage;
26 use Org\Mxchange\CoreFramework\Manager\ManageableApplication;
27 use Org\Mxchange\CoreFramework\Menu\RenderableMenu;
28 use Org\Mxchange\CoreFramework\Middleware\Debug\DebugMiddleware;
29 use Org\Mxchange\CoreFramework\Parser\Parseable;
30 use Org\Mxchange\CoreFramework\Registry\GenericRegistry;
31 use Org\Mxchange\CoreFramework\Result\Database\CachedDatabaseResult;
32 use Org\Mxchange\CoreFramework\Result\Search\SearchableResult;
33 use Org\Mxchange\CoreFramework\Stacker\Stackable;
34 use Org\Mxchange\CoreFramework\State\Stateable;
35 use Org\Mxchange\CoreFramework\Stream\Input\InputStream;
36 use Org\Mxchange\CoreFramework\Stream\Output\OutputStreamer;
37 use Org\Mxchange\CoreFramework\Stream\Output\OutputStream;
38 use Org\Mxchange\CoreFramework\Template\CompileableTemplate;
39 use Org\Mxchange\CoreFramework\User\ManageableAccount;
40 use Org\Mxchange\CoreFramework\Utils\String\StringUtils;
41 use Org\Mxchange\CoreFramework\Visitor\Visitor;
45 use \InvalidArgumentException;
51 * The simulator system class is the super class of all other classes. This
52 * class handles saving of games etc.
54 * @author Roland Haeder <webmaster@shipsimu.org>
56 * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2020 Core Developer Team
57 * @license GNU GPL 3.0 or any newer version
58 * @link http://www.shipsimu.org
60 * This program is free software: you can redistribute it and/or modify
61 * it under the terms of the GNU General Public License as published by
62 * the Free Software Foundation, either version 3 of the License, or
63 * (at your option) any later version.
65 * This program is distributed in the hope that it will be useful,
66 * but WITHOUT ANY WARRANTY; without even the implied warranty of
67 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
68 * GNU General Public License for more details.
70 * You should have received a copy of the GNU General Public License
71 * along with this program. If not, see <http://www.gnu.org/licenses/>.
73 abstract class BaseFrameworkSystem extends stdClass implements FrameworkInterface {
75 * Length of output from hash()
77 private static $hashLength = NULL;
80 * Self-referencing instance
82 private static $instance = NULL;
87 private $realClass = __CLASS__;
90 * Search criteria instance
92 private $searchInstance = NULL;
95 * Update criteria instance
97 private $updateInstance = NULL;
100 * Template engine instance
102 private $templateInstance = NULL;
105 * Database result instance
107 private $resultInstance = NULL;
110 * Instance for user class
112 private $userInstance = NULL;
117 private $rngInstance = NULL;
120 * Instance of a crypto helper
122 private $cryptoInstance = NULL;
125 * Instance of an Iterator class
127 private $iteratorInstance = NULL;
130 * Instance of the list
132 private $listInstance = NULL;
137 private $menuInstance = NULL;
140 * Instance of the image
142 private $imageInstance = NULL;
145 * Instance of the stacker
147 private $stackInstance = NULL;
150 * A Parseable instance
152 private $parserInstance = NULL;
155 * A helper instance for the form
157 private $helperInstance = NULL;
160 * An instance of a InputStream class
162 private $inputStreamInstance = NULL;
165 * An instance of a OutputStream class
167 private $outputStreamInstance = NULL;
172 private $handlerInstance = NULL;
175 * Visitor handler instance
177 private $visitorInstance = NULL;
180 * An instance of a database wrapper class
182 private $wrapperInstance = NULL;
185 * An instance of a file I/O pointer class (not handler)
187 private $pointerInstance = NULL;
192 private $stateInstance = NULL;
197 private $callbackInstance = NULL;
202 private $genericArray = array();
204 /***********************
205 * Exception codes.... *
206 ***********************/
208 // @todo Try to clean these constants up
209 const EXCEPTION_IS_NULL_POINTER = 0x001;
210 const EXCEPTION_IS_NO_OBJECT = 0x002;
211 const EXCEPTION_IS_NO_ARRAY = 0x003;
212 const EXCEPTION_MISSING_METHOD = 0x004;
213 const EXCEPTION_CLASSES_NOT_MATCHING = 0x005;
214 const EXCEPTION_INDEX_OUT_OF_BOUNDS = 0x006;
215 const EXCEPTION_DIMENSION_ARRAY_INVALID = 0x007;
216 const EXCEPTION_ITEM_NOT_TRADEABLE = 0x008;
217 const EXCEPTION_ITEM_NOT_IN_PRICE_LIST = 0x009;
218 const EXCEPTION_GENDER_IS_WRONG = 0x00a;
219 const EXCEPTION_BIRTH_DATE_IS_INVALID = 0x00b;
220 const EXCEPTION_EMPTY_STRUCTURES_ARRAY = 0x00c;
221 const EXCEPTION_HAS_ALREADY_PERSONELL_LIST = 0x00d;
222 const EXCEPTION_NOT_ENOUGTH_UNEMPLOYEES = 0x00e;
223 const EXCEPTION_TOTAL_PRICE_NOT_CALCULATED = 0x00f;
224 const EXCEPTION_HARBOR_HAS_NO_SHIPYARDS = 0x010;
225 const EXCEPTION_CONTRACT_PARTNER_INVALID = 0x011;
226 const EXCEPTION_CONTRACT_PARTNER_MISMATCH = 0x012;
227 const EXCEPTION_CONTRACT_ALREADY_SIGNED = 0x013;
228 const EXCEPTION_UNEXPECTED_EMPTY_STRING = 0x014;
229 const EXCEPTION_PATH_NOT_FOUND = 0x015;
230 const EXCEPTION_INVALID_PATH_NAME = 0x016;
231 const EXCEPTION_READ_PROTECED_PATH = 0x017;
232 const EXCEPTION_WRITE_PROTECED_PATH = 0x018;
233 const EXCEPTION_DIR_POINTER_INVALID = 0x019;
234 const EXCEPTION_FILE_POINTER_INVALID = 0x01a;
235 const EXCEPTION_INVALID_RESOURCE = 0x01b;
236 const EXCEPTION_UNEXPECTED_OBJECT = 0x01c;
237 const EXCEPTION_LIMIT_ELEMENT_IS_UNSUPPORTED = 0x01d;
238 const EXCEPTION_GETTER_IS_MISSING = 0x01e;
239 const EXCEPTION_ARRAY_EXPECTED = 0x01f;
240 const EXCEPTION_ARRAY_HAS_INVALID_COUNT = 0x020;
241 const EXCEPTION_ID_IS_INVALID_FORMAT = 0x021;
242 const EXCEPTION_MD5_CHECKSUMS_MISMATCH = 0x022;
243 const EXCEPTION_UNEXPECTED_STRING_SIZE = 0x023;
244 const EXCEPTION_SIMULATOR_ID_INVALID = 0x024;
245 const EXCEPTION_MISMATCHING_COMPRESSORS = 0x025;
246 const EXCEPTION_CONTAINER_ITEM_IS_NULL = 0x026;
247 const EXCEPTION_ITEM_IS_NO_ARRAY = 0x027;
248 const EXCEPTION_CONTAINER_MAYBE_DAMAGED = 0x028;
249 const EXCEPTION_INVALID_STRING = 0x029;
250 const EXCEPTION_VARIABLE_NOT_SET = 0x02a;
251 const EXCEPTION_ATTRIBUTES_ARE_MISSING = 0x02b;
252 const EXCEPTION_ARRAY_ELEMENTS_MISSING = 0x02c;
253 const EXCEPTION_TEMPLATE_ENGINE_UNSUPPORTED = 0x02d;
254 const EXCEPTION_UNSPPORTED_OPERATION = 0x02e;
255 const EXCEPTION_FACTORY_REQUIRE_PARAMETER = 0x02f;
256 const EXCEPTION_MISSING_ELEMENT = 0x030;
257 const EXCEPTION_HEADERS_ALREADY_SENT = 0x031;
258 const EXCEPTION_DEFAULT_CONTROLLER_GONE = 0x032;
259 const EXCEPTION_CLASS_NOT_FOUND = 0x033;
260 const EXCEPTION_REQUIRED_INTERFACE_MISSING = 0x034;
261 const EXCEPTION_FATAL_ERROR = 0x035;
262 const EXCEPTION_FILE_NOT_FOUND = 0x036;
263 const EXCEPTION_ASSERTION_FAILED = 0x037;
264 const EXCEPTION_FILE_NOT_REACHABLE = 0x038;
265 const EXCEPTION_FILE_CANNOT_BE_READ = 0x039;
266 const EXCEPTION_FILE_CANNOT_BE_WRITTEN = 0x03a;
267 const EXCEPTION_PATH_CANNOT_BE_WRITTEN = 0x03b;
268 const EXCEPTION_DATABASE_UPDATED_NOT_ALLOWED = 0x03c;
269 const EXCEPTION_FILTER_CHAIN_INTERCEPTED = 0x03d;
270 const EXCEPTION_INVALID_SOCKET = 0x03e;
271 const EXCEPTION_SELF_INSTANCE = 0x03f;
274 * Startup time in miliseconds
276 private static $startupTime = 0;
279 * Protected super constructor
281 * @param $className Name of the class
284 protected function __construct (string $className) {
286 $this->setRealClass($className);
288 // Is the startup time set? (0 cannot be true anymore)
289 if (self::$startupTime == 0) {
291 self::$startupTime = microtime(true);
296 * Destructor for all classes. You should not call this method on your own.
300 public function __destruct () {
301 // Flush any updated entries to the database
302 $this->flushPendingUpdates();
304 // Is this object already destroyed?
305 if ($this->__toString() != 'DestructedObject') {
306 // Destroy all informations about this class but keep some text about it alive
307 $this->setRealClass('DestructedObject');
308 } elseif ((defined('DEBUG_DESTRUCTOR')) && (is_object($this->getDebugInstance()))) {
309 // Already destructed object
310 self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('The object <span class="object_name">%s</span> is already destroyed.',
314 // Do not call this twice
315 trigger_error(__METHOD__ . ': Called twice.');
321 * The __call() method where all non-implemented methods end up
323 * @param $methodName Name of the missing method
324 * @args $args Arguments passed to the method
327 public final function __call ($methodName, $args) {
329 self::$instance = $this;
331 // Call static method
332 self::__callStatic($methodName, $args);
334 // Clear self-instance
335 self::$instance = NULL;
339 * The __callStatic() method where all non-implemented static methods end up
341 * @param $methodName Name of the missing method
342 * @param $args Arguments passed to the method
344 * @throws InvalidArgumentException If self::$instance is not a framework's own object
346 public static final function __callStatic ($methodName, $args) {
348 //* PRINT-DEBUG: */ printf('[%s:%d]: methodName=%s,args[]=%s - CALLED!' . PHP_EOL, __METHOD__, __LINE__, $methodName, gettype($args));
350 // Init argument string and class name
352 $className = 'unknown';
354 // Is self-instance set?
355 if (self::$instance instanceof FrameworkInterface) {
356 // Framework's own instance
357 $className = self::$instance->__toString();
358 } elseif (!is_null(self::$instance)) {
360 throw new InvalidArgumentException(sprintf('self::instance[%s] is not expected.', gettype(self::$instance)), self::EXCEPTION_SELF_INSTANCE);
363 // Is it NULL, empty or an array?
364 if (is_null($args)) {
366 $argsString = 'NULL';
367 } elseif (is_array($args)) {
371 // Some arguments are there
372 foreach ($args as $arg) {
373 // Add data about the argument
374 $argsString .= gettype($arg) . ':';
377 // Found a NULL argument
378 $argsString .= 'NULL';
379 } elseif (is_string($arg)) {
380 // Add length for strings
381 $argsString .= strlen($arg);
382 } elseif ((is_int($arg)) || (is_float($arg))) {
385 } elseif (is_array($arg)) {
386 // .. or size if array
387 $argsString .= count($arg);
388 } elseif (is_object($arg)) {
390 $reflection = new ReflectionClass($arg);
392 // Is an other object, maybe no __toString() available
393 $argsString .= $reflection->getName();
394 } elseif ($arg === true) {
395 // ... is boolean 'true'
396 $argsString .= 'true';
397 } elseif ($arg === false) {
398 // ... is boolean 'false'
399 $argsString .= 'false';
402 // Comma for next one
407 if (substr($argsString, -2, 1) == ',') {
409 $argsString = substr($argsString, 0, -2);
415 // Invalid arguments!
416 $argsString = sprintf('!INVALID:%s!', gettype($args));
419 // Output stub message
420 // @TODO __CLASS__ does always return BaseFrameworkSystem but not the extending (=child) class
421 self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s::%s]: Stub! Args: %s',
432 * Getter for $realClass
434 * @return $realClass The name of the real class (not BaseFrameworkSystem)
436 public function __toString () {
437 return $this->realClass;
441 * Magic method to catch setting of missing but set class fields/attributes
443 * @param $name Name of the field/attribute
444 * @param $value Value to store
447 public final function __set ($name, $value) {
448 $this->debugBackTrace(sprintf('Tried to set a missing field. name=%s, value[%s]=%s',
451 print_r($value, true)
456 * Magic method to catch getting of missing fields/attributes
458 * @param $name Name of the field/attribute
461 public final function __get ($name) {
462 $this->debugBackTrace(sprintf('Tried to get a missing field. name=%s',
468 * Magic method to catch unsetting of missing fields/attributes
470 * @param $name Name of the field/attribute
473 public final function __unset ($name) {
474 $this->debugBackTrace(sprintf('Tried to unset a missing field. name=%s',
480 * Magic method to catch object serialization
482 * @return $unsupported Unsupported method
483 * @throws UnsupportedOperationException Objects of this framework cannot be serialized
485 public final function __sleep () {
486 throw new UnsupportedOperationException(array($this, __FUNCTION__), self::EXCEPTION_UNSPPORTED_OPERATION);
490 * Magic method to catch object deserialization
492 * @return $unsupported Unsupported method
493 * @throws UnsupportedOperationException Objects of this framework cannot be serialized
495 public final function __wakeup () {
496 throw new UnsupportedOperationException(array($this, __FUNCTION__), self::EXCEPTION_UNSPPORTED_OPERATION);
500 * Magic method to catch calls when an object instance is called
502 * @return $unsupported Unsupported method
503 * @throws UnsupportedOperationException Objects of this framework cannot be serialized
505 public final function __invoke () {
506 throw new UnsupportedOperationException(array($this, __FUNCTION__), self::EXCEPTION_UNSPPORTED_OPERATION);
510 * Setter for the real class name
512 * @param $realClass Class name (string)
515 public final function setRealClass ($realClass) {
517 $this->realClass = (string) $realClass;
521 * Setter for database result instance
523 * @param $resultInstance An instance of a database result class
525 * @todo SearchableResult and UpdateableResult shall have a super interface to use here
527 protected final function setResultInstance (SearchableResult $resultInstance) {
528 $this->resultInstance = $resultInstance;
532 * Getter for database result instance
534 * @return $resultInstance An instance of a database result class
536 public final function getResultInstance () {
537 return $this->resultInstance;
541 * Setter for template engine instances
543 * @param $templateInstance An instance of a template engine class
546 protected final function setTemplateInstance (CompileableTemplate $templateInstance) {
547 $this->templateInstance = $templateInstance;
551 * Getter for template engine instances
553 * @return $templateInstance An instance of a template engine class
555 protected final function getTemplateInstance () {
556 return $this->templateInstance;
560 * Setter for search instance
562 * @param $searchInstance Searchable criteria instance
565 public final function setSearchInstance (LocalSearchCriteria $searchInstance) {
566 $this->searchInstance = $searchInstance;
570 * Getter for search instance
572 * @return $searchInstance Searchable criteria instance
574 public final function getSearchInstance () {
575 return $this->searchInstance;
579 * Setter for update instance
581 * @param $updateInstance An instance of a LocalUpdateCriteria clase
584 public final function setUpdateInstance (LocalUpdateCriteria $updateInstance) {
585 $this->updateInstance = $updateInstance;
589 * Getter for update instance
591 * @return $updateInstance Updateable criteria instance
593 public final function getUpdateInstance () {
594 return $this->updateInstance;
598 * Setter for debug instance
600 * @param $debugInstance The instance for debug output class
603 public final function setDebugInstance (DebugMiddleware $debugInstance) {
604 GenericRegistry::getRegistry()->addInstance('debug', $debugInstance);
608 * Getter for debug instance
610 * @return $debugInstance Instance to class DebugConsoleOutput or DebugWebOutput
612 public final function getDebugInstance () {
613 // Get debug instance
614 $debugInstance = GenericRegistry::getRegistry()->getInstance('debug');
617 return $debugInstance;
621 * Setter for web output instance
623 * @param $webInstance The instance for web output class
626 public final function setWebOutputInstance (OutputStreamer $webInstance) {
627 GenericRegistry::getRegistry()->addInstance('web_output', $webInstance);
631 * Getter for web output instance
633 * @return $webOutputInstance - Instance to class WebOutput
635 public final function getWebOutputInstance () {
636 $webOutputInstance = GenericRegistry::getRegistry()->getInstance('web_output');
637 return $webOutputInstance;
641 * Private getter for language instance
643 * @return $langInstance An instance to the language sub-system
645 protected final function getLanguageInstance () {
646 $langInstance = GenericRegistry::getRegistry()->getInstance('language');
647 return $langInstance;
651 * Setter for language instance
653 * @param $langInstance An instance to the language sub-system
655 * @see LanguageSystem
657 public final function setLanguageInstance (ManageableLanguage $langInstance) {
658 GenericRegistry::getRegistry()->addInstance('language', $langInstance);
662 * Protected setter for user instance
664 * @param $userInstance An instance of a user class
667 protected final function setUserInstance (ManageableAccount $userInstance) {
668 $this->userInstance = $userInstance;
672 * Getter for user instance
674 * @return $userInstance An instance of a user class
676 public final function getUserInstance () {
677 return $this->userInstance;
681 * Setter for RNG instance
683 * @param $rngInstance An instance of a random number generator (RNG)
686 protected final function setRngInstance (RandomNumberGenerator $rngInstance) {
687 $this->rngInstance = $rngInstance;
691 * Getter for RNG instance
693 * @return $rngInstance An instance of a random number generator (RNG)
695 public final function getRngInstance () {
696 return $this->rngInstance;
700 * Setter for Cryptable instance
702 * @param $cryptoInstance An instance of a Cryptable class
705 protected final function setCryptoInstance (Cryptable $cryptoInstance) {
706 $this->cryptoInstance = $cryptoInstance;
710 * Getter for Cryptable instance
712 * @return $cryptoInstance An instance of a Cryptable class
714 public final function getCryptoInstance () {
715 return $this->cryptoInstance;
719 * Setter for the list instance
721 * @param $listInstance A list of Listable
724 protected final function setListInstance (Listable $listInstance) {
725 $this->listInstance = $listInstance;
729 * Getter for the list instance
731 * @return $listInstance A list of Listable
733 protected final function getListInstance () {
734 return $this->listInstance;
738 * Setter for the menu instance
740 * @param $menuInstance A RenderableMenu instance
743 protected final function setMenuInstance (RenderableMenu $menuInstance) {
744 $this->menuInstance = $menuInstance;
748 * Getter for the menu instance
750 * @return $menuInstance A RenderableMenu instance
752 protected final function getMenuInstance () {
753 return $this->menuInstance;
757 * Setter for image instance
759 * @param $imageInstance An instance of an image
762 public final function setImageInstance (BaseImage $imageInstance) {
763 $this->imageInstance = $imageInstance;
767 * Getter for image instance
769 * @return $imageInstance An instance of an image
771 public final function getImageInstance () {
772 return $this->imageInstance;
776 * Setter for stacker instance
778 * @param $stackInstance An instance of an stacker
781 public final function setStackInstance (Stackable $stackInstance) {
782 $this->stackInstance = $stackInstance;
786 * Getter for stacker instance
788 * @return $stackInstance An instance of an stacker
790 public final function getStackInstance () {
791 return $this->stackInstance;
795 * Setter for Parseable instance
797 * @param $parserInstance An instance of an Parseable
800 public final function setParserInstance (Parseable $parserInstance) {
801 $this->parserInstance = $parserInstance;
805 * Getter for Parseable instance
807 * @return $parserInstance An instance of an Parseable
809 public final function getParserInstance () {
810 return $this->parserInstance;
814 * Setter for DatabaseWrapper instance
816 * @param $wrapperInstance An instance of an DatabaseWrapper
819 public final function setWrapperInstance (DatabaseWrapper $wrapperInstance) {
820 $this->wrapperInstance = $wrapperInstance;
824 * Getter for DatabaseWrapper instance
826 * @return $wrapperInstance An instance of an DatabaseWrapper
828 public final function getWrapperInstance () {
829 return $this->wrapperInstance;
833 * Setter for helper instance
835 * @param $helperInstance An instance of a helper class
838 protected final function setHelperInstance (Helper $helperInstance) {
839 $this->helperInstance = $helperInstance;
843 * Getter for helper instance
845 * @return $helperInstance An instance of a helper class
847 public final function getHelperInstance () {
848 return $this->helperInstance;
852 * Getter for a InputStream instance
854 * @param $inputStreamInstance The InputStream instance
856 protected final function getInputStreamInstance () {
857 return $this->inputStreamInstance;
861 * Setter for a InputStream instance
863 * @param $inputStreamInstance The InputStream instance
866 protected final function setInputStreamInstance (InputStream $inputStreamInstance) {
867 $this->inputStreamInstance = $inputStreamInstance;
871 * Getter for a OutputStream instance
873 * @param $outputStreamInstance The OutputStream instance
875 protected final function getOutputStreamInstance () {
876 return $this->outputStreamInstance;
880 * Setter for a OutputStream instance
882 * @param $outputStreamInstance The OutputStream instance
885 protected final function setOutputStreamInstance (OutputStream $outputStreamInstance) {
886 $this->outputStreamInstance = $outputStreamInstance;
890 * Setter for handler instance
892 * @param $handlerInstance An instance of a Handleable class
895 protected final function setHandlerInstance (Handleable $handlerInstance) {
896 $this->handlerInstance = $handlerInstance;
900 * Getter for handler instance
902 * @return $handlerInstance A Handleable instance
904 protected final function getHandlerInstance () {
905 return $this->handlerInstance;
909 * Setter for visitor instance
911 * @param $visitorInstance A Visitor instance
914 protected final function setVisitorInstance (Visitor $visitorInstance) {
915 $this->visitorInstance = $visitorInstance;
919 * Getter for visitor instance
921 * @return $visitorInstance A Visitor instance
923 protected final function getVisitorInstance () {
924 return $this->visitorInstance;
928 * Setter for Iterator instance
930 * @param $iteratorInstance An instance of an Iterator
933 protected final function setIteratorInstance (Iterator $iteratorInstance) {
934 $this->iteratorInstance = $iteratorInstance;
938 * Getter for Iterator instance
940 * @return $iteratorInstance An instance of an Iterator
942 public final function getIteratorInstance () {
943 return $this->iteratorInstance;
947 * Setter for FilePointer instance
949 * @param $pointerInstance An instance of an FilePointer class
952 protected final function setPointerInstance (FilePointer $pointerInstance) {
953 $this->pointerInstance = $pointerInstance;
957 * Getter for FilePointer instance
959 * @return $pointerInstance An instance of an FilePointer class
961 public final function getPointerInstance () {
962 return $this->pointerInstance;
966 * Unsets pointer instance which triggers a call of __destruct() if the
967 * instance is still there. This is surely not fatal on already "closed"
968 * file pointer instances.
970 * I don't want to mess around with above setter by giving it a default
971 * value NULL as setter should always explicitly only set (existing) object
972 * instances and NULL is NULL.
976 protected final function unsetPointerInstance () {
978 $this->pointerInstance = NULL;
982 * Setter for state instance
984 * @param $stateInstance A Stateable instance
987 public final function setStateInstance (Stateable $stateInstance) {
988 $this->stateInstance = $stateInstance;
992 * Getter for state instance
994 * @return $stateInstance A Stateable instance
996 public final function getStateInstance () {
997 return $this->stateInstance;
1001 * Setter for call-back instance
1003 * @param $callbackInstance An instance of a FrameworkInterface class
1006 public final function setCallbackInstance (FrameworkInterface $callbackInstance) {
1007 $this->callbackInstance = $callbackInstance;
1011 * Getter for call-back instance
1013 * @return $callbackInstance An instance of a FrameworkInterface class
1015 protected final function getCallbackInstance () {
1016 return $this->callbackInstance;
1020 * Checks whether an object equals this object. You should overwrite this
1021 * method to implement own equality checks
1023 * @param $objectInstance An instance of a FrameworkInterface object
1024 * @return $equals Whether both objects equals
1026 public function equals (FrameworkInterface $objectInstance) {
1029 $this->__toString() == $objectInstance->__toString()
1031 $this->hashCode() == $objectInstance->hashCode()
1034 // Return the result
1039 * Generates a generic hash code of this class. You should really overwrite
1040 * this method with your own hash code generator code. But keep KISS in mind.
1042 * @return $hashCode A generic hash code respresenting this whole class
1044 public function hashCode () {
1046 return crc32($this->__toString());
1050 * Appends a trailing slash to a string
1052 * @param $str A string (maybe) without trailing slash
1053 * @return $str A string with an auto-appended trailing slash
1055 public final function addMissingTrailingSlash ($str) {
1056 // Is there a trailing slash?
1057 if (substr($str, -1, 1) != '/') {
1061 // Return string with trailing slash
1066 * Prepare the template engine (HtmlTemplateEngine by default) for a given
1067 * application helper instance (ApplicationHelper by default).
1069 * @param $applicationInstance An application helper instance or
1070 * null if we shall use the default
1071 * @return $templateInstance The template engine instance
1072 * @throws NullPointerException If the discovered application
1073 * instance is still null
1075 protected function prepareTemplateInstance (ManageableApplication $applicationInstance = NULL) {
1076 // Is the application instance set?
1077 if (is_null($applicationInstance)) {
1078 // Get the current instance
1079 $applicationInstance = GenericRegistry::getRegistry()->getInstance('application');
1082 if (is_null($applicationInstance)) {
1083 // Thrown an exception
1084 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
1088 // Initialize the template engine
1089 $templateInstance = ObjectFactory::createObjectByConfiguredName('html_template_class');
1091 // Return the prepared instance
1092 return $templateInstance;
1096 * Debugs this instance by putting out it's full content
1098 * @param $message Optional message to show in debug output
1101 public final function debugInstance ($message = '') {
1102 // Restore the error handler to avoid trouble with missing array elements or undeclared variables
1103 restore_error_handler();
1108 // Is a message set?
1109 if (!empty($message)) {
1110 // Construct message
1111 $content = sprintf('<div class="debug_message">
1113 </div>' . PHP_EOL, $message);
1116 // Generate the output
1117 $content .= sprintf('<pre>%s</pre>',
1120 print_r($this, true)
1126 ApplicationEntryPoint::exitApplication(sprintf('<div class="debug_header">
1129 <div class="debug_content">
1133 <div class="debug_include_list">
1136 $this->__toString(),
1138 ClassLoader::getSelfInstance()->getPrintableIncludeList()
1143 * Replaces control characters with printable output
1145 * @param $str String with control characters
1146 * @return $str Replaced string
1148 protected function replaceControlCharacters ($str) {
1151 chr(13), '[r]', str_replace(
1152 chr(10), '[n]', str_replace(
1162 * Output a partial stub message for the caller method
1164 * @param $message An optional message to display
1167 protected function partialStub ($message = '') {
1169 $stubMessage = 'Partial stub!';
1171 // Is an extra message given?
1172 if (!empty($message)) {
1173 // Then add it as well
1174 $stubMessage .= ' Message: ' . $message;
1177 // Debug instance is there?
1178 if (!is_null($this->getDebugInstance())) {
1179 // Output stub message
1180 self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($stubMessage);
1183 trigger_error($stubMessage);
1189 * Outputs a debug backtrace and stops further script execution
1191 * @param $message An optional message to output
1192 * @param $doExit Whether exit the program (true is default)
1195 public function debugBackTrace ($message = '', $doExit = true) {
1196 // Sorry, there is no other way getting this nice backtrace
1197 if (!empty($message)) {
1199 printf('Message: %s<br />' . PHP_EOL, $message);
1203 debug_print_backtrace();
1207 if ($doExit === true) {
1213 * Creates an instance of a debugger instance
1215 * @param $className Name of the class (currently unsupported)
1216 * @param $lineNumber Line number where the call was made
1217 * @return $debugInstance An instance of a debugger class
1218 * @deprecated Not fully, as the new Logger facilities are not finished yet.
1220 public final static function createDebugInstance ($className, $lineNumber = NULL) {
1221 // Is the instance set?
1222 if (!GenericRegistry::getRegistry()->instanceExists('debug')) {
1223 // Init debug instance
1224 $debugInstance = NULL;
1228 // Get a debugger instance
1229 $debugInstance = DebugMiddleware::createDebugMiddleware(FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('debug_' . FrameworkBootstrap::getRequestTypeFromSystem() . '_class'), $className);
1230 } catch (NullPointerException $e) {
1231 // Didn't work, no instance there
1232 exit(sprintf('Cannot create debugInstance! Exception=%s,message=%s,className=%s,lineNumber=%d' . PHP_EOL, $e->__toString(), $e->getMessage(), $className, $lineNumber));
1235 // Empty string should be ignored and used for testing the middleware
1236 DebugMiddleware::getSelfInstance()->output('');
1238 // Set it in registry
1239 GenericRegistry::getRegistry()->addInstance('debug', $debugInstance);
1241 // Get instance from registry
1242 $debugInstance = GenericRegistry::getRegistry()->getDebugInstance();
1246 return $debugInstance;
1250 * Simple output of a message with line-break
1252 * @param $message Message to output
1255 public function outputLine ($message) {
1257 print($message . PHP_EOL);
1261 * Outputs a debug message whether to debug instance (should be set!) or
1262 * dies with or ptints the message. Do NEVER EVER rewrite the exit() call to
1263 * ApplicationEntryPoint::app_exit(), this would cause an endless loop.
1265 * @param $message Message we shall send out...
1266 * @param $doPrint Whether print or die here (default: print)
1267 * @paran $stripTags Whether to strip tags (default: false)
1270 public function debugOutput ($message, $doPrint = true, $stripTags = false) {
1271 // Set debug instance to NULL
1272 $debugInstance = NULL;
1275 $backtrace = debug_backtrace(!DEBUG_BACKTRACE_PROVIDE_OBJECT);
1277 // Is function partialStub/__callStatic ?
1278 if (in_array($backtrace[1]['function'], array('partialStub', '__call', '__callStatic'))) {
1279 // Prepend class::function:line from 3rd element
1280 $message = sprintf('[%s::%s:%d]: %s',
1281 $backtrace[2]['class'],
1282 $backtrace[2]['function'],
1283 (isset($backtrace[2]['line']) ? $backtrace[2]['line'] : '0'),
1287 // Prepend class::function:line from 2nd element
1288 $message = sprintf('[%s::%s:%d]: %s',
1289 $backtrace[1]['class'],
1290 $backtrace[1]['function'],
1291 (isset($backtrace[1]['line']) ? $backtrace[1]['line'] : '0'),
1298 // Get debug instance
1299 $debugInstance = $this->getDebugInstance();
1300 } catch (NullPointerException $e) {
1301 // The debug instance is not set (yet)
1304 // Is the debug instance there?
1305 if (is_object($debugInstance)) {
1306 // Use debug output handler
1307 $debugInstance->output($message, $stripTags);
1309 if ($doPrint === false) {
1310 // Die here if not printed
1314 // Are debug times enabled?
1315 if (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('debug_' . FrameworkBootstrap::getRequestTypeFromSystem() . '_output_timings') == 'Y') {
1317 $message = $this->getPrintableExecutionTime() . $message;
1321 if ($doPrint === true) {
1323 $this->outputLine($message);
1332 * Marks up the code by adding e.g. line numbers
1334 * @param $phpCode Unmarked PHP code
1335 * @return $markedCode Marked PHP code
1337 public function markupCode ($phpCode) {
1342 $errorArray = error_get_last();
1344 // Init the code with error message
1345 if (is_array($errorArray)) {
1347 $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>',
1348 basename($errorArray['file']),
1349 $errorArray['line'],
1350 $errorArray['message'],
1355 // Add line number to the code
1356 foreach (explode(chr(10), $phpCode) as $lineNo => $code) {
1358 $markedCode .= sprintf('<span id="code_line">%s</span>: %s' . PHP_EOL,
1360 htmlentities($code, ENT_QUOTES)
1369 * Filter a given GMT timestamp (non Uni* stamp!) to make it look more
1370 * beatiful for web-based front-ends. If null is given a message id
1371 * null_timestamp will be resolved and returned.
1373 * @param $timestamp Timestamp to prepare (filter) for display
1374 * @return $readable A readable timestamp
1376 public function doFilterFormatTimestamp ($timestamp) {
1377 // Default value to return
1380 // Is the timestamp null?
1381 if (is_null($timestamp)) {
1382 // Get a message string
1383 $readable = $this->getLanguageInstance()->getMessage('null_timestamp');
1385 switch ($this->getLanguageInstance()->getLanguageCode()) {
1386 case 'de': // German format is a bit different to default
1387 // Split the GMT stamp up
1388 $dateTime = explode(' ', $timestamp );
1389 $dateArray = explode('-', $dateTime[0]);
1390 $timeArray = explode(':', $dateTime[1]);
1392 // Construct the timestamp
1393 $readable = sprintf(FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('german_date_time'),
1403 default: // Default is pass-through
1404 $readable = $timestamp;
1414 * Filter a given number into a localized number
1416 * @param $value The raw value from e.g. database
1417 * @return $localized Localized value
1419 public function doFilterFormatNumber ($value) {
1420 // Generate it from config and localize dependencies
1421 switch ($this->getLanguageInstance()->getLanguageCode()) {
1422 case 'de': // German format is a bit different to default
1423 $localized = number_format($value, FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('decimals'), ',', '.');
1426 default: // US, etc.
1427 $localized = number_format($value, FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('decimals'), '.', ',');
1436 * "Getter" for databse entry
1438 * @return $entry An array with database entries
1439 * @throws NullPointerException If the database result is not found
1440 * @throws InvalidDatabaseResultException If the database result is invalid
1442 protected final function getDatabaseEntry () {
1443 // Is there an instance?
1444 if (!$this->getResultInstance() instanceof SearchableResult) {
1445 // Throw an exception here
1446 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
1450 $this->getResultInstance()->rewind();
1452 // Do we have an entry?
1453 if ($this->getResultInstance()->valid() === false) {
1454 // @TODO Move the constant to e.g. BaseDatabaseResult when there is a non-cached database result available
1455 throw new InvalidDatabaseResultException(array($this, $this->getResultInstance()), CachedDatabaseResult::EXCEPTION_INVALID_DATABASE_RESULT);
1459 $this->getResultInstance()->next();
1462 $entry = $this->getResultInstance()->current();
1469 * Getter for field name
1471 * @param $fieldName Field name which we shall get
1472 * @return $fieldValue Field value from the user
1473 * @throws NullPointerException If the result instance is null
1475 public final function getField (string $fieldName) {
1476 // Default field value
1479 // Get result instance
1480 $resultInstance = $this->getResultInstance();
1482 // Is this instance null?
1483 if (is_null($resultInstance)) {
1484 // Then the user instance is no longer valid (expired cookies?)
1485 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
1488 // Get current array
1489 $fieldArray = $resultInstance->current();
1490 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($fieldName.':<pre>'.print_r($fieldArray, true).'</pre>');
1492 // Convert dashes to underscore
1493 $fieldName2 = StringUtils::convertDashesToUnderscores($fieldName);
1495 // Does the field exist?
1496 if ($this->isFieldSet($fieldName)) {
1498 $fieldValue = $fieldArray[$fieldName2];
1499 } elseif (defined('DEVELOPER')) {
1500 // Missing field entry, may require debugging
1501 self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ']:fieldArray<pre>=' . print_r($fieldArray, true) . '</pre>,fieldName=' . $fieldName . ' not found!');
1503 // Missing field entry, may require debugging
1504 self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ']:fieldName=' . $fieldName . ' not found!');
1512 * Checks if given field is set
1514 * @param $fieldName Field name to check
1515 * @return $isSet Whether the given field name is set
1516 * @throws NullPointerException If the result instance is null
1518 public function isFieldSet (string $fieldName) {
1519 // Get result instance
1520 $resultInstance = $this->getResultInstance();
1522 // Is this instance null?
1523 if (is_null($resultInstance)) {
1524 // Then the user instance is no longer valid (expired cookies?)
1525 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
1528 // Get current array
1529 $fieldArray = $resultInstance->current();
1530 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('[' . $this->__toString() . ':' . __LINE__ . '] fieldName=' . $fieldName . ',fieldArray=<pre>'.print_r($fieldArray, true).'</pre>');
1532 // Convert dashes to underscore
1533 $fieldName = StringUtils::convertDashesToUnderscores($fieldName);
1536 $isSet = isset($fieldArray[$fieldName]);
1543 * Flushs all pending updates to the database layer
1547 public function flushPendingUpdates () {
1548 // Get result instance
1549 $resultInstance = $this->getResultInstance();
1551 // Do we have data to update?
1552 if ((is_object($resultInstance)) && ($resultInstance->ifDataNeedsFlush())) {
1553 // Get wrapper class name config entry
1554 $configEntry = $resultInstance->getUpdateInstance()->getWrapperConfigEntry();
1556 // Create object instance
1557 $wrapperInstance = DatabaseWrapperFactory::createWrapperByConfiguredName($configEntry);
1559 // Yes, then send the whole result to the database layer
1560 $wrapperInstance->doUpdateByResult($this->getResultInstance());
1565 * Outputs a deprecation warning to the developer.
1567 * @param $message The message we shall output to the developer
1569 * @todo Write a logging mechanism for productive mode
1571 public function deprecationWarning ($message) {
1572 // Is developer mode active?
1573 if (defined('DEVELOPER')) {
1574 // Debug instance is there?
1575 if (!is_null($this->getDebugInstance())) {
1576 // Output stub message
1577 self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($message);
1580 trigger_error($message . "<br />\n");
1584 // @TODO Finish this part!
1585 $this->partialStub('Developer mode inactive. Message:' . $message);
1590 * Checks whether the given PHP extension is loaded
1592 * @param $phpExtension The PHP extension we shall check
1593 * @return $isLoaded Whether the PHP extension is loaded
1595 public final function isPhpExtensionLoaded ($phpExtension) {
1597 $isLoaded = in_array($phpExtension, get_loaded_extensions());
1604 * "Getter" as a time() replacement but with milliseconds. You should use this
1605 * method instead of the encapsulated getimeofday() function.
1607 * @return $milliTime Timestamp with milliseconds
1609 public function getMilliTime () {
1610 // Get the time of day as float
1611 $milliTime = gettimeofday(true);
1618 * Idles (sleeps) for given milliseconds
1620 * @return $hasSlept Whether it goes fine
1622 public function idle ($milliSeconds) {
1623 // Sleep is fine by default
1626 // Idle so long with found function
1627 if (function_exists('time_sleep_until')) {
1628 // Get current time and add idle time
1629 $sleepUntil = $this->getMilliTime() + abs($milliSeconds) / 1000;
1631 // New PHP 5.1.0 function found, ignore errors
1632 $hasSlept = @time_sleep_until($sleepUntil);
1635 * My Sun station doesn't have that function even with latest PHP
1638 usleep($milliSeconds * 1000);
1646 * Checks whether the given encoded data was encoded with Base64
1648 * @param $encodedData Encoded data we shall check
1649 * @return $isBase64 Whether the encoded data is Base64
1651 protected function isBase64Encoded ($encodedData) {
1653 $isBase64 = (@base64_decode($encodedData, true) !== false);
1660 * Gets a cache key from Criteria instance
1662 * @param $criteriaInstance An instance of a Criteria class
1663 * @param $onlyKeys Only use these keys for a cache key
1664 * @return $cacheKey A cache key suitable for lookup/storage purposes
1666 protected function getCacheKeyByCriteria (Criteria $criteriaInstance, array $onlyKeys = array()) {
1668 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FRAMEWORK-SYSTEM: criteriaInstance=' . $criteriaInstance->__toString() . ',onlyKeys()=' . count($onlyKeys) . ' - CALLED!');
1669 $cacheKey = sprintf('%s@%s',
1670 $this->__toString(),
1671 $criteriaInstance->getCacheKey($onlyKeys)
1675 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FRAMEWORK-SYSTEM: cacheKey=' . $cacheKey . ' - EXIT!');
1680 * Getter for startup time in miliseconds
1682 * @return $startupTime Startup time in miliseconds
1684 protected function getStartupTime () {
1685 return self::$startupTime;
1689 * "Getter" for a printable currently execution time in nice braces
1691 * @return $executionTime Current execution time in nice braces
1693 protected function getPrintableExecutionTime () {
1694 // Caculate the execution time
1695 $executionTime = microtime(true) - $this->getStartupTime();
1697 // Pack it in nice braces
1698 $executionTime = sprintf('[ %01.5f ] ', $executionTime);
1701 return $executionTime;
1705 * Hashes a given string with a simple but stronger hash function (no salt)
1706 * and hex-encode it.
1708 * @param $str The string to be hashed
1709 * @return $hash The hash from string $str
1711 public static final function hash ($str) {
1712 // Hash given string with (better secure) hasher
1713 $hash = bin2hex(mhash(MHASH_SHA256, $str));
1720 * "Getter" for length of hash() output. This will be "cached" to speed up
1723 * @return $length Length of hash() output
1725 public static final function getHashLength () {
1727 if (is_null(self::$hashLength)) {
1728 // No, then hash a string and save its length.
1729 self::$hashLength = strlen(self::hash('abc123'));
1733 return self::$hashLength;
1737 * Checks whether the given number is really a number (only chars 0-9).
1739 * @param $num A string consisting only chars between 0 and 9
1740 * @param $castValue Whether to cast the value to double. Do only use this to secure numbers from Requestable classes.
1741 * @param $assertMismatch Whether to assert mismatches
1742 * @return $ret The (hopefully) secured numbered value
1744 public function bigintval ($num, $castValue = true, $assertMismatch = false) {
1745 // Filter all numbers out
1746 $ret = preg_replace('/[^0123456789]/', '', $num);
1749 if ($castValue === true) {
1750 // Cast to biggest numeric type
1751 $ret = (double) $ret;
1754 // Assert only if requested
1755 if ($assertMismatch === true) {
1756 // Has the whole value changed?
1757 assert(('' . $ret . '' != '' . $num . '') && (!is_null($num)));
1765 * Checks whether the given hexadecimal number is really a hex-number (only chars 0-9,a-f).
1767 * @param $num A string consisting only chars between 0 and 9
1768 * @param $assertMismatch Whether to assert mismatches
1769 * @return $ret The (hopefully) secured hext-numbered value
1771 public function hexval ($num, $assertMismatch = false) {
1772 // Filter all numbers out
1773 $ret = preg_replace('/[^0123456789abcdefABCDEF]/', '', $num);
1775 // Assert only if requested
1776 if ($assertMismatch === true) {
1777 // Has the whole value changed?
1778 assert(('' . $ret . '' != '' . $num . '') && (!is_null($num)));
1786 * Determines if an element is set in the generic array
1788 * @param $keyGroup Main group for the key
1789 * @param $subGroup Sub group for the key
1790 * @param $key Key to check
1791 * @param $element Element to check
1792 * @return $isset Whether the given key is set
1794 protected final function isGenericArrayElementSet ($keyGroup, $subGroup, $key, $element) {
1796 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element);
1799 $isset = isset($this->genericArray[$keyGroup][$subGroup][$key][$element]);
1805 * Determines if a key is set in the generic array
1807 * @param $keyGroup Main group for the key
1808 * @param $subGroup Sub group for the key
1809 * @param $key Key to check
1810 * @return $isset Whether the given key is set
1812 protected final function isGenericArrayKeySet ($keyGroup, $subGroup, $key) {
1814 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
1817 $isset = isset($this->genericArray[$keyGroup][$subGroup][$key]);
1825 * Determines if a group is set in the generic array
1827 * @param $keyGroup Main group
1828 * @param $subGroup Sub group
1829 * @return $isset Whether the given group is set
1831 protected final function isGenericArrayGroupSet ($keyGroup, $subGroup) {
1833 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup);
1836 $isset = isset($this->genericArray[$keyGroup][$subGroup]);
1843 * Getter for sub key group
1845 * @param $keyGroup Main key group
1846 * @param $subGroup Sub key group
1847 * @return $array An array with all array elements
1849 protected final function getGenericSubArray ($keyGroup, $subGroup) {
1851 if (!$this->isGenericArrayGroupSet($keyGroup, $subGroup)) {
1852 // No, then abort here
1853 trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' not found.');
1858 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',value=' . print_r($this->genericArray[$keyGroup][$subGroup], true));
1861 return $this->genericArray[$keyGroup][$subGroup];
1865 * Unsets a given key in generic array
1867 * @param $keyGroup Main group for the key
1868 * @param $subGroup Sub group for the key
1869 * @param $key Key to unset
1872 protected final function unsetGenericArrayKey ($keyGroup, $subGroup, $key) {
1874 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
1877 unset($this->genericArray[$keyGroup][$subGroup][$key]);
1881 * Unsets a given element in generic array
1883 * @param $keyGroup Main group for the key
1884 * @param $subGroup Sub group for the key
1885 * @param $key Key to unset
1886 * @param $element Element to unset
1889 protected final function unsetGenericArrayElement ($keyGroup, $subGroup, $key, $element) {
1891 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element);
1894 unset($this->genericArray[$keyGroup][$subGroup][$key][$element]);
1898 * Append a string to a given generic array key
1900 * @param $keyGroup Main group for the key
1901 * @param $subGroup Sub group for the key
1902 * @param $key Key to unset
1903 * @param $value Value to add/append
1906 protected final function appendStringToGenericArrayKey ($keyGroup, $subGroup, $key, $value, $appendGlue = '') {
1908 //* 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);
1910 // Is it already there?
1911 if ($this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
1913 $this->genericArray[$keyGroup][$subGroup][$key] .= $appendGlue . (string) $value;
1916 $this->genericArray[$keyGroup][$subGroup][$key] = (string) $value;
1921 * Append a string to a given generic array element
1923 * @param $keyGroup Main group for the key
1924 * @param $subGroup Sub group for the key
1925 * @param $key Key to unset
1926 * @param $element Element to check
1927 * @param $value Value to add/append
1930 protected final function appendStringToGenericArrayElement ($keyGroup, $subGroup, $key, $element, $value, $appendGlue = '') {
1932 //* 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);
1934 // Is it already there?
1935 if ($this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element)) {
1937 $this->genericArray[$keyGroup][$subGroup][$key][$element] .= $appendGlue . (string) $value;
1940 $this->setStringGenericArrayElement($keyGroup, $subGroup, $key, $element, $value);
1945 * Sets a string in a given generic array element
1947 * @param $keyGroup Main group for the key
1948 * @param $subGroup Sub group for the key
1949 * @param $key Key to unset
1950 * @param $element Element to check
1951 * @param $value Value to add/append
1954 protected final function setStringGenericArrayElement ($keyGroup, $subGroup, $key, $element, $value, $appendGlue = '') {
1956 //* 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);
1959 $this->genericArray[$keyGroup][$subGroup][$key][$element] = (string) $value;
1963 * Initializes given generic array group
1965 * @param $keyGroup Main group for the key
1966 * @param $subGroup Sub group for the key
1967 * @param $key Key to use
1968 * @param $forceInit Optionally force initialization
1971 protected final function initGenericArrayGroup ($keyGroup, $subGroup, $forceInit = false) {
1973 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',forceInit=' . intval($forceInit));
1975 // Is it already set?
1976 if (($forceInit === false) && ($this->isGenericArrayGroupSet($keyGroup, $subGroup))) {
1977 // Already initialized
1978 trigger_error(__METHOD__ . ':keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' already initialized.');
1983 $this->genericArray[$keyGroup][$subGroup] = array();
1987 * Initializes given generic array key
1989 * @param $keyGroup Main group for the key
1990 * @param $subGroup Sub group for the key
1991 * @param $key Key to use
1992 * @param $forceInit Optionally force initialization
1995 protected final function initGenericArrayKey ($keyGroup, $subGroup, $key, $forceInit = false) {
1997 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',forceInit=' . intval($forceInit));
1999 // Is it already set?
2000 if (($forceInit === false) && ($this->isGenericArrayKeySet($keyGroup, $subGroup, $key))) {
2001 // Already initialized
2002 trigger_error(__METHOD__ . ':keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' already initialized.');
2007 $this->genericArray[$keyGroup][$subGroup][$key] = array();
2011 * Initializes given generic array element
2013 * @param $keyGroup Main group for the key
2014 * @param $subGroup Sub group for the key
2015 * @param $key Key to use
2016 * @param $element Element to use
2017 * @param $forceInit Optionally force initialization
2020 protected final function initGenericArrayElement ($keyGroup, $subGroup, $key, $element, $forceInit = false) {
2022 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ',forceInit=' . intval($forceInit));
2024 // Is it already set?
2025 if (($forceInit === false) && ($this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element))) {
2026 // Already initialized
2027 trigger_error(__METHOD__ . ':keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ' already initialized.');
2032 $this->genericArray[$keyGroup][$subGroup][$key][$element] = array();
2036 * Pushes an element to a generic key
2038 * @param $keyGroup Main group for the key
2039 * @param $subGroup Sub group for the key
2040 * @param $key Key to use
2041 * @param $value Value to add/append
2042 * @return $count Number of array elements
2044 protected final function pushValueToGenericArrayKey ($keyGroup, $subGroup, $key, $value) {
2046 //* NOISY-DEBUG: */ if (!is_object($value)) $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',value[' . gettype($value) . ']=' . print_r($value, true));
2049 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
2051 $this->initGenericArrayKey($keyGroup, $subGroup, $key);
2055 $count = array_push($this->genericArray[$keyGroup][$subGroup][$key], $value);
2058 //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], true));
2059 //* DEBUG: */ print(__METHOD__ . ': count=' . $count . PHP_EOL);
2064 * Pushes an element to a generic array element
2066 * @param $keyGroup Main group for the key
2067 * @param $subGroup Sub group for the key
2068 * @param $key Key to use
2069 * @param $element Element to check
2070 * @param $value Value to add/append
2071 * @return $count Number of array elements
2073 protected final function pushValueToGenericArrayElement ($keyGroup, $subGroup, $key, $element, $value) {
2075 //* 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));
2078 if (!$this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element)) {
2080 $this->initGenericArrayElement($keyGroup, $subGroup, $key, $element);
2084 $count = array_push($this->genericArray[$keyGroup][$subGroup][$key][$element], $value);
2087 //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], true));
2088 //* DEBUG: */ print(__METHOD__ . ': count=' . $count . PHP_EOL);
2093 * Pops an element from a generic group
2095 * @param $keyGroup Main group for the key
2096 * @param $subGroup Sub group for the key
2097 * @param $key Key to unset
2098 * @return $value Last "popped" value
2100 protected final function popGenericArrayElement ($keyGroup, $subGroup, $key) {
2102 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2105 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
2107 trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' not found.');
2112 $value = array_pop($this->genericArray[$keyGroup][$subGroup][$key]);
2115 //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], true));
2116 //* DEBUG: */ print(__METHOD__ . ': value[' . gettype($value) . ']=' . print_r($value, true) . PHP_EOL);
2121 * Shifts an element from a generic group
2123 * @param $keyGroup Main group for the key
2124 * @param $subGroup Sub group for the key
2125 * @param $key Key to unset
2126 * @return $value Last "popped" value
2128 protected final function shiftGenericArrayElement ($keyGroup, $subGroup, $key) {
2130 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2133 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
2135 trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' not found.');
2140 $value = array_shift($this->genericArray[$keyGroup][$subGroup][$key]);
2143 //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], true));
2144 //* DEBUG: */ print(__METHOD__ . ': value[' . gettype($value) . ']=' . print_r($value, true) . PHP_EOL);
2149 * Count generic array group
2151 * @param $keyGroup Main group for the key
2152 * @return $count Count of given group
2154 protected final function countGenericArray ($keyGroup) {
2156 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup);
2159 if (!isset($this->genericArray[$keyGroup])) {
2161 trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ' not found.');
2166 $count = count($this->genericArray[$keyGroup]);
2169 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',count=' . $count);
2176 * Count generic array sub group
2178 * @param $keyGroup Main group for the key
2179 * @param $subGroup Sub group for the key
2180 * @return $count Count of given group
2182 protected final function countGenericArrayGroup ($keyGroup, $subGroup) {
2184 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup);
2187 if (!$this->isGenericArrayGroupSet($keyGroup, $subGroup)) {
2189 trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' not found.');
2194 $count = count($this->genericArray[$keyGroup][$subGroup]);
2197 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',count=' . $count);
2204 * Count generic array elements
2206 * @param $keyGroup Main group for the key
2207 * @param $subGroup Sub group for the key
2208 * @para $key Key to count
2209 * @return $count Count of given key
2211 protected final function countGenericArrayElements ($keyGroup, $subGroup, $key) {
2213 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2216 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
2218 trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' not found.');
2220 } elseif (!$this->isValidGenericArrayGroup($keyGroup, $subGroup)) {
2222 trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' is not an array.');
2227 $count = count($this->genericArray[$keyGroup][$subGroup][$key]);
2230 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',count=' . $count);
2237 * Getter for whole generic group array
2239 * @param $keyGroup Key group to get
2240 * @return $array Whole generic array group
2242 protected final function getGenericArray ($keyGroup) {
2244 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup);
2247 if (!isset($this->genericArray[$keyGroup])) {
2249 trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ' does not exist.');
2254 return $this->genericArray[$keyGroup];
2258 * Setter for generic array key
2260 * @param $keyGroup Key group to get
2261 * @param $subGroup Sub group for the key
2262 * @param $key Key to unset
2263 * @param $value Mixed value from generic array element
2266 protected final function setGenericArrayKey ($keyGroup, $subGroup, $key, $value) {
2268 //* NOISY-DEBUG: */ if (!is_object($value)) $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',value[' . gettype($value) . ']=' . print_r($value, true));
2271 $this->genericArray[$keyGroup][$subGroup][$key] = $value;
2275 * Getter for generic array key
2277 * @param $keyGroup Key group to get
2278 * @param $subGroup Sub group for the key
2279 * @param $key Key to unset
2280 * @return $value Mixed value from generic array element
2282 protected final function getGenericArrayKey ($keyGroup, $subGroup, $key) {
2284 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2287 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
2289 trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' does not exist.');
2294 return $this->genericArray[$keyGroup][$subGroup][$key];
2298 * Sets a value in given generic array key/element
2300 * @param $keyGroup Main group for the key
2301 * @param $subGroup Sub group for the key
2302 * @param $key Key to set
2303 * @param $element Element to set
2304 * @param $value Value to set
2307 protected final function setGenericArrayElement ($keyGroup, $subGroup, $key, $element, $value) {
2309 //* 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));
2312 $this->genericArray[$keyGroup][$subGroup][$key][$element] = $value;
2316 * Getter for generic array element
2318 * @param $keyGroup Key group to get
2319 * @param $subGroup Sub group for the key
2320 * @param $key Key to look for
2321 * @param $element Element to look for
2322 * @return $value Mixed value from generic array element
2324 protected final function getGenericArrayElement ($keyGroup, $subGroup, $key, $element) {
2326 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element);
2329 if (!$this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element)) {
2331 trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ' does not exist.');
2336 return $this->genericArray[$keyGroup][$subGroup][$key][$element];
2340 * Checks if a given sub group is valid (array)
2342 * @param $keyGroup Key group to get
2343 * @param $subGroup Sub group for the key
2344 * @return $isValid Whether given sub group is valid
2346 protected final function isValidGenericArrayGroup ($keyGroup, $subGroup) {
2348 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup);
2351 $isValid = (($this->isGenericArrayGroupSet($keyGroup, $subGroup)) && (is_array($this->getGenericSubArray($keyGroup, $subGroup))));
2358 * Checks if a given key is valid (array)
2360 * @param $keyGroup Key group to get
2361 * @param $subGroup Sub group for the key
2362 * @param $key Key to check
2363 * @return $isValid Whether given sub group is valid
2365 protected final function isValidGenericArrayKey ($keyGroup, $subGroup, $key) {
2367 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2370 $isValid = (($this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) && (is_array($this->getGenericArrayKey($keyGroup, $subGroup, $key))));
2377 * Initializes the web output instance
2381 protected function initWebOutputInstance () {
2382 // Get application instance
2383 $applicationInstance = GenericRegistry::getRegistry()->getInstance('application');
2385 // Init web output instance
2386 $outputInstance = ObjectFactory::createObjectByConfiguredName('output_class', array($applicationInstance));
2389 $this->setWebOutputInstance($outputInstance);
2393 * Translates boolean true to 'Y' and false to 'N'
2395 * @param $boolean Boolean value
2396 * @return $translated Translated boolean value
2398 public static final function translateBooleanToYesNo (bool $boolean) {
2399 // Make sure it is really boolean
2400 assert(is_bool($boolean));
2403 $translated = ($boolean === true) ? 'Y' : 'N';
2405 // ... and return it
2410 * Creates a full-qualified file name (FQFN) for given file name by adding
2411 * a configured temporary file path to it.
2413 * @param $infoInstance An instance of a SplFileInfo class
2414 * @return $tempInstance An instance of a SplFileInfo class (temporary file)
2415 * @throw PathWriteProtectedException If the path in 'temp_file_path' is write-protected
2416 * @throws FileIoException If the file cannot be written
2418 protected static function createTempPathForFile (SplFileInfo $infoInstance) {
2420 $basePath = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('temp_file_path');
2422 // Is the path writeable?
2423 if (!is_writable($basePath)) {
2424 // Path is write-protected
2425 throw new PathWriteProtectedException($infoInstance, self::EXCEPTION_PATH_CANNOT_BE_WRITTEN);
2429 $tempInstance = new SplFileInfo($basePath . DIRECTORY_SEPARATOR . $infoInstance->getBasename());
2432 if (!FrameworkBootstrap::isReachableFilePath($tempInstance)) {
2434 throw new FileIoException($tempInstance, self::EXCEPTION_FILE_NOT_REACHABLE);
2438 return $tempInstance;
2442 * "Getter" for a printable state name
2444 * @return $stateName Name of the node's state in a printable format
2446 public final function getPrintableState () {
2447 // Default is 'null'
2448 $stateName = 'null';
2450 // Get the state instance
2451 $stateInstance = $this->getStateInstance();
2453 // Is it an instance of Stateable?
2454 if ($stateInstance instanceof Stateable) {
2455 // Then use that state name
2456 $stateName = $stateInstance->getStateName();