From 99211861eb60cc2d0baa1f4408d88a08e412f46e Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Mon, 9 Oct 2023 22:06:39 +0000 Subject: [PATCH] update --- Algorithm/Clustering/Kmeans.php | 2 +- Algorithm/Maze/MazeGenerator.php | 2 +- Business/BusinessHelper.php | 27 ++++++ .../Database/Mapper/DataMapperFactory.php | 14 +++ DataStorage/Database/Mapper/MapperType.php | 6 +- DataStorage/Database/Mapper/ReadMapper.php | 42 ++++++++- DataStorage/Database/Mapper/WriteMapper.php | 7 +- Localization/ISO3166NameEnum.php | 22 ++--- Localization/ISO3166Trait.php | 44 ++++++++- Localization/RegionEnum.php | 92 +++++++++++++++++++ Message/ResponseAbstract.php | 2 +- Stdlib/Base/Enum.php | 3 +- Stdlib/Base/EnumArray.php | 4 +- Stdlib/Base/FloatInt.php | 6 +- Stdlib/Base/SmartDateTime.php | 44 +++++++++ Utils/Barcode/QR.php | 2 +- Utils/Parser/Markdown/Markdown.php | 8 +- Utils/RnG/File.php | 4 +- Utils/RnG/Name.php | 4 +- Utils/RnG/Phone.php | 2 +- tests/Message/Http/HttpResponseTest.php | 2 +- tests/Message/ResponseAbstractTest.php | 4 +- tests/Module/ModuleAbstractTest.php | 4 +- 23 files changed, 302 insertions(+), 45 deletions(-) create mode 100644 Business/BusinessHelper.php create mode 100644 Localization/RegionEnum.php diff --git a/Algorithm/Clustering/Kmeans.php b/Algorithm/Clustering/Kmeans.php index e11bc7e55..99399320e 100755 --- a/Algorithm/Clustering/Kmeans.php +++ b/Algorithm/Clustering/Kmeans.php @@ -207,7 +207,7 @@ final class Kmeans */ private function kpp(array $points, int $n) : array { - $clusters = [clone $points[\mt_rand(0, \count($points) - 1)]]; + $clusters = [clone $points[\array_rand($points, 1)]]; $d = \array_fill(0, $n, 0.0); for ($i = 1; $i < $n; ++$i) { diff --git a/Algorithm/Maze/MazeGenerator.php b/Algorithm/Maze/MazeGenerator.php index 1b8df0e3e..8b180257e 100755 --- a/Algorithm/Maze/MazeGenerator.php +++ b/Algorithm/Maze/MazeGenerator.php @@ -81,7 +81,7 @@ class MazeGenerator if (!empty($neighbors)) { --$n; - $next = $neighbors[\mt_rand(0, \count($neighbors) - 1)]; + $next = $neighbors[\array_rand($neighbors, 1)]; $unvisited[$next[0] + 1][$next[1] + 1] = false; if ($next[0] === $pos[0]) { diff --git a/Business/BusinessHelper.php b/Business/BusinessHelper.php new file mode 100644 index 000000000..b15bffff5 --- /dev/null +++ b/Business/BusinessHelper.php @@ -0,0 +1,27 @@ +count(); } + /** + * Create read mapper + * + * @param ConnectionAbstract $db Database connection + * + * @return ReadMapper + * + * @since 1.0.0 + */ + public static function sum(ConnectionAbstract $db = null) : ReadMapper + { + return (new ReadMapper(new static(), $db ?? self::$db))->sum(); + } + /** * Create read mapper * diff --git a/DataStorage/Database/Mapper/MapperType.php b/DataStorage/Database/Mapper/MapperType.php index c7fa29c8f..158ea6f2c 100755 --- a/DataStorage/Database/Mapper/MapperType.php +++ b/DataStorage/Database/Mapper/MapperType.php @@ -40,9 +40,11 @@ abstract class MapperType extends Enum public const COUNT_MODELS = 12; - public const MODEL_EXISTS = 13; + public const SUM_MODELS = 13; - public const MODEL_HAS_RELATION = 14; + public const MODEL_EXISTS = 14; + + public const MODEL_HAS_RELATION = 15; // -------------------------------------------- // diff --git a/DataStorage/Database/Mapper/ReadMapper.php b/DataStorage/Database/Mapper/ReadMapper.php index 812057805..551d0864d 100755 --- a/DataStorage/Database/Mapper/ReadMapper.php +++ b/DataStorage/Database/Mapper/ReadMapper.php @@ -118,6 +118,20 @@ final class ReadMapper extends DataMapperAbstract return $this; } + /** + * Create sum mapper + * + * @return self + * + * @since 1.0.0 + */ + public function sum() : self + { + $this->type = MapperType::SUM_MODELS; + + return $this; + } + /** * Create exists mapper * @@ -205,6 +219,8 @@ final class ReadMapper extends DataMapperAbstract return $this->executeGetRaw(); case MapperType::COUNT_MODELS: return $this->executeCount(); + case MapperType::SUM_MODELS: + return $this->executeSum(); case MapperType::MODEL_EXISTS: return $this->executeExists(); case MapperType::MODEL_HAS_RELATION: @@ -404,11 +420,35 @@ final class ReadMapper extends DataMapperAbstract */ public function executeCount() : int { - $query = $this->getQuery(null, ['COUNT(*)' => 'count']); + $query = $this->getQuery( + null, + [ + 'COUNT(' . (empty($this->columns) ? '*' : \implode($this->columns)) . ')' => 'count' + ] + ); return (int) $query->execute()?->fetchColumn(); } + /** + * Sum the number of elements + * + * @return int + * + * @since 1.0.0 + */ + public function executeSum() : int|float + { + $query = $this->getQuery( + null, + [ + 'SUM(' . (empty($this->columns) ? '*' : \implode($this->columns)) . ')' => 'sum' + ] + ); + + return $query->execute()?->fetchColumn(); + } + /** * Check if any element exists * diff --git a/DataStorage/Database/Mapper/WriteMapper.php b/DataStorage/Database/Mapper/WriteMapper.php index eacf8ca49..bc7d5f068 100755 --- a/DataStorage/Database/Mapper/WriteMapper.php +++ b/DataStorage/Database/Mapper/WriteMapper.php @@ -232,7 +232,7 @@ final class WriteMapper extends DataMapperAbstract if (isset($this->mapper::BELONGS_TO[$propertyName]['by'])) { // has by (obj is stored as a different model e.g. model = profile but reference/db is account) - if ($this->mapper::BELONGS_TO[$propertyName]['private']) { + if ($this->mapper::BELONGS_TO[$propertyName]['private'] ?? false) { $refClass = new \ReflectionClass($obj); $refProp = $refClass->getProperty($this->mapper::BELONGS_TO[$propertyName]['by']); $obj = $refProp->getValue($obj); @@ -339,9 +339,10 @@ final class WriteMapper extends DataMapperAbstract $relProperty = $relReflectionClass->getProperty($internalName); } - // todo maybe consider to just set the column type to object, and then check for that (might be faster) + // @todo maybe consider to just set the column type to object, and then check for that (might be faster) if (isset($mapper::BELONGS_TO[$internalName]) - || isset($mapper::OWNS_ONE[$internalName])) { + || isset($mapper::OWNS_ONE[$internalName]) + ) { if ($isRelPrivate) { $relProperty->setValue($value, $this->mapper::createNullModel($objId)); } else { diff --git a/Localization/ISO3166NameEnum.php b/Localization/ISO3166NameEnum.php index 3ea40046f..b7f92f05e 100755 --- a/Localization/ISO3166NameEnum.php +++ b/Localization/ISO3166NameEnum.php @@ -78,7 +78,7 @@ class ISO3166NameEnum extends Enum public const _BTN = 'Bhutan'; - public const _BOL = 'Bolivia (Plurinational State of)'; + public const _BOL = 'Bolivia'; public const _BES = 'Bonaire, Sint Eustatius and Saba'; @@ -234,7 +234,7 @@ class ISO3166NameEnum extends Enum public const _IDN = 'Indonesia'; - public const _IRN = 'Iran (Islamic Republic of)'; + public const _IRN = 'Iran'; public const _IRQ = 'Iraq'; @@ -260,9 +260,9 @@ class ISO3166NameEnum extends Enum public const _KIR = 'Kiribati'; - public const _PRK = 'Korea (Democratic People\'s Republic of)'; + public const _PRK = 'North Korea'; - public const _KOR = 'Korea (Republic of)'; + public const _KOR = 'South Korea'; public const _KWT = 'Kuwait'; @@ -314,9 +314,9 @@ class ISO3166NameEnum extends Enum public const _MEX = 'Mexico'; - public const _FSM = 'Micronesia (Federated States of)'; + public const _FSM = 'Micronesia'; - public const _MDA = 'Moldova (Republic of)'; + public const _MDA = 'Moldova'; public const _MCO = 'Monaco'; @@ -364,7 +364,7 @@ class ISO3166NameEnum extends Enum public const _PLW = 'Palau'; - public const _PSE = 'Palestine, State of'; + public const _PSE = 'Palestine'; public const _PAN = 'Panama'; @@ -460,11 +460,11 @@ class ISO3166NameEnum extends Enum public const _SYR = 'Syrian Arab Republic'; - public const _TWN = 'Taiwan, Province of China[a]'; + public const _TWN = 'Taiwan'; public const _TJK = 'Tajikistan'; - public const _TZA = 'Tanzania, United Republic of'; + public const _TZA = 'Tanzania'; public const _THA = 'Thailand'; @@ -494,7 +494,7 @@ class ISO3166NameEnum extends Enum public const _ARE = 'United Arab Emirates'; - public const _GBR = 'United Kingdom of Great Britain and Northern Ireland'; + public const _GBR = 'United Kingdom'; public const _USA = 'United States of America'; @@ -506,7 +506,7 @@ class ISO3166NameEnum extends Enum public const _VUT = 'Vanuatu'; - public const _VEN = 'Venezuela (Bolivarian Republic of)'; + public const _VEN = 'Venezuela'; public const _VNM = 'Viet Nam'; diff --git a/Localization/ISO3166Trait.php b/Localization/ISO3166Trait.php index 0b2451a1c..92c42706a 100644 --- a/Localization/ISO3166Trait.php +++ b/Localization/ISO3166Trait.php @@ -37,10 +37,44 @@ trait ISO3166Trait { /** @var string $code3 */ $code3 = ISO3166TwoEnum::getName($code); + if ($code3 === false) { + $code3 = ''; + } return self::getByName($code3); } + /** + * Get countries in a region + * + * @param string $region Region name + * + * @return array + * + * @since 1.0.0 + */ + public static function getSubregions(string $region) : array + { + $region = \strtolower($region); + + switch ($region) { + case 'continents': + return ['Europe', 'Asia', 'America', 'Oceania', 'Africa']; + case 'europe': + return ['North-Europe', 'South-Europe', 'East-Europe', 'West-Europe']; + case 'asia': + return ['Central-Asia', 'South-Asia', 'Southeast-Asia', 'East-Asia', 'West-Asia']; + case 'america': + return ['North-america', 'South-america', 'Central-america', 'Caribbean']; + case 'oceania': + return ['Australia', 'Polynesia', 'Melanesia', 'Micronesia', 'Antarctica']; + case 'africa': + return ['North-Africa', 'South-Africa', 'East-Africa', 'West-Africa', 'Central-Africa']; + default: + return [$region]; + } + } + /** * Get countries in a region * @@ -55,6 +89,14 @@ trait ISO3166Trait $region = \strtolower($region); switch ($region) { + case 'continents': + return \array_merge( + self::getRegion('europe'), + self::getRegion('asia'), + self::getRegion('america'), + self::getRegion('oceania'), + self::getRegion('africa') + ); case 'europe': return \array_merge( self::getRegion('north-europe'), @@ -83,7 +125,7 @@ trait ISO3166Trait self::getRegion('polynesia'), self::getRegion('melanesia'), self::getRegion('micronesia'), - self::getRegion('antartica') + self::getRegion('antarctica') ); case 'africa': return \array_merge( diff --git a/Localization/RegionEnum.php b/Localization/RegionEnum.php new file mode 100644 index 000000000..86d4eef34 --- /dev/null +++ b/Localization/RegionEnum.php @@ -0,0 +1,92 @@ +data; diff --git a/Stdlib/Base/Enum.php b/Stdlib/Base/Enum.php index 3eb2f59d8..5000cb211 100755 --- a/Stdlib/Base/Enum.php +++ b/Stdlib/Base/Enum.php @@ -70,9 +70,8 @@ abstract class Enum { $reflect = new \ReflectionClass(static::class); $constants = $reflect->getConstants(); - $keys = \array_keys($constants); - return $constants[$keys[\mt_rand(0, \count($constants) - 1)]]; + return $constants[\array_rand($constants, 1)]; } /** diff --git a/Stdlib/Base/EnumArray.php b/Stdlib/Base/EnumArray.php index bc4fb6d93..87a25fb32 100755 --- a/Stdlib/Base/EnumArray.php +++ b/Stdlib/Base/EnumArray.php @@ -119,8 +119,6 @@ abstract class EnumArray */ public static function getRandom() : mixed { - $keys = \array_keys(static::$constants); - - return static::$constants[$keys[\mt_rand(0, \count(static::$constants) - 1)]]; + return static::$constants[\array_rand(static::$constants, 1)]; } } diff --git a/Stdlib/Base/FloatInt.php b/Stdlib/Base/FloatInt.php index e03a0d808..1104f0d18 100755 --- a/Stdlib/Base/FloatInt.php +++ b/Stdlib/Base/FloatInt.php @@ -158,17 +158,15 @@ class FloatInt implements SerializableInterface */ public function getAmount(?int $decimals = 2) : string { - $isNegative = $this->value < 0 ? 1 : 0; - $value = $this->value === 0 ? \str_repeat('0', self::MAX_DECIMALS) : (string) \round($this->value, -self::MAX_DECIMALS + $decimals); - $left = \substr($value, 0, -self::MAX_DECIMALS + $isNegative); + $left = \substr($value, 0, -self::MAX_DECIMALS); /** @var string $left */ $left = $left === false ? '0' : $left; - $right = \substr($value, -self::MAX_DECIMALS + $isNegative); + $right = \substr($value, -self::MAX_DECIMALS); if ($right === false) { throw new \Exception(); // @codeCoverageIgnore diff --git a/Stdlib/Base/SmartDateTime.php b/Stdlib/Base/SmartDateTime.php index e987e75a5..686b347a6 100755 --- a/Stdlib/Base/SmartDateTime.php +++ b/Stdlib/Base/SmartDateTime.php @@ -359,4 +359,48 @@ class SmartDateTime extends \DateTime return $days; } + + public static function startOfYear(int $month = 1) : \DateTime + { + return new \DateTime(\date('Y') . '-' . \sprintf('%02d', $month) . '-01'); + } + + public static function endOfYear(int $month = 1) : \DateTime + { + return new \DateTime(\date('Y') . '-' . self::calculateMonthIndex(13 - $month, $month) . '-31'); + } + + public static function startOfMonth() : \DateTime + { + return new \DateTime(\date('Y-m') . '-01'); + } + + public static function endOfMonth() : \DateTime + { + return new \DateTime(\date('Y-m-t')); + } + + public static function monthDiff(\DateTime $d1, \DateTime $d2) : int + { + $interval = $d1->diff($d2); + + return ($interval->y * 12) + $interval->m; + } + + /** + * Calculates the current month index based on the start of the fiscal year. + * + * @param int $month Current month + * @param int $start Start of the fiscal year (01 = January) + * + * @return int + * + * @since 1.0.0; + */ + public static function calculateMonthIndex(int $month, int $start = 1) : int + { + $mod = ($month - $start); + + return \abs(($mod < 0 ? 12 + $mod : $mod) % 12) + 1; + } } diff --git a/Utils/Barcode/QR.php b/Utils/Barcode/QR.php index b17f38232..6dc3f5d10 100755 --- a/Utils/Barcode/QR.php +++ b/Utils/Barcode/QR.php @@ -1091,7 +1091,7 @@ class QR extends TwoDAbstract $howManuOut = 8 - (self::QR_FIND_FROM_RANDOM % 9); for ($i = 0; $i < $howManuOut; ++$i) { // @note: This is why the same content can result in different QR codes - $remPos = \mt_rand(0, \count($checked_masks) - 1); + $remPos = \array_rand($checked_masks, 1); unset($checked_masks[$remPos]); $checked_masks = \array_values($checked_masks); } diff --git a/Utils/Parser/Markdown/Markdown.php b/Utils/Parser/Markdown/Markdown.php index a7fd75db7..7c1d8bdda 100755 --- a/Utils/Parser/Markdown/Markdown.php +++ b/Utils/Parser/Markdown/Markdown.php @@ -291,7 +291,7 @@ class Markdown if (\strpos($Excerpt['text'], '>') !== false && \preg_match("/^<((mailto:)?{$commonMarkEmail})>/i", $Excerpt['text'], $matches) ){ - $url = $matches[1]; + $url = UriFactory::build($matches[1]); if (!isset($matches[2])) { @@ -496,7 +496,7 @@ class Markdown if (\strpos($Excerpt['context'], 'http') !== false && \preg_match('/\bhttps?+:[\/]{2}[^\s<]+\b\/*+/ui', $Excerpt['context'], $matches, \PREG_OFFSET_CAPTURE) ) { - $url = $matches[0][0]; + $url = UriFactory::build($matches[0][0]); return [ 'extent' => \strlen($matches[0][0]), @@ -521,7 +521,7 @@ class Markdown if (\strpos($Excerpt['text'], '>') !== false && \preg_match('/^<(\w++:\/{2}[^ >]++)>/i', $Excerpt['text'], $matches)) { - $url = $matches[1]; + $url = UriFactory::build($matches[1]); return [ 'extent' => \strlen($matches[0]), @@ -3727,7 +3727,7 @@ class Markdown if (\preg_match('/^[(]\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*+"|\'[^\']*+\'))?\s*+[)]/', $remainder, $matches)) { - $Element['attributes']['href'] = $matches[1]; + $Element['attributes']['href'] = UriFactory::build($matches[1]); if (isset($matches[2])) { diff --git a/Utils/RnG/File.php b/Utils/RnG/File.php index dd0938180..22b951659 100755 --- a/Utils/RnG/File.php +++ b/Utils/RnG/File.php @@ -59,8 +59,8 @@ class File $source = self::$extensions; } - $key = \mt_rand(0, \count($source) - 1); + $key = \array_rand($source, 1); - return $source[$key][\mt_rand(0, \count($source[$key]) - 1)]; + return $source[$key][\array_rand($source[$key], 1)]; } } diff --git a/Utils/RnG/Name.php b/Utils/RnG/Name.php index 234932adf..f02a9faec 100755 --- a/Utils/RnG/Name.php +++ b/Utils/RnG/Name.php @@ -493,8 +493,8 @@ class Name */ public static function generateName(array $type, string $origin = 'western') : string { - $rndType = \mt_rand(0, \count($type) - 1); + $rndType = \array_rand($type, 1); - return self::$names[$origin][$type[$rndType]][\mt_rand(0, \count(self::$names[$origin][$type[$rndType]]) - 1)]; + return self::$names[$origin][$type[$rndType]][\array_rand(self::$names[$origin][$type[$rndType]], 1)]; } } diff --git a/Utils/RnG/Phone.php b/Utils/RnG/Phone.php index a9059b8d3..bdfe6f699 100755 --- a/Utils/RnG/Phone.php +++ b/Utils/RnG/Phone.php @@ -52,7 +52,7 @@ class Phone $numberString = \str_replace( '$1', - (string) $countries[\array_keys($countries)[\mt_rand(0, \count($countries) - 1)]], + (string) $countries[\array_rand($countries, 1)], $numberString ); } diff --git a/tests/Message/Http/HttpResponseTest.php b/tests/Message/Http/HttpResponseTest.php index 45f6478d7..571c327ad 100755 --- a/tests/Message/Http/HttpResponseTest.php +++ b/tests/Message/Http/HttpResponseTest.php @@ -58,7 +58,7 @@ final class HttpResponseTest extends \PHPUnit\Framework\TestCase public function testResponseInputOutput() : void { $this->response->setResponse(['a' => 1]); - self::assertEquals(1, $this->response->get('a')); + self::assertEquals(1, $this->response->getData('a')); } /** diff --git a/tests/Message/ResponseAbstractTest.php b/tests/Message/ResponseAbstractTest.php index fd76956a3..f4df8aab2 100755 --- a/tests/Message/ResponseAbstractTest.php +++ b/tests/Message/ResponseAbstractTest.php @@ -53,7 +53,7 @@ final class ResponseAbstractTest extends \PHPUnit\Framework\TestCase */ public function testDefault() : void { - self::assertNull($this->response->get('asdf')); + self::assertNull($this->response->getData('asdf')); self::assertEquals('', $this->response->getBody()); } @@ -75,6 +75,6 @@ final class ResponseAbstractTest extends \PHPUnit\Framework\TestCase public function testDataInputOutput() : void { $this->response->set('asdf', false); - self::assertFalse($this->response->get('asdf')); + self::assertFalse($this->response->getData('asdf')); } } diff --git a/tests/Module/ModuleAbstractTest.php b/tests/Module/ModuleAbstractTest.php index ff14928a7..c586e79bd 100755 --- a/tests/Module/ModuleAbstractTest.php +++ b/tests/Module/ModuleAbstractTest.php @@ -258,7 +258,7 @@ final class ModuleAbstractTest extends \PHPUnit\Framework\TestCase 'message' => 'Test Message!', 'response' => [1, 'test string', 'bool' => true], ], - $response->get('') + $response->getData('') ); } @@ -276,7 +276,7 @@ final class ModuleAbstractTest extends \PHPUnit\Framework\TestCase self::assertEquals( [1, 'test string', 'bool' => true], - $response->get('') + $response->getData('') ); }