X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=framework%2Fbootstrap%2Fclass_FrameworkBootstrap.php;h=79302a32066ea1e66cc8666ecd69c0b361c5ab64;hb=027c5659e968546a21be37e70d700c7e14cba993;hp=e5d27674116b33130d1acf7e510bbd7af8f6986d;hpb=645d7022e1e74573bd7511fb98ae3ac4e341464e;p=core.git diff --git a/framework/bootstrap/class_FrameworkBootstrap.php b/framework/bootstrap/class_FrameworkBootstrap.php index e5d27674..79302a32 100644 --- a/framework/bootstrap/class_FrameworkBootstrap.php +++ b/framework/bootstrap/class_FrameworkBootstrap.php @@ -8,9 +8,11 @@ use Org\Mxchange\CoreFramework\Connection\Database\DatabaseConnection; use Org\Mxchange\CoreFramework\Connector\Database\DatabaseConnector; use Org\Mxchange\CoreFramework\Console\Tools\ConsoleTools; use Org\Mxchange\CoreFramework\EntryPoint\ApplicationEntryPoint; -use Org\Mxchange\CoreFramework\Factory\ObjectFactory; +use Org\Mxchange\CoreFramework\Factory\Object\ObjectFactory; +use Org\Mxchange\CoreFramework\Generic\FrameworkInterface; use Org\Mxchange\CoreFramework\Generic\NullPointerException; use Org\Mxchange\CoreFramework\Helper\Application\ApplicationHelper; +use Org\Mxchange\CoreFramework\Localization\ManageableLanguage; use Org\Mxchange\CoreFramework\Loader\ClassLoader; use Org\Mxchange\CoreFramework\Manager\ManageableApplication; use Org\Mxchange\CoreFramework\Middleware\Debug\DebugMiddleware; @@ -18,6 +20,7 @@ use Org\Mxchange\CoreFramework\Object\BaseFrameworkSystem; use Org\Mxchange\CoreFramework\Registry\GenericRegistry; use Org\Mxchange\CoreFramework\Request\Requestable; use Org\Mxchange\CoreFramework\Response\Responseable; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; // Import SPL stuff use \BadMethodCallException; @@ -29,7 +32,7 @@ use \SplFileInfo; * * @author Roland Haeder * @version 0.0.0 - * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2020 Core Developer Team + * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2023 Core Developer Team * @license GNU GPL 3.0 or any newer version * @link http://www.ship-simu.org * @@ -73,11 +76,16 @@ final class FrameworkBootstrap { */ 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) @@ -96,7 +104,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 @@ -116,12 +134,30 @@ final class FrameworkBootstrap { if (is_null(self::$configurationInstance)) { // Init new instance self::$configurationInstance = new FrameworkConfiguration(); - } // END - if + } // Return it return self::$configurationInstance; } + /** + * Getter for detected application name + * + * @return $detectedApplicationName Detected name of application + */ + 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; + } + /** * "Getter" to get response/request type from analysis of the system. * @@ -135,7 +171,7 @@ final class FrameworkBootstrap { if (isset($_SERVER['HTTP_HOST'])) { // Then it is a HTML response/request. $requestType = 'html'; - } // END - if + } // Return it return $requestType; @@ -167,8 +203,8 @@ final class FrameworkBootstrap { // Abort lookup as it has been found in open_basedir break; - } // END - if - } // END - foreach + } + } } else { // If open_basedir is not set, all is allowed $isReachable = true; @@ -212,14 +248,12 @@ final class FrameworkBootstrap { * @throws InvalidArgumentException If file was not found or not readable or deprecated */ public static function loadInclude (SplFileInfo $fileInstance) { - // Trace message - //* NOISY-DEBUG: */ printf('[%s:%d]: fileInstance=%s - CALLED!' . PHP_EOL, __METHOD__, __LINE__, $fileInstance); - // Should be there ... + //* NOISY-DEBUG: */ printf('[%s:%d]: fileInstance=%s - CALLED!' . PHP_EOL, __METHOD__, __LINE__, $fileInstance); if (!self::isReadableFile($fileInstance)) { // Abort here throw new InvalidArgumentException(sprintf('Cannot find fileInstance.pathname=%s.', $fileInstance->getPathname())); - } // END - if + } // Load it require_once $fileInstance->getPathname(); @@ -229,20 +263,28 @@ final class FrameworkBootstrap { } /** - * Does the actual bootstrap + * Does the actual bootstrap. I think the amount of statically loaded + * include files cannot be reduced here as those files are need to early + * in the bootstrap phase. If you can find an other solution than this, with + * lesser "static includes" (means not loaded by the class loader), please + * let me know. * * @return void */ public static function doBootstrap () { // Load basic include files to continue bootstrapping + //* NOISY-DEBUG: */ printf('[%s:%d]: CALLED!' . PHP_EOL, __METHOD__, __LINE__); 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%sclass_StringUtils.php', ApplicationEntryPoint::detectFrameworkPath(), DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR))); + self::loadInclude(new SplFileInfo(sprintf('%smain%sclasses%sutils%sstrings%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(new SplFileInfo(sprintf('%s%s', ApplicationEntryPoint::detectFrameworkPath(), 'config-global.php'))); + + // Trace message + //* NOISY-DEBUG: */ printf('[%s:%d]: EXIT!' . PHP_EOL, __METHOD__, __LINE__); } /** @@ -263,7 +305,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). */ @@ -285,25 +327,21 @@ final class FrameworkBootstrap { * @return void */ public static function prepareApplication () { - // Configuration entry 'detected_app_name' must be set, get it here, including full path - $application = self::getConfigurationInstance()->getConfigEntry('detected_app_name'); - $fullPath = self::getConfigurationInstance()->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 file instance - $fileInstance = new SplFileInfo(sprintf('%s%s.php', $fullPath, $fileName)); + $fileInstance = new SplFileInfo(sprintf('%s%s.php', self::getDetectedApplicationPath(), $fileName)); // Determine if this file is wanted/readable/deprecated 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, $fileInstance->getBasename())); + 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.', $fileInstance->getBasename(), $application)); + 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; @@ -312,15 +350,18 @@ 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($fileInstance); - } // END - foreach + } + + // After this, sort the configuration array + self::getConfigurationInstance()->sortConfigurationArray(); // Scan for application's classes, exceptions and interfaces ClassLoader::scanApplicationClasses(); @@ -333,47 +374,39 @@ final class FrameworkBootstrap { * @return void */ public static function startApplication () { - // Configuration entry 'detected_app_name' must be set, get it here - $application = self::getConfigurationInstance()->getConfigEntry('detected_app_name'); - // Is there an application helper instance? $applicationInstance = call_user_func_array( - array( + [ 'Org\Mxchange\CoreFramework\Helper\Application\ApplicationHelper', 'getSelfInstance' - ), array() + ], [] ); // 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, + 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, + 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 + self::getDetectedApplicationName() )); } - // Init template engine - self::getResponseInstance()->initTemplateEngine($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); - + foreach (['setupApplicationData', 'initApplication', 'launchApplication'] as $methodName) { // Call method - call_user_func(array($applicationInstance, $methodName)); - } // END - foreach + //*NOISY-DEBUG: */ printf('[%s:%d]: Calling methodName=%s ...' . PHP_EOL, __METHOD__, __LINE__, $methodName); + call_user_func([$applicationInstance, $methodName]); + } } /** @@ -389,7 +422,7 @@ final class FrameworkBootstrap { if (self::getDatabaseInstance() instanceof DatabaseConnector) { // Yes, then abort here throw new BadMethodCallException('Method called twice.'); - } // END - if + } // Initialize database layer $databaseInstance = ObjectFactory::createObjectByConfiguredName(self::getConfigurationInstance()->getConfigEntry('database_type') . '_class'); @@ -426,7 +459,7 @@ final class FrameworkBootstrap { * 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'])); - } // END - if + } // Al fine, set it self::$serverAddress = $serverIp; @@ -434,7 +467,7 @@ final class FrameworkBootstrap { // Run auto-detecting through console tools lib self::$serverAddress = ConsoleTools::acquireSelfIpAddress(); } - } // END - if + } // Return it return self::$serverAddress; @@ -445,20 +478,13 @@ final class FrameworkBootstrap { * * @param $timezone The timezone string (e.g. Europe/Berlin) * @return $success If timezone was accepted - * @throws NullPointerException If $timezone is NULL * @throws InvalidArgumentException If $timezone is empty */ - public static function setDefaultTimezone ($timezone) { - // Is it null? - if (is_null($timezone)) { - // Throw NPE - throw new NullPointerException(NULL, BaseFrameworkSystem::EXCEPTION_IS_NULL_POINTER); - } elseif (!is_string($timezone)) { - // Is not a string - throw new InvalidArgumentException(sprintf('timezone[]=%s is not a string', gettype($timezone))); - } elseif ((is_string($timezone)) && (empty($timezone))) { + public static function setDefaultTimezone (string $timezone) { + // Is it set? + if (empty($timezone)) { // Entry is empty - throw new InvalidArgumentException('timezone is empty'); + throw new InvalidArgumentException('Parameter "timezone" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } // Default success @@ -511,7 +537,7 @@ final class FrameworkBootstrap { if (self::isHttpSecured()) { // Add the >s< for HTTPS $protocol = 'https'; - } // END - if + } // Construct the full URL and secure it against CSRF attacks $baseUrl = sprintf('%s://%s%s', $protocol, self::detectDomain(), self::detectScriptPath()); @@ -533,7 +559,7 @@ final class FrameworkBootstrap { if (isset($_SERVER['SERVER_NAME'])) { // Detect the full domain $fullDomain = htmlentities(strip_tags($_SERVER['SERVER_NAME']), ENT_QUOTES); - } // END - if + } // Return it return $fullDomain; @@ -553,7 +579,7 @@ final class FrameworkBootstrap { 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'])); - } // END - if + } // Return it return $scriptPath; @@ -572,7 +598,7 @@ final class FrameworkBootstrap { * @return void */ private static function scanFrameworkClasses () { - // Include the class loader function + // Include class loader require self::getConfigurationInstance()->getConfigEntry('framework_base_path') . 'loader/class_ClassLoader.php'; // Register auto-load function with the SPL @@ -594,7 +620,7 @@ final class FrameworkBootstrap { $requestType = self::getRequestTypeFromSystem(); // Create a new request object - $requestInstance = ObjectFactory::createObjectByName(sprintf('Org\Mxchange\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); @@ -604,11 +630,10 @@ final class FrameworkBootstrap { // Then use it $request = strtolower($requestInstance->getRequestElement('request')); $requestType = $request; - } // END - if + } // ... and a new response object - $responseClass = sprintf('Org\Mxchange\CoreFramework\Response\%sResponse', BaseFrameworkSystem::convertToClassName($request)); - $responseInstance = ObjectFactory::createObjectByName($responseClass); + $responseInstance = ObjectFactory::createObjectByName(sprintf('Org\Mxchange\CoreFramework\Response\%sResponse', StringUtils::convertToClassName($request))); // Remember response instance here self::setResponseInstance($responseInstance); @@ -628,22 +653,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', self::getConfigurationInstance()->getConfigEntry('application_base_path'), - $application, + $applicationName, DIRECTORY_SEPARATOR ); @@ -651,12 +676,12 @@ 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 - self::getConfigurationInstance()->setConfigEntry('detected_full_app_path', $applicationPath); - self::getConfigurationInstance()->setConfigEntry('detected_app_name' , $application); + self::$detectedApplicationPath = $applicationPath; + self::$detectedApplicationName = $applicationName; } /** @@ -717,4 +742,23 @@ final class FrameworkBootstrap { 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; + } + }