* @version 0.3.0 * @copyright Copyright(c) 2007, 2008 Roland Haeder, this is free software * @license GNU GPL 3.0 or any newer version * @link http://www.mxchange.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 * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ class BaseFrameworkSystem extends stdClass implements FrameworkInterface { /** * The instance to the debug output handler (should be DebugConsoleOutput or DebugWebOutput) * * @see DebugConsoleOutput * @see DebugWebOutput */ private static $debug = null; /** * The instance to the web output handler (should be WebOutput) * * @see WebOutput */ private static $webOutput = null; /** * The instance to the compression layer which should be CompressorChannel */ private static $compressor = null; /** * The configuration instance which shall be FrameworkConfiguration */ private static $cfgInstance = null; /** * The instance to the database layer which should be DatabaseConnection */ private $dbInstance = null; /** * The real class name */ private $realClass = "FrameworkSystem"; /** * A human-readable description for this simulator part */ private $objectDescription = "Namenlose Framework-Einheit"; /** * The unique ID string for identifying all type of classes */ private $uniqueID = ""; /** * Thousands seperator */ private $thousands = "."; // German /** * Decimal seperator */ private $decimals = ","; // German /** * The language instance for the template loader */ private $langInstance = null; /** * The file I/O instance for the template loader */ private $fileIOInstance = null; /*********************** * Exception codes.... * ***********************/ const EXCEPTION_IS_NULL_POINTER = 0x001; const EXCEPTION_IS_NO_OBJECT = 0x002; const EXCEPTION_IS_NO_ARRAY = 0x003; const EXCEPTION_MISSING_METHOD = 0x004; const EXCEPTION_CLASSES_NOT_MATCHING = 0x005; const EXCEPTION_INDEX_OUT_OF_BOUNDS = 0x006; const EXCEPTION_DIMENSION_ARRAY_INVALID = 0x007; const EXCEPTION_ITEM_NOT_TRADEABLE = 0x008; const EXCEPTION_ITEM_NOT_IN_PRICE_LIST = 0x009; const EXCEPTION_GENDER_IS_WRONG = 0x00a; const EXCEPTION_BIRTH_DATE_IS_INVALID = 0x00b; const EXCEPTION_EMPTY_STRUCTURES_ARRAY = 0x00c; const EXCEPTION_HAS_ALREADY_PERSONELL_LIST = 0x00d; const EXCEPTION_NOT_ENOUGTH_UNEMPLOYEES = 0x00e; const EXCEPTION_TOTAL_PRICE_NOT_CALCULATED = 0x00f; const EXCEPTION_HARBOR_HAS_NO_SHIPYARDS = 0x010; const EXCEPTION_CONTRACT_PARTNER_INVALID = 0x011; const EXCEPTION_CONTRACT_PARTNER_MISMATCH = 0x012; const EXCEPTION_CONTRACT_ALREADY_SIGNED = 0x013; const EXCEPTION_UNEXPECTED_EMPTY_STRING = 0x014; const EXCEPTION_PATH_NOT_FOUND = 0x015; const EXCEPTION_INVALID_PATH_NAME = 0x016; const EXCEPTION_READ_PROTECED_PATH = 0x017; const EXCEPTION_WRITE_PROTECED_PATH = 0x018; const EXCEPTION_DIR_POINTER_INVALID = 0x019; const EXCEPTION_FILE_POINTER_INVALID = 0x01a; const EXCEPTION_INVALID_DIRECTORY_POINTER = 0x01b; const EXCEPTION_UNEXPECTED_OBJECT = 0x01c; const EXCEPTION_LIMIT_ELEMENT_IS_UNSUPPORTED = 0x01d; const EXCEPTION_GETTER_IS_MISSING = 0x01e; const EXCEPTION_ARRAY_EXPECTED = 0x01f; const EXCEPTION_ARRAY_HAS_INVALID_COUNT = 0x020; const EXCEPTION_ID_IS_INVALID_FORMAT = 0x021; const EXCEPTION_MD5_CHECKSUMS_MISMATCH = 0x022; const EXCEPTION_UNEXPECTED_STRING_SIZE = 0x023; const EXCEPTION_SIMULATOR_ID_INVALID = 0x024; const EXCEPTION_MISMATCHING_COMPRESSORS = 0x025; const EXCEPTION_CONTAINER_ITEM_IS_NULL = 0x026; const EXCEPTION_ITEM_IS_NO_ARRAY = 0x027; const EXCEPTION_CONTAINER_MAYBE_DAMAGED = 0x028; const EXCEPTION_INVALID_STRING = 0x029; const EXCEPTION_VARIABLE_NOT_SET = 0x02a; const EXCEPTION_ATTRIBUTES_ARE_MISSING = 0x02b; const EXCEPTION_ARRAY_ELEMENTS_MISSING = 0x02c; const EXCEPTION_TEMPLATE_ENGINE_UNSUPPORTED = 0x02d; const EXCEPTION_MISSING_LANGUAGE_HANDLER = 0x02e; const EXCEPTION_MISSING_FILE_IO_HANDLER = 0x02f; const EXCEPTION_MISSING_ELEMENT = 0x030; /** * In the super constructor these system classes shall be ignored or else * we would get an endless calling loop. * *--------------------------------------------------------------------* * ATTENTION: IF YOU REMOVE ONE OF THEM YOU WILL SHOOT YOUR SERVER!!! * *--------------------------------------------------------------------* */ private $systemClasses = array( "DebugMiddleware", // Debug middleware output sub-system "DebugWebOutput", // Debug web output sub-system "DebugConsoleOutput", // Debug console output sub-system "DebugErrorLogOutput", // Debug error_log() output sub-system "CompressorChannel", // Compressor sub-system "FrameworkDirectoryPointer", // Directory handler sub-system "NullCompressor", // Null compressor "Bzip2Compressor", // BZIP2 compressor "GzipCompressor", // GZIP compressor "WebOutput", // Web output sub-system ); /** * Private super constructor * * @return void */ protected function __construct ($class) { // Set real class $this->setRealClass($class); // Init this instance $this->initInstance($class); } /** * Destructor reached... * * @return void */ public function __destruct() { // Is this object already destroyed? if ($this->__toString() != "DestructedObject") { // Debug message if ((defined('DEBUG_DESTRUCTOR')) && (is_object($this->getDebugInstance()))) { $this->getDebugInstance()->output(sprintf("[%s:] Das Objekt %s wird zerstört.
\n", __CLASS__, $this->__toString() )); } // Destroy all informations about this class but keep some text about it alive $this->setObjectDescription(sprintf("Entferntes Objekt %s", $this->__toString())); $this->setRealClass("DestructedObject"); $this->resetUniqueID(); } elseif ((defined('DEBUG_DESTRUCTOR')) && (is_object($this->getDebugInstance()))) { // Already destructed object $this->getDebugInstance()->output(sprintf("[%s:] Das Objekt %s wurde bereits zerstört.
\n", __CLASS__, $this->__toString() )); } } /** * The call method where all non-implemented methods end up * * @return void */ public final function __call ($methodName, $args) { // Implode all given arguments $argsString = implode("|", $args); if (empty($argsString)) $argsString = "NULL"; $this->getDebugInstance()->output(sprintf("[%s::%s] Stub! Args: %s", $this->__toString(), $methodName, $argsString )); // Return nothing return null; } /** * Initializes the instance * * @return void */ public function initInstance ($class) { // Get the current (singleton) configuration instance $this->setConfigInstance(FrameworkConfiguration::createFrameworkConfiguration()); // Is the class weather debug nor compressor channel? if (!in_array($class, $this->systemClasses)) { // Initialize debug instance if (is_null($this->getDebugInstance())) { // Set the debug output system if it is not debug class ;) $this->setDebugInstance(DebugMiddleware::createDebugMiddleware($this->getConfigInstance()->readConfig("debug_engine"))); } // Initialize web instance if (is_null($this->getWebOutputInstance())) { // Generate the eval() command $eval = sprintf("\$this->setWebOutputInstance(%s::create%s(\"%s\"));", $this->getConfigInstance()->readConfig("web_engine"), $this->getConfigInstance()->readConfig("web_engine"), $this->getConfigInstance()->readConfig("web_content_type") ); // Debug message if ((defined('DEBUG_EVAL')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:] Konstruierte PHP-Anweisung:
%s

\n", $this->__toString(), htmlentities($eval) )); // Run the command eval($eval); } // Initialize compressor channel if (is_null($this->getCompressorChannel())) { // Set the compressor channel $this->setCompressorChannel(CompressorChannel::createCompressorChannel(sprintf("%s%s", PATH, $this->getConfigInstance()->readConfig("compressor_base_path") ))); } // Initialize database middleware if (is_null($this->getDatabaseInstance())) { // Get the middleware instance $db = DatabaseConnection::getInstance(); if (is_object($db)) { // Set the database middleware $this->setDatabaseInstance($db); } } // Debug output if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] Alle Sub-Systeme sind initialisiert.
\n", $this->__toString() )); } } /** * Setter for language instance * * @param $configInstance The configuration instance which shall * be FrameworkConfiguration * @return void */ public final function setConfigInstance (FrameworkConfiguration $configInstance) { self::$cfgInstance = $configInstance; if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] Konfigurations-Handler auf %s gesetzt.
\n", $this->__toString(), $configInstance->__toString() )); } /** * Getter for configuration instance * * @return $cfhInstance - Configuration instance */ public final function getConfigInstance () { if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] Konfigurations-Handler %s angefordert.
\n", $this->__toString(), self::$cfgInstance->__toString() )); return self::$cfgInstance; } /** * Setter for debug instance * * @param $debugInstance The instance for debug output class * @return void */ public final function setDebugInstance (DebugMiddleware $debugInstance) { self::$debug = $debugInstance; if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] Debug-Handler auf %s gesetzt.
\n", $this->__toString(), $this->getDebugInstance()->__toString() )); } /** * Getter for debug instance * * @return $debug - Instance to class DebugConsoleOutput or DebugWebOutput */ public final function getDebugInstance () { return self::$debug; } /** * Setter for web output instance * * @param $webInstance The instance for web output class * @return void */ public final function setWebOutputInstance (OutputStreamer $webInstance) { self::$webOutput = $webInstance; if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] Web-Handler auf %s gesetzt.
\n", $this->__toString(), $this->getWebOutputInstance()->__toString() )); } /** * Getter for web output instance * * @return $webOutput - Instance to class WebOutput */ public final function getWebOutputInstance () { return self::$webOutput; } /** * Static setter for database instance * * @param $dbInstance The instance for the database connection * (forced DatabaseConnection) * @return void */ public final function setDatabaseInstance (DatabaseConnection $dbInstance) { if ((defined('DEBUG_SYSTEM')) && (is_object($dbInstance->getDebugInstance()))) $dbInstance->getDebugInstance()->output(sprintf("[%s:] Datenbankschicht gesetzt.
\n", $dbInstance->__toString() )); $this->dbInstance = $dbInstance; } /** * Getter for $realClass * * @return $realClass The name of the real class (not BaseFrameworkSystem) */ public final function __toString () { if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] __toString() erreicht.
\n", $this->realClass )); return $this->realClass; } /** * Setter for the real class name * * @param $realClass Class name (string) * @return void */ public final function setRealClass ($realClass) { // Cast to string $realClass = (string) $realClass; // Set real class $this->realClass = $realClass; } /** * Generate unique ID from a lot entropy * * @return void */ public final function createUniqueID () { if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] createUniqueID aufgerufen.
\n", $this->__toString() )); // Existiert noch keine? if (empty($this->uniqueID)) { if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] createUniqueID erzeugt neue Unique-ID.
\n", $this->__toString() )); // Correct missing class name $corrected = false; if ($this->__toString() == "") { $this->setRealClass(__CLASS__); $corrected = true; } // Neue ID erstellen $tempID = false; while (true) { // Generate a unique ID number $tempID = $this->generateIdNumber(); $isUsed = false; // Try to figure out if the ID number is not yet used try { if (is_object($this->getDatabaseInstance())) { $isUsed = $this->getDatabaseInstance()->isUniqueIdUsed($tempID, true); } } catch (FrameworkException $e) { // Catches all and ignores all ;-) } if ( ( $tempID !== false ) && ( ( $this->getDatabaseInstance() === null ) || ( ( is_object($this->getDatabaseInstance()) ) && ( !$isUsed ) ) ) ) { // Abort the loop break; } } // Debug message if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] uniqueID ist auf %s gesetzt.
\n", $this->__toString(), $tempID )); // Apply the new ID $this->setUniqueID($tempID); // Revert maybe corrected class name if ($corrected) { $this->setRealClass(""); } // Remove system classes if we are in a system class if ((isset($this->systemClasses)) && (in_array($this->__toString(), $this->systemClasses))) { // This may save some RAM... $this->removeSystemArray(); } } } /** * Generates a new ID number for classes based from the class' real name, * the description and some random data * * @return $tempID The new (temporary) ID number */ private final function generateIdNumber () { return sprintf("%s@%s", $this->__toString(), md5(sprintf("%s:%s:%s:%s:%s:%s", $this->__toString(), $this->getObjectDescription(), time(), getenv('REMOTE_ADDR'), getenv('SERVER_ADDR'), mt_rand() )) ); } /** * Setter for unique ID * * @param $uniqueID The newly generated unique ID number * @return void */ private final function setUniqueID ($uniqueID) { // Cast to string $uniqueID = (string) $uniqueID; // Debug message if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] Unique-ID gesetzt auf %s.
\n", $this->__toString(), $uniqueID )); // Set the ID number $this->uniqueID = $uniqueID; } /** * Getter for unique ID * * @return $uniqueID The unique ID of this class */ public final function getUniqueID () { if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] Unique-ID angefordert.
\n", $this->__toString() )); return $this->uniqueID; } /** * Resets or recreates the unique ID number * * @return void */ public final function resetUniqueID() { // Sweet and simple... ;-) $newUniqueID = $this->generateIdNumber(); if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] Unique-ID zurückgesetzt auf %s.
\n", $this->__toString(), $newUniqueID )); $this->setUniqueID($newUniqueID); } /** * Getter for simulator description * * @return $objectDescription The description of this simulation part */ public final function getObjectDescription () { if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] getObjectDescription erreicht.
\n", $this->__toString() )); if (isset($this->objectDescription)) { return $this->objectDescription; } else { return null; } } /** * Setter for simulation part description * * @param $objectDescription The description as string for this simulation part * @return void */ public final function setObjectDescription ($objectDescription) { $this->objectDescription = (String) $objectDescription; if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] Teilbeschreibung wird auf %s gesetzt.
\n", $this->__toString(), $this->objectDescription )); } /** * Validate if given object is the same as current * * @param $object An object instance for comparison with this class * @return boolean The result of comparing both's unique ID */ public final function equals ($object) { return ($this->getUniqueID() == $object->getUniqueID()); } /** * Compare if both simulation part description and class name matches * (shall be enougth) * * @param $itemInstance An object instance to an other class * @return boolean The result of comparing class name simulation part description */ public function itemMatches ($itemInstance) { return ( ( $this->__toString() == $itemInstance->__toString() ) && ( $this->getObjectDescription() == $itemInstance->getObjectDescription() ) ); } /** * Compare class name of this and given class name * * @param $class The class name as string from the other class * @return boolean The result of comparing both class names */ public final function isClass ($class) { if ((defined('DEBUG_SYSTEM')) && (is_object($this->getDebugInstance()))) $this->getDebugInstance()->output(sprintf("[%s:] %s=%s?
\n", $this->__toString(), $this->__toString(), $class )); return ($this->__toString() == $class); } /** * Stub method (only real cabins shall override it) * * @return boolean false = is no cabin, true = is a cabin */ public function isCabin () { return false; } /** * Stub method for tradeable objects * * @return boolean false = is not tradeable by the Merchant class, * true = is a tradeable object */ public function isTradeable () { return false; } /** * Formats computer generated price values into human-understandable formats * with thousand and decimal seperators. * * @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 */ 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); } // Cast the number $value = (float) $value; if (defined('DEBUG_CORE') && is_object($this->getDebugInstance())) $this->getDebugInstance()->output(sprintf("[%s:] %d wird umformatiert.
\n", $this->__toString(), $value )); // Reformat the US number $price = sprintf("%s %s", number_format($value, $decNum, $this->decimals, $this->thousands), $currency ); // Return as string... return $price; } /** * Removes number formating characters * * @return void */ public final function removeNumberFormaters () { if (defined('DEBUG_CORE') && is_object($this->getDebugInstance())) $this->getDebugInstance()->output(sprintf("[%s:] Zahlenumformatierungszeichen werden entfernt.
\n", $this->__toString() )); unset($this->thousands); unset($this->decimals); } /** * Getter for database layer * * @return $dbInstance The database layer instance */ public final function getDatabaseInstance () { if (defined('DEBUG_CORE') && is_object($this->getDebugInstance())) $this->getDebugInstance()->output(sprintf("[%s:] Datenbank-Instanz %s angefordert.
\n", $this->__toString(), $this->dbInstance )); return $this->dbInstance; } /** * Setter for compressor channel * * @param $compressorChannel An instance of CompressorChannel * @return void */ public final function setCompressorChannel (CompressorChannel $compressorChannel) { self::$compressor = $compressorChannel; } /** * Getter for compressor channel * * @return $compressor The compressor channel */ public final function getCompressorChannel () { return self::$compressor; } /** * Remove the $systemClasses array from memory * * @return void */ public final function removeSystemArray () { unset($this->systemClasses); } /** * Create a file name and path name from the object's unique ID number. * The left part of the ID shall always be a valid class name and the * right part an ID number. * * @return $pfn The file name with a prepended path name * @throws NoArrayCreatedException If explode() fails to create an array * @throws InvalidArrayCountException If the array contains less or * more than two elements */ public final function getPathFileNameFromObject () { // Get the main object's unique ID. We use this as a path/filename combination $pathFile = $this->getUniqueID(); // Split it up in path and file name $pathFile = explode("@", $pathFile); // Are there two elements? Index 0 is the path, 1 the file name + global extension if (!is_array($pathFile)) { // No array found throw new NoArrayCreatedException(array($this, "pathFile"), self::EXCEPTION_ARRAY_EXPECTED); } elseif (count($pathFile) != 2) { // Invalid ID returned! throw new InvalidArrayCountException(array($this, "pathFile", count($pathFile), 2), self::EXCEPTION_ARRAY_HAS_INVALID_COUNT); } // Auto-append missing trailing slash $pathFile[0] = $this->addMissingTrailingSlash($pathFile[0]); // Create the file name and return it $pfn = ($pathFile[0] . $pathFile[1]); return $pfn; } /** * 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 .= "/"; return $str; } /** * Private getter for language instance * * @return $langInstance An instance to the language sub-system */ protected final function getLanguageInstance () { return $this->langInstance; } /** * Setter for language instance * * @param $langInstance An instance to the language sub-system * @return void * @see LanguageSystem */ public final function setLanguageInstance (ManageableLanguage $langInstance) { $this->langInstance = $langInstance; } /** * Private getter for file IO instance * * @return $fileIOInstance An instance to the file I/O sub-system */ protected final function getFileIOInstance () { return $this->fileIOInstance; } /** * Setter for file I/O instance * * @param $fileIOInstance An instance to the file I/O sub-system * @return void */ public final function setFileIOInstance (FileIOHandler $fileIOInstance) { $this->fileIOInstance = $fileIOInstance; } /** * Prepare the template engine (TemplateEngine by default) for a given * application helper instance (ApplicationHelper by default). * * @param $appInstance An application helper instance * @return $tplEngine The template engine instance * @throws NullPointerException If the template engine could not * be initialized * @throws UnsupportedTemplateEngineException If $tplEngine is an * unsupported template engine * @throws MissingLanguageHandlerException If the language sub-system * is not yet initialized */ protected function prepareTemplateEngine (BaseFrameworkSystem $appInstance) { // Generate FQFN for all application templates $fqfn = sprintf("%s%s/%s/%s", PATH, $this->getConfigInstance()->readConfig("application_path"), strtolower($appInstance->getAppShortName()), $this->getConfigInstance()->readConfig("tpl_base_path") ); // Are both instances set? if ($appInstance->getLanguageInstance() === null) { // Invalid language instance throw new MissingLanguageHandlerException($appInstance, self::EXCEPTION_MISSING_LANGUAGE_HANDLER); } elseif ($appInstance->getFileIOInstance() === null) { // Invalid language instance throw new MissingFileIoHandlerException($appInstance, self::EXCEPTION_MISSING_FILE_IO_HANDLER); } // Initialize the template engine $tplEngine = null; $eval = sprintf("\$tplEngine = %s::create%s( \"%s\", \$appInstance->getLanguageInstance(), \$appInstance->getFileIOInstance() );", $this->getConfigInstance()->readConfig("tpl_engine"), $this->getConfigInstance()->readConfig("tpl_engine"), $fqfn ); // Debug message if ((!is_null($this->getDebugInstance())) && (defined('DEBUG_EVAL'))) { $this->getDebugInstance()->output(sprintf("[%s:] Konstruierte PHP-Anweisung:
%s

\n", $this->__toString(), htmlentities($eval) )); } // Run the command eval($eval); // Is it a valid instance? if (is_null($tplEngine)) { // No class returned throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER); } elseif (!$tplEngine instanceof CompileableTemplate) { // Not an object! ;-( throw new UnsupportedTemplateEngineException($tplEngine, self::EXCEPTION_TEMPLATE_ENGINE_UNSUPPORTED); } // Return the prepared instance return $tplEngine; } } // [EOF] ?>