diff --git a/Api/EUVAT/EUVATVies.php b/Api/EUVAT/EUVATVies.php index 2a8bb0d60..4fcda0f99 100755 --- a/Api/EUVAT/EUVATVies.php +++ b/Api/EUVAT/EUVATVies.php @@ -211,11 +211,11 @@ final class EUVATVies implements EUVATInterface $result['vat'] = $json['isValid'] ? 'A' : 'B'; $result['name'] = $json['isValid']; - $result['city'] = \stripos($json['address'], "\n") !== false + $result['city'] = \stripos($json['address'] ?? '', "\n") !== false ? \substr($json['address'], \stripos($json['address'], "\n") + 1) : ''; - $result['postal'] = \stripos($json['address'], "\n") !== false + $result['postal'] = \stripos($json['address'] ?? '', "\n") !== false ? \substr( $json['address'], \stripos($json['address'], "\n") + 1, @@ -223,9 +223,9 @@ final class EUVATVies implements EUVATInterface ) : ''; - $result['address'] = \stripos($json['address'], "\n") !== false + $result['address'] = \stripos($json['address'] ?? '', "\n") !== false ? \substr($json['address'], 0, \stripos($json['address'], "\n") - 1) - : $json['address']; + : ($json['address'] ?? ''); $result['name'] = $result['name'] === '---' ? '' : $result['name']; $result['city'] = $result['city'] === '---' ? '' : $result['city']; diff --git a/DataStorage/Database/Mapper/DataMapperFactory.php b/DataStorage/Database/Mapper/DataMapperFactory.php index aac250992..54ed7b7c3 100755 --- a/DataStorage/Database/Mapper/DataMapperFactory.php +++ b/DataStorage/Database/Mapper/DataMapperFactory.php @@ -443,7 +443,7 @@ class DataMapperFactory * * @since 1.0.0 */ - public static function createNullModel(mixed $id = null) : mixed + public static function createNullModel(mixed $id = null, ?string $member = null) : mixed { $class = empty(static::MODEL) ? \substr(static::class, 0, -6) : static::MODEL; $parts = \explode('\\', $class); @@ -451,7 +451,18 @@ class DataMapperFactory $parts[$c] = 'Null' . $name; $class = \implode('\\', $parts); - return $id !== null ? new $class($id) : new $class(); + $model = $member === null && $id !== null ? new $class($id) : new $class(); + + if ($member !== null) { + // @bug This is just a quick fix, we don't know if "id" is the primary key in case of obj. + if (\is_object($model->{$member})) { + $model->{$member}->id = $id; + } else { + $model->{$member} = $id; + } + } + + return $model; } /** diff --git a/DataStorage/Database/Mapper/ReadMapper.php b/DataStorage/Database/Mapper/ReadMapper.php index 7a6370f8a..5a742cd93 100755 --- a/DataStorage/Database/Mapper/ReadMapper.php +++ b/DataStorage/Database/Mapper/ReadMapper.php @@ -232,7 +232,7 @@ final class ReadMapper extends DataMapperAbstract return $this->executeGetRaw(...$options); case MapperType::GET_ALL: /** @var null|Builder ...$options */ - return $this->executeGetAll(...$options); + return $this->executeGetArray(...$options); case MapperType::GET_RANDOM: return $this->executeRandom(); case MapperType::COUNT_MODELS: @@ -427,8 +427,10 @@ final class ReadMapper extends DataMapperAbstract * * @since 1.0.0 */ - public function executeGetAll(?Builder $query = null) : array + public function executeGetArray(?Builder $query = null) : array { + $this->getAll(); + $result = $this->executeGet($query); if (\is_object($result) @@ -449,6 +451,8 @@ final class ReadMapper extends DataMapperAbstract */ public function executeCount() : int { + $this->count(); + $query = $this->getQuery( null, [ @@ -468,6 +472,8 @@ final class ReadMapper extends DataMapperAbstract */ public function executeSum() : int|float { + $this->sum(); + $query = $this->getQuery( null, [ @@ -492,6 +498,8 @@ final class ReadMapper extends DataMapperAbstract */ public function executeExists() : bool { + $this->exists(); + $query = $this->getQuery(null, [1]); return ($query->execute()?->fetchColumn() ?? 0) > 0; @@ -1039,7 +1047,10 @@ final class ReadMapper extends DataMapperAbstract if (\array_key_exists($this->mapper::OWNS_ONE[$member]['external'] . '_d' . $this->depth . $this->joinAlias, $result)) { return isset($this->mapper::OWNS_ONE[$member]['column']) ? $result[$this->mapper::OWNS_ONE[$member]['external'] . '_d' . $this->depth . $this->joinAlias] - : $mapper::createNullModel($result[$this->mapper::OWNS_ONE[$member]['external'] . '_d' . $this->depth . $this->joinAlias]); + : $mapper::createNullModel( + $result[$this->mapper::OWNS_ONE[$member]['external'] . '_d' . $this->depth . $this->joinAlias], + $this->mapper::OWNS_ONE[$member]['by'] ?? null + ); } else { return $default; } @@ -1077,7 +1088,10 @@ final class ReadMapper extends DataMapperAbstract if (\array_key_exists($this->mapper::BELONGS_TO[$member]['external'] . '_d' . $this->depth . $this->joinAlias, $result)) { return isset($this->mapper::BELONGS_TO[$member]['column']) ? $result[$this->mapper::BELONGS_TO[$member]['external'] . '_d' . $this->depth . $this->joinAlias] - : $mapper::createNullModel($result[$this->mapper::BELONGS_TO[$member]['external'] . '_d' . $this->depth . $this->joinAlias]); + : $mapper::createNullModel( + $result[$this->mapper::BELONGS_TO[$member]['external'] . '_d' . $this->depth . $this->joinAlias], + $this->mapper::BELONGS_TO[$member]['by'] ?? null + ); } else { return $default; } @@ -1182,6 +1196,10 @@ final class ReadMapper extends DataMapperAbstract continue; } + if (($many['conditional'] ?? false) && \is_array($objects[$key])) { + $objects[$key] = \reset($objects[$key]); + } + $refProp = $refClass->getProperty($member); $refProp->setValue($objs[$idx], !\is_array($objects[$key]) && ($many['conditional'] ?? false) === false ? [$many['mapper']::getObjectId($objects[$key]) => $objects[$key]] @@ -1194,6 +1212,10 @@ final class ReadMapper extends DataMapperAbstract continue; } + if (($many['conditional'] ?? false) && \is_array($objects[$key])) { + $objects[$key] = \reset($objects[$key]); + } + $objs[$idx]->{$member} = !\is_array($objects[$key]) && ($many['conditional'] ?? false) === false ? [$many['mapper']::getObjectId($objects[$key]) => $objects[$key]] : $objects[$key]; // if conditional === true the obj will be assigned (e.g. hasMany localizations but only one is loaded for the model) diff --git a/Message/Http/HttpRequest.php b/Message/Http/HttpRequest.php index 6d4649627..6ef20f278 100755 --- a/Message/Http/HttpRequest.php +++ b/Message/Http/HttpRequest.php @@ -493,6 +493,10 @@ final class HttpRequest extends RequestAbstract $paths[] = $pathArray[$j]; } + // @bug Since we are hashing the path elements without delimiter /test/path/here is the same as /testpath/here + // The reason for doing this without delimiter was probably because of different environments (web vs socket vs console) + // However, we could literally choose any delimiter INTERNALLY as long as it is the same across all Request classes. + // If this ever gets changed remember to also change the Navigation/ApiController.php file $this->hash[] = \sha1(\implode('', $paths)); } } diff --git a/Stdlib/Base/FloatInt.php b/Stdlib/Base/FloatInt.php index 94815f843..a76100506 100755 --- a/Stdlib/Base/FloatInt.php +++ b/Stdlib/Base/FloatInt.php @@ -285,7 +285,7 @@ class FloatInt implements SerializableInterface } /** - * Mult. + * Multiply. * * @param int|float $value Value to multiply with * @@ -347,7 +347,7 @@ class FloatInt implements SerializableInterface } /** - * Searialze. + * Serialize. * * @return string * diff --git a/Utils/ColorUtils.php b/Utils/ColorUtils.php index 90e8461b0..38f4c3254 100755 --- a/Utils/ColorUtils.php +++ b/Utils/ColorUtils.php @@ -71,4 +71,53 @@ final class ColorUtils return $i; } + + /** + * Calculate the color distance + * + * Important: This is not how humans perceive color differences + * + * @param array $rgb1 RGB 1 + * @param array $rgb2 RGB 2 + * + * @return float + * + * @see approximateColorDistance + * + * @since 1.0.0 + */ + public static function colorDistance(array $rgb1, array $rgb2) : float + { + $r = ($rgb2['r'] - $rgb1['r']); + $g = ($rgb2['g'] - $rgb1['g']); + $b = ($rgb2['b'] - $rgb1['b']); + + return \sqrt($r * $r + $g * $g + $b * $b); + } + + /** + * Approximate the perceived color distance + * + * @param array $rgb1 RGB 1 + * @param array $rgb2 RGB 2 + * + * @return float + * + * @see https://www.compuphase.com/cmetric.htm + * + * @since 1.0.0 + */ + public static function approximateColorDistance(array $rgb1, array $rgb2) : float + { + $rMean = (int) (($rgb1['r'] + $rgb2['r']) / 2); + $r = ($rgb2['r'] - $rgb1['r']); + $g = ($rgb2['g'] - $rgb1['g']); + $b = ($rgb2['b'] - $rgb1['b']); + + return \sqrt( + (((512 + $rMean) * $r * $r) >> 8) + + 4 * $g * $g + + (((767 - $rMean) * $b * $b) >> 8) + ); + } } diff --git a/Utils/ImageUtils.php b/Utils/ImageUtils.php index 5db0e0110..b21857953 100755 --- a/Utils/ImageUtils.php +++ b/Utils/ImageUtils.php @@ -72,7 +72,7 @@ final class ImageUtils } /** - * Calculate lightess from rgb values + * Calculate lightness from rgb values * * @param int $r Red * @param int $g Green @@ -365,7 +365,7 @@ final class ImageUtils * * @since 1.0.0 */ - private static function getAverageColor($src, $x, $y, $width, $height, $area = 10) : int + private static function getAverageColor(\GdImage $src, int $x, int $y, int $width, int $height, int $area = 10) : int { $colors = []; @@ -387,4 +387,26 @@ final class ImageUtils return (int) (\array_sum($colors) / \count($colors)); } + + /** + * Calculate the average color based on random probes + * + * @param \GdImage $src Image resource + * @param int $probes Count of random color probes/samples + * + * @return int + * + * @since 1.0.0 + */ + public static function averageColorRandom(\GdImage $src, int $probes = 25) : int + { + $dim = [\imagesx($src), \imagesy($src)]; + + $color = 0; + for ($i = 0; $i < $probes; ++$i) { + $color += \imagecolorat($src, \mt_rand(0, $dim[0]), \mt_rand(0, $dim[1])); + } + + return $color / $probes; + } } diff --git a/tests/Ai/Ocr/Tesseract/basic.txt b/tests/Ai/Ocr/Tesseract/basic.txt index 80b44e1e6..de4b2c744 100755 --- a/tests/Ai/Ocr/Tesseract/basic.txt +++ b/tests/Ai/Ocr/Tesseract/basic.txt @@ -1,16 +1,66 @@ -, you Can filter an image to emphasize certain -inted with filtering include smoothing, sharpening, +ee rrr -pixel in the output image is determined by applying -€ corresponding input pixel. A pixel's neighborhood is -eeNeighborhood or Block Processing: An Overview for +nain? -§ filtering in which the value of an output pixel is a linear -od. +AP tne e va eo -alled convolution. Convolution is a neighborhood -boring input pixels. The matrix of weights is called the -‘4 Correlation kernel that has been rotated 12 + + + + + + + +em + +mple, you can filter an image to emphasize certain +mented with filtering include smoothing, sharpening, + + + +ive pixel in the output image is determined by applying +a comesponding input pixel. A pixel’s neighborhood is +. (SeeNeighborhood or Block Processing: An Overview for +tering in which the value of an output pixel is a linear + + E ‘ +} +ane + +- —_ +J + + + + + + + + + +. _ + +Called convolution. Convolution is 2 neighborhood + +Nb: nboring input pixels. The matrix of weights is called th +sa Correlation kernel that has been rotated 120 c + +~~ +rn — +, ~ + +- + +a +“= +4 + +() + +(D + +Sec +— \ No newline at end of file diff --git a/tests/Ai/Ocr/Tesseract/thresholding.txt b/tests/Ai/Ocr/Tesseract/thresholding.txt index b280b646f..7843b9013 100755 --- a/tests/Ai/Ocr/Tesseract/thresholding.txt +++ b/tests/Ai/Ocr/Tesseract/thresholding.txt @@ -1,29 +1,29 @@ -t Is Image Filtering in the Spatial Domain? +What Is Image Filtering in the Spatial Domain? -What Is Ima +a a ee om o-beme- ee -Filtering is a technique for modifying or enhancing an image. For example, you can filter an image to emphasize certain +Filtering Is a technique for modifying or enhancing an image. For example, you can filter an image to emphasize certain features or remove other features. Image processing operations implemented with filtering include smoothing, sharpening, -and edge enhancement. +_ and edge enhancement. + Filtering is a neighborhood operation, in which the value of any given pixel in the output image is determined by applying -some algorithm to the values of the pixels in the neighborhood of the corresponding input pixel. A pixel’s neighborhood is +some algorithm to the values of the pixels in the neighborhood of the corresponding input pixel. A pixel'’s neighborhocd is some set of pixels, defined by their locations relative to that pixel. (SeeNeighborhood or Block Processing: An Overview for -a general discussion of neighborhood Operations.) Linear filtering is filtering in which the value of an output pixel is a linear +a general discussion of neighborhood operations.) Linear filtering is filtering in which the value ofan output pixel is a linear combination of the values of the pixels in the input pixel's neighborhood. Convolution -Linear filtering of an image is accomplished through an operation called convolution. Convolution is a neightornood +Linear filtering of an image is accomplished through an operation called convolution. Convolution is aneightornood -Operation in which each output pixel is the weighted sum of neighboring input pixels. The matrix of weights is called the +operation in which each output pixel is the weighted sum of neighboring input pixels. The matrix of weights is called the +convolution kemel, also known as the filter. A convolution kernel is a correlation kernel that has been rotated 1 20 cearses. For example, suppose the image is -A=[17 24 1 8 15 -2305 7 14 16 -4 6 13 26 22 -1@ 12 19 21 3 - - +A=[17 24 1 8g 45 +23 5 7 14 146 +4 6 13 20 22 +1@ 12 19 23 3 \ No newline at end of file diff --git a/tests/DataStorage/Cache/Connection/MemCachedTest.php b/tests/DataStorage/Cache/Connection/MemCachedTest.php index d985a1db8..0b9d943d7 100755 --- a/tests/DataStorage/Cache/Connection/MemCachedTest.php +++ b/tests/DataStorage/Cache/Connection/MemCachedTest.php @@ -44,6 +44,10 @@ final class MemCachedTest extends \PHPUnit\Framework\TestCase protected function tearDown() : void { + if (!isset($this->cache)) { + return; + } + $this->cache->flushAll(); } diff --git a/tests/DataStorage/Cache/Connection/RedisCacheTest.php b/tests/DataStorage/Cache/Connection/RedisCacheTest.php index ff5cf323f..3a91050be 100755 --- a/tests/DataStorage/Cache/Connection/RedisCacheTest.php +++ b/tests/DataStorage/Cache/Connection/RedisCacheTest.php @@ -45,6 +45,10 @@ final class RedisCacheTest extends \PHPUnit\Framework\TestCase protected function tearDown() : void { + if (!isset($this->cache)) { + return; + } + $this->cache->flushAll(); } diff --git a/tests/DataStorage/Database/DataMapperAbstractTest.php b/tests/DataStorage/Database/DataMapperAbstractTest.php index db205ecba..7a60d9f05 100755 --- a/tests/DataStorage/Database/DataMapperAbstractTest.php +++ b/tests/DataStorage/Database/DataMapperAbstractTest.php @@ -349,7 +349,7 @@ final class DataMapperAbstractTest extends \PHPUnit\Framework\TestCase public function testCount() : void { BaseModelMapper::create()->execute($this->model); - self::assertEquals(1, BaseModelMapper::count()->execute()); + self::assertEquals(1, BaseModelMapper::count()->executeCount()); } public function testSum() : void diff --git a/tests/Module/dummyModule/README.md b/tests/Module/dummyModule/README.md deleted file mode 100644 index 1becba2bb..000000000 --- a/tests/Module/dummyModule/README.md +++ /dev/null @@ -1 +0,0 @@ -404: Not Found \ No newline at end of file diff --git a/tests/Module/dummyModule/Replace.md b/tests/Module/dummyModule/Replace.md deleted file mode 100644 index 85d44f7ea..000000000 --- a/tests/Module/dummyModule/Replace.md +++ /dev/null @@ -1 +0,0 @@ -To copy! \ No newline at end of file diff --git a/tests/Module/dummyModule/copyHere/a.md b/tests/Module/dummyModule/copyHere/a.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/Module/dummyModule/copyHere/sub/b.txt b/tests/Module/dummyModule/copyHere/sub/b.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/Module/dummyModule/externalCopy.md b/tests/Module/dummyModule/externalCopy.md deleted file mode 100644 index 85d44f7ea..000000000 --- a/tests/Module/dummyModule/externalCopy.md +++ /dev/null @@ -1 +0,0 @@ -To copy! \ No newline at end of file diff --git a/tests/Module/dummyModule/moveHere/a.md b/tests/Module/dummyModule/moveHere/a.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/Module/dummyModule/moveHere/sub/b.txt b/tests/Module/dummyModule/moveHere/sub/b.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/Module/dummyModule/toCopy/a.md b/tests/Module/dummyModule/toCopy/a.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/Module/dummyModule/toCopy/sub/b.txt b/tests/Module/dummyModule/toCopy/sub/b.txt deleted file mode 100644 index e69de29bb..000000000