X-Git-Url: https://git.mxchange.org/?p=core.git;a=blobdiff_plain;f=inc%2Fclasses%2Fmain%2Fclass_BaseFrameworkSystem.php;h=be6499dc3f5d7e7a0cfa9beaff4199b913e5bdf7;hp=9491cb23c2015afaf8ddf9894542481e19a6fd6b;hb=d6e26d0565685dbdba5ba14dd7e9c44c26b1378e;hpb=e62ba6655bd415a349dc4fb2dea913f07c39be0c diff --git a/inc/classes/main/class_BaseFrameworkSystem.php b/inc/classes/main/class_BaseFrameworkSystem.php index 9491cb23..be6499dc 100644 --- a/inc/classes/main/class_BaseFrameworkSystem.php +++ b/inc/classes/main/class_BaseFrameworkSystem.php @@ -3,11 +3,11 @@ * The simulator system class is the super class of all other classes. This * class handles saving of games etc. * - * @author Roland Haeder + * @author Roland Haeder * @version 0.0.0 - * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2011 Core Developer Team + * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2013 Core Developer Team * @license GNU GPL 3.0 or any newer version - * @link http://www.ship-simu.org + * @link http://www.shipsimu.org * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,161 +23,236 @@ * along with this program. If not, see . */ class BaseFrameworkSystem extends stdClass implements FrameworkInterface { + /** + * Length of count + */ + const LENGTH_COUNT = 20; + + /** + * Length of position + */ + const LENGTH_POSITION = 20; + + /** + * The real class name + */ + private $realClass = 'BaseFrameworkSystem'; + /** * Instance of a request class */ - private $requestInstance = null; + private $requestInstance = NULL; /** * Instance of a response class */ - private $responseInstance = null; + private $responseInstance = NULL; /** * Search criteria instance */ - private $searchInstance = null; + private $searchInstance = NULL; /** * Update criteria instance */ - private $updateInstance = null; + private $updateInstance = NULL; /** * The file I/O instance for the template loader */ - private $fileIoInstance = null; + private $fileIoInstance = NULL; /** * Resolver instance */ - private $resolverInstance = null; + private $resolverInstance = NULL; /** * Template engine instance */ - private $templateInstance = null; + private $templateInstance = NULL; /** * Database result instance */ - private $resultInstance = null; + private $resultInstance = NULL; /** * Instance for user class */ - private $userInstance = null; + private $userInstance = NULL; /** * A controller instance */ - private $controllerInstance = null; + private $controllerInstance = NULL; /** * Instance of a RNG */ - private $rngInstance = null; + private $rngInstance = NULL; /** * Instance of a crypto helper */ - private $cryptoInstance = null; + private $cryptoInstance = NULL; /** * Instance of an Iterator class */ - private $iteratorInstance = null; + private $iteratorInstance = NULL; /** * Instance of the list */ - private $listInstance = null; + private $listInstance = NULL; /** * Instance of a menu */ - private $menuInstance = null; + private $menuInstance = NULL; /** * Instance of the image */ - private $imageInstance = null; + private $imageInstance = NULL; /** * Instance of the stacker */ - private $stackerInstance = null; + private $stackerInstance = NULL; /** * A Compressor instance */ - private $compressorInstance = null; + private $compressorInstance = NULL; /** * A Parseable instance */ - private $parserInstance = null; + private $parserInstance = NULL; /** * A ProtocolHandler instance */ - private $protocolInstance = null; + private $protocolInstance = NULL; /** * A database wrapper instance */ - private $databaseInstance = null; + private $databaseInstance = NULL; /** * A helper instance for the form */ - private $helperInstance = null; + private $helperInstance = NULL; /** * An instance of a Sourceable class */ - private $sourceInstance = null; + private $sourceInstance = NULL; /** - * An instance of a InputStreamable class + * An instance of a InputStream class */ - private $inputStreamInstance = null; + private $inputStreamInstance = NULL; /** - * An instance of a OutputStreamable class + * An instance of a OutputStream class */ - private $outputStreamInstance = null; + private $outputStreamInstance = NULL; /** - * The real class name + * Networkable handler instance */ - private $realClass = 'BaseFrameworkSystem'; + private $handlerInstance = NULL; + + /** + * Visitor handler instance + */ + private $visitorInstance = NULL; + + /** + * DHT instance + */ + private $dhtInstance = NULL; /** * An instance of a database wrapper class */ - private $wrapperInstance = null; + private $wrapperInstance = NULL; + + /** + * An instance of a file I/O pointer class (not handler) + */ + private $pointerInstance = NULL; + + /** + * An instance of an index + */ + private $indexInstance = NULL; /** - * Thousands seperator + * Thousands separator */ private $thousands = '.'; // German /** - * Decimal seperator + * Decimal separator */ private $decimals = ','; // German /** * Socket resource */ - private $socketResource = false; + private $socketResource = FALSE; /** * Package data */ private $packageData = array(); + /** + * Generic array + */ + private $genericArray = array(); + + /** + * Length of output from hash() + */ + private static $hashLength = NULL; + + /** + * Counter for total entries + */ + private $totalEntries = 0; + + /** + * Current seek position + */ + private $seekPosition = 0; + + /** + * Size of header + */ + private $headerSize = 0; + + /** + * File header + */ + private $header = array(); + + /** + * Seek positions for gaps ("fragmentation") + */ + private $gaps = array(); + + /** + * Seek positions for damaged entries (e.g. mismatching hash sum, ...) + */ + private $damagedEntries = array(); + /*********************** * Exception codes.... * ***********************/ @@ -229,6 +304,7 @@ class BaseFrameworkSystem extends stdClass implements FrameworkInterface { const EXCEPTION_ARRAY_ELEMENTS_MISSING = 0x02c; const EXCEPTION_TEMPLATE_ENGINE_UNSUPPORTED = 0x02d; const EXCEPTION_UNSPPORTED_OPERATION = 0x02e; + const EXCEPTION_FACTORY_REQUIRE_PARAMETER = 0x02f; const EXCEPTION_MISSING_ELEMENT = 0x030; const EXCEPTION_HEADERS_ALREADY_SENT = 0x031; const EXCEPTION_DEFAULT_CONTROLLER_GONE = 0x032; @@ -239,9 +315,11 @@ class BaseFrameworkSystem extends stdClass implements FrameworkInterface { const EXCEPTION_ASSERTION_FAILED = 0x037; const EXCEPTION_FILE_CANNOT_BE_READ = 0x038; const EXCEPTION_DATABASE_UPDATED_NOT_ALLOWED = 0x039; - const EXCEPTION_FILTER_CHAIN_INTERCEPTED = 0x040; + const EXCEPTION_FILTER_CHAIN_INTERCEPTED = 0x03a; - // Hexadecimal->Decimal translation array + /** + * Hexadecimal->Decimal translation array + */ private static $hexdec = array( '0' => 0, '1' => 1, @@ -261,7 +339,9 @@ class BaseFrameworkSystem extends stdClass implements FrameworkInterface { 'f' => 15 ); - // Decimal->hexadecimal translation array + /** + * Decimal->hexadecimal translation array + */ private static $dechex = array( 0 => '0', 1 => '1', @@ -281,6 +361,11 @@ class BaseFrameworkSystem extends stdClass implements FrameworkInterface { 15 => 'f' ); + /** + * Startup time in miliseconds + */ + private static $startupTime = 0; + /** * Protected super constructor * @@ -294,16 +379,22 @@ class BaseFrameworkSystem extends stdClass implements FrameworkInterface { // Set configuration instance if no registry ... if (!$this instanceof Register) { // ... because registries doesn't need to be configured - $this->setConfigInstance(FrameworkConfiguration::getInstance()); + $this->setConfigInstance(FrameworkConfiguration::getSelfInstance()); + } // END - if + + // Is the startup time set? (0 cannot be TRUE anymore) + if (self::$startupTime == 0) { + // Then set it + self::$startupTime = microtime(TRUE); } // END - if } /** - * Destructor reached... + * Destructor for all classes * * @return void */ - public function __destruct() { + public function __destruct () { // Flush any updated entries to the database $this->flushPendingUpdates(); @@ -313,10 +404,14 @@ class BaseFrameworkSystem extends stdClass implements FrameworkInterface { $this->setRealClass('DestructedObject'); } elseif ((defined('DEBUG_DESTRUCTOR')) && (is_object($this->getDebugInstance()))) { // Already destructed object - $this->debugOutput(sprintf("[%s:] The object %s is already destroyed.", + self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:] The object %s is already destroyed.', __CLASS__, $this->__toString() )); + } else { + // Do not call this twice + trigger_error(__METHOD__ . ': Called twice.'); + exit; } } @@ -328,21 +423,50 @@ class BaseFrameworkSystem extends stdClass implements FrameworkInterface { * @return void */ public final function __call ($methodName, $args) { - // Implode all given arguments + return self::__callStatic($methodName, $args); + } + + /** + * The __callStatic() method where all non-implemented static methods end up + * + * @param $methodName Name of the missing method + * @args $args Arguments passed to the method + * @return void + */ + public static final function __callStatic ($methodName, $args) { + // Init argument string $argsString = ''; + + // Is it empty or an array? if (empty($args)) { // No arguments $argsString = 'NULL'; } elseif (is_array($args)) { // Some arguments are there foreach ($args as $arg) { - // Add the type - $argsString .= $this->replaceControlCharacters($arg) . ' (' . gettype($arg); + // Add the value itself if not array. This prevents 'array to string conversion' message + if (is_array($arg)) { + $argsString .= 'Array'; + } else { + $argsString .= $arg; + } + + // Add data about the argument + $argsString .= ' (' . gettype($arg); - // Add length if type is string if (is_string($arg)) { - $argsString .= ', '.strlen($arg); - } // END - if + // Add length for strings + $argsString .= ', ' . strlen($arg); + } elseif (is_array($arg)) { + // .. or size if array + $argsString .= ', ' . count($arg); + } elseif ($arg === TRUE) { + // ... is boolean 'TRUE' + $argsString .= ', TRUE'; + } elseif ($arg === FALSE) { + // ... is boolean 'FALSE' + $argsString .= ', FALSE'; + } // Closing bracket $argsString .= '), '; @@ -358,14 +482,14 @@ class BaseFrameworkSystem extends stdClass implements FrameworkInterface { } // Output stub message - $this->debugOutput(sprintf("[%s->%s] Stub! Args: %s", - $this->__toString(), + // @TODO __CLASS__ does always return BaseFrameworkSystem but not the extending (=child) class + self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[unknown::%s:] Stub! Args: %s', $methodName, $argsString )); // Return nothing - return null; + return NULL; } /** @@ -385,10 +509,10 @@ class BaseFrameworkSystem extends stdClass implements FrameworkInterface { * @return void */ public final function __set ($name, $value) { - $this->debugBackTrace(sprintf("Tried to set a missing field. name=%s, value[%s]=%s", + $this->debugBackTrace(sprintf('Tried to set a missing field. name=%s, value[%s]=%s', $name, gettype($value), - $value + print_r($value, TRUE) )); } @@ -399,7 +523,7 @@ class BaseFrameworkSystem extends stdClass implements FrameworkInterface { * @return void */ public final function __get ($name) { - $this->debugBackTrace(sprintf("Tried to get a missing field. name=%s", + $this->debugBackTrace(sprintf('Tried to get a missing field. name=%s', $name )); } @@ -411,11 +535,22 @@ class BaseFrameworkSystem extends stdClass implements FrameworkInterface { * @return void */ public final function __unset ($name) { - $this->debugBackTrace(sprintf("Tried to unset a missing field. name=%s", + $this->debugBackTrace(sprintf('Tried to unset a missing field. name=%s', $name )); } + /** + * Setter for the real class name + * + * @param $realClass Class name (string) + * @return void + */ + public final function setRealClass ($realClass) { + // Set real class + $this->realClass = (string) $realClass; + } + /** * Setter for database result instance * @@ -559,7 +694,7 @@ class BaseFrameworkSystem extends stdClass implements FrameworkInterface { /** * Setter for web output instance * - * @param $webInstance The instance for web output class + * @param $webInstance The instance for web output class * @return void */ public final function setWebOutputInstance (OutputStreamer $webInstance) { @@ -579,30 +714,30 @@ class BaseFrameworkSystem extends stdClass implements FrameworkInterface { /** * Setter for database instance * - * @param $dbInstance The instance for the database connection (forced DatabaseConnection) + * @param $databaseInstance The instance for the database connection (forced DatabaseConnection) * @return void */ - public final function setDatabaseInstance (DatabaseConnection $dbInstance) { - Registry::getRegistry()->addInstance('db_instance', $dbInstance); + public final function setDatabaseInstance (DatabaseConnection $databaseInstance) { + Registry::getRegistry()->addInstance('db_instance', $databaseInstance); } /** * Getter for database layer * - * @return $dbInstance The database layer instance + * @return $databaseInstance The database layer instance */ public final function getDatabaseInstance () { // Get instance - $dbInstance = Registry::getRegistry()->getInstance('db_instance'); + $databaseInstance = Registry::getRegistry()->getInstance('db_instance'); // Return instance - return $dbInstance; + return $databaseInstance; } /** * Setter for compressor channel * - * @param $compressorInstance An instance of CompressorChannel + * @param $compressorInstance An instance of CompressorChannel * @return void */ public final function setCompressorChannel (CompressorChannel $compressorInstance) { @@ -678,1148 +813,2333 @@ class BaseFrameworkSystem extends stdClass implements FrameworkInterface { } /** - * Setter for the real class name + * Private getter for language instance * - * @param $realClass Class name (string) - * @return void + * @return $langInstance An instance to the language sub-system */ - public final function setRealClass ($realClass) { - // Cast to string - $realClass = (string) $realClass; - - // Set real class - $this->realClass = $realClass; + protected final function getLanguageInstance () { + $langInstance = Registry::getRegistry()->getInstance('language'); + return $langInstance; } /** - * Checks wether an object equals this object. You should overwrite this - * method to implement own equality checks + * Setter for language instance * - * @param $objectInstance An instance of a FrameworkInterface object - * @return $equals Wether both objects equals + * @param $langInstance An instance to the language sub-system + * @return void + * @see LanguageSystem */ - public function equals (FrameworkInterface $objectInstance) { - // Now test it - $equals = (( - $this->__toString() == $objectInstance->__toString() - ) && ( - $this->hashCode() == $objectInstance->hashCode() - )); - - // Return the result - return $equals; + public final function setLanguageInstance (ManageableLanguage $langInstance) { + Registry::getRegistry()->addInstance('language', $langInstance); } /** - * Generates a generic hash code of this class. You should really overwrite - * this method with your own hash code generator code. But keep KISS in mind. + * Private getter for file IO instance * - * @return $hashCode A generic hash code respresenting this whole class + * @return $fileIoInstance An instance to the file I/O sub-system */ - public function hashCode () { - // Simple hash code - return crc32($this->__toString()); + protected final function getFileIoInstance () { + return $this->fileIoInstance; } /** - * Formats computer generated price values into human-understandable formats - * with thousand and decimal seperators. + * Setter for file I/O instance * - * @param $value The in computer format value for a price - * @param $currency The currency symbol (use HTML-valid characters!) - * @param $decNum Number of decimals after commata - * @return $price The for the current language formated price string - * @throws MissingDecimalsThousandsSeperatorException If decimals or - * thousands seperator - * is missing + * @param $fileIoInstance An instance to the file I/O sub-system + * @return void */ - public function formatCurrency ($value, $currency = '€', $decNum = 2) { - // Are all required attriutes set? - if ((!isset($this->decimals)) || (!isset($this->thousands))) { - // Throw an exception - throw new MissingDecimalsThousandsSeperatorException($this, self::EXCEPTION_ATTRIBUTES_ARE_MISSING); - } // END - if - - // Cast the number - $value = (float) $value; - - // Reformat the US number - $price = number_format($value, $decNum, $this->decimals, $this->thousands) . $currency; - - // Return as string... - return $price; + public final function setFileIoInstance (IoHandler $fileIoInstance) { + $this->fileIoInstance = $fileIoInstance; } /** - * Private getter for language instance + * Protected setter for user instance * - * @return $langInstance An instance to the language sub-system + * @param $userInstance An instance of a user class + * @return void */ - protected final function getLanguageInstance () { - $langInstance = Registry::getRegistry()->getInstance('language'); - return $langInstance; + protected final function setUserInstance (ManageableAccount $userInstance) { + $this->userInstance = $userInstance; } /** - * Setter for language instance + * Getter for user instance * - * @param $langInstance An instance to the language sub-system - * @return void - * @see LanguageSystem + * @return $userInstance An instance of a user class */ - public final function setLanguageInstance (ManageableLanguage $langInstance) { - Registry::getRegistry()->addInstance('language', $langInstance); + public final function getUserInstance () { + return $this->userInstance; } /** - * Appends a trailing slash to a string + * Setter for controller instance (this surely breaks a bit the MVC patterm) * - * @param $str A string (maybe) without trailing slash - * @return $str A string with an auto-appended trailing slash + * @param $controllerInstance An instance of the controller + * @return void */ - public final function addMissingTrailingSlash ($str) { - // Is there a trailing slash? - if (substr($str, -1, 1) != '/') { - $str .= '/'; - } // END - if - - // Return string with trailing slash - return $str; + public final function setControllerInstance (Controller $controllerInstance) { + $this->controllerInstance = $controllerInstance; } /** - * Private getter for file IO instance + * Getter for controller instance (this surely breaks a bit the MVC patterm) * - * @return $fileIoInstance An instance to the file I/O sub-system + * @return $controllerInstance An instance of the controller */ - protected final function getFileIoInstance () { - return $this->fileIoInstance; + public final function getControllerInstance () { + return $this->controllerInstance; } /** - * Setter for file I/O instance + * Setter for RNG instance * - * @param $fileIoInstance An instance to the file I/O sub-system + * @param $rngInstance An instance of a random number generator (RNG) * @return void */ - public final function setFileIoInstance (FileIoHandler $fileIoInstance) { - $this->fileIoInstance = $fileIoInstance; + protected final function setRngInstance (RandomNumberGenerator $rngInstance) { + $this->rngInstance = $rngInstance; } /** - * Prepare the template engine (WebTemplateEngine by default) for a given - * application helper instance (ApplicationHelper by default). + * Getter for RNG instance * - * @param $applicationInstance An application helper instance or - * null if we shall use the default - * @return $templateInstance The template engine instance - * @throws NullPointerException If the discovered application - * instance is still null + * @return $rngInstance An instance of a random number generator (RNG) */ - protected function prepareTemplateInstance (ManageableApplication $applicationInstance = null) { - // Is the application instance set? - if (is_null($applicationInstance)) { - // Get the current instance - $applicationInstance = $this->getApplicationInstance(); - - // Still null? - if (is_null($applicationInstance)) { - // Thrown an exception - throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER); - } // END - if - } // END - if - - // Initialize the template engine - $templateInstance = ObjectFactory::createObjectByConfiguredName('web_template_class'); - - // Return the prepared instance - return $templateInstance; + public final function getRngInstance () { + return $this->rngInstance; } /** - * Debugs this instance by putting out it's full content + * Setter for Cryptable instance * - * @param $message Optional message to show in debug output + * @param $cryptoInstance An instance of a Cryptable class * @return void */ - public final function debugInstance ($message = '') { - // Restore the error handler to avoid trouble with missing array elements or undeclared variables - restore_error_handler(); - - // Init content - $content = ''; - - // Is a message set? - if (!empty($message)) { - // Construct message - $content = sprintf("
Message: %s
\n", $message); - } // END - if - - // Generate the output - $content .= sprintf("
%s
", - trim( - htmlentities( - print_r($this, true) - ) - ) - ); - - // Output it - ApplicationEntryPoint::app_die(sprintf("
%s debug output:
%s
\nLoaded includes:
%s
", - $this->__toString(), - $content, - ClassLoader::getInstance()->getPrintableIncludeList() - )); + protected final function setCryptoInstance (Cryptable $cryptoInstance) { + $this->cryptoInstance = $cryptoInstance; } /** - * Replaces control characters with printable output + * Getter for Cryptable instance * - * @param $str String with control characters - * @return $str Replaced string + * @return $cryptoInstance An instance of a Cryptable class */ - protected function replaceControlCharacters ($str) { - // Replace them - $str = str_replace( - "\r", '[r]', str_replace( - "\n", '[n]', str_replace( - "\t", '[t]', - $str - ))); + public final function getCryptoInstance () { + return $this->cryptoInstance; + } - // Return it - return $str; + /** + * Setter for the list instance + * + * @param $listInstance A list of Listable + * @return void + */ + protected final function setListInstance (Listable $listInstance) { + $this->listInstance = $listInstance; } /** - * Output a partial stub message for the caller method + * Getter for the list instance * - * @param $message An optional message to display - * @return void + * @return $listInstance A list of Listable */ - protected function partialStub ($message = '') { - // Get the backtrace - $backtrace = debug_backtrace(); + protected final function getListInstance () { + return $this->listInstance; + } - // Generate the class::method string - $methodName = 'UnknownClass->unknownMethod'; - if ((isset($backtrace[1]['class'])) && (isset($backtrace[1]['function']))) { - $methodName = $backtrace[1]['class'] . '->' . $backtrace[1]['function']; - } // END - if + /** + * Setter for the menu instance + * + * @param $menuInstance A RenderableMenu instance + * @return void + */ + protected final function setMenuInstance (RenderableMenu $menuInstance) { + $this->menuInstance = $menuInstance; + } - // Construct the full message - $stubMessage = sprintf("[%s:] Partial stub!", - $methodName - ); + /** + * Getter for the menu instance + * + * @return $menuInstance A RenderableMenu instance + */ + protected final function getMenuInstance () { + return $this->menuInstance; + } - // Is the extra message given? - if (!empty($message)) { - // Then add it as well - $stubMessage .= sprintf(" Message: %s", $message); - } // END - if + /** + * Setter for image instance + * + * @param $imageInstance An instance of an image + * @return void + */ + public final function setImageInstance (BaseImage $imageInstance) { + $this->imageInstance = $imageInstance; + } - // Debug instance is there? - if (!is_null($this->getDebugInstance())) { - // Output stub message - $this->debugOutput($stubMessage); - } else { - // Trigger an error - trigger_error($stubMessage . "
\n"); - } + /** + * Getter for image instance + * + * @return $imageInstance An instance of an image + */ + public final function getImageInstance () { + return $this->imageInstance; } /** - * Outputs a debug backtrace and stops further script execution + * Setter for stacker instance * - * @param $message An optional message to output + * @param $stackerInstance An instance of an stacker * @return void */ - public function debugBackTrace ($message = '') { - // Sorry, there is no other way getting this nice backtrace - if (!empty($message)) { - // Output message - printf("Message: %s
\n", $message); - } // END - if + public final function setStackerInstance (Stackable $stackerInstance) { + $this->stackerInstance = $stackerInstance; + } - print("
\n");
-		debug_print_backtrace();
-		print("
"); - exit(); + /** + * Getter for stacker instance + * + * @return $stackerInstance An instance of an stacker + */ + public final function getStackerInstance () { + return $this->stackerInstance; } /** - * Outputs a debug message wether to debug instance (should be set!) or dies with or pints the message + * Setter for compressor instance * - * @param $message Message we shall send out... - * @param $doPrint Wether we shall print or die here which first is the default + * @param $compressorInstance An instance of an compressor * @return void */ - public function debugOutput ($message, $doPrint = true) { - // Get debug instance - $debugInstance = $this->getDebugInstance(); + public final function setCompressorInstance (Compressor $compressorInstance) { + $this->compressorInstance = $compressorInstance; + } - // Is the debug instance there? - if (is_object($debugInstance)) { - // Use debug output handler - $debugInstance->output($message); + /** + * Getter for compressor instance + * + * @return $compressorInstance An instance of an compressor + */ + public final function getCompressorInstance () { + return $this->compressorInstance; + } - if ($doPrint === false) { - // Die here if not printed - die(); - } // END - if - } else { - // Put directly out - if ($doPrint === true) { - print($message); - } else { - // DO NOT REWRITE THIS TO app_die() !!! - die($message); - } - } + /** + * Setter for Parseable instance + * + * @param $parserInstance An instance of an Parseable + * @return void + */ + public final function setParserInstance (Parseable $parserInstance) { + $this->parserInstance = $parserInstance; } /** - * Converts e.g. a command from URL to a valid class by keeping out bad characters + * Getter for Parseable instance * - * @param $str The string, what ever it is needs to be converted - * @return $className Generated class name + * @return $parserInstance An instance of an Parseable */ - public function convertToClassName ($str) { - // Init class name - $className = ''; + public final function getParserInstance () { + return $this->parserInstance; + } - // Convert all dashes in underscores - $str = $this->convertDashesToUnderscores($str); + /** + * Setter for ProtocolHandler instance + * + * @param $protocolInstance An instance of an ProtocolHandler + * @return void + */ + public final function setProtocolInstance (ProtocolHandler $protocolInstance = NULL) { + $this->protocolInstance = $protocolInstance; + } - // Now use that underscores to get classname parts for hungarian style - foreach (explode('_', $str) as $strPart) { - // Make the class name part lower case and first upper case - $className .= ucfirst(strtolower($strPart)); - } // END - foreach + /** + * Getter for ProtocolHandler instance + * + * @return $protocolInstance An instance of an ProtocolHandler + */ + public final function getProtocolInstance () { + return $this->protocolInstance; + } - // Return class name - return $className; + /** + * Setter for DatabaseWrapper instance + * + * @param $wrapperInstance An instance of an DatabaseWrapper + * @return void + */ + public final function setWrapperInstance (DatabaseWrapper $wrapperInstance) { + $this->wrapperInstance = $wrapperInstance; } /** - * Converts dashes to underscores, e.g. useable for configuration entries + * Getter for DatabaseWrapper instance * - * @param $str The string with maybe dashes inside - * @return $str The converted string with no dashed, but underscores + * @return $wrapperInstance An instance of an DatabaseWrapper */ - public final function convertDashesToUnderscores ($str) { - // Convert them all - $str = str_replace('-', '_', $str); + public final function getWrapperInstance () { + return $this->wrapperInstance; + } - // Return converted string - return $str; + /** + * Setter for socket resource + * + * @param $socketResource A valid socket resource + * @return void + */ + public final function setSocketResource ($socketResource) { + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput($this->__toString() . '::' . __FUNCTION__ . ': socketResource=' . $socketResource . ',previous[' . gettype($this->socketResource) . ']=' . $this->socketResource); + $this->socketResource = $socketResource; } /** - * Marks up the code by adding e.g. line numbers + * Getter for socket resource * - * @param $phpCode Unmarked PHP code - * @return $markedCode Marked PHP code + * @return $socketResource A valid socket resource */ - public function markupCode ($phpCode) { - // Init marked code - $markedCode = ''; + public final function getSocketResource () { + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput($this->__toString() . '::' . __FUNCTION__ . ': socketResource[' . gettype($this->socketResource) . ']=' . $this->socketResource); + return $this->socketResource; + } - // Get last error - $errorArray = error_get_last(); + /** + * Setter for helper instance + * + * @param $helperInstance An instance of a helper class + * @return void + */ + protected final function setHelperInstance (Helper $helperInstance) { + $this->helperInstance = $helperInstance; + } - // Init the code with error message - if (is_array($errorArray)) { - // Get error infos - $markedCode = sprintf("
File: %s, Line: %s, Message: %s, Type: %s
", - basename($errorArray['file']), - $errorArray['line'], - $errorArray['message'], - $errorArray['type'] - ); - } // END - if + /** + * Getter for helper instance + * + * @return $helperInstance An instance of a helper class + */ + public final function getHelperInstance () { + return $this->helperInstance; + } - // Add line number to the code - foreach (explode("\n", $phpCode) as $lineNo => $code) { - // Add line numbers - $markedCode .= sprintf("%s: %s\n", - ($lineNo + 1), - htmlentities($code, ENT_QUOTES) - ); - } // END - foreach + /** + * Setter for a Sourceable instance + * + * @param $sourceInstance The Sourceable instance + * @return void + */ + protected final function setSourceInstance (Sourceable $sourceInstance) { + $this->sourceInstance = $sourceInstance; + } - // Return the code - return $markedCode; + /** + * Getter for a Sourceable instance + * + * @return $sourceInstance The Sourceable instance + */ + protected final function getSourceInstance () { + return $this->sourceInstance; } /** - * Filter a given GMT timestamp (non Uni* stamp!) to make it look more - * beatiful for web-based front-ends. If null is given a message id - * null_timestamp will be resolved and returned. + * Getter for a InputStream instance * - * @param $timestamp Timestamp to prepare (filter) for display - * @return $readable A readable timestamp + * @param $inputStreamInstance The InputStream instance */ - public function doFilterFormatTimestamp ($timestamp) { - // Default value to return - $readable = '???'; + protected final function getInputStreamInstance () { + return $this->inputStreamInstance; + } - // Is the timestamp null? - if (is_null($timestamp)) { - // Get a message string + /** + * Setter for a InputStream instance + * + * @param $inputStreamInstance The InputStream instance + * @return void + */ + protected final function setInputStreamInstance (InputStream $inputStreamInstance) { + $this->inputStreamInstance = $inputStreamInstance; + } + + /** + * Getter for a OutputStream instance + * + * @param $outputStreamInstance The OutputStream instance + */ + protected final function getOutputStreamInstance () { + return $this->outputStreamInstance; + } + + /** + * Setter for a OutputStream instance + * + * @param $outputStreamInstance The OutputStream instance + * @return void + */ + protected final function setOutputStreamInstance (OutputStream $outputStreamInstance) { + $this->outputStreamInstance = $outputStreamInstance; + } + + /** + * Setter for handler instance + * + * @param $handlerInstance An instance of a Handleable class + * @return void + */ + protected final function setHandlerInstance (Handleable $handlerInstance) { + $this->handlerInstance = $handlerInstance; + } + + /** + * Getter for handler instance + * + * @return $handlerInstance A Networkable instance + */ + protected final function getHandlerInstance () { + return $this->handlerInstance; + } + + /** + * Setter for visitor instance + * + * @param $visitorInstance A Visitor instance + * @return void + */ + protected final function setVisitorInstance (Visitor $visitorInstance) { + $this->visitorInstance = $visitorInstance; + } + + /** + * Getter for visitor instance + * + * @return $visitorInstance A Visitor instance + */ + protected final function getVisitorInstance () { + return $this->visitorInstance; + } + + /** + * Setter for DHT instance + * + * @param $dhtInstance A Distributable instance + * @return void + */ + protected final function setDhtInstance (Distributable $dhtInstance) { + $this->dhtInstance = $dhtInstance; + } + + /** + * Getter for DHT instance + * + * @return $dhtInstance A Distributable instance + */ + protected final function getDhtInstance () { + return $this->dhtInstance; + } + + /** + * Setter for raw package Data + * + * @param $packageData Raw package Data + * @return void + */ + public final function setPackageData (array $packageData) { + $this->packageData = $packageData; + } + + /** + * Getter for raw package Data + * + * @return $packageData Raw package Data + */ + public function getPackageData () { + return $this->packageData; + } + + + /** + * Setter for Iterator instance + * + * @param $iteratorInstance An instance of an Iterator + * @return void + */ + protected final function setIteratorInstance (Iterator $iteratorInstance) { + $this->iteratorInstance = $iteratorInstance; + } + + /** + * Getter for Iterator instance + * + * @return $iteratorInstance An instance of an Iterator + */ + public final function getIteratorInstance () { + return $this->iteratorInstance; + } + + /** + * Setter for InputOutputPointer instance + * + * @param $pointerInstance An instance of an InputOutputPointer class + * @return void + */ + protected final function setPointerInstance (InputOutputPointer $pointerInstance) { + $this->pointerInstance = $pointerInstance; + } + + /** + * Getter for InputOutputPointer instance + * + * @return $pointerInstance An instance of an InputOutputPointer class + */ + public final function getPointerInstance () { + return $this->pointerInstance; + } + + /** + * Setter for Indexable instance + * + * @param $indexInstance An instance of an Indexable class + * @return void + */ + protected final function setIndexInstance (Indexable $indexInstance) { + $this->indexInstance = $indexInstance; + } + + /** + * Getter for Indexable instance + * + * @return $indexInstance An instance of an Indexable class + */ + public final function getIndexInstance () { + return $this->indexInstance; + } + + /** + * Checks whether an object equals this object. You should overwrite this + * method to implement own equality checks + * + * @param $objectInstance An instance of a FrameworkInterface object + * @return $equals Whether both objects equals + */ + public function equals (FrameworkInterface $objectInstance) { + // Now test it + $equals = (( + $this->__toString() == $objectInstance->__toString() + ) && ( + $this->hashCode() == $objectInstance->hashCode() + )); + + // Return the result + return $equals; + } + + /** + * Generates a generic hash code of this class. You should really overwrite + * this method with your own hash code generator code. But keep KISS in mind. + * + * @return $hashCode A generic hash code respresenting this whole class + */ + public function hashCode () { + // Simple hash code + return crc32($this->__toString()); + } + + /** + * Formats computer generated price values into human-understandable formats + * with thousand and decimal separators. + * + * @param $value The in computer format value for a price + * @param $currency The currency symbol (use HTML-valid characters!) + * @param $decNum Number of decimals after commata + * @return $price The for the current language formated price string + * @throws MissingDecimalsThousandsSeparatorException If decimals or + * thousands separator + * is missing + */ + public function formatCurrency ($value, $currency = '€', $decNum = 2) { + // Are all required attriutes set? + if ((!isset($this->decimals)) || (!isset($this->thousands))) { + // Throw an exception + throw new MissingDecimalsThousandsSeparatorException($this, self::EXCEPTION_ATTRIBUTES_ARE_MISSING); + } // END - if + + // Cast the number + $value = (float) $value; + + // Reformat the US number + $price = number_format($value, $decNum, $this->decimals, $this->thousands) . $currency; + + // Return as string... + return $price; + } + + /** + * Appends a trailing slash to a string + * + * @param $str A string (maybe) without trailing slash + * @return $str A string with an auto-appended trailing slash + */ + public final function addMissingTrailingSlash ($str) { + // Is there a trailing slash? + if (substr($str, -1, 1) != '/') { + $str .= '/'; + } // END - if + + // Return string with trailing slash + return $str; + } + + /** + * Prepare the template engine (WebTemplateEngine by default) for a given + * application helper instance (ApplicationHelper by default). + * + * @param $applicationInstance An application helper instance or + * null if we shall use the default + * @return $templateInstance The template engine instance + * @throws NullPointerException If the discovered application + * instance is still null + */ + protected function prepareTemplateInstance (ManageableApplication $applicationInstance = NULL) { + // Is the application instance set? + if (is_null($applicationInstance)) { + // Get the current instance + $applicationInstance = $this->getApplicationInstance(); + + // Still null? + if (is_null($applicationInstance)) { + // Thrown an exception + throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER); + } // END - if + } // END - if + + // Initialize the template engine + $templateInstance = ObjectFactory::createObjectByConfiguredName('web_template_class'); + + // Return the prepared instance + return $templateInstance; + } + + /** + * Debugs this instance by putting out it's full content + * + * @param $message Optional message to show in debug output + * @return void + */ + public final function debugInstance ($message = '') { + // Restore the error handler to avoid trouble with missing array elements or undeclared variables + restore_error_handler(); + + // Init content + $content = ''; + + // Is a message set? + if (!empty($message)) { + // Construct message + $content = sprintf('
Message: %s
' . PHP_EOL, $message); + } // END - if + + // Generate the output + $content .= sprintf('
%s
', + trim( + htmlentities( + print_r($this, TRUE) + ) + ) + ); + + // Output it + ApplicationEntryPoint::app_exit(sprintf('
%s debug output:
%s
Loaded includes:
%s
', + $this->__toString(), + $content, + ClassLoader::getSelfInstance()->getPrintableIncludeList() + )); + } + + /** + * Replaces control characters with printable output + * + * @param $str String with control characters + * @return $str Replaced string + */ + protected function replaceControlCharacters ($str) { + // Replace them + $str = str_replace( + chr(13), '[r]', str_replace( + chr(10), '[n]', str_replace( + chr(9) , '[t]', + $str + ))); + + // Return it + return $str; + } + + /** + * Output a partial stub message for the caller method + * + * @param $message An optional message to display + * @return void + */ + protected function partialStub ($message = '') { + // Get the backtrace + $backtrace = debug_backtrace(); + + // Generate the class::method string + $methodName = 'UnknownClass->unknownMethod'; + if ((isset($backtrace[1]['class'])) && (isset($backtrace[1]['function']))) { + $methodName = $backtrace[1]['class'] . '->' . $backtrace[1]['function']; + } // END - if + + // Construct the full message + $stubMessage = sprintf('[%s:] Partial stub!', + $methodName + ); + + // Is the extra message given? + if (!empty($message)) { + // Then add it as well + $stubMessage .= ' Message: ' . $message; + } // END - if + + // Debug instance is there? + if (!is_null($this->getDebugInstance())) { + // Output stub message + self::createDebugInstance(__CLASS__)->debugOutput($stubMessage); + } else { + // Trigger an error + trigger_error($stubMessage); + exit; + } + } + + /** + * Outputs a debug backtrace and stops further script execution + * + * @param $message An optional message to output + * @param $doExit Whether exit the program (TRUE is default) + * @return void + */ + public function debugBackTrace ($message = '', $doExit = TRUE) { + // Sorry, there is no other way getting this nice backtrace + if (!empty($message)) { + // Output message + printf('Message: %s
' . chr(10), $message); + } // END - if + + print('
');
+		debug_print_backtrace();
+		print('
'); + + // Exit program? + if ($doExit === TRUE) { + exit(); + } // END - if + } + + /** + * Creates an instance of a debugger instance + * + * @param $className Name of the class (currently unsupported) + * @return $debugInstance An instance of a debugger class + */ + public final static function createDebugInstance ($className) { + // Is the instance set? + if (!Registry::getRegistry()->instanceExists('debug')) { + // Init debug instance + $debugInstance = NULL; + + // Try it + try { + // Get a debugger instance + $debugInstance = DebugMiddleware::createDebugMiddleware(FrameworkConfiguration::getSelfInstance()->getConfigEntry('debug_class')); + } catch (NullPointerException $e) { + // Didn't work, no instance there + exit('Cannot create debugInstance! Exception=' . $e->__toString() . ', message=' . $e->getMessage()); + } + + // Empty string should be ignored and used for testing the middleware + DebugMiddleware::getSelfInstance()->output(''); + + // Set it in its own class. This will set it in the registry + $debugInstance->setDebugInstance($debugInstance); + } else { + // Get instance from registry + $debugInstance = Registry::getRegistry()->getDebugInstance(); + } + + // Return it + return $debugInstance; + } + + /** + * Simple output of a message with line-break + * + * @param $message Message to output + * @return void + */ + public function outputLine ($message) { + // Simply output it + print($message . PHP_EOL); + } + + /** + * Outputs a debug message whether to debug instance (should be set!) or + * dies with or ptints the message. Do NEVER EVER rewrite the exit() call to + * ApplicationEntryPoint::app_exit(), this would cause an endless loop. + * + * @param $message Message we shall send out... + * @param $doPrint Whether print or die here (default: print) + * @paran $stripTags Whether to strip tags (default: FALSE) + * @return void + */ + public function debugOutput ($message, $doPrint = TRUE, $stripTags = FALSE) { + // Set debug instance to NULL + $debugInstance = NULL; + + // Try it: + try { + // Get debug instance + $debugInstance = $this->getDebugInstance(); + } catch (NullPointerException $e) { + // The debug instance is not set (yet) + } + + // Is the debug instance there? + if (is_object($debugInstance)) { + // Use debug output handler + $debugInstance->output($message, $stripTags); + + if ($doPrint === FALSE) { + // Die here if not printed + exit(); + } // END - if + } else { + // Are debug times enabled? + if ($this->getConfigInstance()->getConfigEntry('debug_output_timings') == 'Y') { + // Prepent it + $message = $this->getPrintableExecutionTime() . $message; + } // END - if + + // Put directly out + if ($doPrint === TRUE) { + // Print message + $this->outputLine($message); + } else { + // Die here + exit($message); + } + } + } + + /** + * Converts e.g. a command from URL to a valid class by keeping out bad characters + * + * @param $str The string, what ever it is needs to be converted + * @return $className Generated class name + */ + public function convertToClassName ($str) { + // Init class name + $className = ''; + + // Convert all dashes in underscores + $str = $this->convertDashesToUnderscores($str); + + // Now use that underscores to get classname parts for hungarian style + foreach (explode('_', $str) as $strPart) { + // Make the class name part lower case and first upper case + $className .= ucfirst(strtolower($strPart)); + } // END - foreach + + // Return class name + return $className; + } + + /** + * Converts dashes to underscores, e.g. useable for configuration entries + * + * @param $str The string with maybe dashes inside + * @return $str The converted string with no dashed, but underscores + */ + public final function convertDashesToUnderscores ($str) { + // Convert them all + $str = str_replace('-', '_', $str); + + // Return converted string + return $str; + } + + /** + * Marks up the code by adding e.g. line numbers + * + * @param $phpCode Unmarked PHP code + * @return $markedCode Marked PHP code + */ + public function markupCode ($phpCode) { + // Init marked code + $markedCode = ''; + + // Get last error + $errorArray = error_get_last(); + + // Init the code with error message + if (is_array($errorArray)) { + // Get error infos + $markedCode = sprintf('
File: %s, Line: %s, Message: %s, Type: %s
', + basename($errorArray['file']), + $errorArray['line'], + $errorArray['message'], + $errorArray['type'] + ); + } // END - if + + // Add line number to the code + foreach (explode(chr(10), $phpCode) as $lineNo => $code) { + // Add line numbers + $markedCode .= sprintf('%s: %s' . chr(10), + ($lineNo + 1), + htmlentities($code, ENT_QUOTES) + ); + } // END - foreach + + // Return the code + return $markedCode; + } + + /** + * Filter a given GMT timestamp (non Uni* stamp!) to make it look more + * beatiful for web-based front-ends. If null is given a message id + * null_timestamp will be resolved and returned. + * + * @param $timestamp Timestamp to prepare (filter) for display + * @return $readable A readable timestamp + */ + public function doFilterFormatTimestamp ($timestamp) { + // Default value to return + $readable = '???'; + + // Is the timestamp null? + if (is_null($timestamp)) { + // Get a message string $readable = $this->getLanguageInstance()->getMessage('null_timestamp'); } else { - switch ($this->getLanguageInstance()->getLanguageCode()) { - case 'de': // German format is a bit different to default - // Split the GMT stamp up - $dateTime = explode(' ', $timestamp ); - $dateArray = explode('-', $dateTime[0]); - $timeArray = explode(':', $dateTime[1]); + switch ($this->getLanguageInstance()->getLanguageCode()) { + case 'de': // German format is a bit different to default + // Split the GMT stamp up + $dateTime = explode(' ', $timestamp ); + $dateArray = explode('-', $dateTime[0]); + $timeArray = explode(':', $dateTime[1]); + + // Construct the timestamp + $readable = sprintf($this->getConfigInstance()->getConfigEntry('german_date_time'), + $dateArray[0], + $dateArray[1], + $dateArray[2], + $timeArray[0], + $timeArray[1], + $timeArray[2] + ); + break; + + default: // Default is pass-through + $readable = $timestamp; + break; + } // END - switch + } + + // Return the stamp + return $readable; + } + + /** + * Filter a given number into a localized number + * + * @param $value The raw value from e.g. database + * @return $localized Localized value + */ + public function doFilterFormatNumber ($value) { + // Generate it from config and localize dependencies + switch ($this->getLanguageInstance()->getLanguageCode()) { + case 'de': // German format is a bit different to default + $localized = number_format($value, $this->getConfigInstance()->getConfigEntry('decimals'), ',', '.'); + break; + + default: // US, etc. + $localized = number_format($value, $this->getConfigInstance()->getConfigEntry('decimals'), '.', ','); + break; + } // END - switch + + // Return it + return $localized; + } + + /** + * "Getter" for databse entry + * + * @return $entry An array with database entries + * @throws NullPointerException If the database result is not found + * @throws InvalidDatabaseResultException If the database result is invalid + */ + protected final function getDatabaseEntry () { + // Is there an instance? + if (is_null($this->getResultInstance())) { + // Throw an exception here + throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER); + } // END - if + + // Rewind it + $this->getResultInstance()->rewind(); + + // Do we have an entry? + if ($this->getResultInstance()->valid() === FALSE) { + throw new InvalidDatabaseResultException(array($this, $this->getResultInstance()), DatabaseResult::EXCEPTION_INVALID_DATABASE_RESULT); + } // END - if + + // Get next entry + $this->getResultInstance()->next(); + + // Fetch it + $entry = $this->getResultInstance()->current(); + + // And return it + return $entry; + } + + /** + * Getter for field name + * + * @param $fieldName Field name which we shall get + * @return $fieldValue Field value from the user + * @throws NullPointerException If the result instance is null + */ + public final function getField ($fieldName) { + // Default field value + $fieldValue = NULL; + + // Get result instance + $resultInstance = $this->getResultInstance(); + + // Is this instance null? + if (is_null($resultInstance)) { + // Then the user instance is no longer valid (expired cookies?) + throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER); + } // END - if + + // Get current array + $fieldArray = $resultInstance->current(); + //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput($fieldName.':
'.print_r($fieldArray, TRUE).'
'); + + // Convert dashes to underscore + $fieldName = $this->convertDashesToUnderscores($fieldName); + + // Does the field exist? + if (isset($fieldArray[$fieldName])) { + // Get it + $fieldValue = $fieldArray[$fieldName]; + } else { + // Missing field entry, may require debugging + self::createDebugInstance(__CLASS__)->debugOutput($this->__toString() . ':fieldname=' . $fieldName . ' not found!'); + } - // Construct the timestamp - $readable = sprintf($this->getConfigInstance()->getConfigEntry('german_date_time'), - $dateArray[0], - $dateArray[1], - $dateArray[2], - $timeArray[0], - $timeArray[1], - $timeArray[2] - ); - break; + // Return it + return $fieldValue; + } - default: // Default is pass-through - $readable = $timestamp; - break; - } // END - switch + /** + * Flushs all pending updates to the database layer + * + * @return void + */ + public function flushPendingUpdates () { + // Get result instance + $resultInstance = $this->getResultInstance(); + + // Do we have data to update? + if ((is_object($resultInstance)) && ($resultInstance->ifDataNeedsFlush())) { + // Get wrapper class name config entry + $configEntry = $resultInstance->getUpdateInstance()->getWrapperConfigEntry(); + + // Create object instance + $wrapperInstance = ObjectFactory::createObjectByConfiguredName($configEntry); + + // Yes, then send the whole result to the database layer + $wrapperInstance->doUpdateByResult($this->getResultInstance()); + } // END - if + } + + /** + * Outputs a deprecation warning to the developer. + * + * @param $message The message we shall output to the developer + * @return void + * @todo Write a logging mechanism for productive mode + */ + public function deprecationWarning ($message) { + // Is developer mode active? + if (defined('DEVELOPER')) { + // Debug instance is there? + if (!is_null($this->getDebugInstance())) { + // Output stub message + self::createDebugInstance(__CLASS__)->debugOutput($message); + } else { + // Trigger an error + trigger_error($message . "
\n"); + exit; + } + } else { + // @TODO Finish this part! + $this->partialStub('Developer mode inactive. Message:' . $message); + } + } + + /** + * Checks whether the given PHP extension is loaded + * + * @param $phpExtension The PHP extension we shall check + * @return $isLoaded Whether the PHP extension is loaded + */ + public final function isPhpExtensionLoaded ($phpExtension) { + // Is it loaded? + $isLoaded = in_array($phpExtension, get_loaded_extensions()); + + // Return result + return $isLoaded; + } + + /** + * "Getter" as a time() replacement but with milliseconds. You should use this + * method instead of the encapsulated getimeofday() function. + * + * @return $milliTime Timestamp with milliseconds + */ + public function getMilliTime () { + // Get the time of day as float + $milliTime = gettimeofday(TRUE); + + // Return it + return $milliTime; + } + + /** + * Idles (sleeps) for given milliseconds + * + * @return $hasSlept Whether it goes fine + */ + public function idle ($milliSeconds) { + // Sleep is fine by default + $hasSlept = TRUE; + + // Idle so long with found function + if (function_exists('time_sleep_until')) { + // Get current time and add idle time + $sleepUntil = $this->getMilliTime() + abs($milliSeconds) / 1000; + + // New PHP 5.1.0 function found, ignore errors + $hasSlept = @time_sleep_until($sleepUntil); + } else { + /* + * My Sun station doesn't have that function even with latest PHP + * package. :( + */ + usleep($milliSeconds * 1000); + } + + // Return result + return $hasSlept; + } + /** + * Converts a hexadecimal string, even with negative sign as first string to + * a decimal number using BC functions. + * + * This work is based on comment #86673 on php.net documentation page at: + * + * + * @param $hex Hexadecimal string + * @return $dec Decimal number + */ + protected function hex2dec ($hex) { + // Convert to all lower-case + $hex = strtolower($hex); + + // Detect sign (negative/positive numbers) + $sign = ''; + if (substr($hex, 0, 1) == '-') { + $sign = '-'; + $hex = substr($hex, 1); + } // END - if + + // Decode the hexadecimal string into a decimal number + $dec = 0; + for ($i = strlen($hex) - 1, $e = 1; $i >= 0; $i--, $e = bcmul($e, 16)) { + $factor = self::$hexdec[substr($hex, $i, 1)]; + $dec = bcadd($dec, bcmul($factor, $e)); + } // END - for + + // Return the decimal number + return $sign . $dec; + } + + /** + * Converts even very large decimal numbers, also signed, to a hexadecimal + * string. + * + * This work is based on comment #97756 on php.net documentation page at: + * + * + * @param $dec Decimal number, even with negative sign + * @param $maxLength Optional maximum length of the string + * @return $hex Hexadecimal string + */ + protected function dec2hex ($dec, $maxLength = 0) { + // maxLength can be zero or devideable by 2 + assert(($maxLength == 0) || (($maxLength % 2) == 0)); + + // Detect sign (negative/positive numbers) + $sign = ''; + if ($dec < 0) { + $sign = '-'; + $dec = abs($dec); + } // END - if + + // Encode the decimal number into a hexadecimal string + $hex = ''; + do { + $hex = self::$dechex[($dec % (2 ^ 4))] . $hex; + $dec /= (2 ^ 4); + } while ($dec >= 1); + + /* + * Leading zeros are required for hex-decimal "numbers". In some + * situations more leading zeros are wanted, so check for both + * conditions. + */ + if ($maxLength > 0) { + // Prepend more zeros + $hex = str_pad($hex, $maxLength, '0', STR_PAD_LEFT); + } elseif ((strlen($hex) % 2) != 0) { + // Only make string's length dividable by 2 + $hex = '0' . $hex; } - // Return the stamp - return $readable; + // Return the hexadecimal string + return $sign . $hex; + } + + /** + * Converts a ASCII string (0 to 255) into a decimal number. + * + * @param $asc The ASCII string to be converted + * @return $dec Decimal number + */ + protected function asc2dec ($asc) { + // Convert it into a hexadecimal number + $hex = bin2hex($asc); + + // And back into a decimal number + $dec = $this->hex2dec($hex); + + // Return it + return $dec; + } + + /** + * Converts a decimal number into an ASCII string. + * + * @param $dec Decimal number + * @return $asc An ASCII string + */ + protected function dec2asc ($dec) { + // First convert the number into a hexadecimal string + $hex = $this->dec2hex($dec); + + // Then convert it into the ASCII string + $asc = $this->hex2asc($hex); + + // Return it + return $asc; + } + + /** + * Converts a hexadecimal number into an ASCII string. Negative numbers + * are not allowed. + * + * @param $hex Hexadecimal string + * @return $asc An ASCII string + */ + protected function hex2asc ($hex) { + // Check for length, it must be devideable by 2 + //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('hex='.$hex); + assert((strlen($hex) % 2) == 0); + + // Walk the string + $asc = ''; + for ($idx = 0; $idx < strlen($hex); $idx+=2) { + // Get the decimal number of the chunk + $part = hexdec(substr($hex, $idx, 2)); + + // Add it to the final string + $asc .= chr($part); + } // END - for + + // Return the final string + return $asc; + } + + /** + * Checks whether the given encoded data was encoded with Base64 + * + * @param $encodedData Encoded data we shall check + * @return $isBase64 Whether the encoded data is Base64 + */ + protected function isBase64Encoded ($encodedData) { + // Determine it + $isBase64 = (@base64_decode($encodedData, TRUE) !== FALSE); + + // Return it + return $isBase64; } /** - * Filter a given number into a localized number + * "Getter" to get response/request type from analysis of the system. * - * @param $value The raw value from e.g. database - * @return $localized Localized value + * @return $responseType Analyzed response type */ - public function doFilterFormatNumber ($value) { - // Generate it from config and localize dependencies - switch ($this->getLanguageInstance()->getLanguageCode()) { - case 'de': // German format is a bit different to default - $localized = number_format($value, $this->getConfigInstance()->getConfigEntry('decimals'), ',', '.'); - break; + protected function getResponseTypeFromSystem () { + // Default is console + $responseType = 'console'; - default: // US, etc. - $localized = number_format($value, $this->getConfigInstance()->getConfigEntry('decimals'), '.', ','); - break; - } // END - switch + // Is 'HTTP_HOST' set? + if (isset($_SERVER['HTTP_HOST'])) { + // Then it is a HTTP response/request + $responseType = 'http'; + } // END - if // Return it - return $localized; + return $responseType; } /** - * "Getter" for databse entry + * Gets a cache key from Criteria instance * - * @return $entry An array with database entries - * @throws NullPointerException If the database result is not found - * @throws InvalidDatabaseResultException If the database result is invalid + * @param $criteriaInstance An instance of a Criteria class + * @param $onlyKeys Only use these keys for a cache key + * @return $cacheKey A cache key suitable for lookup/storage purposes */ - protected final function getDatabaseEntry () { - // Is there an instance? - if (is_null($this->getResultInstance())) { - // Throw an exception here - throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER); - } // END - if + protected function getCacheKeyByCriteria (Criteria $criteriaInstance, array $onlyKeys = array()) { + // Generate it + $cacheKey = sprintf('%s@%s', + $this->__toString(), + $criteriaInstance->getCacheKey($onlyKeys) + ); - // Rewind it - $this->getResultInstance()->rewind(); + // And return it + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput($this->__toString() . ': cacheKey=' . $cacheKey); + return $cacheKey; + } - // Do we have an entry? - if ($this->getResultInstance()->valid() === false) { - throw new InvalidDatabaseResultException(array($this, $this->getResultInstance()), DatabaseResult::EXCEPTION_INVALID_DATABASE_RESULT); - } // END - if + /** + * Getter for startup time in miliseconds + * + * @return $startupTime Startup time in miliseconds + */ + protected function getStartupTime () { + return self::$startupTime; + } - // Get next entry - $this->getResultInstance()->next(); + /** + * "Getter" for a printable currently execution time in nice braces + * + * @return $executionTime Current execution time in nice braces + */ + protected function getPrintableExecutionTime () { + // Caculate the execution time + $executionTime = microtime(TRUE) - $this->getStartupTime(); - // Fetch it - $entry = $this->getResultInstance()->current(); + // Pack it in nice braces + $executionTime = sprintf('[ %01.5f ] ', $executionTime); // And return it - return $entry; + return $executionTime; } /** - * Getter for field name + * Hashes a given string with a simple but stronger hash function (no salt) + * and hex-encode it. * - * @param $fieldName Field name which we shall get - * @return $fieldValue Field value from the user - * @throws NullPointerException If the result instance is null + * @param $str The string to be hashed + * @return $hash The hash from string $str */ - public final function getField ($fieldName) { - // Default field value - $fieldValue = null; - - // Get result instance - $resultInstance = $this->getResultInstance(); - - // Is this instance null? - if (is_null($resultInstance)) { - // Then the user instance is no longer valid (expired cookies?) - throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER); - } // END - if + public static final function hash ($str) { + // Hash given string with (better secure) hasher + $hash = bin2hex(mhash(MHASH_SHA256, $str)); - // Get current array - $fieldArray = $resultInstance->current(); - //* DEBUG: */ $this->debugOutput($fieldName.':
'.print_r($fieldArray, true).'
'); + // Return it + return $hash; + } - // Does the field exist? - if (isset($fieldArray[$fieldName])) { - // Get it - $fieldValue = $fieldArray[$fieldName]; + /** + * "Getter" for length of hash() output. This will be "cached" to speed up + * things. + * + * @return $length Length of hash() output + */ + public static final function getHashLength () { + // Is it cashed? + if (is_null(self::$hashLength)) { + // No, then hash a string and save its length. + self::$hashLength = strlen(self::hash('abc123')); } // END - if // Return it - return $fieldValue; + return self::$hashLength; } /** - * Protected setter for user instance + * Checks whether the given number is really a number (only chars 0-9). * - * @param $userInstance An instance of a user class - * @return void + * @param $num A string consisting only chars between 0 and 9 + * @param $castValue Whether to cast the value to double. Do only use this to secure numbers from Requestable classes. + * @param $assertMismatch Whether to assert mismatches + * @return $ret The (hopefully) secured numbered value */ - protected final function setUserInstance (ManageableAccount $userInstance) { - $this->userInstance = $userInstance; + public function bigintval ($num, $castValue = TRUE, $assertMismatch = FALSE) { + // Filter all numbers out + $ret = preg_replace('/[^0123456789]/', '', $num); + + // Shall we cast? + if ($castValue === TRUE) { + // Cast to biggest numeric type + $ret = (double) $ret; + } // END - if + + // Assert only if requested + if ($assertMismatch === TRUE) { + // Has the whole value changed? + assert(('' . $ret . '' != '' . $num . '') && (!is_null($num))); + } // END - if + + // Return result + return $ret; } /** - * Getter for user instance + * Checks whether the given hexadecimal number is really a hex-number (only chars 0-9,a-f). * - * @return $userInstance An instance of a user class + * @param $num A string consisting only chars between 0 and 9 + * @param $assertMismatch Whether to assert mismatches + * @return $ret The (hopefully) secured hext-numbered value */ - public final function getUserInstance () { - return $this->userInstance; + public function hexval ($num, $assertMismatch = FALSE) { + // Filter all numbers out + $ret = preg_replace('/[^0123456789abcdefABCDEF]/', '', $num); + + // Assert only if requested + if ($assertMismatch === TRUE) { + // Has the whole value changed? + assert(('' . $ret . '' != '' . $num . '') && (!is_null($num))); + } // END - if + + // Return result + return $ret; } /** - * Setter for controller instance (this surely breaks a bit the MVC patterm) + * Checks whether start/end marker are set * - * @param $controllerInstance An instance of the controller - * @return void + * @param $data Data to be checked + * @return $isset Whether start/end marker are set */ - public final function setControllerInstance (Controller $controllerInstance) { - $this->controllerInstance = $controllerInstance; + public final function ifStartEndMarkersSet ($data) { + // Determine it + $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)); + + // ... and return it + return $isset; } /** - * Getter for controller instance (this surely breaks a bit the MVC patterm) + * Determines if an element is set in the generic array * - * @return $controllerInstance An instance of the controller + * @param $keyGroup Main group for the key + * @param $subGroup Sub group for the key + * @param $key Key to check + * @param $element Element to check + * @return $isset Whether the given key is set */ - public final function getControllerInstance () { - return $this->controllerInstance; - } + protected final function isGenericArrayElementSet ($keyGroup, $subGroup, $key, $element) { + // Debug message + //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element); + // Is it there? + $isset = isset($this->genericArray[$keyGroup][$subGroup][$key][$element]); + + // Return it + return $isset; + } /** - * Flushs all pending updates to the database layer + * Determines if a key is set in the generic array * - * @return void + * @param $keyGroup Main group for the key + * @param $subGroup Sub group for the key + * @param $key Key to check + * @return $isset Whether the given key is set */ - public function flushPendingUpdates () { - // Get result instance - $resultInstance = $this->getResultInstance(); - - // Do we have data to update? - if ((is_object($resultInstance)) && ($resultInstance->ifDataNeedsFlush())) { - // Get wrapper class name config entry - $configEntry = $resultInstance->getUpdateInstance()->getWrapperConfigEntry(); + protected final function isGenericArrayKeySet ($keyGroup, $subGroup, $key) { + // Debug message + //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key); - // Create object instance - $wrapperInstance = ObjectFactory::createObjectByConfiguredName($configEntry); + // Is it there? + $isset = isset($this->genericArray[$keyGroup][$subGroup][$key]); - // Yes, then send the whole result to the database layer - $wrapperInstance->doUpdateByResult($this->getResultInstance()); - } // END - if + // Return it + return $isset; } + /** - * Outputs a deprecation warning to the developer. + * Determines if a group is set in the generic array * - * @param $message The message we shall output to the developer - * @return void - * @todo Write a logging mechanism for productive mode + * @param $keyGroup Main group + * @param $subGroup Sub group + * @return $isset Whether the given group is set */ - public function deprecationWarning ($message) { - // Is developer mode active? - if (defined('DEVELOPER')) { - // Debug instance is there? - if (!is_null($this->getDebugInstance())) { - // Output stub message - $this->debugOutput($message); - } else { - // Trigger an error - trigger_error($message . "
\n"); - } - } else { - // @TODO Finish this part! - $this->partialStub('Developer mode inactive. Message:' . $message); - } + protected final function isGenericArrayGroupSet ($keyGroup, $subGroup) { + // Debug message + //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup); + + // Is it there? + $isset = isset($this->genericArray[$keyGroup][$subGroup]); + + // Return it + return $isset; } /** - * Checks wether the given PHP extension is loaded + * Getter for sub key group * - * @param $phpExtension The PHP extension we shall check - * @return $isLoaded Wether the PHP extension is loaded + * @param $keyGroup Main key group + * @param $subGroup Sub key group + * @return $array An array with all array elements */ - public final function isPhpExtensionLoaded ($phpExtension) { - // Is it loaded? - $isLoaded = in_array($phpExtension, get_loaded_extensions()); + protected final function getGenericSubArray ($keyGroup, $subGroup) { + // Is it there? + if (!$this->isGenericArrayGroupSet($keyGroup, $subGroup)) { + // No, then abort here + trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' not found.'); + exit; + } // END - if - // Return result - return $isLoaded; + // Debug message + //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',value=' . print_r($this->genericArray[$keyGroup][$subGroup], TRUE)); + + // Return it + return $this->genericArray[$keyGroup][$subGroup]; } /** - * Setter for RNG instance + * Unsets a given key in generic array * - * @param $rngInstance An instance of a random number generator (RNG) + * @param $keyGroup Main group for the key + * @param $subGroup Sub group for the key + * @param $key Key to unset * @return void */ - protected final function setRngInstance (RandomNumberGenerator $rngInstance) { - $this->rngInstance = $rngInstance; + protected final function unsetGenericArrayKey ($keyGroup, $subGroup, $key) { + // Debug message + //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key); + + // Remove it + unset($this->genericArray[$keyGroup][$subGroup][$key]); } /** - * Getter for RNG instance + * Unsets a given element in generic array * - * @return $rngInstance An instance of a random number generator (RNG) + * @param $keyGroup Main group for the key + * @param $subGroup Sub group for the key + * @param $key Key to unset + * @param $element Element to unset + * @return void */ - public final function getRngInstance () { - return $this->rngInstance; + protected final function unsetGenericArrayElement ($keyGroup, $subGroup, $key, $element) { + // Debug message + //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element); + + // Remove it + unset($this->genericArray[$keyGroup][$subGroup][$key][$element]); } /** - * Setter for Cryptable instance + * Append a string to a given generic array key * - * @param $cryptoInstance An instance of a Cryptable class + * @param $keyGroup Main group for the key + * @param $subGroup Sub group for the key + * @param $key Key to unset + * @param $value Value to add/append * @return void */ - protected final function setCryptoInstance (Cryptable $cryptoInstance) { - $this->cryptoInstance = $cryptoInstance; + protected final function appendStringToGenericArrayKey ($keyGroup, $subGroup, $key, $value, $appendGlue = '') { + // Debug message + //* 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); + + // Is it already there? + if ($this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) { + // Append it + $this->genericArray[$keyGroup][$subGroup][$key] .= $appendGlue . (string) $value; + } else { + // Add it + $this->genericArray[$keyGroup][$subGroup][$key] = (string) $value; + } } /** - * Getter for Cryptable instance + * Append a string to a given generic array element * - * @return $cryptoInstance An instance of a Cryptable class + * @param $keyGroup Main group for the key + * @param $subGroup Sub group for the key + * @param $key Key to unset + * @param $element Element to check + * @param $value Value to add/append + * @return void */ - public final function getCryptoInstance () { - return $this->cryptoInstance; + protected final function appendStringToGenericArrayElement ($keyGroup, $subGroup, $key, $element, $value, $appendGlue = '') { + // Debug message + //* 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); + + // Is it already there? + if ($this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element)) { + // Append it + $this->genericArray[$keyGroup][$subGroup][$key][$element] .= $appendGlue . (string) $value; + } else { + // Add it + $this->genericArray[$keyGroup][$subGroup][$key][$element] = (string) $value; + } } /** - * Setter for Iterator instance + * Initializes given generic array group * - * @param $iteratorInstance An instance of an Iterator + * @param $keyGroup Main group for the key + * @param $subGroup Sub group for the key + * @param $key Key to use + * @param $forceInit Optionally force initialization * @return void */ - protected final function setIteratorInstance (Iterator $iteratorInstance) { - $this->iteratorInstance = $iteratorInstance; + protected final function initGenericArrayGroup ($keyGroup, $subGroup, $forceInit = FALSE) { + // Debug message + //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',forceInit=' . intval($forceInit)); + + // Is it already set? + if (($forceInit === FALSE) && ($this->isGenericArrayGroupSet($keyGroup, $subGroup))) { + // Already initialized + trigger_error(__METHOD__ . ':keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' already initialized.'); + exit; + } // END - if + + // Initialize it + $this->genericArray[$keyGroup][$subGroup] = array(); } /** - * Getter for Iterator instance + * Initializes given generic array key * - * @return $iteratorInstance An instance of an Iterator + * @param $keyGroup Main group for the key + * @param $subGroup Sub group for the key + * @param $key Key to use + * @param $forceInit Optionally force initialization + * @return void */ - public final function getIteratorInstance () { - return $this->iteratorInstance; + protected final function initGenericArrayKey ($keyGroup, $subGroup, $key, $forceInit = FALSE) { + // Debug message + //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',forceInit=' . intval($forceInit)); + + // Is it already set? + if (($forceInit === FALSE) && ($this->isGenericArrayKeySet($keyGroup, $subGroup, $key))) { + // Already initialized + trigger_error(__METHOD__ . ':keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' already initialized.'); + exit; + } // END - if + + // Initialize it + $this->genericArray[$keyGroup][$subGroup][$key] = array(); } /** - * "Getter" as a time() replacement but with milliseconds. You should use this - * method instead of the encapsulated getimeofday() function. + * Initializes given generic array element * - * @return $milliTime Timestamp with milliseconds + * @param $keyGroup Main group for the key + * @param $subGroup Sub group for the key + * @param $key Key to use + * @param $element Element to use + * @param $forceInit Optionally force initialization + * @return void */ - public function getMilliTime () { - // Get the time of day as float - $milliTime = gettimeofday(true); + protected final function initGenericArrayElement ($keyGroup, $subGroup, $key, $element, $forceInit = FALSE) { + // Debug message + //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ',forceInit=' . intval($forceInit)); - // Return it - return $milliTime; + // Is it already set? + if (($forceInit === FALSE) && ($this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element))) { + // Already initialized + trigger_error(__METHOD__ . ':keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ' already initialized.'); + exit; + } // END - if + + // Initialize it + $this->genericArray[$keyGroup][$subGroup][$key][$element] = array(); } /** - * Idles (sleeps) for given milliseconds + * Pushes an element to a generic key * - * @return $hasSlept Wether it goes fine + * @param $keyGroup Main group for the key + * @param $subGroup Sub group for the key + * @param $key Key to use + * @param $value Value to add/append + * @return $count Number of array elements */ - public function idle ($milliSeconds) { - // Sleep is fine by default - $hasSlept = true; + protected final function pushValueToGenericArrayKey ($keyGroup, $subGroup, $key, $value) { + // Debug message + //* NOISY-DEBUG: */ if (!is_object($value)) $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',value[' . gettype($value) . ']=' . print_r($value, TRUE)); - // Idle so long with found function - if (function_exists('time_sleep_until')) { - // Get current time and add idle time - $sleepUntil = $this->getMilliTime() + abs($milliSeconds) / 1000; + // Is it set? + if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) { + // Initialize array + $this->initGenericArrayKey($keyGroup, $subGroup, $key); + } // END - if - // New PHP 5.1.0 function found, ignore errors - $hasSlept = @time_sleep_until($sleepUntil); - } else { - // My Sun Station doesn't have that function even with latest PHP - // package. :( - usleep($milliSeconds * 1000); - } + // Then push it + $count = array_push($this->genericArray[$keyGroup][$subGroup][$key], $value); - // Return result - return $hasSlept; + // Return count + //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], TRUE)); + //* DEBUG: */ print(__METHOD__ . ': count=' . $count . PHP_EOL); + return $count; } /** - * Setter for the list instance + * Pushes an element to a generic array element * - * @param $listInstance A list of Listable - * @return void + * @param $keyGroup Main group for the key + * @param $subGroup Sub group for the key + * @param $key Key to use + * @param $element Element to check + * @param $value Value to add/append + * @return $count Number of array elements */ - protected final function setListInstance (Listable $listInstance) { - $this->listInstance = $listInstance; - } + protected final function pushValueToGenericArrayElement ($keyGroup, $subGroup, $key, $element, $value) { + // Debug message + //* 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)); - /** - * Getter for the list instance - * - * @return $listInstance A list of Listable - */ - protected final function getListInstance () { - return $this->listInstance; + // Is it set? + if (!$this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element)) { + // Initialize array + $this->initGenericArrayElement($keyGroup, $subGroup, $key, $element); + } // END - if + + // Then push it + $count = array_push($this->genericArray[$keyGroup][$subGroup][$key][$element], $value); + + // Return count + //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], TRUE)); + //* DEBUG: */ print(__METHOD__ . ': count=' . $count . PHP_EOL); + return $count; } /** - * Setter for the menu instance + * Pops an element from a generic group * - * @param $menuInstance A RenderableMenu instance - * @return void + * @param $keyGroup Main group for the key + * @param $subGroup Sub group for the key + * @param $key Key to unset + * @return $value Last "popped" value */ - protected final function setMenuInstance (RenderableMenu $menuInstance) { - $this->menuInstance = $menuInstance; + protected final function popGenericArrayElement ($keyGroup, $subGroup, $key) { + // Debug message + //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key); + + // Is it set? + if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) { + // Not found + trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' not found.'); + exit; + } // END - if + + // Then "pop" it + $value = array_pop($this->genericArray[$keyGroup][$subGroup][$key]); + + // Return value + //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], TRUE)); + //* DEBUG: */ print(__METHOD__ . ': value[' . gettype($value) . ']=' . print_r($value, TRUE) . PHP_EOL); + return $value; } /** - * Getter for the menu instance + * Shifts an element from a generic group * - * @return $menuInstance A RenderableMenu instance + * @param $keyGroup Main group for the key + * @param $subGroup Sub group for the key + * @param $key Key to unset + * @return $value Last "popped" value */ - protected final function getMenuInstance () { - return $this->menuInstance; + protected final function shiftGenericArrayElement ($keyGroup, $subGroup, $key) { + // Debug message + //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key); + + // Is it set? + if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) { + // Not found + trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' not found.'); + exit; + } // END - if + + // Then "shift" it + $value = array_shift($this->genericArray[$keyGroup][$subGroup][$key]); + + // Return value + //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], TRUE)); + //* DEBUG: */ print(__METHOD__ . ': value[' . gettype($value) . ']=' . print_r($value, TRUE) . PHP_EOL); + return $value; } /** - * Setter for image instance + * Count generic array group * - * @param $imageInstance An instance of an image - * @return void + * @param $keyGroup Main group for the key + * @return $count Count of given group */ - public final function setImageInstance (BaseImage $imageInstance) { - $this->imageInstance = $imageInstance; + protected final function countGenericArray ($keyGroup) { + // Debug message + //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup); + + // Is it there? + if (!isset($this->genericArray[$keyGroup])) { + // Abort here + trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ' not found.'); + exit; + } // END - if + + // Then count it + $count = count($this->genericArray[$keyGroup]); + + // Debug message + //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',count=' . $count); + + // Return it + return $count; } /** - * Getter for image instance + * Count generic array sub group * - * @return $imageInstance An instance of an image + * @param $keyGroup Main group for the key + * @param $subGroup Sub group for the key + * @return $count Count of given group */ - public final function getImageInstance () { - return $this->imageInstance; + protected final function countGenericArrayGroup ($keyGroup, $subGroup) { + // Debug message + //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup); + + // Is it there? + if (!$this->isGenericArrayGroupSet($keyGroup, $subGroup)) { + // Abort here + trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' not found.'); + exit; + } // END - if + + // Then count it + $count = count($this->genericArray[$keyGroup][$subGroup]); + + // Debug message + //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',count=' . $count); + + // Return it + return $count; } /** - * Setter for stacker instance + * Count generic array elements * - * @param $stackerInstance An instance of an stacker - * @return void + * @param $keyGroup Main group for the key + * @param $subGroup Sub group for the key + * @para $key Key to count + * @return $count Count of given key */ - public final function setStackerInstance (Stackable $stackerInstance) { - $this->stackerInstance = $stackerInstance; + protected final function countGenericArrayElements ($keyGroup, $subGroup, $key) { + // Debug message + //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key); + + // Is it there? + if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) { + // Abort here + trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' not found.'); + exit; + } elseif (!$this->isValidGenericArrayGroup($keyGroup, $subGroup)) { + // Not valid + trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' is not an array.'); + exit; + } + + // Then count it + $count = count($this->genericArray[$keyGroup][$subGroup][$key]); + + // Debug message + //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',count=' . $count); + + // Return it + return $count; } /** - * Getter for stacker instance + * Getter for whole generic group array * - * @return $stackerInstance An instance of an stacker + * @param $keyGroup Key group to get + * @return $array Whole generic array group */ - public final function getStackerInstance () { - return $this->stackerInstance; + protected final function getGenericArray ($keyGroup) { + // Debug message + //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup); + + // Is it there? + if (!isset($this->genericArray[$keyGroup])) { + // Then abort here + trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ' does not exist.'); + exit; + } // END - if + + // Return it + return $this->genericArray[$keyGroup]; } /** - * Setter for compressor instance + * Setter for generic array key * - * @param $compressorInstance An instance of an compressor + * @param $keyGroup Key group to get + * @param $subGroup Sub group for the key + * @param $key Key to unset + * @param $value Mixed value from generic array element * @return void */ - public final function setCompressorInstance (Compressor $compressorInstance) { - $this->compressorInstance = $compressorInstance; + protected final function setGenericArrayKey ($keyGroup, $subGroup, $key, $value) { + // Debug message + //* NOISY-DEBUG: */ if (!is_object($value)) $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',value[' . gettype($value) . ']=' . print_r($value, TRUE)); + + // Set value here + $this->genericArray[$keyGroup][$subGroup][$key] = $value; } /** - * Getter for compressor instance + * Getter for generic array key * - * @return $compressorInstance An instance of an compressor + * @param $keyGroup Key group to get + * @param $subGroup Sub group for the key + * @param $key Key to unset + * @return $value Mixed value from generic array element */ - public final function getCompressorInstance () { - return $this->compressorInstance; + protected final function getGenericArrayKey ($keyGroup, $subGroup, $key) { + // Debug message + //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key); + + // Is it there? + if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) { + // Then abort here + trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' does not exist.'); + exit; + } // END - if + + // Return it + return $this->genericArray[$keyGroup][$subGroup][$key]; } /** - * Setter for Parseable instance + * Sets a value in given generic array key/element * - * @param $parserInstance An instance of an Parseable + * @param $keyGroup Main group for the key + * @param $subGroup Sub group for the key + * @param $key Key to set + * @param $element Element to set + * @param $value Value to set * @return void */ - public final function setParserInstance (Parseable $parserInstance) { - $this->parserInstance = $parserInstance; + protected final function setGenericArrayElement ($keyGroup, $subGroup, $key, $element, $value) { + // Debug message + //* 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)); + + // Then set it + $this->genericArray[$keyGroup][$subGroup][$key][$element] = $value; } /** - * Getter for Parseable instance + * Getter for generic array element * - * @return $parserInstance An instance of an Parseable + * @param $keyGroup Key group to get + * @param $subGroup Sub group for the key + * @param $key Key to look for + * @param $element Element to look for + * @return $value Mixed value from generic array element */ - public final function getParserInstance () { - return $this->parserInstance; + protected final function getGenericArrayElement ($keyGroup, $subGroup, $key, $element) { + // Debug message + //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element); + + // Is it there? + if (!$this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element)) { + // Then abort here + trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ' does not exist.'); + exit; + } // END - if + + // Return it + return $this->genericArray[$keyGroup][$subGroup][$key][$element]; } /** - * Setter for ProtocolHandler instance + * Checks if a given sub group is valid (array) * - * @param $protocolInstance An instance of an ProtocolHandler - * @return void + * @param $keyGroup Key group to get + * @param $subGroup Sub group for the key + * @return $isValid Whether given sub group is valid */ - public final function setProtocolInstance (ProtocolHandler $protocolInstance) { - $this->protocolInstance = $protocolInstance; + protected final function isValidGenericArrayGroup ($keyGroup, $subGroup) { + // Debug message + //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup); + + // Determine it + $isValid = (($this->isGenericArrayGroupSet($keyGroup, $subGroup)) && (is_array($this->getGenericSubArray($keyGroup, $subGroup)))); + + // Return it + return $isValid; } /** - * Getter for ProtocolHandler instance + * Checks if a given key is valid (array) * - * @return $protocolInstance An instance of an ProtocolHandler + * @param $keyGroup Key group to get + * @param $subGroup Sub group for the key + * @param $key Key to check + * @return $isValid Whether given sub group is valid */ - public final function getProtocolInstance () { - return $this->protocolInstance; + protected final function isValidGenericArrayKey ($keyGroup, $subGroup, $key) { + // Debug message + //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key); + + // Determine it + $isValid = (($this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) && (is_array($this->getGenericArrayKey($keyGroup, $subGroup, $key)))); + + // Return it + return $isValid; } /** - * Setter for BaseDatabaseWrapper instance + * Translates boolean TRUE to 'Y' and FALSE to 'N' * - * @param $wrapperInstance An instance of an BaseDatabaseWrapper - * @return void + * @param $boolean Boolean value + * @return $translated Translated boolean value */ - public final function setWrapperInstance (BaseDatabaseWrapper $wrapperInstance) { - $this->wrapperInstance = $wrapperInstance; + public static final function translateBooleanToYesNo ($boolean) { + // Make sure it is really boolean + assert(is_bool($boolean)); + + // "Translate" it + $translated = ($boolean === TRUE) ? 'Y' : 'N'; + + // ... and return it + return $translated; } /** - * Getter for BaseDatabaseWrapper instance + * Initializes counter for valid entries, arrays for damaged entries and + * an array for gap seek positions. If you call this method on your own, + * please re-analyze the file structure. So you are better to call + * analyzeFile() instead of this method. * - * @return $wrapperInstance An instance of an BaseDatabaseWrapper + * @return void */ - public final function getWrapperInstance () { - return $this->wrapperInstance; + protected function initCountersGapsArray () { + // Init counter and seek position + $this->setCounter(0); + $this->setSeekPosition(0); + + // Init arrays + $this->gaps = array(); + $this->damagedEntries = array(); } /** - * Setter for socket resource + * Getter for total entries * - * @param $socketResource A valid socket resource - * @return void + * @return $totalEntries Total entries in this file */ - public final function setSocketResource ($socketResource) { - $this->socketResource = $socketResource; + protected final function getCounter () { + // Get it + return $this->totalEntries; } /** - * Getter for socket resource + * Setter for total entries * - * @return $socketResource A valid socket resource + * @param $totalEntries Total entries in this file + * @return void */ - public function getSocketResource () { - return $this->socketResource; + protected final function setCounter ($counter) { + // Set it + $this->totalEntries = $counter; } /** - * Setter for helper instance + * Increment counter * - * @param $helperInstance An instance of a helper class * @return void */ - protected final function setHelperInstance (Helper $helperInstance) { - $this->helperInstance = $helperInstance; + protected final function incrementCounter () { + // Get it + $this->totalEntries++; } /** - * Getter for helper instance + * Getter for header size * - * @return $helperInstance An instance of a helper class + * @return $totalEntries Size of file header */ - public final function getHelperInstance () { - return $this->helperInstance; + protected final function getHeaderSize () { + // Get it + return $this->headerSize; } /** - * Setter for a Sourceable instance + * Setter for header size * - * @param $sourceInstance The Sourceable instance + * @param $headerSize Size of file header * @return void */ - protected final function setSourceInstance (Sourceable $sourceInstance) { - $this->sourceInstance = $sourceInstance; + protected final function setHeaderSize ($headerSize) { + // Set it + $this->headerSize = $headerSize; } /** - * Getter for a InputStreamable instance + * Getter for header array * - * @param $inputStreamInstance The InputStreamable instance + * @return $totalEntries Size of file header */ - protected final function getInputStreamInstance () { - return $this->inputStreamInstance; + protected final function getHeade () { + // Get it + return $this->header; } /** - * Setter for a InputStreamable instance + * Setter for header * - * @param $inputStreamInstance The InputStreamable instance + * @param $header Array for a file header * @return void */ - protected final function setInputStreamInstance (InputStreamable $inputStreamInstance) { - $this->inputStreamInstance = $inputStreamInstance; + protected final function setHeader (array $header) { + // Set it + $this->header = $header; } /** - * Getter for a OutputStreamable instance + * Getter for seek position * - * @param $outputStreamInstance The OutputStreamable instance + * @return $seekPosition Current seek position (stored here in object) */ - protected final function getOutputStreamInstance () { - return $this->outputStreamInstance; + protected final function getSeekPosition () { + // Get it + return $this->seekPosition; } /** - * Setter for a OutputStreamable instance + * Setter for seek position * - * @param $outputStreamInstance The OutputStreamable instance + * @param $seekPosition Current seek position (stored here in object) * @return void */ - protected final function setOutputStreamInstance (OutputStreamable $outputStreamInstance) { - $this->outputStreamInstance = $outputStreamInstance; + protected final function setSeekPosition ($seekPosition) { + // And set it + $this->seekPosition = $seekPosition; } /** - * Setter for raw package Data + * Updates seekPosition attribute from file to avoid to much access on file. * - * @param $packageData Raw package Data * @return void */ - public final function setPackageData (array $packageData) { - $this->packageData = $packageData; - } + protected function updateSeekPosition () { + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] CALLED!', __METHOD__, __LINE__)); - /** - * Getter for raw package Data - * - * @return $packageData Raw package Data - */ - public function getPackageData () { - return $this->packageData; + // Get key (= seek position) + $seekPosition = $this->getIteratorInstance()->key(); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] Setting seekPosition=%s', __METHOD__, __LINE__, $seekPosition)); + + // And set it here + $this->setSeekPosition($seekPosition); + + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] EXIT!', __METHOD__, __LINE__)); } /** - * Converts a hexadecimal string, even with negative sign as first string to - * a decimal number using BC functions. + * Checks whether the file header is initialized * - * This work is based on comment #86673 on php.net documentation page at: - * - * - * @param $hex Hexadecimal string - * @return $dec Decimal number + * @return $isInitialized Whether the file header is initialized */ - protected function hex2dec ($hex) { - // Convert to all lower-case - $hex = strtolower($hex); + protected function isFileHeaderInitialized () { + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] CALLED!', __METHOD__, __LINE__)); - // Detect sign (negative/positive numbers) - $sign = ''; - if (substr($hex, 0, 1) == '-') { - $sign = '-'; - $hex = substr($hex, 1); - } // END - if + // Is the method there? + assert(is_callable(array($this, 'readFileHeader'))); - // Decode the hexadecimal string into a decimal number - $dec = 0; - for ($i = strlen($hex) - 1, $e = 1; $i >= 0; $i--, $e = bcmul($e, 16)) { - $factor = self::$hexdec[substr($hex, $i, 1)]; - $dec = bcadd($dec, bcmul($factor, $e)); - } // END - for + // Default is not initialized + $isInitialized = FALSE; - // Return the decimal number - return $sign . $dec; + // Is the file initialized? + if ($this->isFileInitialized()) { + // Some bytes has been written, so rewind to start of it. + $rewindStatus = $this->getIteratorInstance()->rewind(); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] rewindStatus=%s', __METHOD__, __LINE__, $rewindStatus)); + + // Is the rewind() call successfull? + if ($rewindStatus != 1) { + // Something bad happened + self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] Could not rewind().', __METHOD__, __LINE__)); + } // END - if + + // Read file header + $this->readFileHeader(); + + // The above method does already check the header + $isInitialized = TRUE; + } // END - if + + // Return result + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] isInitialized=%d - EXIT!', __METHOD__, __LINE__, intval($isInitialized))); + return $isInitialized; } /** - * Converts even very large decimal numbers, also with negative sign, to a - * hexadecimal string. - * - * This work is based on comment #97756 on php.net documentation page at: - * + * Checks whether the assigned file has been initialized * - * @param $dec Decimal number, even with negative sign - * @param $maxLength Optional maximum length of the string - * @return $hex Hexadecimal string + * @return $isInitialized Whether the file's size is zero */ - protected function dec2hex ($dec, $maxLength = 0) { - // maxLength can be zero or devideable by 2 - assert(($maxLength == 0) || (($maxLength % 2) == 0)); - - // Detect sign (negative/positive numbers) - $sign = ''; - if ($dec < 0) { - $sign = '-'; - $dec = abs($dec); - } // END - if + protected function isFileInitialized () { + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] CALLED!', __METHOD__, __LINE__)); - // Encode the decimal number into a hexadecimal string - $hex = ''; - do { - $hex = self::$dechex[($dec % 16)] . $hex; - $dec /= 16; - } while ($dec >= 1); + // Get it from iterator which holds the pointer instance. If FALSE is returned + $fileSize = $this->getIteratorInstance()->size(); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] fileSize=%s', __METHOD__, __LINE__, $fileSize)); /* - * We need hexadecimal strings with leading zeros if the length cannot - * be divided by 2 + * The returned file size should not be FALSE or NULL as this means + * that the pointer class does not work correctly. */ - if ($maxLength > 0) { - // Prepend more zeros - $hex = $this->prependStringToString($hex, '0', $maxLength); - } elseif ((strlen($hex) % 2) != 0) { - $hex = '0' . $hex; - } + assert(is_int($fileSize)); - // Return the hexadecimal string - return $sign . $hex; + // Is more than 0 returned? + $isInitialized = ($fileSize > 0); + + // Return result + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] isInitialized=%d - EXIT!', __METHOD__, __LINE__, intval($isInitialized))); + return $isInitialized; } /** - * Converts a ASCII string (0 to 255) into a decimal number. + * Creates the assigned file * - * @param $asc The ASCII string to be converted - * @return $dec Decimal number + * @return void */ - protected function asc2dec ($asc) { - // Convert it into a hexadecimal number - $hex = bin2hex($asc); + protected function createFileHeader () { + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] CALLED!', __METHOD__, __LINE__)); - // And back into a decimal number - $dec = $this->hex2dec($hex); + // The method flushFileHeader() must be callable + assert(is_callable(array($this, 'flushFileHeader'))); - // Return it - return $dec; + // The file's header should not be initialized here + assert(!$this->isFileHeaderInitialized()); + + // Simple flush file header which will create it. + $this->flushFileHeader(); + + // Seek to beginning of file + $this->getIteratorInstance()->rewind(); + + // And update seek position ... + $this->updateSeekPosition(); + + // ... to write it back into the file + $this->flushFileHeader(); + + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] EXIT!!', __METHOD__, __LINE__)); } /** - * Converts a decimal number into an ASCII string. + * Seeks to old position * - * @param $dec Decimal number - * @return $asc An ASCII string + * @return void */ - protected function dec2asc ($dec) { - // First convert the number into a hexadecimal string - $hex = $this->dec2hex($dec); - - // Then convert it into the ASCII string - $asc = $this->hex2asc($hex); - - // Return it - return $asc; + protected function seekToOldPosition () { + // Seek to currently ("old") saved position + $this->getIteratorInstance()->seek($this->getSeekPosition()); } /** - * Converts a hexadecimal number into an ASCII string. Negative numbers - * are not allowed. + * Writes data at given position * - * @param $hex Hexadecimal string - * @return $asc An ASCII string + * @param $seekPosition Seek position + * @param $data Data to be written + * @param $flushHeader Whether to flush the header (default: flush) + * @return void */ - protected function hex2asc ($hex) { - // Check for length, it must be devideable by 2 - //* DEBUG: */ $this->debugOutput('hex='.$hex); - assert((strlen($hex) % 2) == 0); + protected function writeData ($seekPosition, $data, $flushHeader = TRUE) { + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] seekPosition=%s,data()=%s - CALLED!', __METHOD__, __LINE__, $seekPosition, strlen($data))); - // Walk the string - $asc = ''; - for ($idx = 0; $idx < strlen($hex); $idx+=2) { - // Get the decimal number of the chunk - $part = hexdec(substr($hex, $idx, 2)); + // Write data at given position + $this->getIteratorInstance()->writeAtPosition($seekPosition, $data); - // Add it to the final string - $asc .= chr($part); - } // END - for + // Update seek position + $this->updateSeekPosition(); - // Return the final string - return $asc; + // Flush the header? + if ($flushHeader === TRUE) { + // Flush header + $this->flushFileHeader(); + } // END - if + + // Seek to old position + $this->seekToOldPosition(); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] EXIT!', __METHOD__, __LINE__)); } /** - * Prepends a given string $prepend to $str with a given total length + * Pre-allocates file (if enabled) with some space for later faster write access. * - * @param $str Given original string which should be prepended - * @param $prepend The string to prepend - * @param $length Total length of the final string - * @return $strFinal Final prepended string + * @param $type Type of the file + * @return void */ - protected function prependStringToString ($str, $prepend, $length) { - // Set final string to original string by default - $strFinal = $str; + protected function preAllocateFile ($type) { + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] CALLED!', __METHOD__, __LINE__)); - // Can it devided - if (strlen($str) < $length) { - // Difference between total length and length of original string - $diff = $length - strlen($str); + // caluclateMinimumFileEntryLength() must be callable + assert(is_callable(array($this, 'caluclateMinimumFileEntryLength'))); - // Prepend the string - $prepend = str_repeat($prepend, ($diff / strlen($prepend) + 1)); + // Is it enabled? + if ($this->getConfigInstance()->getConfigEntry($type . '_pre_allocate_enabled') != 'Y') { + // Not enabled + self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] Not pre-allocating file.', __METHOD__, __LINE__)); - // Make sure it will definedly fit - assert(strlen($prepend) >= $diff); + // Don't continue here. + return; + } // END - if - // Cut it a little down - $prepend = substr($prepend, 0, $diff); - //* DEBUG: */ $this->debugOutput('prepend('.strlen($prepend).')='.$prepend.',diff='.$diff.',length='.$length); + // Message to user + self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] Pre-allocating file ...', __METHOD__, __LINE__)); - // Construct the final prepended string - $strFinal = $prepend . $str; - } // END - if + // Calculate minimum length for one entry + $minLengthEntry = $this->caluclateMinimumFileEntryLength(); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] minLengthEntry=%s', __METHOD__, __LINE__, $minLengthEntry)); - // Return it - return $strFinal; - } + // Calulcate seek position + $seekPosition = $minLengthEntry * $this->getConfigInstance()->getConfigEntry($type . '_pre_allocate_count'); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] seekPosition=%s', __METHOD__, __LINE__, $seekPosition)); - /** - * Checks wether the given encoded data was encoded with Base64 - * - * @param $encodedData Encoded data we shall check - * @return $isBase64 Wether the encoded data is Base64 - */ - protected function isBase64Encoded ($encodedData) { - // Determine it - $isBase64 = (@base64_decode($encodedData, true) !== false); + // Now simply write a NUL there. This will pre-allocate the file. + $this->writeData($seekPosition, chr(0)); - // Return it - return $isBase64; + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] EXIT!', __METHOD__, __LINE__)); } }