From edd4693111033d0d2633b419bfccc58f191a393e Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Thu, 21 Apr 2022 23:52:01 +0200 Subject: [PATCH] doc fixes --- Ai/NeuralNetwork/Neuron.php | 3 +- Ai/Ocr/BasicOcr.php | 4 + Algorithm/Clustering/Kmeans.php | 20 +-- Algorithm/Sort/CycleSort.php | 4 +- CONTRIBUTING.md | 2 +- .../Database/Connection/ConnectionFactory.php | 2 +- .../Database/Connection/MysqlConnection.php | 2 +- .../Connection/PostgresConnection.php | 2 +- .../Connection/SqlServerConnection.php | 2 +- .../Database/Mapper/DataMapperFactory.php | 2 +- DataStorage/Database/Mapper/ReadMapper.php | 2 +- DataStorage/Database/Mapper/WriteMapper.php | 1 + DataStorage/Database/Query/Builder.php | 5 + DataStorage/Session/FileSessionHandler.php | 20 +-- Localization/Localization.php | 6 +- Log/FileLogger.php | 13 +- Log/LoggerInterface.php | 38 ++--- Math/Matrix/Matrix.php | 22 ++- Message/Console/ConsoleRequest.php | 1 + Message/Console/ConsoleResponse.php | 1 + Message/Http/HttpRequest.php | 2 +- Message/Http/HttpResponse.php | 5 +- Message/RequestAbstract.php | 8 +- Model/Html/Head.php | 8 -- Model/Message/Dom.php | 7 +- Model/Message/FormValidation.php | 7 +- Model/Message/Notify.php | 7 +- Model/Message/Redirect.php | 7 +- Model/Message/Reload.php | 7 +- Module/ModuleManager.php | 11 +- Module/PackageManager.php | 2 +- Module/UninstallerAbstract.php | 2 +- README.md | 134 ++++++------------ Stdlib/Base/HeapItemInterface.php | 2 +- Stdlib/Base/Iban.php | 9 +- Stdlib/Base/Location.php | 4 + System/File/Ftp/Directory.php | 23 ++- System/File/Ftp/File.php | 9 +- System/File/Local/Directory.php | 10 +- Utils/ArrayUtils.php | 8 +- .../Spreadsheet/SpreadsheetDatabaseMapper.php | 3 + Validation/Finance/Iban.php | 4 +- .../Database/TestModel/BaseModelMapper.php | 2 +- 43 files changed, 216 insertions(+), 217 deletions(-) diff --git a/Ai/NeuralNetwork/Neuron.php b/Ai/NeuralNetwork/Neuron.php index bc63de2d2..4dba657c5 100644 --- a/Ai/NeuralNetwork/Neuron.php +++ b/Ai/NeuralNetwork/Neuron.php @@ -22,7 +22,8 @@ namespace phpOMS\Ai\NeuralNetwork; * @link https://karaka.app * @since 1.0.0 */ -class Neuron { +class Neuron +{ /** * Neuron inputs * diff --git a/Ai/Ocr/BasicOcr.php b/Ai/Ocr/BasicOcr.php index 1d2192759..934104e48 100644 --- a/Ai/Ocr/BasicOcr.php +++ b/Ai/Ocr/BasicOcr.php @@ -107,11 +107,15 @@ final class BasicOcr if (($read = \fread($fp, 4)) === false || ($unpack = \unpack('N', $read)) === false) { return []; // @codeCoverageIgnore } + + /** @var int<0, max> $numberOfRows */ $numberOfRows = (int) $unpack[1]; if (($read = \fread($fp, 4)) === false || ($unpack = \unpack('N', $read)) === false) { return []; // @codeCoverageIgnore } + + /** @var int<0, max> $numberOfColumns */ $numberOfColumns = (int) $unpack[1]; $images = []; diff --git a/Algorithm/Clustering/Kmeans.php b/Algorithm/Clustering/Kmeans.php index 67d59eabc..202bea746 100644 --- a/Algorithm/Clustering/Kmeans.php +++ b/Algorithm/Clustering/Kmeans.php @@ -40,14 +40,6 @@ final class Kmeans */ private \Closure $metric; - /** - * Amount of different clusters - * - * @var int - * @since 1.0.0 - */ - private int $clusters = 1; - /** * Points of the cluster centers * @@ -56,14 +48,6 @@ final class Kmeans */ private $clusterCenters = []; - /** - * Points to clusterize - * - * @var PointInterface[] - * @since 1.0.0 - */ - private array $points = []; - /** * Constructor * @@ -75,9 +59,7 @@ final class Kmeans */ public function __construct(array $points, int $clusters, \Closure $metric = null) { - $this->points = $points; - $this->clusters = $clusters; - $this->metric = $metric ?? function (PointInterface $a, PointInterface $b) { + $this->metric = $metric ?? function (PointInterface $a, PointInterface $b) { $aCoordinates = $a->getCoordinates(); $bCoordinates = $b->getCoordinates(); diff --git a/Algorithm/Sort/CycleSort.php b/Algorithm/Sort/CycleSort.php index aa991b772..522d69f5c 100755 --- a/Algorithm/Sort/CycleSort.php +++ b/Algorithm/Sort/CycleSort.php @@ -79,11 +79,11 @@ final class CycleSort implements SortInterface } } - while ($item->equals($list[$pos])) { + while (isset($list[$pos]) && $item->equals($list[$pos])) { ++$pos; } - if (!$item->equals($list[$pos])) { + if (isset($list[$pos])) { $old = $list[$pos]; $list[$pos] = $item; $item = $old; diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e9b4371b6..4bbb819f4 100755 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,7 @@ Generally, the development philosophy is result orientated. This means that anyo Developers are encouraged to pick open tasks with high priorities according to their own skill level. Senior developers may directly assign tasks to developers based on their importance. New developers may find it easier to start with a task that has a low priority as they often also have a lower difficulty. -Open tasks can be found in the project overview: [PROJECT.md](../Project/PROJECT.md) +Open tasks can be found in the project overview: [PROJECT.md](https://github.com/Karaka-Management/Organization-Guide/blob/master/Project/PROJECT.md) Tasks currently in development are prefixed in the priority column with an asterisk `*` and a name tag in the task description of the developer who is working on the task. diff --git a/DataStorage/Database/Connection/ConnectionFactory.php b/DataStorage/Database/Connection/ConnectionFactory.php index 6ebca3bdb..41b7358bd 100755 --- a/DataStorage/Database/Connection/ConnectionFactory.php +++ b/DataStorage/Database/Connection/ConnectionFactory.php @@ -41,7 +41,7 @@ final class ConnectionFactory * * Overwrites current connection if existing * - * @param array{db:string, database:string}|array{db:string, host:string, port:int, login:string, password:string, database:string} $dbdata the basic database information for establishing a connection + * @param array{db:string, host?:string, port?:int, login?:string, password?:string, database:string} $dbdata the basic database information for establishing a connection * * @return ConnectionAbstract * diff --git a/DataStorage/Database/Connection/MysqlConnection.php b/DataStorage/Database/Connection/MysqlConnection.php index b757b7381..f85fc51b4 100755 --- a/DataStorage/Database/Connection/MysqlConnection.php +++ b/DataStorage/Database/Connection/MysqlConnection.php @@ -37,7 +37,7 @@ final class MysqlConnection extends ConnectionAbstract * * Creates the database object and overwrites all default values. * - * @param array{db:string, host:string, port:int, login:string, password:string, database:string} $dbdata the basic database information for establishing a connection + * @param array{db:string, host?:string, port?:int, login?:string, password?:string, database:string} $dbdata the basic database information for establishing a connection * * @since 1.0.0 */ diff --git a/DataStorage/Database/Connection/PostgresConnection.php b/DataStorage/Database/Connection/PostgresConnection.php index 8e7821666..8e098baa1 100755 --- a/DataStorage/Database/Connection/PostgresConnection.php +++ b/DataStorage/Database/Connection/PostgresConnection.php @@ -38,7 +38,7 @@ final class PostgresConnection extends ConnectionAbstract * * Creates the database object and overwrites all default values. * - * @param array{db:string, host:string, port:int, login:string, password:string, database:string} $dbdata the basic database information for establishing a connection + * @param array{db:string, host?:string, port?:int, login?:string, password?:string, database:string} $dbdata the basic database information for establishing a connection * * @since 1.0.0 */ diff --git a/DataStorage/Database/Connection/SqlServerConnection.php b/DataStorage/Database/Connection/SqlServerConnection.php index cc7fc62af..f32e17e2b 100755 --- a/DataStorage/Database/Connection/SqlServerConnection.php +++ b/DataStorage/Database/Connection/SqlServerConnection.php @@ -38,7 +38,7 @@ final class SqlServerConnection extends ConnectionAbstract * * Creates the database object and overwrites all default values. * - * @param array{db:string, host:string, port:int, login:string, password:string, database:string} $dbdata the basic database information for establishing a connection + * @param array{db:string, host?:string, port?:int, login?:string, password?:string, database:string} $dbdata the basic database information for establishing a connection * * @since 1.0.0 */ diff --git a/DataStorage/Database/Mapper/DataMapperFactory.php b/DataStorage/Database/Mapper/DataMapperFactory.php index fadd8eae5..b7725c186 100644 --- a/DataStorage/Database/Mapper/DataMapperFactory.php +++ b/DataStorage/Database/Mapper/DataMapperFactory.php @@ -91,7 +91,7 @@ class DataMapperFactory /** * Belongs to. * - * @var array + * @var array * @since 1.0.0 */ public const BELONGS_TO = []; diff --git a/DataStorage/Database/Mapper/ReadMapper.php b/DataStorage/Database/Mapper/ReadMapper.php index a231b0662..c0ef5eddc 100644 --- a/DataStorage/Database/Mapper/ReadMapper.php +++ b/DataStorage/Database/Mapper/ReadMapper.php @@ -287,7 +287,7 @@ final class ReadMapper extends DataMapperAbstract { $query = $this->getQuery(null, ['COUNT(*)' => 'count']); - return (int) $query->execute()->fetchColumn(); + return (int) $query->execute()?->fetchColumn(); } /** diff --git a/DataStorage/Database/Mapper/WriteMapper.php b/DataStorage/Database/Mapper/WriteMapper.php index d79c20919..3d594c181 100644 --- a/DataStorage/Database/Mapper/WriteMapper.php +++ b/DataStorage/Database/Mapper/WriteMapper.php @@ -143,6 +143,7 @@ final class WriteMapper extends DataMapperAbstract $query->insert($column['name'])->value($value); } else { if (\stripos($column['internal'], '/') !== false) { + /** @var array $tValue */ $path = \substr($column['internal'], \stripos($column['internal'], '/') + 1); $tValue = ArrayUtils::getArray($path, $tValue, '/'); } diff --git a/DataStorage/Database/Query/Builder.php b/DataStorage/Database/Query/Builder.php index 02d6364a7..71d6d5377 100644 --- a/DataStorage/Database/Query/Builder.php +++ b/DataStorage/Database/Query/Builder.php @@ -1395,8 +1395,13 @@ class Builder extends BuilderAbstract */ public function execute() : ?PDOStatement { + $sth = null; + try { $sth = $this->connection->con->prepare($this->toSql()); + if ($sth === false) { + return null; + } foreach ($this->binds as $key => $bind) { $type = self::getBindParamType($bind); diff --git a/DataStorage/Session/FileSessionHandler.php b/DataStorage/Session/FileSessionHandler.php index 1e882d0ad..140c677af 100644 --- a/DataStorage/Session/FileSessionHandler.php +++ b/DataStorage/Session/FileSessionHandler.php @@ -72,7 +72,7 @@ final class FileSessionHandler implements \SessionHandlerInterface, \SessionIdIn * * @since 1.0.0 */ - public function open($savePath, $sessionName) + public function open(string $savePath, string $sessionName) : bool { $this->savePath = $savePath; @@ -96,17 +96,17 @@ final class FileSessionHandler implements \SessionHandlerInterface, \SessionIdIn * * @param string $id Session id * - * @return string + * @return false|string * * @since 1.0.0 */ - public function read($id) + public function read(string $id) : string|false { if (!\is_file($this->savePath . '/sess_' . $id)) { return ''; } - return (string) \file_get_contents($this->savePath . '/sess_' . $id); + return \file_get_contents($this->savePath . '/sess_' . $id); } /** @@ -119,7 +119,7 @@ final class FileSessionHandler implements \SessionHandlerInterface, \SessionIdIn * * @since 1.0.0 */ - public function write($id, $data) + public function write(string $id, string $data) : bool { return \file_put_contents($this->savePath . '/sess_' . $id, $data) === false ? false : true; } @@ -133,7 +133,7 @@ final class FileSessionHandler implements \SessionHandlerInterface, \SessionIdIn * * @since 1.0.0 */ - public function destroy($id) + public function destroy(string $id) : bool { $file = $this->savePath . '/sess_' . $id; if (\is_file($file)) { @@ -148,16 +148,16 @@ final class FileSessionHandler implements \SessionHandlerInterface, \SessionIdIn * * @param int $maxlifetime Maximum session data life time * - * @return bool + * @return int|false * * @since 1.0.0 */ - public function gc($maxlifetime) + public function gc(int $maxlifetime) : int|false { $files = \glob("{$this->savePath}/sess_*"); if ($files === false) { - return false; + return 0; } foreach ($files as $file) { @@ -166,6 +166,6 @@ final class FileSessionHandler implements \SessionHandlerInterface, \SessionIdIn } } - return true; + return 1; } } diff --git a/Localization/Localization.php b/Localization/Localization.php index 8b2bfa53d..1518863e0 100644 --- a/Localization/Localization.php +++ b/Localization/Localization.php @@ -269,7 +269,7 @@ class Localization implements \JsonSerializable } $json = \json_decode($fileContent, true); - if ($json === false) { + if (!\is_array($json)) { return; } @@ -284,7 +284,7 @@ class Localization implements \JsonSerializable } $json = \json_decode($fileContent, true); - if ($json === false) { + if (!\is_array($json)) { return; } @@ -294,7 +294,7 @@ class Localization implements \JsonSerializable /** * Load localization from locale * - * @param array $locale Locale data + * @param array{language?:string, country?:string, currency?:array{code?:string}, thousand?:string, angle?:string, temperatur?:string, weight?:array, speed?:array, length?:array, area?:array, volume?:array, precision?:array, timezone?:string, datetime?:array} $locale Locale data * * @return void * diff --git a/Log/FileLogger.php b/Log/FileLogger.php index d8c61f371..a90ad49f6 100644 --- a/Log/FileLogger.php +++ b/Log/FileLogger.php @@ -207,9 +207,9 @@ final class FileLogger implements LoggerInterface /** * Interpolate context * - * @param string $message Log schema - * @param array $context Context to log - * @param string $level Log level + * @param string $message Log schema + * @param array $context Context to log + * @param string $level Log level * * @return string * @@ -231,7 +231,12 @@ final class FileLogger implements LoggerInterface } } - $backtrace = \str_replace(["\r\n", "\r", "\n"], ' ', \json_encode($backtrace)); + $encodedBacktrace = \json_encode($backtrace); + if (!\is_string($encodedBacktrace)) { + $encodedBacktrace = ''; + } + + $backtrace = \str_replace(["\r\n", "\r", "\n"], ' ', $encodedBacktrace); $replace['{backtrace}'] = $backtrace; $replace['{datetime}'] = \sprintf('%--19s', (new \DateTimeImmutable('NOW'))->format('Y-m-d H:i:s')); diff --git a/Log/LoggerInterface.php b/Log/LoggerInterface.php index 048097809..cf1ea1842 100755 --- a/Log/LoggerInterface.php +++ b/Log/LoggerInterface.php @@ -27,8 +27,8 @@ interface LoggerInterface /** * System is unusable. * - * @param string $message Logging message schema - * @param array $context Context to log + * @param string $message Logging message schema + * @param array $context Context to log * * @return void */ @@ -40,8 +40,8 @@ interface LoggerInterface * Example: Entire website down, database unavailable, etc. This should * trigger the SMS alerts and wake you up. * - * @param string $message Logging message schema - * @param array $context Context to log + * @param string $message Logging message schema + * @param array $context Context to log * * @return void */ @@ -52,8 +52,8 @@ interface LoggerInterface * * Example: Application component unavailable, unexpected exception. * - * @param string $message Logging message schema - * @param array $context Context to log + * @param string $message Logging message schema + * @param array $context Context to log * * @return void */ @@ -63,8 +63,8 @@ interface LoggerInterface * Runtime errors that do not require immediate action but should typically * be logged and monitored. * - * @param string $message Logging message schema - * @param array $context Context to log + * @param string $message Logging message schema + * @param array $context Context to log * * @return void */ @@ -76,8 +76,8 @@ interface LoggerInterface * Example: Use of deprecated APIs, poor use of an API, undesirable things * that are not necessarily wrong. * - * @param string $message Logging message schema - * @param array $context Context to log + * @param string $message Logging message schema + * @param array $context Context to log * * @return void */ @@ -86,8 +86,8 @@ interface LoggerInterface /** * Normal but significant events. * - * @param string $message Logging message schema - * @param array $context Context to log + * @param string $message Logging message schema + * @param array $context Context to log * * @return void */ @@ -98,8 +98,8 @@ interface LoggerInterface * * Example: User logs in, SQL logs. * - * @param string $message Logging message schema - * @param array $context Context to log + * @param string $message Logging message schema + * @param array $context Context to log * * @return void */ @@ -108,8 +108,8 @@ interface LoggerInterface /** * Detailed debug information. * - * @param string $message Logging message schema - * @param array $context Context to log + * @param string $message Logging message schema + * @param array $context Context to log * * @return void */ @@ -118,9 +118,9 @@ interface LoggerInterface /** * Logs with an arbitrary level. * - * @param string $level Log level/severeness - * @param string $message Logging message schema - * @param array $context Context to log + * @param string $level Log level/severeness + * @param string $message Logging message schema + * @param array $context Context to log * * @return void */ diff --git a/Math/Matrix/Matrix.php b/Math/Matrix/Matrix.php index ae61a87c6..ac945aa04 100644 --- a/Math/Matrix/Matrix.php +++ b/Math/Matrix/Matrix.php @@ -704,6 +704,10 @@ class Matrix implements \ArrayAccess, \Iterator */ public function offsetGet(mixed $offset) : mixed { + if (!\is_int($offset)) { + return 0; + } + $offset = (int) $offset; $row = (int) ($offset / $this->m); @@ -737,8 +741,12 @@ class Matrix implements \ArrayAccess, \Iterator /** * {@inheritdoc} */ - public function offsetExists($offset) : bool + public function offsetExists(mixed $offset) : bool { + if (!\is_int($offset)) { + return false; + } + $offset = (int) $offset; $row = (int) ($offset / $this->m); @@ -756,8 +764,12 @@ class Matrix implements \ArrayAccess, \Iterator /** * {@inheritdoc} */ - public function offsetSet($offset, $value) : void + public function offsetSet(mixed $offset, mixed $value) : void { + if (!\is_int($offset) || !\is_numeric($value)) { + return; + } + $offset = (int) $offset; $row = (int) ($offset / $this->m); $this->matrix[$row][$offset - $row * $this->n] = $value; @@ -766,8 +778,12 @@ class Matrix implements \ArrayAccess, \Iterator /** * {@inheritdoc} */ - public function offsetUnset($offset) : void + public function offsetUnset(mixed $offset) : void { + if (!\is_int($offset)) { + return; + } + $offset = (int) $offset; $row = (int) ($offset / $this->m); unset($this->matrix[$row][$offset - $row * $this->n]); diff --git a/Message/Console/ConsoleRequest.php b/Message/Console/ConsoleRequest.php index ccf01a833..f5f057e74 100644 --- a/Message/Console/ConsoleRequest.php +++ b/Message/Console/ConsoleRequest.php @@ -94,6 +94,7 @@ final class ConsoleRequest extends RequestAbstract $key = '-' . \mb_strtolower($key); if ($type === null) { + /** @var string[] $this->data */ return ArrayUtils::getArg($key, $this->data); } diff --git a/Message/Console/ConsoleResponse.php b/Message/Console/ConsoleResponse.php index 9a46305c6..980b1253f 100644 --- a/Message/Console/ConsoleResponse.php +++ b/Message/Console/ConsoleResponse.php @@ -115,6 +115,7 @@ final class ConsoleResponse extends ResponseAbstract implements RenderableInterf } } + /** @var array{0:bool} $data */ return $this->getRaw($data[0] ?? false); } diff --git a/Message/Http/HttpRequest.php b/Message/Http/HttpRequest.php index f33839b36..192418c4d 100644 --- a/Message/Http/HttpRequest.php +++ b/Message/Http/HttpRequest.php @@ -139,7 +139,7 @@ final class HttpRequest extends RequestAbstract } $json = \json_decode($input, true); - if ($json === false || $json === null) { + if (!\is_array($json)) { throw new \Exception('Is not valid json ' . $input); } diff --git a/Message/Http/HttpResponse.php b/Message/Http/HttpResponse.php index 83ba4d6dc..c0fd750cd 100644 --- a/Message/Http/HttpResponse.php +++ b/Message/Http/HttpResponse.php @@ -94,7 +94,9 @@ final class HttpResponse extends ResponseAbstract implements RenderableInterface */ public function getJsonData() : array { - return \json_decode($this->getRaw(), true) ?? []; + $json = \json_decode($this->getRaw(), true); + + return !\is_array($json) ? [] : $json; } /** @@ -115,6 +117,7 @@ final class HttpResponse extends ResponseAbstract implements RenderableInterface } } + /** @var array{0:bool} $data */ return $this->getRaw(\stripos($type ?? '', MimeType::M_HTML) !== false ? ($data[0] ?? false) : false); } diff --git a/Message/RequestAbstract.php b/Message/RequestAbstract.php index 47abcd5b3..e5de9ad95 100644 --- a/Message/RequestAbstract.php +++ b/Message/RequestAbstract.php @@ -37,7 +37,7 @@ abstract class RequestAbstract implements MessageInterface /** * Request data. * - * @var array + * @var array * @since 1.0.0 */ protected array $data = []; @@ -80,7 +80,7 @@ abstract class RequestAbstract implements MessageInterface * @param string $key Data key * @param string $type Return type * - * @return null|int|string|float|bool + * @return mixed * * @since 1.0.0 */ @@ -133,7 +133,7 @@ abstract class RequestAbstract implements MessageInterface $json = \json_decode($this->data[$key], true); - return $json === false ? [] : $json ?? []; + return !\is_array($json) ? [] : $json; } /** @@ -180,7 +180,7 @@ abstract class RequestAbstract implements MessageInterface { $data = []; foreach ($this->data as $key => $value) { - if (\preg_match('/' . $regex . '/', $key) === 1) { + if (\preg_match('/' . $regex . '/', (string) $key) === 1) { $data[$key] = $value; } } diff --git a/Model/Html/Head.php b/Model/Html/Head.php index ff56ff715..5acda975c 100755 --- a/Model/Html/Head.php +++ b/Model/Html/Head.php @@ -54,14 +54,6 @@ final class Head implements RenderableInterface */ private array $assets = []; - /** - * Is the header set? - * - * @var bool - * @since 1.0.0 - */ - private bool $hasContent = false; - /** * Page meta. * diff --git a/Model/Message/Dom.php b/Model/Message/Dom.php index 74d1c414b..a81f55422 100644 --- a/Model/Message/Dom.php +++ b/Model/Message/Dom.php @@ -147,9 +147,12 @@ final class Dom implements SerializableInterface */ public function unserialize(mixed $raw) : void { - $unserialized = \json_decode($raw, true); + if (!\is_string($raw)) { + return; + } - if ($unserialized === false) { + $unserialized = \json_decode($raw, true); + if (!\is_array($unserialized)) { return; } diff --git a/Model/Message/FormValidation.php b/Model/Message/FormValidation.php index ceb11a01b..1a93597df 100644 --- a/Model/Message/FormValidation.php +++ b/Model/Message/FormValidation.php @@ -79,9 +79,12 @@ final class FormValidation implements \JsonSerializable, SerializableInterface */ public function unserialize(mixed $raw) : void { - $unserialized = \json_decode($raw, true); + if (!\is_string($raw)) { + return; + } - if ($unserialized === false) { + $unserialized = \json_decode($raw, true); + if (!\is_array($unserialized)) { return; } diff --git a/Model/Message/Notify.php b/Model/Message/Notify.php index 99c91c76f..5e61f1dd8 100644 --- a/Model/Message/Notify.php +++ b/Model/Message/Notify.php @@ -183,9 +183,12 @@ final class Notify implements \JsonSerializable, SerializableInterface */ public function unserialize(mixed $raw) : void { - $unserialized = \json_decode($raw, true); + if (!\is_string($raw)) { + return; + } - if ($unserialized === false) { + $unserialized = \json_decode($raw, true); + if (!\is_array($unserialized)) { return; } diff --git a/Model/Message/Redirect.php b/Model/Message/Redirect.php index 1a28c58e6..f4e56babe 100644 --- a/Model/Message/Redirect.php +++ b/Model/Message/Redirect.php @@ -125,9 +125,12 @@ final class Redirect implements \JsonSerializable, SerializableInterface */ public function unserialize(mixed $raw) : void { - $unserialized = \json_decode($raw, true); + if (!\is_string($raw)) { + return; + } - if ($unserialized === false) { + $unserialized = \json_decode($raw, true); + if (!\is_array($unserialized)) { return; } diff --git a/Model/Message/Reload.php b/Model/Message/Reload.php index 2f5760701..bfadc75c2 100644 --- a/Model/Message/Reload.php +++ b/Model/Message/Reload.php @@ -85,9 +85,12 @@ final class Reload implements \JsonSerializable, SerializableInterface */ public function unserialize(mixed $raw) : void { - $unserialized = \json_decode($raw, true); + if (!\is_string($raw)) { + return; + } - if ($unserialized === false) { + $unserialized = \json_decode($raw, true); + if (!\is_array($unserialized)) { return; } diff --git a/Module/ModuleManager.php b/Module/ModuleManager.php index 06ca9331d..42e50cf95 100644 --- a/Module/ModuleManager.php +++ b/Module/ModuleManager.php @@ -207,12 +207,13 @@ final class ModuleManager } $content = \file_get_contents($path); - $json = \json_decode($content === false ? '[]' : $content, true); - if ($json === false) { - return []; + $json = \json_decode($content === false ? '[]' : $content, true); + if (!\is_array($json)) { + return $this->active; } + /** @var array{name:array{internal:string}} $json */ $this->active[$json['name']['internal']] = $json; } } @@ -325,9 +326,10 @@ final class ModuleManager ->execute(); if ($sth === null) { - return []; + return $this->installed; } + /** @var string[] $installed */ $installed = $sth->fetchAll(\PDO::FETCH_COLUMN); foreach ($installed as $module) { @@ -754,6 +756,7 @@ final class ModuleManager if (!isset($this->running[$class])) { if (Autoloader::exists($class) !== false) { try { + /** @var ModuleAbstract $obj */ $obj = new $class($this->app); $this->running[$name] = $obj; $this->registerRequesting($obj); diff --git a/Module/PackageManager.php b/Module/PackageManager.php index 4096d86d1..4adaf7de9 100644 --- a/Module/PackageManager.php +++ b/Module/PackageManager.php @@ -123,7 +123,7 @@ final class PackageManager $contents = \file_get_contents($this->extractPath . '/info.json'); $info = \json_decode($contents === false ? '[]' : $contents, true); - $this->info = $info === false ? [] : $info; + $this->info = !\is_array($info) ? [] : $info; } /** diff --git a/Module/UninstallerAbstract.php b/Module/UninstallerAbstract.php index 7d7bda37f..4ef3470e8 100644 --- a/Module/UninstallerAbstract.php +++ b/Module/UninstallerAbstract.php @@ -108,7 +108,7 @@ abstract class UninstallerAbstract } foreach ($definitions as $name => $definition) { - $builder->dropTable($name ?? ''); + $builder->dropTable($name); } $builder->execute(); diff --git a/README.md b/README.md index 165f7ff42..b7cc16177 100755 --- a/README.md +++ b/README.md @@ -1,119 +1,75 @@ -# Karaka -

