X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=framework%2Fbootstrap%2Fclass_FrameworkBootstrap.php;h=4790acda2c17bbda6d8d08e19085e8adc6d3e67d;hb=2218902056efcf9a2c66fe7c24995e066bd7cd11;hp=16e5863d0e3e4d6589f044e70088dc04e880137e;hpb=d368d588ce51693181e74a6bee9f96e8e78b96d4;p=core.git diff --git a/framework/bootstrap/class_FrameworkBootstrap.php b/framework/bootstrap/class_FrameworkBootstrap.php index 16e5863d..4790acda 100644 --- a/framework/bootstrap/class_FrameworkBootstrap.php +++ b/framework/bootstrap/class_FrameworkBootstrap.php @@ -1,31 +1,37 @@ * @version 0.0.0 - * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Core Developer Team + * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2020 Core Developer Team * @license GNU GPL 3.0 or any newer version * @link http://www.ship-simu.org * @@ -44,6 +50,11 @@ use \BadMethodCallException; */ final class FrameworkBootstrap { + /** + * Detected server address + */ + private static $serverAddress = NULL; + /** * Instance of a Requestable class */ @@ -54,11 +65,26 @@ final class FrameworkBootstrap { */ private static $responseInstance = NULL; + /** + * Instance of a FrameworkConfiguration class + */ + private static $configurationInstance = NULL; + + /** + * Database instance + */ + private static $databaseInstance = NULL; + + /** + * Language system instance + */ + private static $languageInstance = NULL; + /* * Includes applications may have. They will be tried in the given order, * some will become soon deprecated. */ - private static $configAppIncludes = array( + private static $configAppIncludes = [ // The ApplicationHelper class (required) 'class_ApplicationHelper' => 'required', // Some debugging stuff (optional but can be committed) @@ -77,7 +103,17 @@ final class FrameworkBootstrap { 'init' => 'deprecated', // Application starter (deprecated) 'starter' => 'deprecated', - ); + ]; + + /** + * Detected application's name + */ + private static $detectedApplicationName; + + /** + * Detected application's full path + */ + private static $detectedApplicationPath; /** * Private constructor, no instance is needed from this class as only @@ -88,21 +124,37 @@ final class FrameworkBootstrap { } /** - * Getter for request instance + * Some "getter" for a configuration instance, making sure, it is unique * - * @return $requestInstance An instance of a Requestable class + * @return $configurationInstance An instance of a FrameworkConfiguration class */ - public static function getRequestInstance () { - return self::$requestInstance; + public static function getConfigurationInstance () { + // Is the instance there? + if (is_null(self::$configurationInstance)) { + // Init new instance + self::$configurationInstance = new FrameworkConfiguration(); + } + + // Return it + return self::$configurationInstance; } /** - * Getter for response instance + * Getter for detected application name * - * @return $responseInstance An instance of a Responseable class + * @return $detectedApplicationName Detected name of application */ - public static function getResponseInstance () { - return self::$responseInstance; + public static function getDetectedApplicationName () { + return self::$detectedApplicationName; + } + + /** + * Getter for detected application's full path + * + * @return $detectedApplicationPath Detected full path of application + */ + public static function getDetectedApplicationPath () { + return self::$detectedApplicationPath; } /** @@ -118,7 +170,7 @@ final class FrameworkBootstrap { if (isset($_SERVER['HTTP_HOST'])) { // Then it is a HTML response/request. $requestType = 'html'; - } // END - if + } // Return it return $requestType; @@ -129,26 +181,29 @@ final class FrameworkBootstrap { * gurantee that the file is actually readable and/or writeable. If you need * such gurantee then please use isReadableFile() instead. * - * @param $filePathName Name of the file/path to be checked + * @param $fileInstance An instance of a SplFileInfo class * @return $isReachable Whether it is within open_basedir() */ - public static function isReachableFilePath ($filePathName) { + public static function isReachableFilePath (SplFileInfo $fileInstance) { // Is not reachable by default $isReachable = false; // Get open_basedir parameter - $openBaseDir = ini_get('open_basedir'); + $openBaseDir = trim(ini_get('open_basedir')); // Is it set? if (!empty($openBaseDir)) { // Check all entries foreach (explode(PATH_SEPARATOR, $openBaseDir) as $dir) { // Check on existence - if (substr($filePathName, 0, strlen($dir)) == $dir) { + if (substr($fileInstance->getPathname(), 0, strlen($dir)) == $dir) { // Is reachable $isReachable = true; - } // END - if - } // END - foreach + + // Abort lookup as it has been found in open_basedir + break; + } + } } else { // If open_basedir is not set, all is allowed $isReachable = true; @@ -162,23 +217,21 @@ final class FrameworkBootstrap { * Checks whether the give file is within open_basedir() (done by * isReachableFilePath()), is actually a file and is readable. * - * @param $fileName Name of the file to be checked + * @param $fileInstance An instance of a SplFileInfo class * @return $isReadable Whether the file is readable (and therefor exists) */ - public static function isReadableFile ($fileName) { + public static function isReadableFile (SplFileInfo $fileInstance) { // Default is not readable $isReadable = false; - // Is within parameters, so check if it is a file and readable + // Check if it is a file and readable $isReadable = ( ( - self::isReachableFilePath($fileName) - ) && ( - file_exists($fileName) + self::isReachableFilePath($fileInstance) ) && ( - is_file($fileName) + $fileInstance->isFile() ) && ( - is_readable($fileName) + $fileInstance->isReadable() ) ); @@ -189,22 +242,22 @@ final class FrameworkBootstrap { /** * Loads given include file * - * @param $fqfn Include's FQFN + * @param $fileInstance An instance of a SplFileInfo class * @return void - * @throws InvalidArgumentException If $fqfn was not found or not readable or deprecated + * @throws InvalidArgumentException If file was not found or not readable or deprecated */ - public static function loadInclude ($fqfn) { + public static function loadInclude (SplFileInfo $fileInstance) { // Trace message - //* NOISY-DEBUG: */ printf('[%s:%d]: fqfn=%s - CALLED!' . PHP_EOL, __METHOD__, __LINE__, $fqfn); + //* NOISY-DEBUG: */ printf('[%s:%d]: fileInstance=%s - CALLED!' . PHP_EOL, __METHOD__, __LINE__, $fileInstance); // Should be there ... - if (!self::isReadableFile($fqfn)) { + if (!self::isReadableFile($fileInstance)) { // Abort here - throw new InvalidArgumentException(sprintf('Cannot find fqfn=%s.', $fqfn)); - } // END - if + throw new InvalidArgumentException(sprintf('Cannot find fileInstance.pathname=%s.', $fileInstance->getPathname())); + } // Load it - require $fqfn; + require_once $fileInstance->getPathname(); // Trace message //* NOISY-DEBUG: */ printf('[%s:%d]: EXIT!' . PHP_EOL, __METHOD__, __LINE__); @@ -217,12 +270,14 @@ final class FrameworkBootstrap { */ public static function doBootstrap () { // Load basic include files to continue bootstrapping - self::loadInclude(sprintf('%smain%sinterfaces%sclass_FrameworkInterface.php', ApplicationEntryPoint::detectFrameworkPath(), DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR)); - self::loadInclude(sprintf('%smain%sinterfaces%sregistry%sclass_Registerable.php', ApplicationEntryPoint::detectFrameworkPath(), DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR)); - self::loadInclude(sprintf('%sconfig%sclass_FrameworkConfiguration.php', ApplicationEntryPoint::detectFrameworkPath(), DIRECTORY_SEPARATOR)); + self::loadInclude(new SplFileInfo(sprintf('%smain%sinterfaces%sclass_FrameworkInterface.php', ApplicationEntryPoint::detectFrameworkPath(), DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR))); + self::loadInclude(new SplFileInfo(sprintf('%smain%sclasses%sclass_BaseFrameworkSystem.php', ApplicationEntryPoint::detectFrameworkPath(), DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR))); + self::loadInclude(new SplFileInfo(sprintf('%smain%sclasses%sutils%sstring%sclass_StringUtils.php', ApplicationEntryPoint::detectFrameworkPath(), DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR))); + self::loadInclude(new SplFileInfo(sprintf('%smain%sinterfaces%sregistry%sclass_Registerable.php', ApplicationEntryPoint::detectFrameworkPath(), DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR))); + self::loadInclude(new SplFileInfo(sprintf('%sconfig%sclass_FrameworkConfiguration.php', ApplicationEntryPoint::detectFrameworkPath(), DIRECTORY_SEPARATOR))); // Load global configuration - self::loadInclude(sprintf('%s%s', ApplicationEntryPoint::detectFrameworkPath(), 'config-global.php')); + self::loadInclude(new SplFileInfo(sprintf('%s%s', ApplicationEntryPoint::detectFrameworkPath(), 'config-global.php'))); } /** @@ -243,7 +298,7 @@ final class FrameworkBootstrap { /* * 2) Determine the request type, console or web and store request and - * response here. This also initializes the request instance will + * response here. This also initializes the request instance with * all given parameters (see doc-tag for possible sources of * parameters). */ @@ -251,7 +306,7 @@ final class FrameworkBootstrap { /* * 3) Now, that there are all request parameters being available, check - * if 'app' is supplied. If it is not found, abort execution, if + * if 'application' is supplied. If it is not found, abort execution, if * found, continue below with next step. */ self::validateApplicationParameter(); @@ -265,26 +320,22 @@ final class FrameworkBootstrap { * @return void */ public static function prepareApplication () { - // Configuration entry 'detected_app_name' must be set, get it here, including full path - $application = FrameworkConfiguration::getSelfInstance()->getConfigEntry('detected_app_name'); - $fullPath = FrameworkConfiguration::getSelfInstance()->getConfigEntry('detected_full_app_path'); - /* * Now check and load all files, found deprecated files will throw a * warning at the user. */ foreach (self::$configAppIncludes as $fileName => $status) { - // Construct FQFN - $fqfn = sprintf('%s%s.php', $fullPath, $fileName); + // Construct file instance + $fileInstance = new SplFileInfo(sprintf('%s%s.php', self::getDetectedApplicationPath(), $fileName)); // Determine if this file is wanted/readable/deprecated - if (($status == 'required') && (!self::isReadableFile($fqfn))) { + if (($status == 'required') && (!self::isReadableFile($fileInstance))) { // Nope, required file cannot be found/read from - ApplicationEntryPoint::exitApplication(sprintf('Application "%s" does not have required file "%s.php". Please add it.', $application, $fileName)); - } elseif ((file_exists($fqfn)) && (!is_readable($fqfn))) { + ApplicationEntryPoint::exitApplication(sprintf('Application "%s" does not have required file "%s.php". Please add it.', self::getDetectedApplicationName(), $fileInstance->getBasename())); + } elseif (($fileInstance->isFile()) && (!$fileInstance->isReadable())) { // Found, not readable file - ApplicationEntryPoint::exitApplication(sprintf('File "%s.php" from application "%s" cannot be read. Please fix CHMOD.', $fileName, $application)); - } elseif (($status != 'required') && (!self::isReadableFile($fqfn))) { + ApplicationEntryPoint::exitApplication(sprintf('File "%s.php" from application "%s" cannot be read. Please fix CHMOD.', $fileInstance->getBasename(), self::getDetectedApplicationName())); + } elseif (($status != 'required') && (!self::isReadableFile($fileInstance))) { // Not found but optional/deprecated file, skip it continue; } @@ -292,15 +343,15 @@ final class FrameworkBootstrap { // Is the file deprecated? if ($status == 'deprecated') { // Issue warning - trigger_error(sprintf('Deprecated file "%s.php" found, will not load it to avoid problems. Please remove it from your application "%s" to avoid this warning.', $fileName, $application), E_USER_WARNING); + trigger_error(sprintf('Deprecated file "%s.php" found, will not load it to avoid problems. Please remove it from your application "%s" to avoid this warning.', $fileName, self::getDetectedApplicationName()), E_USER_WARNING); // Skip loading deprecated file continue; - } // END - if + } // Load it - self::loadInclude($fqfn); - } // END - foreach + self::loadInclude($fileInstance); + } // Scan for application's classes, exceptions and interfaces ClassLoader::scanApplicationClasses(); @@ -313,47 +364,41 @@ final class FrameworkBootstrap { * @return void */ public static function startApplication () { - // Configuration entry 'detected_app_name' must be set, get it here - $application = FrameworkConfiguration::getSelfInstance()->getConfigEntry('detected_app_name'); - // Is there an application helper instance? $applicationInstance = call_user_func_array( array( - 'CoreFramework\Helper\Application\ApplicationHelper', 'getSelfInstance' - ), array() + 'Org\Mxchange\CoreFramework\Helper\Application\ApplicationHelper', 'getSelfInstance' + ), [] ); // Some sanity checks if ((empty($applicationInstance)) || (is_null($applicationInstance))) { // Something went wrong! - ApplicationEntryPoint::exitApplication(sprintf("[Main:] The application %s could not be launched because the helper class %s is not loaded.", - $application, - 'CoreFramework\Helper\Application\ApplicationHelper' + ApplicationEntryPoint::exitApplication(sprintf('[Main:] The application %s could not be launched because the helper class %s is not loaded.', + self::getDetectedApplicationName(), + 'Org\Mxchange\CoreFramework\Helper\Application\ApplicationHelper' )); } elseif (!is_object($applicationInstance)) { // No object! - ApplicationEntryPoint::exitApplication(sprintf("[Main:] The application %s could not be launched because 'app' is not an object (%s).", - $application, + ApplicationEntryPoint::exitApplication(sprintf('[Main:] The application %s could not be launched because 'app' is not an object (%s).', + self::getDetectedApplicationName(), gettype($applicationInstance) )); } elseif (!($applicationInstance instanceof ManageableApplication)) { // Missing interface - ApplicationEntryPoint::exitApplication(sprintf("[Main:] The application %s could not be launched because 'app' is lacking required interface ManageableApplication.", - $application + ApplicationEntryPoint::exitApplication(sprintf('[Main:] The application %s could not be launched because 'app' is lacking required interface ManageableApplication.', + self::getDetectedApplicationName() )); } - // Set it in registry - Registry::getRegistry()->addInstance('app', $applicationInstance); - // Now call all methods in one go foreach (array('setupApplicationData', 'initApplication', 'launchApplication') as $methodName) { // Debug message - //* NOISY-DEBUG: */ printf('[%s:%d]: Calling methodName=%s ...' . PHP_EOL, __METHOD__, __LINE__, $methodName); + //*NOISY-DEBUG: */ printf('[%s:%d]: Calling methodName=%s ...' . PHP_EOL, __METHOD__, __LINE__, $methodName); // Call method call_user_func(array($applicationInstance, $methodName)); - } // END - if + } } /** @@ -366,19 +411,170 @@ final class FrameworkBootstrap { $applicationInstance = ApplicationHelper::getSelfInstance(); // Is the database instance already set? - if ($applicationInstance instanceof DatabaseConnector) { + if (self::getDatabaseInstance() instanceof DatabaseConnector) { // Yes, then abort here throw new BadMethodCallException('Method called twice.'); - } // END - if + } // Initialize database layer - $databaseInstance = ObjectFactory::createObjectByConfiguredName(FrameworkConfiguration::getSelfInstance()->getConfigEntry('database_type') . '_class'); + $databaseInstance = ObjectFactory::createObjectByConfiguredName(self::getConfigurationInstance()->getConfigEntry('database_type') . '_class'); // Prepare database instance $connectionInstance = DatabaseConnection::createDatabaseConnection(DebugMiddleware::getSelfInstance(), $databaseInstance); // Set it in application helper - $applicationInstance->setDatabaseInstance($connectionInstance); + self::setDatabaseInstance($connectionInstance); + } + + /** + * Detects the server address (SERVER_ADDR) and set it in configuration + * + * @return $serverAddress The detected server address + * @throws UnknownHostnameException If SERVER_NAME cannot be resolved to an IP address + * @todo Have to check some more entries from $_SERVER here + */ + public static function detectServerAddress () { + // Is the entry set? + if (!isset(self::$serverAddress)) { + // Is it set in $_SERVER? + if (!empty($_SERVER['SERVER_ADDR'])) { + // Set it from $_SERVER + self::$serverAddress = $_SERVER['SERVER_ADDR']; + } elseif (isset($_SERVER['SERVER_NAME'])) { + // Resolve IP address + $serverIp = ConsoleTools::resolveIpAddress($_SERVER['SERVER_NAME']); + + // Is it valid? + if ($serverIp === false) { + /* + * Why is gethostbyname() returning the host name and not + * false as many other PHP functions are doing? ;-( + */ + throw new UnknownHostnameException(sprintf('Cannot resolve "%s" to an IP address. Please fix your setup.', $_SERVER['SERVER_NAME'])); + } + + // Al fine, set it + self::$serverAddress = $serverIp; + } else { + // Run auto-detecting through console tools lib + self::$serverAddress = ConsoleTools::acquireSelfIpAddress(); + } + } + + // Return it + return self::$serverAddress; + } + + /** + * Setter for default time zone (must be correct!) + * + * @param $timezone The timezone string (e.g. Europe/Berlin) + * @return $success If timezone was accepted + * @throws InvalidArgumentException If $timezone is empty + */ + public static function setDefaultTimezone (string $timezone) { + // Is it set? + if (empty($timezone)) { + // Entry is empty + throw new InvalidArgumentException('timezone is empty'); + } + + // Default success + $success = FALSE; + + /* + * Set desired time zone to prevent date() and related functions to + * issue an E_WARNING. + */ + $success = date_default_timezone_set($timezone); + + // Return status + return $success; + } + + /** + * Checks whether HTTPS is set in $_SERVER + * + * @return $isset Whether HTTPS is set + * @todo Test more fields + */ + public static function isHttpSecured () { + return ( + ( + ( + isset($_SERVER['HTTPS']) + ) && ( + strtolower($_SERVER['HTTPS']) == 'on' + ) + ) || ( + ( + isset($_SERVER['HTTP_X_FORWARDED_PROTO']) + ) && ( + strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https' + ) + ) + ); + } + + /** + * Dectect and return the base URL for all URLs and forms + * + * @return $baseUrl Detected base URL + */ + public static function detectBaseUrl () { + // Initialize the URL + $protocol = 'http'; + + // Do we have HTTPS? + if (self::isHttpSecured()) { + // Add the >s< for HTTPS + $protocol = 'https'; + } + + // Construct the full URL and secure it against CSRF attacks + $baseUrl = sprintf('%s://%s%s', $protocol, self::detectDomain(), self::detectScriptPath()); + + // Return the URL + return $baseUrl; + } + + /** + * Detect safely and return the full domain where this script is installed + * + * @return $fullDomain The detected full domain + */ + public static function detectDomain () { + // Full domain is localnet.invalid by default + $fullDomain = 'localnet.invalid'; + + // Is the server name there? + if (isset($_SERVER['SERVER_NAME'])) { + // Detect the full domain + $fullDomain = htmlentities(strip_tags($_SERVER['SERVER_NAME']), ENT_QUOTES); + } + + // Return it + return $fullDomain; + } + + /** + * Detect safely the script path without trailing slash which is the glue + * between "http://your-domain.invalid/" and "script-name.php" + * + * @return $scriptPath The script path extracted from $_SERVER['SCRIPT_NAME'] + */ + public static function detectScriptPath () { + // Default is empty + $scriptPath = ''; + + // Is the scriptname set? + if (isset($_SERVER['SCRIPT_NAME'])) { + // Get dirname from it and replace back-slashes with slashes for lame OSes... + $scriptPath = str_replace("\\", '/', dirname($_SERVER['SCRIPT_NAME'])); + } + + // Return it + return $scriptPath; } /** @@ -395,10 +591,10 @@ final class FrameworkBootstrap { */ private static function scanFrameworkClasses () { // Include the class loader function - require FrameworkConfiguration::getSelfInstance()->getConfigEntry('framework_base_path') . 'loader/class_ClassLoader.php'; + require self::getConfigurationInstance()->getConfigEntry('framework_base_path') . 'loader/class_ClassLoader.php'; // Register auto-load function with the SPL - spl_autoload_register('CoreFramework\Loader\ClassLoader::autoLoad'); + spl_autoload_register('Org\Mxchange\CoreFramework\Loader\ClassLoader::autoLoad'); // Scan for all framework classes, exceptions and interfaces ClassLoader::scanFrameworkClasses(); @@ -416,7 +612,7 @@ final class FrameworkBootstrap { $requestType = self::getRequestTypeFromSystem(); // Create a new request object - $requestInstance = ObjectFactory::createObjectByName(sprintf('CoreFramework\Request\%sRequest', BaseFrameworkSystem::convertToClassName($request))); + $requestInstance = ObjectFactory::createObjectByName(sprintf('Org\Mxchange\CoreFramework\Request\%sRequest', StringUtils::convertToClassName($request))); // Remember request instance here self::setRequestInstance($requestInstance); @@ -426,10 +622,10 @@ final class FrameworkBootstrap { // Then use it $request = strtolower($requestInstance->getRequestElement('request')); $requestType = $request; - } // END - if + } // ... and a new response object - $responseClass = sprintf('CoreFramework\Response\%sResponse', BaseFrameworkSystem::convertToClassName($request)); + $responseClass = sprintf('Org\Mxchange\CoreFramework\Response\%sResponse', StringUtils::convertToClassName($request)); $responseInstance = ObjectFactory::createObjectByName($responseClass); // Remember response instance here @@ -437,7 +633,7 @@ final class FrameworkBootstrap { } /** - * 3) Validate parameter 'app' if it is set and the application is there. + * 3) Validate parameter 'application' if it is set and the application is there. * * @return void */ @@ -450,22 +646,22 @@ final class FrameworkBootstrap { * application (by user). */ ApplicationEntryPoint::exitApplication('No application specified. Please provide a parameter "app" and retry.'); - } // END - if + } // Get it for local usage - $application = self::getRequestInstance()->getRequestElement('app'); + $applicationName = self::getRequestInstance()->getRequestElement('app'); // Secure it, by keeping out tags - $application = htmlentities(strip_tags($application), ENT_QUOTES); + $applicationName = htmlentities(strip_tags($applicationName), ENT_QUOTES); // Secure it a little more with a reg.exp. - $application = preg_replace('/([^a-z0-9_-])+/i', '', $application); + $applicationName = preg_replace('/([^a-z0-9_-])+/i', '', $applicationName); // Construct FQPN (Full-Qualified Path Name) for ApplicationHelper class $applicationPath = sprintf( '%s%s%s', - FrameworkConfiguration::getSelfInstance()->getConfigEntry('application_base_path'), - $application, + self::getConfigurationInstance()->getConfigEntry('application_base_path'), + $applicationName, DIRECTORY_SEPARATOR ); @@ -473,13 +669,32 @@ final class FrameworkBootstrap { // Is the path there? This secures a bit the parameter (from untrusted source). if ((!is_dir($applicationPath)) || (!is_readable($applicationPath))) { // Not found or not readable - ApplicationEntryPoint::exitApplication(sprintf('Application "%s" not found.', $application)); - } // END - if + ApplicationEntryPoint::exitApplication(sprintf('Application "%s" not found.', $applicationName)); + } // Set the detected application's name and full path for later usage - FrameworkConfiguration::getSelfInstance()->setConfigEntry('detected_full_app_path', $applicationPath); - FrameworkConfiguration::getSelfInstance()->setConfigEntry('detected_app_name' , $application); + self::$detectedApplicationPath = $applicationPath; + self::$detectedApplicationName = $applicationName; + } + + /** + * Getter for request instance + * + * @return $requestInstance An instance of a Requestable class + */ + public static function getRequestInstance () { + return self::$requestInstance; + } + + /** + * Getter for response instance + * + * @return $responseInstance An instance of a Responseable class + */ + public static function getResponseInstance () { + return self::$responseInstance; } + /** * Setter for request instance * @@ -500,4 +715,43 @@ final class FrameworkBootstrap { self::$responseInstance = $responseInstance; } + /** + * Setter for database instance + * + * @param $databaseInstance An instance of a DatabaseConnection class + * @return void + */ + public static function setDatabaseInstance (DatabaseConnection $databaseInstance) { + self::$databaseInstance = $databaseInstance; + } + + /** + * Getter for database instance + * + * @return $databaseInstance An instance of a DatabaseConnection class + */ + public static function getDatabaseInstance () { + // Return instance + return self::$databaseInstance; + } + + /** + * Private getter for language instance + * + * @return $languageInstance An instance of a ManageableLanguage class + */ + public static function getLanguageInstance () { + return self::$languageInstance; + } + + /** + * Setter for language instance + * + * @param $languageInstance An instance of a ManageableLanguage class + * @return void + */ + public static function setLanguageInstance (ManageableLanguage $languageInstance) { + self::$languageInstance = $languageInstance; + } + }