From: Roland Häder Date: Fri, 8 Jan 2021 06:56:54 +0000 (+0100) Subject: Continued: X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=d11657434a0f9a9fe67b823f501b5cd9742124ae;p=core.git Continued: - moved utilities classes to plural path names and namespaces - added ArrayUtils class for handling arrrays - used that new class' method to map numeric array elements to associative Signed-off-by: Roland Häder --- diff --git a/application/tests/class_ApplicationHelper.php b/application/tests/class_ApplicationHelper.php index 948f821b..e21b8751 100644 --- a/application/tests/class_ApplicationHelper.php +++ b/application/tests/class_ApplicationHelper.php @@ -10,7 +10,7 @@ use Org\Mxchange\CoreFramework\Loader\ClassLoader; use Org\Mxchange\CoreFramework\Manager\ManageableApplication; use Org\Mxchange\CoreFramework\Registry\Registerable; use Org\Mxchange\CoreFramework\Template\CompileableTemplate; -use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; /** * A class holding general data about the application and some methods for diff --git a/framework/bootstrap/class_FrameworkBootstrap.php b/framework/bootstrap/class_FrameworkBootstrap.php index f9ddae7f..6894866e 100644 --- a/framework/bootstrap/class_FrameworkBootstrap.php +++ b/framework/bootstrap/class_FrameworkBootstrap.php @@ -19,7 +19,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\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; // Import SPL stuff use \BadMethodCallException; @@ -247,10 +247,8 @@ 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())); @@ -264,20 +262,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%sstring%sclass_StringUtils.php', ApplicationEntryPoint::detectFrameworkPath(), DIRECTORY_SEPARATOR, 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__); } /** @@ -392,12 +398,10 @@ final class FrameworkBootstrap { } // 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)); + //*NOISY-DEBUG: */ printf('[%s:%d]: Calling methodName=%s ...' . PHP_EOL, __METHOD__, __LINE__, $methodName); + call_user_func([$applicationInstance, $methodName]); } } @@ -590,7 +594,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 @@ -625,8 +629,7 @@ final class FrameworkBootstrap { } // ... and a new response object - $responseClass = sprintf('Org\Mxchange\CoreFramework\Response\%sResponse', StringUtils::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); diff --git a/framework/config/class_FrameworkConfiguration.php b/framework/config/class_FrameworkConfiguration.php index 2afe681b..2984c376 100644 --- a/framework/config/class_FrameworkConfiguration.php +++ b/framework/config/class_FrameworkConfiguration.php @@ -9,7 +9,7 @@ use Org\Mxchange\CoreFramework\Generic\FrameworkInterface; use Org\Mxchange\CoreFramework\Generic\UnsupportedOperationException; use Org\Mxchange\CoreFramework\Object\BaseFrameworkSystem; use Org\Mxchange\CoreFramework\Registry\Registerable; -use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; // Import SPL stuff use \InvalidArgumentException; diff --git a/framework/main/classes/class_BaseFrameworkSystem.php b/framework/main/classes/class_BaseFrameworkSystem.php index 5a7b7537..adda64f4 100644 --- a/framework/main/classes/class_BaseFrameworkSystem.php +++ b/framework/main/classes/class_BaseFrameworkSystem.php @@ -19,7 +19,7 @@ use Org\Mxchange\CoreFramework\Registry\GenericRegistry; use Org\Mxchange\CoreFramework\Result\Database\CachedDatabaseResult; use Org\Mxchange\CoreFramework\State\Stateable; use Org\Mxchange\CoreFramework\Stream\Output\OutputStreamer; -use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; // Import SPL stuff use \stdClass; diff --git a/framework/main/classes/commands/html/class_HtmlLoginAreaCommand.php b/framework/main/classes/commands/html/class_HtmlLoginAreaCommand.php index 9a7b6691..a03fa2b5 100644 --- a/framework/main/classes/commands/html/class_HtmlLoginAreaCommand.php +++ b/framework/main/classes/commands/html/class_HtmlLoginAreaCommand.php @@ -14,7 +14,7 @@ use Org\Mxchange\CoreFramework\Registry\GenericRegistry; use Org\Mxchange\CoreFramework\Request\Requestable; use Org\Mxchange\CoreFramework\Resolver\Command\CommandResolver; use Org\Mxchange\CoreFramework\Response\Responseable; -use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; /** * A command for the login area (member/gamer area) diff --git a/framework/main/classes/criteria/class_BaseCriteria.php b/framework/main/classes/criteria/class_BaseCriteria.php index 8463c416..a477e072 100644 --- a/framework/main/classes/criteria/class_BaseCriteria.php +++ b/framework/main/classes/criteria/class_BaseCriteria.php @@ -6,7 +6,7 @@ namespace Org\Mxchange\CoreFramework\Criteria; use Org\Mxchange\CoreFramework\Bootstrap\FrameworkBootstrap; use Org\Mxchange\CoreFramework\Criteria\Search\SearchCriteria; use Org\Mxchange\CoreFramework\Object\BaseFrameworkSystem; -use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; /** * A general crtieria class diff --git a/framework/main/classes/feature/class_FrameworkFeature.php b/framework/main/classes/feature/class_FrameworkFeature.php index 5b7049e8..5bfb48f5 100644 --- a/framework/main/classes/feature/class_FrameworkFeature.php +++ b/framework/main/classes/feature/class_FrameworkFeature.php @@ -7,7 +7,7 @@ use Org\Mxchange\CoreFramework\Bootstrap\FrameworkBootstrap; use Org\Mxchange\CoreFramework\Factory\Object\ObjectFactory; use Org\Mxchange\CoreFramework\Loader\NoClassException; use Org\Mxchange\CoreFramework\Object\BaseFrameworkSystem; -use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; /** * The general feature management class. No instance is needed as this class diff --git a/framework/main/classes/file_directories/binary/stack/class_StackFile.php b/framework/main/classes/file_directories/binary/stack/class_StackFile.php index 8fc987dc..26294f82 100644 --- a/framework/main/classes/file_directories/binary/stack/class_StackFile.php +++ b/framework/main/classes/file_directories/binary/stack/class_StackFile.php @@ -8,7 +8,7 @@ use Org\Mxchange\CoreFramework\Filesystem\Stack\FileStacker; use Org\Mxchange\CoreFramework\Filesystem\File\BaseBinaryFile; use Org\Mxchange\CoreFramework\Generic\UnsupportedOperationException; use Org\Mxchange\CoreFramework\Stack\File\StackableFile; -use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; // Import SPL stuff use \BadMethodCallException; diff --git a/framework/main/classes/helper/class_BaseHelper.php b/framework/main/classes/helper/class_BaseHelper.php index 5052d76e..5ef47da6 100644 --- a/framework/main/classes/helper/class_BaseHelper.php +++ b/framework/main/classes/helper/class_BaseHelper.php @@ -8,7 +8,7 @@ use Org\Mxchange\CoreFramework\Generic\FrameworkInterface; use Org\Mxchange\CoreFramework\Generic\NullPointerException; use Org\Mxchange\CoreFramework\Object\BaseFrameworkSystem; use Org\Mxchange\CoreFramework\Registry\GenericRegistry; -use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; /** * A generic helper class with generic methods diff --git a/framework/main/classes/helper/html/links/class_HtmlLinkHelper.php b/framework/main/classes/helper/html/links/class_HtmlLinkHelper.php index adcf9843..d61d83cd 100644 --- a/framework/main/classes/helper/html/links/class_HtmlLinkHelper.php +++ b/framework/main/classes/helper/html/links/class_HtmlLinkHelper.php @@ -10,7 +10,7 @@ use Org\Mxchange\CoreFramework\Generic\NullPointerException; use Org\Mxchange\CoreFramework\Helper\Application\ApplicationHelper; use Org\Mxchange\CoreFramework\Helper\Template\HelpableTemplate; use Org\Mxchange\CoreFramework\Registry\GenericRegistry; -use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; use Org\Mxchange\CoreFramework\Template\CompileableTemplate; /** diff --git a/framework/main/classes/index/class_BaseIndex.php b/framework/main/classes/index/class_BaseIndex.php index e0e68beb..ca13dbc8 100644 --- a/framework/main/classes/index/class_BaseIndex.php +++ b/framework/main/classes/index/class_BaseIndex.php @@ -8,7 +8,7 @@ use Org\Mxchange\CoreFramework\Factory\Object\ObjectFactory; use Org\Mxchange\CoreFramework\Filesystem\File\BaseBinaryFile; use Org\Mxchange\CoreFramework\Generic\UnsupportedOperationException; use Org\Mxchange\CoreFramework\Object\BaseFrameworkSystem; -use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; use Org\Mxchange\CoreFramework\Traits\Iterator\IteratorTrait; // Import SPL stuff diff --git a/framework/main/classes/index/file/class_BaseFileIndex.php b/framework/main/classes/index/file/class_BaseFileIndex.php index 47cac677..ae2fa3a9 100644 --- a/framework/main/classes/index/file/class_BaseFileIndex.php +++ b/framework/main/classes/index/file/class_BaseFileIndex.php @@ -9,7 +9,7 @@ use Org\Mxchange\CoreFramework\Filesystem\File\BaseBinaryFile; use Org\Mxchange\CoreFramework\Filesystem\File\BinaryFile; use Org\Mxchange\CoreFramework\Index\BaseIndex; use Org\Mxchange\CoreFramework\Index\Indexable; -use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; // Import SPL stuff use \OutOfBoundsException; diff --git a/framework/main/classes/request/html/class_HtmlRequest.php b/framework/main/classes/request/html/class_HtmlRequest.php index 78310b00..5620782a 100644 --- a/framework/main/classes/request/html/class_HtmlRequest.php +++ b/framework/main/classes/request/html/class_HtmlRequest.php @@ -4,7 +4,7 @@ namespace Org\Mxchange\CoreFramework\Request; // Import framework stuff use Org\Mxchange\CoreFramework\Request\Requestable; -use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; /** * A concrete and secured HTML request class to make HTML requests more abstract diff --git a/framework/main/classes/resolver/action/class_BaseActionResolver.php b/framework/main/classes/resolver/action/class_BaseActionResolver.php index 1cb83cec..856ed621 100644 --- a/framework/main/classes/resolver/action/class_BaseActionResolver.php +++ b/framework/main/classes/resolver/action/class_BaseActionResolver.php @@ -5,7 +5,7 @@ namespace Org\Mxchange\CoreFramework\Resolver\Action; // Import framework stuff use Org\Mxchange\CoreFramework\Factory\Object\ObjectFactory; use Org\Mxchange\CoreFramework\Resolver\BaseResolver; -use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; // Import SPL stuff use \InvalidArgumentException; diff --git a/framework/main/classes/resolver/class_BaseResolver.php b/framework/main/classes/resolver/class_BaseResolver.php index dddb5626..a1f399a2 100644 --- a/framework/main/classes/resolver/class_BaseResolver.php +++ b/framework/main/classes/resolver/class_BaseResolver.php @@ -5,7 +5,7 @@ namespace Org\Mxchange\CoreFramework\Resolver; // Import framework stuff use Org\Mxchange\CoreFramework\Generic\FrameworkInterface; use Org\Mxchange\CoreFramework\Object\BaseFrameworkSystem; -use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; /** * A generic resolver class diff --git a/framework/main/classes/resolver/command/class_BaseCommandResolver.php b/framework/main/classes/resolver/command/class_BaseCommandResolver.php index c18046bf..3d4eaaaf 100644 --- a/framework/main/classes/resolver/command/class_BaseCommandResolver.php +++ b/framework/main/classes/resolver/command/class_BaseCommandResolver.php @@ -9,7 +9,7 @@ use Org\Mxchange\CoreFramework\Command\InvalidCommandException; use Org\Mxchange\CoreFramework\Factory\Object\ObjectFactory; use Org\Mxchange\CoreFramework\Request\Requestable; use Org\Mxchange\CoreFramework\Resolver\BaseResolver; -use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; // Import SPL stuff use \InvalidArgumentException; diff --git a/framework/main/classes/resolver/controller/class_BaseControllerResolver.php b/framework/main/classes/resolver/controller/class_BaseControllerResolver.php index 2d3669aa..8ee3ddd6 100644 --- a/framework/main/classes/resolver/controller/class_BaseControllerResolver.php +++ b/framework/main/classes/resolver/controller/class_BaseControllerResolver.php @@ -12,7 +12,7 @@ use Org\Mxchange\CoreFramework\Helper\Application\ApplicationHelper; use Org\Mxchange\CoreFramework\Registry\GenericRegistry; use Org\Mxchange\CoreFramework\Resolver\BaseResolver; use Org\Mxchange\CoreFramework\Resolver\Controller\ControllerResolver; -use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; // Import SPL stuff use \InvalidArgumentException; diff --git a/framework/main/classes/stacker/file/class_BaseFileStack.php b/framework/main/classes/stacker/file/class_BaseFileStack.php index badedcb7..59aac997 100644 --- a/framework/main/classes/stacker/file/class_BaseFileStack.php +++ b/framework/main/classes/stacker/file/class_BaseFileStack.php @@ -11,7 +11,8 @@ use Org\Mxchange\CoreFramework\Generic\UnsupportedOperationException; use Org\Mxchange\CoreFramework\Stack\BaseStacker; use Org\Mxchange\CoreFramework\Traits\Index\IndexableTrait; use Org\Mxchange\CoreFramework\Traits\Iterator\IteratorTrait; -use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Arrays\ArrayUtils; // Import SPL stuff use \InvalidArgumentException; @@ -125,39 +126,50 @@ abstract class BaseFileStack extends BaseStacker { */ $header = explode(chr(BinaryFile::SEPARATOR_HEADER_DATA), $data); + // Map numeric indexes to associative indexes + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: header()=%d', count($header))); + $header = ArrayUtils::mapNumericKeysToAssociative($header, [ + BinaryFile::HEADER_NAME_MAGIC, + BinaryFile::HEADER_NAME_TOTAL_ENTRIES, + BinaryFile::HEADER_NAME_SEEK_POSITION, + ]); + // Check if the array has only 3 elements - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: header(%d)=%s', count($header), print_r($header, true))); - if (count($header) != 3) { + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: HEADER_ELEMENT_COUNT=%d,header(%d)=%s', BinaryFile::HEADER_ELEMENT_COUNT, count($header), print_r($header, true))); + if (count($header) != BinaryFile::HEADER_ELEMENT_COUNT) { // Header array count is not expected - throw new UnexpectedValueException(sprintf('data=%s has %d elements, expected 3', + throw new UnexpectedValueException(sprintf('data=%s has %d elements, but expected is %d', $data, - count($header) + count($header), + BinaryFile::HEADER_ELEMENT_COUNT )); - } elseif ($header[0] != StackableFile::STACK_MAGIC) { + } elseif ($header[BinaryFile::HEADER_NAME_MAGIC] != StackableFile::STACK_MAGIC) { // Bad magic throw new InvalidMagicException($data, self::EXCEPTION_BAD_MAGIC); } // Check length of count and seek position - if (strlen($header[1]) != BinaryFile::LENGTH_COUNT) { + if (strlen($header[BinaryFile::HEADER_NAME_TOTAL_ENTRIES]) != BinaryFile::LENGTH_COUNT) { // Count length not valid - throw new UnexpectedValueException(sprintf('header[1](%d)=%s is not expected %d length', - strlen($header[1]), - $header[1], + throw new UnexpectedValueException(sprintf('header[%s](%d)=%s is not expected %d length', + BinaryFile::HEADER_NAME_TOTAL_ENTRIES, + strlen($header[BinaryFile::HEADER_NAME_TOTAL_ENTRIES]), + $header[BinaryFile::HEADER_NAME_TOTAL_ENTRIES], BinaryFile::LENGTH_COUNT )); - } elseif (strlen($header[1]) != BinaryFile::LENGTH_POSITION) { + } elseif (strlen($header[BinaryFile::HEADER_NAME_SEEK_POSITION]) != BinaryFile::LENGTH_POSITION) { // Position length not valid - throw new UnexpectedValueException(sprintf('header[2](%d)=%s is not expected %d length', - strlen($header[1]), - $header[1], + throw new UnexpectedValueException(sprintf('header[%s](%d)=%s is not expected %d length', + BinaryFile::HEADER_NAME_SEEK_POSITION, + strlen($header[BinaryFile::HEADER_NAME_SEEK_POSITION]), + $header[BinaryFile::HEADER_NAME_SEEK_POSITION], BinaryFile::LENGTH_POSITION )); } // Decode count and seek position - $header[1] = hex2bin($header[1]); - $header[2] = hex2bin($header[2]); + $header[BinaryFile::HEADER_NAME_TOTAL_ENTRIES] = hex2bin($header[BinaryFile::HEADER_NAME_TOTAL_ENTRIES]); + $header[BinaryFile::HEADER_NAME_SEEK_POSITION] = hex2bin($header[BinaryFile::HEADER_NAME_SEEK_POSITION]); // Set header here $this->getIteratorInstance()->getBinaryFileInstance()->setHeader($header); diff --git a/framework/main/classes/template/class_BaseTemplateEngine.php b/framework/main/classes/template/class_BaseTemplateEngine.php index 9dd3b358..36dabc28 100644 --- a/framework/main/classes/template/class_BaseTemplateEngine.php +++ b/framework/main/classes/template/class_BaseTemplateEngine.php @@ -14,7 +14,7 @@ use Org\Mxchange\CoreFramework\Object\BaseFrameworkSystem; use Org\Mxchange\CoreFramework\Registry\GenericRegistry; use Org\Mxchange\CoreFramework\Response\Responseable; use Org\Mxchange\CoreFramework\Traits\Handler\Io\IoHandlerTrait; -use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; // Import SPL stuff use \InvalidArgumentException; diff --git a/framework/main/classes/template/image/class_ImageTemplateEngine.php b/framework/main/classes/template/image/class_ImageTemplateEngine.php index a3ce9cc0..c9268cfe 100644 --- a/framework/main/classes/template/image/class_ImageTemplateEngine.php +++ b/framework/main/classes/template/image/class_ImageTemplateEngine.php @@ -13,7 +13,7 @@ use Org\Mxchange\CoreFramework\Registry\GenericRegistry; use Org\Mxchange\CoreFramework\Response\Responseable; use Org\Mxchange\CoreFramework\Template\CompileableTemplate; use Org\Mxchange\CoreFramework\Template\Engine\BaseTemplateEngine; -use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; // Import SPL stuff use \SplFileInfo; diff --git a/framework/main/classes/template/mail/class_MailTemplateEngine.php b/framework/main/classes/template/mail/class_MailTemplateEngine.php index f1afd899..2f80bf29 100644 --- a/framework/main/classes/template/mail/class_MailTemplateEngine.php +++ b/framework/main/classes/template/mail/class_MailTemplateEngine.php @@ -12,7 +12,7 @@ use Org\Mxchange\CoreFramework\Registry\GenericRegistry; use Org\Mxchange\CoreFramework\Response\Responseable; use Org\Mxchange\CoreFramework\Template\CompileableTemplate; use Org\Mxchange\CoreFramework\Template\Engine\BaseTemplateEngine; -use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; // Import SPL stuff use \UnexpectedValueException; diff --git a/framework/main/classes/template/menu/class_MenuTemplateEngine.php b/framework/main/classes/template/menu/class_MenuTemplateEngine.php index 82c1ca6c..a16b9de5 100644 --- a/framework/main/classes/template/menu/class_MenuTemplateEngine.php +++ b/framework/main/classes/template/menu/class_MenuTemplateEngine.php @@ -13,7 +13,7 @@ use Org\Mxchange\CoreFramework\Registry\GenericRegistry; use Org\Mxchange\CoreFramework\Template\Engine\BaseTemplateEngine; use Org\Mxchange\CoreFramework\Template\CompileableTemplate; use Org\Mxchange\CoreFramework\Traits\Stack\StackableTrait; -use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; // Import SPL stuff use \SplFileInfo; diff --git a/framework/main/classes/template/xml/class_BaseXmlTemplateEngine.php b/framework/main/classes/template/xml/class_BaseXmlTemplateEngine.php index 039b45df..fdff28d1 100644 --- a/framework/main/classes/template/xml/class_BaseXmlTemplateEngine.php +++ b/framework/main/classes/template/xml/class_BaseXmlTemplateEngine.php @@ -13,7 +13,7 @@ use Org\Mxchange\CoreFramework\Template\Engine\BaseTemplateEngine; use Org\Mxchange\CoreFramework\Template\Xml\CompileableXmlTemplate; use Org\Mxchange\CoreFramework\Traits\Stack\StackableTrait; use Org\Mxchange\CoreFramework\Traits\Template\CompileableTemplateTrait; -use Org\Mxchange\CoreFramework\Utils\String\StringUtils; +use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils; // Import SPL stuff use \InvalidArgumentException; diff --git a/framework/main/classes/utils/arrays/class_ArrayUtils.php b/framework/main/classes/utils/arrays/class_ArrayUtils.php new file mode 100644 index 00000000..8095ce0a --- /dev/null +++ b/framework/main/classes/utils/arrays/class_ArrayUtils.php @@ -0,0 +1,87 @@ + + * @version 0.0.0 + * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2021 Core Developer Team + * @license GNU GPL 3.0 or any newer version + * @link http://www.ship-simu.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 . + */ +final class ArrayUtils extends BaseFrameworkSystem { + /** + * Private constructor, no instance needed. If PHP would have a static initializer ... + * + * @return void + */ + private function __construct () { + // Call parent constructor + parent::__construct(__CLASS__); + } + + /** + * Maps numeric array keys to their corresponding associative + * (alpha-numberic) parts. + * + * @param $numericArray The array the mapping shall happen on + * @param $mapping Numeric array to map all elements from numeric keys to alpha-numeric keys + * @return $mappedArray An array with mapped values + * @throws InvalidArgumentException If a aparameter is not valid + */ + public static function mapNumericKeysToAssociative (array $numericArray, array $mapping) { + // Validate parameters + if (count($numericArray) == 0) { + // Throw IAE + throw new InvalidArgumentException('Array "numericArray" is empty'); + } elseif (count($mapping) == 0) { + // Throw it again + throw new InvalidArgumentException('Array "mapping" is empty'); + } elseif (count($numericArray) != count($mapping)) { + // Throw it yet again + throw new InvalidArgumentException(sprintf('numericArray()=%d does not match mapping()=%d', count($numericArray), count($mapping))); + } + + // Init mapped array + $mappedArray = []; + + // "Walk" over the mapping array + foreach ($mapping as $sourceIndex => $targetName) { + // Is the source index not there? + if (!array_key_exists($sourceIndex, $numericArray)) { + // Should always be there! + throw new OutOfBoundsException(sprintf('numericArray[%d] does not exist.', $sourceIndex)); + } + + // "Map" (copy) it to new array + $mappedArray[$targetName] = $numericArray[$sourceIndex]; + } + + // Return fully mapped array + return $mappedArray; + } + +} diff --git a/framework/main/classes/utils/number/class_NumberUtils.php b/framework/main/classes/utils/number/class_NumberUtils.php deleted file mode 100644 index b09c8e1e..00000000 --- a/framework/main/classes/utils/number/class_NumberUtils.php +++ /dev/null @@ -1,138 +0,0 @@ - - * @version 0.0.0 - * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2021 Core Developer Team - * @license GNU GPL 3.0 or any newer version - * @link http://www.ship-simu.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 . - */ -final class NumberUtils extends BaseFrameworkSystem { - - /** - * Private constructor, no instance needed. If PHP would have a static initializer ... - * - * @return void - */ - private function __construct () { - // Call parent constructor - parent::__construct(__CLASS__); - } - - /** - * Filter a given number into a localized number - * - * @param $value The raw value from e.g. database - * @return $localized Localized value - */ - public static function doFilterFormatNumber ($value) { - // Generate it from config and localize dependencies - switch (FrameworkBootstrap::getLanguageInstance()->getLanguageCode()) { - case 'de': // German format is a bit different to default - $localized = number_format($value, FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('decimals'), ',', '.'); - break; - - default: // US, etc. - $localized = number_format($value, FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('decimals'), '.', ','); - break; - } - - // Return it - return $localized; - } - - /** - * 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 static function doFilterFormatTimestamp ($timestamp) { - // Default value to return - $readable = '???'; - - // Is the timestamp null? - if (is_null($timestamp)) { - // Get a message string - $readable = FrameworkBootstrap::getLanguageInstance()->getMessage('null_timestamp'); - } else { - switch (FrameworkBootstrap::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(FrameworkBootstrap::getConfigurationInstance()->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; - } - } - - // Return the stamp - return $readable; - } - - /** - * Checks whether the given number is really a number (only chars 0-9). - * - * @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 - */ - public static function bigintval (string $num, bool $castValue = true, bool $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; - } - - // Assert only if requested - if ($assertMismatch === true) { - // Has the whole value changed? - assert(('' . $ret . '' != '' . $num . '') && (!is_null($num))); - } - - // Return result - return $ret; - } - -} diff --git a/framework/main/classes/utils/numbers/class_NumberUtils.php b/framework/main/classes/utils/numbers/class_NumberUtils.php new file mode 100644 index 00000000..02cc8e36 --- /dev/null +++ b/framework/main/classes/utils/numbers/class_NumberUtils.php @@ -0,0 +1,137 @@ + + * @version 0.0.0 + * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2021 Core Developer Team + * @license GNU GPL 3.0 or any newer version + * @link http://www.ship-simu.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 . + */ +final class NumberUtils extends BaseFrameworkSystem { + /** + * Private constructor, no instance needed. If PHP would have a static initializer ... + * + * @return void + */ + private function __construct () { + // Call parent constructor + parent::__construct(__CLASS__); + } + + /** + * Filter a given number into a localized number + * + * @param $value The raw value from e.g. database + * @return $localized Localized value + */ + public static function doFilterFormatNumber ($value) { + // Generate it from config and localize dependencies + switch (FrameworkBootstrap::getLanguageInstance()->getLanguageCode()) { + case 'de': // German format is a bit different to default + $localized = number_format($value, FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('decimals'), ',', '.'); + break; + + default: // US, etc. + $localized = number_format($value, FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('decimals'), '.', ','); + break; + } + + // Return it + return $localized; + } + + /** + * 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 static function doFilterFormatTimestamp ($timestamp) { + // Default value to return + $readable = '???'; + + // Is the timestamp null? + if (is_null($timestamp)) { + // Get a message string + $readable = FrameworkBootstrap::getLanguageInstance()->getMessage('null_timestamp'); + } else { + switch (FrameworkBootstrap::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(FrameworkBootstrap::getConfigurationInstance()->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; + } + } + + // Return the stamp + return $readable; + } + + /** + * Checks whether the given number is really a number (only chars 0-9). + * + * @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 $formatted The (hopefully) secured numbered value + */ + public static function bigintval (string $num, bool $castValue = true, bool $assertMismatch = false) { + // Filter all numbers out + $formatted = preg_replace('/[^0123456789]/', '', $num); + + // Shall we cast? + if ($castValue === true) { + // Cast to biggest numeric type, int is not enough for this cast + $formatted = (double) $formatted; + } + + // Assert only if requested + if ($assertMismatch === true) { + // Has the whole value changed? + assert(('' . $formatted . '' != '' . $num . '') && (!is_null($num))); + } + + // Return result + return $formatted; + } + +} diff --git a/framework/main/classes/utils/string/class_StringUtils.php b/framework/main/classes/utils/string/class_StringUtils.php deleted file mode 100644 index 476700af..00000000 --- a/framework/main/classes/utils/string/class_StringUtils.php +++ /dev/null @@ -1,440 +0,0 @@ - - * @version 0.0.0 - * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2021 Core Developer Team - * @license GNU GPL 3.0 or any newer version - * @link http://www.ship-simu.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 . - */ -final class StringUtils extends BaseFrameworkSystem { - /** - * Thousands separator - */ - private static $thousands = ''; // German - - /** - * Decimal separator - */ - private static $decimals = ''; // German - - /** - * Array with bitmasks and such for pack/unpack methods to support both - * 32-bit and 64-bit systems - */ - private static $packingData = [ - 32 => [ - 'step' => 3, - 'left' => 0xffff0000, - 'right' => 0x0000ffff, - 'factor' => 16, - 'format' => 'II', - ], - 64 => [ - 'step' => 7, - 'left' => 0xffffffff00000000, - 'right' => 0x00000000ffffffff, - 'factor' => 32, - 'format' => 'NN' - ] - ]; - - /** - * Hexadecimal->Decimal translation array - */ - private static $hexdec = [ - '0' => 0, - '1' => 1, - '2' => 2, - '3' => 3, - '4' => 4, - '5' => 5, - '6' => 6, - '7' => 7, - '8' => 8, - '9' => 9, - 'a' => 10, - 'b' => 11, - 'c' => 12, - 'd' => 13, - 'e' => 14, - 'f' => 15 - ]; - - /** - * Decimal->hexadecimal translation array - */ - private static $dechex = [ - 0 => '0', - 1 => '1', - 2 => '2', - 3 => '3', - 4 => '4', - 5 => '5', - 6 => '6', - 7 => '7', - 8 => '8', - 9 => '9', - 10 => 'a', - 11 => 'b', - 12 => 'c', - 13 => 'd', - 14 => 'e', - 15 => 'f' - ]; - - /** - * Simple 64-bit check, thanks to "Salman A" from stackoverflow.com: - * - * The integer size is 4 bytes on 32-bit and 8 bytes on a 64-bit system. - */ - private static $archArrayElement = 0; - - /** - * Private constructor, no instance needed. If PHP would have a static initializer ... - * - * @return void - */ - private function __construct () { - // Call parent constructor - parent::__construct(__CLASS__); - - // Is one not set? - if (empty(self::$archArrayElement)) { - // Set array element - self::$archArrayElement = (PHP_INT_SIZE === 8 ? 64 : 32); - - // Init from configuration - self::$thousands = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('thousands_separator'); - self::$decimals = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('decimals_separator'); - } - } - - /** - * 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 - * @throws NullPointerException If $str is null - * @throws InvalidArgumentException If $str is empty - */ - public static function convertDashesToUnderscores (string $str) { - // Validate parameter - if (empty($str)) { - // Entry is empty - throw new InvalidArgumentException('Parameter "str" is empty'); - } - - // Convert them all - $str = str_replace('-', '_', $str); - - // Return converted string - return $str; - } - - /** - * Encodes raw data (almost any type) by "serializing" it and then pack it - * into a "binary format". - * - * @param $rawData Raw data (almost any type) - * @return $encoded Encoded data - * @throws InvalidArgumentException If $rawData has a non-serializable data type - */ - public static function encodeData ($rawData) { - // Make sure no objects or resources pass through - //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('STRING-UTILS: rawData[]=%s - CALLED!', gettype($rawData))); - if (is_object($rawData) || is_resource($rawData)) { - // Not all variable types should be serialized here - throw new InvalidArgumentException(sprintf('rawData[]=%s cannot be serialized.', gettype($rawData))); - } - - // Init instance - $dummyInstance = new StringUtils(); - - // First "serialize" it (json_encode() is faster than serialize()) - $encoded = self::packString(json_encode($rawData)); - - // And return it - //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('STRING-UTILS: encoded()=%d - EXIT!', strlen($encoded))); - return $encoded; - } - - /** - * 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 static final function convertToClassName (string $str) { - // Init class name - $className = ''; - - // Convert all dashes in underscores - $str = self::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)); - } - - // Return class name - return $className; - } - - /** - * 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 static function formatCurrency (float $value, string $currency = '€', int $decNum = 2) { - // Init instance - $dummyInstance = new StringUtils(); - - // Reformat the US number - $price = number_format($value, $decNum, self::$decimals, self::$thousands) . $currency; - - // Return as string... - return $price; - } - - /** - * 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 - */ - public static function hex2dec (string $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); - } - - // 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)); - } - - // 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 - */ - public static function dec2hex (string $dec, int $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); - } - - // 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 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 - */ - public static function asc2dec (string $asc) { - // Convert it into a hexadecimal number - $hex = bin2hex($asc); - - // And back into a decimal number - $dec = self::hex2dec($hex); - - // Return it - return $dec; - } - - /** - * Converts a decimal number into an ASCII string. - * - * @param $dec Decimal number - * @return $asc An ASCII string - */ - public static function dec2asc (string $dec) { - // First convert the number into a hexadecimal string - $hex = self::dec2hex($dec); - - // Then convert it into the ASCII string - $asc = self::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 - */ - public static function hex2asc ($hex) { - // Check for length, it must be devideable by 2 - //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->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); - } - - // Return the final string - return $asc; - } - - /** - * Pack a string into a "binary format". Please execuse me that this is - * widely undocumented. :-( - * - * @param $str Unpacked string - * @return $packed Packed string - * @todo Improve documentation - */ - private static function packString (string $str) { - // First compress the string (gzcompress is okay) - //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('STRING-UTILS: str=%s - CALLED!', $str)); - $str = gzcompress($str); - - // Init variable - $packed = ''; - - // And start the "encoding" loop - for ($idx = 0; $idx < strlen($str); $idx += self::$packingData[self::$archArrayElement]['step']) { - $big = 0; - for ($i = 0; $i < self::$packingData[self::$archArrayElement]['step']; $i++) { - $factor = (self::$packingData[self::$archArrayElement]['step'] - 1 - $i); - - if (($idx + $i) <= strlen($str)) { - $ord = ord(substr($str, ($idx + $i), 1)); - - $add = $ord * pow(256, $factor); - - $big += $add; - - //print 'idx=' . $idx . ',i=' . $i . ',ord=' . $ord . ',factor=' . $factor . ',add=' . $add . ',big=' . $big . PHP_EOL; - } - } - - // Left/right parts (low/high?) - $l = ($big & self::$packingData[self::$archArrayElement]['left']) >>self::$packingData[self::$archArrayElement]['factor']; - $r = $big & self::$packingData[self::$archArrayElement]['right']; - - // Create chunk - $chunk = str_pad(pack(self::$packingData[self::$archArrayElement]['format'], $l, $r), 8, '0', STR_PAD_LEFT); - //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('STRING-UTILS: big=%d,chunk(%d)=%s', $big, strlen($chunk), md5($chunk))); - - $packed .= $chunk; - } // END - for - - // Return it - //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('STRING-UTILS: packed=%s - EXIT!', $packed)); - return $packed; - } - - /** - * Checks whether the given hexadecimal number is really a hex-number (only chars 0-9,a-f). - * - * @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 static function hexval (string $num, bool $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))); - } - - // Return result - return $ret; - } - -} diff --git a/framework/main/classes/utils/strings/class_StringUtils.php b/framework/main/classes/utils/strings/class_StringUtils.php new file mode 100644 index 00000000..8ca43ddf --- /dev/null +++ b/framework/main/classes/utils/strings/class_StringUtils.php @@ -0,0 +1,440 @@ + + * @version 0.0.0 + * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2021 Core Developer Team + * @license GNU GPL 3.0 or any newer version + * @link http://www.ship-simu.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 . + */ +final class StringUtils extends BaseFrameworkSystem { + /** + * Thousands separator + */ + private static $thousands = ''; // German + + /** + * Decimal separator + */ + private static $decimals = ''; // German + + /** + * Array with bitmasks and such for pack/unpack methods to support both + * 32-bit and 64-bit systems + */ + private static $packingData = [ + 32 => [ + 'step' => 3, + 'left' => 0xffff0000, + 'right' => 0x0000ffff, + 'factor' => 16, + 'format' => 'II', + ], + 64 => [ + 'step' => 7, + 'left' => 0xffffffff00000000, + 'right' => 0x00000000ffffffff, + 'factor' => 32, + 'format' => 'NN' + ] + ]; + + /** + * Hexadecimal->Decimal translation array + */ + private static $hexdec = [ + '0' => 0, + '1' => 1, + '2' => 2, + '3' => 3, + '4' => 4, + '5' => 5, + '6' => 6, + '7' => 7, + '8' => 8, + '9' => 9, + 'a' => 10, + 'b' => 11, + 'c' => 12, + 'd' => 13, + 'e' => 14, + 'f' => 15 + ]; + + /** + * Decimal->hexadecimal translation array + */ + private static $dechex = [ + 0 => '0', + 1 => '1', + 2 => '2', + 3 => '3', + 4 => '4', + 5 => '5', + 6 => '6', + 7 => '7', + 8 => '8', + 9 => '9', + 10 => 'a', + 11 => 'b', + 12 => 'c', + 13 => 'd', + 14 => 'e', + 15 => 'f' + ]; + + /** + * Simple 64-bit check, thanks to "Salman A" from stackoverflow.com: + * + * The integer size is 4 bytes on 32-bit and 8 bytes on a 64-bit system. + */ + private static $archArrayElement = 0; + + /** + * Private constructor, no instance needed. If PHP would have a static initializer ... + * + * @return void + */ + private function __construct () { + // Call parent constructor + parent::__construct(__CLASS__); + + // Is one not set? + if (empty(self::$archArrayElement)) { + // Set array element + self::$archArrayElement = (PHP_INT_SIZE === 8 ? 64 : 32); + + // Init from configuration + self::$thousands = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('thousands_separator'); + self::$decimals = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('decimals_separator'); + } + } + + /** + * 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 + * @throws NullPointerException If $str is null + * @throws InvalidArgumentException If $str is empty + */ + public static function convertDashesToUnderscores (string $str) { + // Validate parameter + if (empty($str)) { + // Entry is empty + throw new InvalidArgumentException('Parameter "str" is empty'); + } + + // Convert them all + $str = str_replace('-', '_', $str); + + // Return converted string + return $str; + } + + /** + * Encodes raw data (almost any type) by "serializing" it and then pack it + * into a "binary format". + * + * @param $rawData Raw data (almost any type) + * @return $encoded Encoded data + * @throws InvalidArgumentException If $rawData has a non-serializable data type + */ + public static function encodeData ($rawData) { + // Make sure no objects or resources pass through + //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('STRING-UTILS: rawData[]=%s - CALLED!', gettype($rawData))); + if (is_object($rawData) || is_resource($rawData)) { + // Not all variable types should be serialized here + throw new InvalidArgumentException(sprintf('rawData[]=%s cannot be serialized.', gettype($rawData))); + } + + // Init instance + $dummyInstance = new StringUtils(); + + // First "serialize" it (json_encode() is faster than serialize()) + $encoded = self::packString(json_encode($rawData)); + + // And return it + //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('STRING-UTILS: encoded()=%d - EXIT!', strlen($encoded))); + return $encoded; + } + + /** + * 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 static final function convertToClassName (string $str) { + // Init class name + $className = ''; + + // Convert all dashes in underscores + $str = self::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)); + } + + // Return class name + return $className; + } + + /** + * 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 static function formatCurrency (float $value, string $currency = '€', int $decNum = 2) { + // Init instance + $dummyInstance = new StringUtils(); + + // Reformat the US number + $price = number_format($value, $decNum, self::$decimals, self::$thousands) . $currency; + + // Return as string... + return $price; + } + + /** + * 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 + */ + public static function hex2dec (string $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); + } + + // 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)); + } + + // 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 + */ + public static function dec2hex (string $dec, int $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); + } + + // 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 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 + */ + public static function asc2dec (string $asc) { + // Convert it into a hexadecimal number + $hex = bin2hex($asc); + + // And back into a decimal number + $dec = self::hex2dec($hex); + + // Return it + return $dec; + } + + /** + * Converts a decimal number into an ASCII string. + * + * @param $dec Decimal number + * @return $asc An ASCII string + */ + public static function dec2asc (string $dec) { + // First convert the number into a hexadecimal string + $hex = self::dec2hex($dec); + + // Then convert it into the ASCII string + $asc = self::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 + */ + public static function hex2asc ($hex) { + // Check for length, it must be devideable by 2 + //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->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); + } + + // Return the final string + return $asc; + } + + /** + * Pack a string into a "binary format". Please execuse me that this is + * widely undocumented. :-( + * + * @param $str Unpacked string + * @return $packed Packed string + * @todo Improve documentation + */ + private static function packString (string $str) { + // First compress the string (gzcompress is okay) + //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('STRING-UTILS: str=%s - CALLED!', $str)); + $str = gzcompress($str); + + // Init variable + $packed = ''; + + // And start the "encoding" loop + for ($idx = 0; $idx < strlen($str); $idx += self::$packingData[self::$archArrayElement]['step']) { + $big = 0; + for ($i = 0; $i < self::$packingData[self::$archArrayElement]['step']; $i++) { + $factor = (self::$packingData[self::$archArrayElement]['step'] - 1 - $i); + + if (($idx + $i) <= strlen($str)) { + $ord = ord(substr($str, ($idx + $i), 1)); + + $add = $ord * pow(256, $factor); + + $big += $add; + + //print 'idx=' . $idx . ',i=' . $i . ',ord=' . $ord . ',factor=' . $factor . ',add=' . $add . ',big=' . $big . PHP_EOL; + } + } + + // Left/right parts (low/high?) + $l = ($big & self::$packingData[self::$archArrayElement]['left']) >>self::$packingData[self::$archArrayElement]['factor']; + $r = $big & self::$packingData[self::$archArrayElement]['right']; + + // Create chunk + $chunk = str_pad(pack(self::$packingData[self::$archArrayElement]['format'], $l, $r), 8, '0', STR_PAD_LEFT); + //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('STRING-UTILS: big=%d,chunk(%d)=%s', $big, strlen($chunk), md5($chunk))); + + $packed .= $chunk; + } // END - for + + // Return it + //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('STRING-UTILS: packed=%s - EXIT!', $packed)); + return $packed; + } + + /** + * Checks whether the given hexadecimal number is really a hex-number (only chars 0-9,a-f). + * + * @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 static function hexval (string $num, bool $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))); + } + + // Return result + return $ret; + } + +}