Logo

-The phpOMS framework is primarily developed for the Karaka application which is a modular web application for small to mid sized companies that need CRM, ERP, Intranet and/or CMS functionalities and much more. The framework is also used in some other tools and websites which compliment the Karaka web application and provides the necessary php functionality. +The **phpOMS** framework is primarily developed for the Karaka application which is a modular web application for small to mid sized companies that need CRM, ERP, Intranet and/or CMS functionalities and much more. The framework is also used in some other tools and websites which compliment the Karaka web application and provides the necessary php functionality. With Karaka you have one partner who can provide all the tools and software solutions you are used to at fair and reasonable prices even for small organizations and companies/startups. Our solutions can be used independently from each other or fully integrated with other solutions we provide. By choosing Karaka as your partner you'll be able to adjust your software based on the changes in your requirements without worrying about integration and workflow optimization. -## Table of content +## Table of Contents -- [Karaka](#karaka) - - [Table of content](#table-of-content) - - [Installation](#installation) - - [Requirements](#requirements) - - [Setup](#setup) - - [End-User](#end-user) - - [Developer](#developer) - - [Philosophy](#philosophy) - - [Development Status](#development-status) - - [Features](#features) - - [Unit Tests](#unit-tests) - - [Become a contributor](#become-a-contributor) - - [Misc](#misc) +- [Table of Contents](#table-of-contents) +- [Requirements](#requirements) + - [Developer tools](#developer-tools) +- [Installation](#installation) +- [Philosophy & Demo](#philosophy--demo) +- [Development status](#development-status) +- [Tech stack](#tech-stack) +- [Become a contributor](#become-a-contributor) +- [Misc](#misc) + +## Requirements + +* PHP 8.1 +* PHP extension: php8.1-dev php8.1-cli php8.1-common php8.1-mysql php8.1-pgsql php8.1-xdebug php8.1-opcache php8.1-pdo php8.1-sqlite php8.1-mbstring php8.1-curl php8.1-imap php8.1-bcmath php8.1-zip php8.1-dom php8.1-xml php8.1-phar php8.1-gd php-pear +* apache2 (recommended) or nginx +* mysql-server (recommended) or postgresql postgresql-contrib +* Tools: tesseract-ocr, pdftotext, pdftoppm +* Make sure that URL rewriting is active! + +### Developer tools + +* Php extension: xdebug +* Tools: Composer, Npm +* Composer tools: phpstan, phpunit, phpcs +* Npm tools: eslint ## Installation -### Requirements +Detailed installation instructions can be found at: -Some of the following requirements are only necessary for developers and not for end-users: +* [Developer Setup](https://github.com/Karaka-Management/Developer-Guide/blob/develop/general/setup.md) +* [User Setup](https://github.com/Karaka-Management/User-Guide/blob/develop/setup/install.md) -* PHP 8.0 -* PHP extension: php8.1 php8.1-dev php8.1-cli php8.1-common php8.1-mysql php8.1-pgsql php8.1-xdebug php8.1-opcache php8.1-pdo php8.1-sqlite php8.1-mbstring php8.1-curl php8.1-imap php8.1-bcmath php8.1-zip php8.1-dom php8.1-xml php8.1-phar php8.1-gd php-pear -* apache2 (recommended) or nginx -* mysql-server or postgresql postgresql-contrib -* Make sure that URL rewriting is active -* Download the Karaka project or clone the Karaka repository (incl. submodules). - -Please note if you are only interested in using the framework without the web application you only have to configure your autoloading correctly for the **phpOMS** framework or use the autoloader provided by the framework in `phpOMS/Autoloader.php` and install the required php extensions mentioned above. - -### Setup - -#### End-User - -After installing the requirements and configuring the web server for the correct path navigate to https://your_url.com/Install and follow the installation process. Afterwards you will be redirected to the installed backend. - -For more detailed information please checkout the [Installation Guide](https://karaka.app/dev/guide?page=setup/installation). - -#### Developer - -https://github.com/karaka-management/Developer-Guide/blob/develop/general/setup.md - -## Philosophy +## Philosophy & Demo We believe software should support a business in it's daily tasks and growth in a very efficient way without frustration. In order to achieve this we constantly take feedback from our customers and expand and improve our software solutions. -Since we believe in our software and transparent business model you can live test parts of our application and it's modules in our demo application at https://karaka.app (user: admin, pass: orange) without any registration or inquiry. This can be done even during the development phase. +You can find a freely available online demo at https://demo.karaka.app (user: admin, pass: orange) without any registration or inquiry. -## Development Status +## Development status -Currently Karaka is still developing the first Alpha version. As soon as we have a running Beta version we are allowing external testers to use our software and a selected amount of inhouse developed modules. The **phpOMS** framework is the component which is developed the furthest and already provides a large amount of functionality which is required by the whole project. +Currently Karaka is still developing the first Alpha version. As soon as we have a running Beta version we are allowing external testers to use our software and a selected amount of inhouse developed modules. General updates can be found in our info section at https://karaka.app/info and developer updates can be found in our developer section at https://karaka.app/dev. In our developer section you can also check out the automatically generated reports such as code coverage, code style, static analysis etc. as well as our code style guide lines and developer documentation. -![Preview](https://raw.githubusercontent.com/Karaka-Management/Assets/master/art/preview.png) +* [Project Status](https://github.com/Karaka-Management/Organization-Guide/blob/master/Project/PROJECT.md) -## Features +## Tech stack -Features this framework provides are: - -* Account/Group management -* Permission management -* Asset management -* Business logic (e.g. sales, marketing, etc.) -* Console support -* WebSocket support -* Event management -* Database management -* Cache management -* Dispatcher -* Router -* Authentication -* Localization -* Logging (console/backend) -* Request/Response management -* Math (e.g. matrix, forecasting, optimization, geometry, stochastics, etc.) -* Module management -* Uri -* Utils (e.g. barcodes, comporession, unit converter, jobqueue, git, etc.) -* Value validation -* View management -* Image processing -* Stdlib (e.g. graph, map, queue, enum, etc.) - -## Unit Tests - -Run the following command in the **parent** directory of the framework for unit tests: - -``` -php .\phpunit.phar --bootstrap .\phpOMS\tests\Bootstrap.php .\phpOMS\tests\ -``` +* Language: php, js, c++, html, css, markdown, shell script +* Database: Maria/MySQL, PostgreSQL, MSSQL, SQLite +* Webserver: apache2, nginx +* Cache: Redis, Memcached ## Become a contributor -Karaka has a very open culture and we always welcome new people who share our philosophy in providing create solutions which just work. Please contact us if you are interested in working together on our application. - -* PHP Developer -* JS Developer -* Artist and/or Frontend -* DevOps - -Check out https://karaka.app/career and our developer section https://karaka.app/dev for more information. +Karaka has a very open culture and we always welcome new people who share our philosophy in providing create solutions which just work. You can find the development process description which also describes how to become a contributer in the [Organization documentation](https://github.com/Karaka-Management/Organization-Guide/blob/master/Processes/Development.md). ## Misc -* Languages: PHP, JS, HTML, CSS +* End-User documentation: https://github.com/Karaka-Management/Documentation +* Developer documentation: https://github.com/Karaka-Management/Developer-Guide +* Organization documentation: https://github.com/Karaka-Management/Organization-Guide * Website: [https://karaka.app](https://karaka.app) * Demo: [https://karaka.app](https://karaka.app) (user: admin, pass: orange) * Dev: [https://karaka.app/dev](https://karaka.app/dev) -* Contact: dennis@karaka.email +* Contact: dennis@karaka.app diff --git a/Stdlib/Base/HeapItemInterface.php b/Stdlib/Base/HeapItemInterface.php index 9140ceb2f..32d8d5b60 100644 --- a/Stdlib/Base/HeapItemInterface.php +++ b/Stdlib/Base/HeapItemInterface.php @@ -27,7 +27,7 @@ interface HeapItemInterface /** * Compare heap items * - * @param HeapItemInterface $item + * @param HeapItemInterface $item Heap item * * @return bool * diff --git a/Stdlib/Base/Iban.php b/Stdlib/Base/Iban.php index a0a2a2cc2..51b0f2ccd 100644 --- a/Stdlib/Base/Iban.php +++ b/Stdlib/Base/Iban.php @@ -115,9 +115,12 @@ class Iban implements SerializableInterface private function getSequence(string $sequence) : string { $country = $this->getCountry(); - $layout = \str_replace(' ', '', IbanEnum::getByName('C_' . $country)); - $start = \stripos($layout, $sequence); - $end = \strrpos($layout, $sequence); + + /** @var string $iban */ + $iban = IbanEnum::getByName('C_' . $country); + $layout = \str_replace(' ', '', $iban); + $start = \stripos($layout, $sequence); + $end = \strrpos($layout, $sequence); if ($start === false || $end === false) { return ''; diff --git a/Stdlib/Base/Location.php b/Stdlib/Base/Location.php index cf5a22bee..29ded4f97 100644 --- a/Stdlib/Base/Location.php +++ b/Stdlib/Base/Location.php @@ -217,6 +217,10 @@ class Location implements \JsonSerializable, SerializableInterface */ public function unserialize(mixed $serialized) : void { + if (!\is_string($serialized)) { + return; + } + $data = \json_decode($serialized, true); if (!\is_array($data)) { diff --git a/System/File/Ftp/Directory.php b/System/File/Ftp/Directory.php index 6bbfc58dc..098ae5f9b 100644 --- a/System/File/Ftp/Directory.php +++ b/System/File/Ftp/Directory.php @@ -55,16 +55,15 @@ class Directory extends FileAbstract implements DirectoryInterface * * @param HttpUri $http Uri * - * @return mixed + * @return null|\FTP\Connection * * @since 1.0.0 */ - public static function ftpConnect(HttpUri $http) : mixed + public static function ftpConnect(HttpUri $http) : ?\FTP\Connection { $con = \ftp_connect($http->host, $http->port, 10); - if ($con === false) { - return false; + return null; } \ftp_login($con, $http->user, $http->pass); @@ -79,14 +78,14 @@ class Directory extends FileAbstract implements DirectoryInterface /** * Constructor. * - * @param HttpUri $uri Uri - * @param string $filter Filter - * @param bool $initialize Should get initialized during construction - * @param null|resource $con Connection + * @param HttpUri $uri Uri + * @param string $filter Filter + * @param bool $initialize Should get initialized during construction + * @param \FTP\Connection $con Connection * * @since 1.0.0 */ - public function __construct(HttpUri $uri, string $filter = '*', bool $initialize = true, $con = null) + public function __construct(HttpUri $uri, string $filter = '*', bool $initialize = true, \FTP\Connection $con = null) { $this->uri = $uri; $this->con = $con ?? self::ftpConnect($uri); @@ -715,7 +714,7 @@ class Directory extends FileAbstract implements DirectoryInterface /** * {@inheritdoc} */ - public function offsetSet($offset, $value) : void + public function offsetSet(mixed $offset, mixed $value) : void { if ($offset === null || !isset($this->nodes[$offset])) { $this->addNode($value); @@ -728,7 +727,7 @@ class Directory extends FileAbstract implements DirectoryInterface /** * {@inheritdoc} */ - public function offsetExists($offset) : bool + public function offsetExists(mixed $offset) : bool { $offset = isset($this->nodes[$offset]) ? $offset : $this->path . '/' . $offset; @@ -738,7 +737,7 @@ class Directory extends FileAbstract implements DirectoryInterface /** * {@inheritdoc} */ - public function offsetUnset($offset) : void + public function offsetUnset(mixed $offset) : void { $offset = isset($this->nodes[$offset]) ? $offset : $this->path . '/' . $offset; diff --git a/System/File/Ftp/File.php b/System/File/Ftp/File.php index af2bf7776..c9dd1e39c 100644 --- a/System/File/Ftp/File.php +++ b/System/File/Ftp/File.php @@ -71,16 +71,15 @@ class File extends FileAbstract implements FileInterface * * @param HttpUri $http Uri * - * @return mixed + * @return null|\FTP\Connection * * @since 1.0.0 */ - public static function ftpConnect(HttpUri $http) : mixed + public static function ftpConnect(HttpUri $http) : ?\FTP\Connection { $con = \ftp_connect($http->host, $http->port, 10); - if ($con === false) { - return false; + return null; } \ftp_login($con, $http->user, $http->pass); @@ -209,7 +208,7 @@ class File extends FileAbstract implements FileInterface /** * {@inheritdoc} */ - public static function prepend($con, string $path, string $content) : bool + public static function prepend(\FTP\Connection $con, string $path, string $content) : bool { return self::put($con, $path, $content, ContentPutMode::PREPEND | ContentPutMode::CREATE); } diff --git a/System/File/Local/Directory.php b/System/File/Local/Directory.php index fe209d81f..6462a41cf 100644 --- a/System/File/Local/Directory.php +++ b/System/File/Local/Directory.php @@ -541,8 +541,12 @@ final class Directory extends FileAbstract implements DirectoryInterface /** * {@inheritdoc} */ - public function offsetSet($offset, $value) : void + public function offsetSet(mixed $offset, mixed $value) : void { + if (!($value instanceof ContainerInterface)) { + return; + } + if ($offset === null || !isset($this->nodes[$offset])) { $this->addNode($value); } else { @@ -554,7 +558,7 @@ final class Directory extends FileAbstract implements DirectoryInterface /** * {@inheritdoc} */ - public function offsetExists($offset) : bool + public function offsetExists(mixed $offset) : bool { $offset = isset($this->nodes[$offset]) ? $offset : $this->path . '/' . $offset; @@ -564,7 +568,7 @@ final class Directory extends FileAbstract implements DirectoryInterface /** * {@inheritdoc} */ - public function offsetUnset($offset) : void + public function offsetUnset(mixed $offset) : void { $offset = isset($this->nodes[$offset]) ? $offset : $this->path . '/' . $offset; diff --git a/Utils/ArrayUtils.php b/Utils/ArrayUtils.php index 9fef0c914..0fa497228 100644 --- a/Utils/ArrayUtils.php +++ b/Utils/ArrayUtils.php @@ -260,8 +260,8 @@ final class ArrayUtils * * Useful for parsing command line parsing * - * @param string $id Id to find - * @param string[] $args CLI command list + * @param string $id Id to find + * @param int[]|string[] $args CLI command list * * @return string * @@ -283,8 +283,8 @@ final class ArrayUtils /** * Check if flag is set * - * @param string $id Id to find - * @param string[] $args CLI command list + * @param string $id Id to find + * @param int[]|string[] $args CLI command list * * @return int * diff --git a/Utils/IO/Spreadsheet/SpreadsheetDatabaseMapper.php b/Utils/IO/Spreadsheet/SpreadsheetDatabaseMapper.php index af49e8f8d..92f4091d7 100644 --- a/Utils/IO/Spreadsheet/SpreadsheetDatabaseMapper.php +++ b/Utils/IO/Spreadsheet/SpreadsheetDatabaseMapper.php @@ -130,6 +130,9 @@ class SpreadsheetDatabaseMapper implements IODatabaseMapper foreach ($queries as $key => $query) { $results = $query->execute()?->fetchAll(\PDO::FETCH_ASSOC); + if ($results === null) { + continue; + } if ($key > $sheetCount - 1) { $sheet->createSheet($key); diff --git a/Validation/Finance/Iban.php b/Validation/Finance/Iban.php index e2a5f68a3..162a2c384 100644 --- a/Validation/Finance/Iban.php +++ b/Validation/Finance/Iban.php @@ -50,7 +50,9 @@ final class Iban extends ValidatorAbstract return false; } - $layout = \str_replace(' ', '', IbanEnum::getByName($enumName)); + /** @var string $enumVal */ + $enumVal = IbanEnum::getByName($enumName); + $layout = \str_replace(' ', '', $enumVal); if (\strlen($value) !== \strlen($layout)) { self::$error = IbanErrorType::INVALID_LENGTH; diff --git a/tests/DataStorage/Database/TestModel/BaseModelMapper.php b/tests/DataStorage/Database/TestModel/BaseModelMapper.php index 4c62eca71..988ed743b 100755 --- a/tests/DataStorage/Database/TestModel/BaseModelMapper.php +++ b/tests/DataStorage/Database/TestModel/BaseModelMapper.php @@ -43,7 +43,7 @@ class BaseModelMapper extends DataMapperFactory /** * Belongs to. * - * @var array + * @var array * @since 1.0.0 */ public const BELONGS_TO = [