From 4414fad940272168c36319cb20253ab7f4f1cd9d Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Tue, 31 Dec 2019 19:54:35 +0100 Subject: [PATCH] add todos from github --- Account/PermissionHandlingTrait.php | 6 +- ApplicationAbstract.php | 6 +- .../Cache/Connection/ConnectionInterface.php | 14 ++ DataStorage/Cache/Connection/FileCache.php | 8 + .../DataStorageConnectionInterface.php | 2 - .../Connection/ConnectionAbstract.php | 5 + .../Database/Connection/MysqlConnection.php | 9 +- .../Connection/PostgresConnection.php | 9 +- .../Database/Connection/SQLiteConnection.php | 7 + .../Connection/SqlServerConnection.php | 7 + DataStorage/Database/DataMapperAbstract.php | 208 ++++++++++++------ DataStorage/Database/Query/Builder.php | 89 ++++---- .../Database/Query/Grammar/Grammar.php | 4 + DataStorage/Database/Schema/Builder.php | 4 + .../Database/Schema/Grammar/Grammar.php | 4 + .../Database/Schema/Grammar/MysqlGrammar.php | 4 + .../CubicSplineInterpolation.php | 6 +- Math/Statistic/Average.php | 8 + Math/Statistic/Forecast/Error.php | 21 ++ .../HypergeometricDistribution.php | 16 +- Message/Http/Request.php | 10 +- Message/Http/Response.php | 49 ++--- Message/Mail/EmailAbstract.php | 3 + Message/Socket/Response.php | 49 ++--- Module/ModuleAbstract.php | 4 +- Module/ModuleManager.php | 3 + Router/WebRouter.php | 20 ++ Stdlib/Graph/BinaryTree.php | 2 - Stdlib/Graph/Node.php | 2 - Utils/ArrayUtils.php | 11 + Utils/Parser/Markdown/Markdown.php | 2 - Utils/StringUtils.php | 4 + .../Database/DataMapperAbstractTest.php | 20 +- .../Database/Query/BuilderTest.php | 9 - tests/Math/Matrix/MatrixTest.php | 7 +- tests/Message/Http/RequestTest.php | 2 +- tests/Utils/ArrayUtilsTest.php | 8 +- tests/Utils/Git/RepositoryTest.php | 1 - tests/Utils/TaskSchedule/ScheduleTest.php | 2 + .../TaskSchedule/SchedulerFactoryTest.php | 5 - 40 files changed, 421 insertions(+), 229 deletions(-) diff --git a/Account/PermissionHandlingTrait.php b/Account/PermissionHandlingTrait.php index accfedd62..70f734e13 100644 --- a/Account/PermissionHandlingTrait.php +++ b/Account/PermissionHandlingTrait.php @@ -21,6 +21,10 @@ namespace phpOMS\Account; * @license OMS License 1.0 * @link https://orange-management.org * @since 1.0.0 + * + * @todo Orange-Management/phpOMS#200 + * Implement remove permission functionality + * Currently only adding permissions is possible but it should also be possible to remove permissions from an account. */ trait PermissionHandlingTrait { @@ -136,7 +140,7 @@ trait PermissionHandlingTrait int $element = null, int $component = null ) : bool { - $app = $app !== null ? \strtolower($app) : $app; // @todo: maybe don't do this because this function get's called so often. + $app = $app !== null ? \strtolower($app) : $app; for ($i = 0; $i < $this->pLength; ++$i) { if ($this->permissions[$i]->hasPermission($permission, $unit, $app, $module, $type, $element, $component)) { diff --git a/ApplicationAbstract.php b/ApplicationAbstract.php index 784e74135..e8fe8f601 100644 --- a/ApplicationAbstract.php +++ b/ApplicationAbstract.php @@ -193,7 +193,8 @@ class ApplicationAbstract * * @return void * - * @todo replace with proper setter (faster) + * @todo Orange-Management/phpOMS#218 + * As soon as readonly member variables are possible the magic methods should be removed. * * @since 1.0.0 */ @@ -213,7 +214,8 @@ class ApplicationAbstract * * @return mixed Returns the value of the application member * - * @todo replace with proper getter (faster) + * @todo Orange-Management/phpOMS#218 + * As soon as readonly member variables are possible the magic methods should be removed. * * @since 1.0.0 */ diff --git a/DataStorage/Cache/Connection/ConnectionInterface.php b/DataStorage/Cache/Connection/ConnectionInterface.php index 156917d60..6898da88c 100644 --- a/DataStorage/Cache/Connection/ConnectionInterface.php +++ b/DataStorage/Cache/Connection/ConnectionInterface.php @@ -23,6 +23,20 @@ use phpOMS\DataStorage\DataStorageConnectionInterface; * @license OMS License 1.0 * @link https://orange-management.org * @since 1.0.0 + * + * @todo Orange-Management/phpOMS#184 + * Add more functions: + * * exists - Checks if the key exists + * * getLike - Get all by pattern + * * removeLike - Remove all by pattern + * * getMult - Get multiple results + * * removeMult - Remove multiple + * * setMult - Set multiple + * * updateExpiration - Update expiration + * * increment - Increment numeric value + * * decrement - Decrement numeric value + * * rename - Rename key + * * save - Save cache (to hard drive or somewhere else) */ interface ConnectionInterface extends DataStorageConnectionInterface { diff --git a/DataStorage/Cache/Connection/FileCache.php b/DataStorage/Cache/Connection/FileCache.php index cd06bf660..6ad79238f 100644 --- a/DataStorage/Cache/Connection/FileCache.php +++ b/DataStorage/Cache/Connection/FileCache.php @@ -39,6 +39,14 @@ use phpOMS\System\File\Local\File; * @license OMS License 1.0 * @link https://orange-management.org * @since 1.0.0 + * + * @todo Orange-Management/phpOMS#182 + * Create file locking + * The file caching should implement a locking solution for the cache files. + * Without it a different process may try to read it while the cache is still getting created. + * A solution could be to create a directory or file called _lock which is getting checked + * (if this file exists reading from cache, modifying or creating it is not allowed except the _lock file is 5 minutes or so old). + * File and or directory creation should be atomic, right? */ final class FileCache extends ConnectionAbstract { diff --git a/DataStorage/DataStorageConnectionInterface.php b/DataStorage/DataStorageConnectionInterface.php index 4541b6e6c..370604d7c 100644 --- a/DataStorage/DataStorageConnectionInterface.php +++ b/DataStorage/DataStorageConnectionInterface.php @@ -43,8 +43,6 @@ interface DataStorageConnectionInterface * * @return void * - * @todo make private, reason was that not everyone wants to connect during initialization?! - * * @since 1.0.0 */ public function connect(array $data) : void; diff --git a/DataStorage/Database/Connection/ConnectionAbstract.php b/DataStorage/Database/Connection/ConnectionAbstract.php index e501dc5ab..9a01eefd8 100644 --- a/DataStorage/Database/Connection/ConnectionAbstract.php +++ b/DataStorage/Database/Connection/ConnectionAbstract.php @@ -29,6 +29,11 @@ use phpOMS\DataStorage\Database\Schema\Grammar\Grammar as SchemaGrammar; * @license OMS License 1.0 * @link https://orange-management.org * @since 1.0.0 + * + * @todo Orange-Management/Modules#100 + * Init only when used + * The database connection should only get initialized when used. + * Setup happens before but initialization should only happen on the first usage. */ abstract class ConnectionAbstract implements ConnectionInterface { diff --git a/DataStorage/Database/Connection/MysqlConnection.php b/DataStorage/Database/Connection/MysqlConnection.php index 2821283d0..63a4226fb 100644 --- a/DataStorage/Database/Connection/MysqlConnection.php +++ b/DataStorage/Database/Connection/MysqlConnection.php @@ -47,7 +47,14 @@ final class MysqlConnection extends ConnectionAbstract $this->type = DatabaseType::MYSQL; $this->grammar = new MysqlGrammar(); $this->schemaGrammar = new MysqlSchemaGrammar(); - $this->connect($dbdata); // todo: remove since this is a side effect that doesn't belong to constructor + + /** + * @todo Orange-Management/phpOMS#219 + * Don't automatically connect to the database during initialization. This should be done in a separate step. + * This also requires to adjust some other framework code which currently expects the database connection to be established after initialization. + * Sometimes DB connections may not be needed and should only be connected to once required. + */ + $this->connect($dbdata); } /** diff --git a/DataStorage/Database/Connection/PostgresConnection.php b/DataStorage/Database/Connection/PostgresConnection.php index fc16d6827..e1044532f 100644 --- a/DataStorage/Database/Connection/PostgresConnection.php +++ b/DataStorage/Database/Connection/PostgresConnection.php @@ -47,7 +47,14 @@ final class PostgresConnection extends ConnectionAbstract $this->type = DatabaseType::PGSQL; $this->grammar = new PostgresGrammar(); $this->schemaGrammar = new PostgresSchemaGrammar(); - $this->connect($dbdata); // todo: remove since this is a side effect that doesn't belong to constructor + + /** + * @todo Orange-Management/phpOMS#219 + * Don't automatically connect to the database during initialization. This should be done in a separate step. + * This also requires to adjust some other framework code which currently expects the database connection to be established after initialization. + * Sometimes DB connections may not be needed and should only be connected to once required. + */ + $this->connect($dbdata); } /** diff --git a/DataStorage/Database/Connection/SQLiteConnection.php b/DataStorage/Database/Connection/SQLiteConnection.php index 305e0ab3f..23b43c452 100644 --- a/DataStorage/Database/Connection/SQLiteConnection.php +++ b/DataStorage/Database/Connection/SQLiteConnection.php @@ -47,6 +47,13 @@ final class SQLiteConnection extends ConnectionAbstract $this->type = DatabaseType::SQLITE; $this->grammar = new SQLiteGrammar(); $this->schemaGrammar = new SQLiteSchemaGrammar(); + + /** + * @todo Orange-Management/phpOMS#219 + * Don't automatically connect to the database during initialization. This should be done in a separate step. + * This also requires to adjust some other framework code which currently expects the database connection to be established after initialization. + * Sometimes DB connections may not be needed and should only be connected to once required. + */ $this->connect($dbdata); } diff --git a/DataStorage/Database/Connection/SqlServerConnection.php b/DataStorage/Database/Connection/SqlServerConnection.php index ef35f1873..924a21563 100644 --- a/DataStorage/Database/Connection/SqlServerConnection.php +++ b/DataStorage/Database/Connection/SqlServerConnection.php @@ -47,6 +47,13 @@ final class SqlServerConnection extends ConnectionAbstract $this->type = DatabaseType::SQLSRV; $this->grammar = new MysqlGrammar(); $this->schemaGrammar = new MysqlSchemaGrammar(); + + /** + * @todo Orange-Management/phpOMS#219 + * Don't automatically connect to the database during initialization. This should be done in a separate step. + * This also requires to adjust some other framework code which currently expects the database connection to be established after initialization. + * Sometimes DB connections may not be needed and should only be connected to once required. + */ $this->connect($dbdata); } diff --git a/DataStorage/Database/DataMapperAbstract.php b/DataStorage/Database/DataMapperAbstract.php index 719db573f..62024b08b 100644 --- a/DataStorage/Database/DataMapperAbstract.php +++ b/DataStorage/Database/DataMapperAbstract.php @@ -31,7 +31,106 @@ use Throwable; * @license OMS License 1.0 * @link https://orange-management.org * @since 1.0.0 - * @todo: currently hasmany, owns one etc. are not using joins. In some cases this could improve the performance instead of separately querying the database + * + * @todo Orange-Management/phpOMS#220 + * Use joins. + * The datamapper is not using any joins currently which could significantly improve the performance of the queries. + * Joins should be used for: + * * composite models (models built from multiple tables) + * * owns one + * * has one + * * belongs to one + * * conditionals + * + * @todo Orange-Management/phpOMS#222 + * Implement conditionals. + * Conditionals are hardcoded or dynamically passed parameters based on which a model is found. + * The best example is the language of a model (e.g. news article), which is stored as foreign key in the model. + * With conditionals it's possible to reference other tables and also return elements based on the value in these tables/columns. + * Possible solution: + * 1. join tables/columns which have conditionals + * 2. perform the select based on the match + * ```php + * TestMapper::getByConditional(['l11n' => 'en']); + * ``` + * + * @todo Orange-Management/phpOMS#73 + * Implement extending + * Allow a data mapper to extend another data mapper. + * This way the object will be inserted first with one data mapper and the remaining fields will be filled by the extended data mapper. + * How can wen solve a mapper extending a mapper ... extending a mapper? + * + * @todo Orange-Management/phpOMS#102 + * Solve N+1 problem + * Currently the datamapper generates separate queries for objects that have relationships defined. + * Most of these relationships could be defined MUCH smarter and reduce the amout of sub-queries e.g. selecting a task and all its comments. + * The get method accepts an array of keys but doesn't select them in bulk but one at a time. + * + * @todo Orange-Management/phpOMS#122 + * Split/Refactor. + * Child extends parent. Parent creates GetMapper, CreateMapper etc. + * Example: + * ```User::get(...)``` + * The get() function (defined in an abstract class) creates internally an instance of GetMapper. + * The GetMapper receives all information such as primaryField, columns etc internally from the get(). + * This transfer of knowledge to the GetMapper could be done in the abstract class as a setup() function. + * Now all mappers are split. The overhead is one additional function call and the setup() function. + * Alternatively, think about using traits in the beginning. + * + * @todo Orange-Management/phpOMS#162 + * Relations by other than primary key + * Currently relations are always defined by the primary key. It would be very helpful to also define relations by other values. + * + * @todo Orange-Management/phpOMS#189 + * Allow model creation with ids + * The datamapper checks if the model has an non-empty id before it creates the mode. + * Some models however can have custom primary keys. + * In this case this check should not be done and therefore a $force flag got implemented in order to force the creation of the mode. + * This should be changed by checking if the primary key is autoincrement or not. + * If it isn't autoincrement the model should be created without an additional flag. + * The problem that arises is that now you need to check if the model is already in the database. + * This could be done based on the database response (error). + * + * @todo Orange-Management/phpOMS#212 + * Replace nested models which are represented as scalar/id with NullModel + * Currently there is a default limit on dependency nesting when you request a model from the database. + * This means a model may have a model as member and that model in return also has some model as member and so on. + * In order to prevent very deep nesting either the default nesting level is used to limit the amount of nesting or the user can specify a nesting depth. + * Once the lowest nesting level is reached the mapper only stores the id in the member variable and NOT the model. + * As a result the member variable can be of type null, int (= primary key of the model), or the model type. + * This results in many special cases which a coder may has to consider. + * It might make sense to only store null and the model in the member variable. + * In order to still restrict the nesting the mapper could create a null model and only populate the id. + * This could reduce the complexity for the user and simplify the use cases. + * Additionally, it would now be possible to type hint the return value of many getter functions ?NullModelName. + * If this gets implemented we also need to adjust some setter functions. + * Many setter functions allow to only specify a id of the model. + * Either this needs to be prevented and a Null model needs to be provided (all null models must have a __construct(int $id = 0) function which allows to pass the id) or the setter function needs to create the null model based on the id. + * Implementing the above mentioned things will take some time but could improve the simplicity and overall code quality by a lot (at least from my personal opinion). + * + * @todo Orange-Management/phpOMS#213 & Orange-Management/phpOMS#224 + * Implement composite models + * All references such as ownsOne, hasMany etc. are based on the mappers for these objects. It should be possible to define single columns only. + * One example where this could be useful is the Address/Localization model. + * In here the country is stored by ID but you probably don't want to load an entire object and only the country name from the country table. + * + * @todo Orange-Management/phpOMS#214 + * Allow to define the model class + * Currently the DataMapper uses the mapper name to find the correct model class. + * This can remain but there should be a member variable or const which allows to define the model::class manually in case the model is different. + * One example could be the Address/Location model in the Address module and phpOMS Localization directory. + * + * @todo Orange-Management/Modules#99 + * Use binds + * Currently databinds are not used. Currently injections are possible. + * + * @todo Orange-Management/Modules#179 + * Replace int models with NullModels + * In many cases int is allowed to represent another model if not the whole model is supposed to be loaded. + * This means we have to check for null, int and model type. + * Instead of using int the NullModel should be used which has a constructor that allows to define the int. + * As a result the datamapper has to be rewritten for the select and insert/update. + * The select needs to set the null model as value and the insert/update needs to extract the id from the null and ignore all other empty values from the null model which obviously are the default values. */ class DataMapperAbstract implements DataMapperInterface { @@ -488,9 +587,7 @@ class DataMapperAbstract implements DataMapperInterface try { self::$db->con->prepare($query->toSql())->execute(); } catch (Throwable $t) { - // @todo: remove after debugging - // @fix: really remove it - // @critical: after we found the bug we MUST remove it! + // only for debugging //var_dump($t->getMessage()); //var_dump($query->toSql()); return -1; @@ -710,16 +807,9 @@ class DataMapperAbstract implements DataMapperInterface } // Setting relation value (id) for relation (since the relation is not stored in an extra relation table) - /** - * @todo: this if comparison is correct, trust me. however, - * manybe it makes more sense to simply check if 'src' isset(static::$hasMany[$propertyName]['src']) - * source shouldn't be set if the relation is stored in the object itself - */ /** @var string $table */ /** @var array $columns */ - if (static::$hasMany[$propertyName]['table'] === static::$hasMany[$propertyName]['mapper']::$table - && isset($mapper::$columns[static::$hasMany[$propertyName]['dst']]) - ) { + if (!isset(static::$hasMany[$propertyName]['src'])) { $relProperty = $relReflectionClass->getProperty($mapper::$columns[static::$hasMany[$propertyName]['dst']]['internal']); if (!$isPublic) { @@ -927,12 +1017,8 @@ class DataMapperAbstract implements DataMapperInterface */ private static function createRelationTable(string $propertyName, array $objsIds, $objId) : void { - /** @todo: see hasMany implementation, checking isset(src) might be enough. although second condition MUST remain. */ /** @var string $table */ - if (!empty($objsIds) - && static::$hasMany[$propertyName]['table'] !== static::$table - && static::$hasMany[$propertyName]['table'] !== static::$hasMany[$propertyName]['mapper']::$table - ) { + if (!empty($objsIds) && isset(static::$hasMany[$propertyName]['src'])) { $relQuery = new Builder(self::$db); $relQuery->prefix(self::$db->getPrefix()) ->into(static::$hasMany[$propertyName]['table']) @@ -1853,7 +1939,10 @@ class DataMapperAbstract implements DataMapperInterface return $objId; } - // @todo: implement array delete + /** + * @todo Orange-Management/phpOMS#221 + * Create the delete functionality for arrays (deleteArray, deleteArrayModel). + */ /** * Populate data. @@ -1947,7 +2036,6 @@ class DataMapperAbstract implements DataMapperInterface */ public static function populateManyToMany(array $result, &$obj, int $depth = 3) : void { - // todo: maybe pass reflectionClass as optional parameter for performance increase $refClass = new \ReflectionClass($obj); foreach ($result as $member => $values) { @@ -2002,8 +2090,6 @@ class DataMapperAbstract implements DataMapperInterface * * @return void * - * @todo accept reflection class as parameter - * * @since 1.0.0 */ public static function populateOwnsOne(&$obj, int $depth = 3) : void @@ -2011,30 +2097,27 @@ class DataMapperAbstract implements DataMapperInterface $refClass = new \ReflectionClass($obj); foreach (static::$ownsOne as $member => $one) { - // todo: is that if necessary? performance is suffering for sure! - if ($refClass->hasProperty($member)) { - $refProp = $refClass->getProperty($member); + $refProp = $refClass->getProperty($member); - if (!($accessible = $refProp->isPublic())) { - $refProp->setAccessible(true); - } + if (!($accessible = $refProp->isPublic())) { + $refProp->setAccessible(true); + } - /** @var string $mapper */ - $mapper = static::$ownsOne[$member]['mapper']; - $id = $refProp->getValue($obj); + /** @var string $mapper */ + $mapper = static::$ownsOne[$member]['mapper']; + $id = $refProp->getValue($obj); - if (self::isNullObject($id)) { - continue; - } + if (self::isNullObject($id)) { + continue; + } - $id = \is_object($id) ? self::getObjectId($id) : $id; - $value = self::getInitialized($mapper, $id) ?? $mapper::get($id, RelationType::ALL, null, $depth); + $id = \is_object($id) ? self::getObjectId($id) : $id; + $value = self::getInitialized($mapper, $id) ?? $mapper::get($id, RelationType::ALL, null, $depth); - $refProp->setValue($obj, $value); + $refProp->setValue($obj, $value); - if (!$accessible) { - $refProp->setAccessible(false); - } + if (!$accessible) { + $refProp->setAccessible(false); } } } @@ -2043,7 +2126,6 @@ class DataMapperAbstract implements DataMapperInterface * * @return void * - * @todo accept reflection class as parameter * @todo do this in the getRaw() part as a join. check if has conditionals and then join the data an then everything can be done in the getModel function. * * @since 1.0.0 @@ -2078,8 +2160,6 @@ class DataMapperAbstract implements DataMapperInterface * * @return void * - * @todo accept reflection class as parameter - * * @since 1.0.0 */ public static function populateOwnsOneArray(array &$obj, int $depth = 3) : void @@ -2102,8 +2182,6 @@ class DataMapperAbstract implements DataMapperInterface * * @return void * - * @todo accept reflection class as parameter - * * @since 1.0.0 */ public static function populateBelongsTo(&$obj, int $depth = 3) : void @@ -2111,30 +2189,27 @@ class DataMapperAbstract implements DataMapperInterface $refClass = new \ReflectionClass($obj); foreach (static::$belongsTo as $member => $one) { - // todo: is that if necessary? performance is suffering for sure! - if ($refClass->hasProperty($member)) { - $refProp = $refClass->getProperty($member); + $refProp = $refClass->getProperty($member); - if (!($accessible = $refProp->isPublic())) { - $refProp->setAccessible(true); - } + if (!($accessible = $refProp->isPublic())) { + $refProp->setAccessible(true); + } - /** @var string $mapper */ - $mapper = static::$belongsTo[$member]['mapper']; - $id = $refProp->getValue($obj); + /** @var string $mapper */ + $mapper = static::$belongsTo[$member]['mapper']; + $id = $refProp->getValue($obj); - if (self::isNullObject($id)) { - continue; - } + if (self::isNullObject($id)) { + continue; + } - $id = \is_object($id) ? self::getObjectId($id) : $id; - $value = self::getInitialized($mapper, $id) ?? $mapper::get($id, RelationType::ALL, null, $depth); + $id = \is_object($id) ? self::getObjectId($id) : $id; + $value = self::getInitialized($mapper, $id) ?? $mapper::get($id, RelationType::ALL, null, $depth); - $refProp->setValue($obj, $value); + $refProp->setValue($obj, $value); - if (!$accessible) { - $refProp->setAccessible(false); - } + if (!$accessible) { + $refProp->setAccessible(false); } } } @@ -2147,8 +2222,6 @@ class DataMapperAbstract implements DataMapperInterface * * @return void * - * @todo accept reflection class as parameter - * * @since 1.0.0 */ public static function populateBelongsToArray(array &$obj, int $depth = 3) : void @@ -2180,7 +2253,7 @@ class DataMapperAbstract implements DataMapperInterface $refClass = new \ReflectionClass($obj); foreach ($result as $column => $value) { - if (!isset($columns[$column]['internal']) /* && $refClass->hasProperty($columns[$column]['internal']) */) { + if (!isset($columns[$column]['internal'])) { continue; } @@ -2293,7 +2366,10 @@ class DataMapperAbstract implements DataMapperInterface * * @return mixed * - * @todo: implement language + * @todo Orange-Management/phpOMS#161 + * Reconsider get*() parameter order + * Check if the parameter order of all of the get functions makes sense or if another order would be better. + * Especially the fill parameter probably should be swapped with the depth filter. * * @since 1.0.0 */ diff --git a/DataStorage/Database/Query/Builder.php b/DataStorage/Database/Query/Builder.php index 18b56c81d..edf080cc9 100644 --- a/DataStorage/Database/Query/Builder.php +++ b/DataStorage/Database/Query/Builder.php @@ -24,6 +24,16 @@ use phpOMS\DataStorage\Database\Connection\ConnectionAbstract; * @license OMS License 1.0 * @link https://orange-management.org * @since 1.0.0 + * + * @todo Orange-Management/phpOMS#33 + * Implement missing grammar & builder functions + * Missing elements are e.g. sum, merge etc. + * + * @todo Orange-Management/phpOMS#194 + * Automatically set prefix during construction + * When constructing the QueryBuilder or SchemaBuilder the connection is passed. + * The connection holds information about the table prefix, yet I force developers to pass a prefix after the builder initialization. + * This should be done automatically! */ class Builder extends BuilderAbstract { @@ -70,10 +80,10 @@ class Builder extends BuilderAbstract /** * Into. * - * @var \Closure|string + * @var string * @since 1.0.0 */ - public $into = null; + public string $into = ''; /** * Into columns. @@ -267,8 +277,6 @@ class Builder extends BuilderAbstract * * @return Builder * - * @todo Closure is not working this way, needs to be evaluated befor assigning - * * @since 1.0.0 */ public function select(...$columns) : self @@ -276,7 +284,7 @@ class Builder extends BuilderAbstract $this->type = QueryType::SELECT; foreach ($columns as $key => $column) { - if (\is_string($column) || $column instanceof self || $column instanceof \Closure) { + if (\is_string($column) || $column instanceof self) { $this->selects[] = $column; } else { throw new \InvalidArgumentException(); @@ -311,8 +319,6 @@ class Builder extends BuilderAbstract * * @return Builder * - * @todo Closure is not working this way, needs to be evaluated befor assigning - * * @since 1.0.0 */ public function random(...$columns) : self @@ -338,7 +344,7 @@ class Builder extends BuilderAbstract { if (\is_array($binds)) { $this->binds += $binds; - } elseif (\is_string($binds) || $binds instanceof \Closure) { + } elseif (\is_string($binds)) { $this->binds[] = $binds; } else { throw new \InvalidArgumentException(); @@ -451,7 +457,7 @@ class Builder extends BuilderAbstract public function from(...$tables) : self { foreach ($tables as $key => $table) { - if (\is_string($table) || $table instanceof self || $table instanceof \Closure) { + if (\is_string($table) || $table instanceof self) { $this->from[] = $table; } else { throw new \InvalidArgumentException(); @@ -481,10 +487,10 @@ class Builder extends BuilderAbstract /** * Where. * - * @param array|\Closure|string|Where $columns Columns - * @param array|string $operator Operator - * @param mixed $values Values - * @param array|string $boolean Boolean condition + * @param array|string|Where $columns Columns + * @param array|string $operator Operator + * @param mixed $values Values + * @param array|string $boolean Boolean condition * * @return Builder * @@ -540,9 +546,9 @@ class Builder extends BuilderAbstract /** * Where and sub condition. * - * @param array|\Closure|string|Where $where Where sub condition - * @param mixed $operator Operator - * @param mixed $values Values + * @param array|string|Where $where Where sub condition + * @param mixed $operator Operator + * @param mixed $values Values * * @return Builder * @@ -556,9 +562,9 @@ class Builder extends BuilderAbstract /** * Where or sub condition. * - * @param array|\Closure|string|Where $where Where sub condition - * @param mixed $operator Operator - * @param mixed $values Values + * @param array|string|Where $where Where sub condition + * @param mixed $operator Operator + * @param mixed $values Values * * @return Builder * @@ -572,9 +578,9 @@ class Builder extends BuilderAbstract /** * Where in. * - * @param array|\Closure|string|Where $column Column - * @param mixed $values Values - * @param string $boolean Boolean condition + * @param array|string|Where $column Column + * @param mixed $values Values + * @param string $boolean Boolean condition * * @return Builder * @@ -590,8 +596,8 @@ class Builder extends BuilderAbstract /** * Where null. * - * @param array|\Closure|string|Where $column Column - * @param string $boolean Boolean condition + * @param array|string|Where $column Column + * @param string $boolean Boolean condition * * @return Builder * @@ -607,8 +613,8 @@ class Builder extends BuilderAbstract /** * Where not null. * - * @param array|\Closure|string|Where $column Column - * @param string $boolean Boolean condition + * @param array|string|Where $column Column + * @param string $boolean Boolean condition * * @return Builder * @@ -624,7 +630,7 @@ class Builder extends BuilderAbstract /** * Group by. * - * @param array|\Closure|string ...$columns Grouping result + * @param array|string ...$columns Grouping result * * @return Builder * @@ -633,7 +639,7 @@ class Builder extends BuilderAbstract public function groupBy(...$columns) : self { foreach ($columns as $key => $column) { - if (\is_string($column) || $column instanceof self || $column instanceof \Closure) { + if (\is_string($column) || $column instanceof self) { $this->groups[] = $column; } else { throw new \InvalidArgumentException(); @@ -646,13 +652,13 @@ class Builder extends BuilderAbstract /** * Order by newest. * - * @param \Closure|string $column Column + * @param string $column Column * * @return Builder * * @since 1.0.0 */ - public function newest($column) : self + public function newest(string $column) : self { $this->orderBy($column, 'DESC'); @@ -662,13 +668,13 @@ class Builder extends BuilderAbstract /** * Order by oldest. * - * @param \Closure|string $column Column + * @param string $column Column * * @return Builder * * @since 1.0.0 */ - public function oldest($column) : self + public function oldest(string $column) : self { $this->orderBy($column, 'ASC'); @@ -678,8 +684,8 @@ class Builder extends BuilderAbstract /** * Order by oldest. * - * @param array|\Closure|string $columns Columns - * @param string|string[] $order Orders + * @param array|string $columns Columns + * @param string|string[] $order Orders * * @return Builder * @@ -687,7 +693,7 @@ class Builder extends BuilderAbstract */ public function orderBy($columns, $order = 'DESC') : self { - if (\is_string($columns) || $columns instanceof \Closure) { + if (\is_string($columns)) { if (!\is_string($order)) { throw new \InvalidArgumentException(); } @@ -893,13 +899,13 @@ class Builder extends BuilderAbstract /** * Table to insert into. * - * @param \Closure|string $table Table + * @param string $table Table * * @return Builder * * @since 1.0.0 */ - public function into($table) : self + public function into(string $table) : self { $this->into = $table; @@ -1011,7 +1017,7 @@ class Builder extends BuilderAbstract $this->type = QueryType::UPDATE; foreach ($tables as $key => $table) { - if (\is_string($table) || $table instanceof self || $table instanceof \Closure) { + if (\is_string($table) || $table instanceof self) { $this->updates[] = $table; } else { throw new \InvalidArgumentException(); @@ -1074,7 +1080,7 @@ class Builder extends BuilderAbstract */ public function join($table, string $type = JoinType::JOIN, string $alias = null) : self { - if (!\is_string($table)&& !($table instanceof self) && !($table instanceof \Closure)) { + if (!\is_string($table)&& !($table instanceof self)) { throw new \InvalidArgumentException(); } @@ -1292,7 +1298,8 @@ class Builder extends BuilderAbstract throw new \InvalidArgumentException('Unknown operator.'); } - // @todo: this is bad! ons needs to have the same key as the join for the grammar to work. since alias are possible this is nec3essary. + // ons needs to have the same key as the join for the grammar to work + // since alias are possible this is necessary $this->ons[\array_keys($this->joins)[$joinCount]][] = [ 'column' => $column, 'operator' => $operator[$i], @@ -1407,8 +1414,6 @@ class Builder extends BuilderAbstract return $column; } elseif ($column instanceof Column) { return $column->getColumn(); - } elseif ($column instanceof \Closure) { - return $column(); } elseif ($column instanceof \Serializable) { return $column->serialize(); } diff --git a/DataStorage/Database/Query/Grammar/Grammar.php b/DataStorage/Database/Query/Grammar/Grammar.php index 32f9cf83f..a78c0b8e7 100644 --- a/DataStorage/Database/Query/Grammar/Grammar.php +++ b/DataStorage/Database/Query/Grammar/Grammar.php @@ -28,6 +28,10 @@ use phpOMS\DataStorage\Database\Query\Where; * @license OMS License 1.0 * @link https://orange-management.org * @since 1.0.0 + * + * @todo Orange-Management/phpOMS#33 + * Implement missing grammar & builder functions + * Missing elements are e.g. sum, merge etc. */ class Grammar extends GrammarAbstract { diff --git a/DataStorage/Database/Schema/Builder.php b/DataStorage/Database/Schema/Builder.php index 15d0c0c9b..73d50576c 100644 --- a/DataStorage/Database/Schema/Builder.php +++ b/DataStorage/Database/Schema/Builder.php @@ -24,6 +24,10 @@ use phpOMS\DataStorage\Database\Query\Builder as QueryBuilder; * @license OMS License 1.0 * @link https://orange-management.org * @since 1.0.0 + * + * @todo Orange-Management/phpOMS#32 + * Implement schema grammar + * Basic create/drop schema grammar created. Next step is to be able to update existing schema and read existing schema. */ class Builder extends QueryBuilder { diff --git a/DataStorage/Database/Schema/Grammar/Grammar.php b/DataStorage/Database/Schema/Grammar/Grammar.php index 04638b740..d3ea1525a 100644 --- a/DataStorage/Database/Schema/Grammar/Grammar.php +++ b/DataStorage/Database/Schema/Grammar/Grammar.php @@ -25,6 +25,10 @@ use phpOMS\DataStorage\Database\Schema\QueryType; * @license OMS License 1.0 * @link https://orange-management.org * @since 1.0.0 + * + * @todo Orange-Management/phpOMS#32 + * Implement schema grammar + * Basic create/drop schema grammar created. Next step is to be able to update existing schema and read existing schema. */ class Grammar extends QueryGrammar { diff --git a/DataStorage/Database/Schema/Grammar/MysqlGrammar.php b/DataStorage/Database/Schema/Grammar/MysqlGrammar.php index 93d753d56..7ad7e90ef 100644 --- a/DataStorage/Database/Schema/Grammar/MysqlGrammar.php +++ b/DataStorage/Database/Schema/Grammar/MysqlGrammar.php @@ -24,6 +24,10 @@ use phpOMS\DataStorage\Database\Query\Builder; * @license OMS License 1.0 * @link https://orange-management.org * @since 1.0.0 + * + * @todo Orange-Management/phpOMS#32 + * Implement schema grammar + * Basic create/drop schema grammar created. Next step is to be able to update existing schema and read existing schema. */ class MysqlGrammar extends Grammar { diff --git a/Math/Numerics/Interpolation/CubicSplineInterpolation.php b/Math/Numerics/Interpolation/CubicSplineInterpolation.php index dcf3ab5c8..d45c9a379 100644 --- a/Math/Numerics/Interpolation/CubicSplineInterpolation.php +++ b/Math/Numerics/Interpolation/CubicSplineInterpolation.php @@ -136,8 +136,7 @@ final class CubicSplineInterpolation implements InterpolationInterface $this->solveC->setV($n - 1, 3.0 * $this->solveA->getV($n - 2) * $h ** 2 + 2.0 * $this->solveB->get($n - 2) * $h + $this->solveC->getV($n - 2)); /** - * @todo: consider linear extrapolation at start and end point - * + * linear extrapolation at start and end point * $this->solveB->setV($n - 1, 0.0) */ } @@ -164,8 +163,7 @@ final class CubicSplineInterpolation implements InterpolationInterface if ($x < $this->points[0]['x']) { return ($this->solveB->get(0) * $h + $this->solveC->getV(0)) * $h + $this->points[0]['y']; /** - * @todo: consider linear extrapolation at start and end point - * + * linear extrapolation at start and end point * ($this->solveC->getV(0)) * $h + $this->points[0]['y']; */ } elseif ($x > $this->points[$n - 1]['x']) { diff --git a/Math/Statistic/Average.php b/Math/Statistic/Average.php index f17e57288..3f14caaa1 100644 --- a/Math/Statistic/Average.php +++ b/Math/Statistic/Average.php @@ -272,6 +272,10 @@ final class Average \sort($values); if ($offset > 0) { + /** + * @todo Orange-Management/phpOMS#175 + * Create unit test. + */ $values = \array_slice($values, $offset, -$offset); } @@ -339,6 +343,10 @@ final class Average \sort($angles); if ($offset > 0) { + /** + * @todo Orange-Management/phpOMS#176 + * Create unit test. + */ $angles = \array_slice($angles, $offset, -$offset); } diff --git a/Math/Statistic/Forecast/Error.php b/Math/Statistic/Forecast/Error.php index b548188fa..6140a88de 100644 --- a/Math/Statistic/Forecast/Error.php +++ b/Math/Statistic/Forecast/Error.php @@ -218,6 +218,9 @@ final class Error * * @return float * + * @todo Orange-Management/phpOMS#167 + * Create unit test. + * * @since 1.0.0 */ public static function getAkaikeInformationCriterion(float $sse, int $observations, int $predictors) : float @@ -252,6 +255,9 @@ final class Error * * @return float * + * @todo Orange-Management/phpOMS#168 + * Create unit test. + * * @since 1.0.0 */ public static function getSchwarzBayesianInformationCriterion(float $sse, int $observations, int $predictors) : float @@ -267,6 +273,9 @@ final class Error * * @return float * + * @todo Orange-Management/phpOMS#169 + * Create unit test. + * * @since 1.0.0 */ public static function getMeanAbsolutePercentageError(array $observed, array $forecasted) : float @@ -282,6 +291,9 @@ final class Error * * @return float * + * @todo Orange-Management/phpOMS#170 + * Create unit test. + * * @since 1.0.0 */ public static function getSymmetricMeanAbsolutePercentageError(array $observed, array $forecasted) : float @@ -303,6 +315,9 @@ final class Error * * @return array * + * @todo Orange-Management/phpOMS#172 + * Create unit test. + * * @since 1.0.0 */ public static function getCrossSectionalScaledErrorArray(array $errors, array $observed) : array @@ -325,6 +340,9 @@ final class Error * * @return float * + * @todo Orange-Management/phpOMS#171 + * Create unit test. + * * @since 1.0.0 */ public static function getCrossSectionalScaledError(float $error, array $observed) : float @@ -360,6 +378,9 @@ final class Error * * @return float * + * @todo Orange-Management/phpOMS#173 + * Create unit test. + * * @since 1.0.0 */ public static function getMeanSquaredScaledError(array $scaledErrors) : float diff --git a/Math/Stochastic/Distribution/HypergeometricDistribution.php b/Math/Stochastic/Distribution/HypergeometricDistribution.php index fba5834dc..5442cbefd 100644 --- a/Math/Stochastic/Distribution/HypergeometricDistribution.php +++ b/Math/Stochastic/Distribution/HypergeometricDistribution.php @@ -35,8 +35,6 @@ final class HypergeometricDistribution * * @return float * - * @todo: this can be heavily optimized - * * @since 1.0.0 */ public static function getPmf(int $K, int $N, int $k, int $n) : float @@ -53,8 +51,6 @@ final class HypergeometricDistribution * * @return float * - * @todo: this can be heavily optimized - * * @since 1.0.0 */ public static function getMean(int $K, int $N, int $n) : float @@ -71,8 +67,6 @@ final class HypergeometricDistribution * * @return int * - * @todo: this can be heavily optimized - * * @since 1.0.0 */ public static function getMode(int $K, int $N, int $n) : int @@ -89,8 +83,6 @@ final class HypergeometricDistribution * * @return float * - * @todo: this can be heavily optimized - * * @since 1.0.0 */ public static function getVariance(int $K, int $N, int $n) : float @@ -107,13 +99,11 @@ final class HypergeometricDistribution * * @return float * - * @todo: this can be heavily optimized - * * @since 1.0.0 */ public static function getStandardDeviation(int $K, int $N, int $n) : float { - return \sqrt(self::getVariance($K, $N, $n)); + return \sqrt($n * $K / $N * ($N - $K) / $N * ($N - $n) / ($N - 1)); } /** @@ -125,8 +115,6 @@ final class HypergeometricDistribution * * @return float * - * @todo: this can be heavily optimized - * * @since 1.0.0 */ public static function getSkewness(int $K, int $N, int $n) : float @@ -144,8 +132,6 @@ final class HypergeometricDistribution * * @return float * - * @todo: this can be heavily optimized - * * @since 1.0.0 */ public static function getExKurtosis(int $K, int $N, int $n) : float diff --git a/Message/Http/Request.php b/Message/Http/Request.php index d2367fb0b..e7c2c9f59 100644 --- a/Message/Http/Request.php +++ b/Message/Http/Request.php @@ -115,7 +115,7 @@ final class Request extends RequestAbstract if (!isset($this->uri)) { $this->initCurrentRequest(); $this->lock(); - $this->cleanupGlobals(); + self::cleanupGlobals(); $this->setupUriBuilder(); } @@ -247,11 +247,9 @@ final class Request extends RequestAbstract * * @return void * - * @todo: consider making this function static. - * * @since 1.0.0 */ - private function cleanupGlobals() : void + public static function cleanupGlobals() : void { unset($_FILES); unset($_GET); @@ -463,11 +461,9 @@ final class Request extends RequestAbstract * * @throws \OutOfRangeException This exception is thrown if the port is out of range * - * @todo: consider making this static - * * @since 1.0.0 */ - public function isHttps(int $port = 443) : bool + public static function isHttps(int $port = 443) : bool { if ($port < 1 || $port > 65535) { throw new \OutOfRangeException('Value "' . $port . '" is out of range.'); diff --git a/Message/Http/Response.php b/Message/Http/Response.php index 6d015d9e1..67cc074b8 100644 --- a/Message/Http/Response.php +++ b/Message/Http/Response.php @@ -166,41 +166,32 @@ final class Response extends ResponseAbstract implements RenderableInterface /** * {@inheritdoc} - * @todo: this whole workflow with json got improved a little bit but this part looks bad. do i really need so much code or could i simplify it */ public function toArray() : array { $result = []; - try { - foreach ($this->response as $key => $response) { - if ($response instanceof View) { - $result[] = $response->toArray(); - } elseif (\is_array($response)) { - $result[] = $response; - } elseif (\is_scalar($response)) { - $result[] = $response; - } elseif ($response instanceof \JsonSerializable) { - $result[] = $response->jsonSerialize(); - } elseif ($response === null) { - continue; - } else { - throw new \Exception('Wrong response type'); - } + foreach ($this->response as $response) { + if ($response instanceof View) { + $result[] = $response->toArray(); + } elseif (\is_array($response) || \is_scalar($response)) { + $result[] = $response; + } elseif ($response instanceof \JsonSerializable) { + $result[] = $response->jsonSerialize(); + } elseif ($response === null) { + continue; + } else { + FileLogger::getInstance('', false) + ->error( + FileLogger::MSG_FULL, [ + 'message' => 'Unknown type.', + 'line' => __LINE__, + 'file' => self::class, + ] + ); } - } catch (\Exception $e) { - FileLogger::getInstance('', false) - ->error( - FileLogger::MSG_FULL, [ - 'message' => $e->getMessage(), - 'line' => __LINE__, - 'file' => self::class, - ] - ); - - $result = []; - } finally { - return $result; } + + return $result; } } diff --git a/Message/Mail/EmailAbstract.php b/Message/Mail/EmailAbstract.php index e072751b1..f730c5236 100644 --- a/Message/Mail/EmailAbstract.php +++ b/Message/Mail/EmailAbstract.php @@ -21,6 +21,9 @@ namespace phpOMS\Message\Mail; * @license OMS License 1.0 * @link https://orange-management.org * @since 1.0.0 + * + * @todo Orange-Management/phpOMS#34 + * Implement!!! */ class EmailAbstract { diff --git a/Message/Socket/Response.php b/Message/Socket/Response.php index 699b393b5..122378f4a 100644 --- a/Message/Socket/Response.php +++ b/Message/Socket/Response.php @@ -148,41 +148,32 @@ final class Response extends ResponseAbstract implements RenderableInterface /** * {@inheritdoc} - * @todo: this whole workflow with json got improved a little bit but this part looks bad. do i really need so much code or could i simplify it */ public function toArray() : array { $result = []; - try { - foreach ($this->response as $key => $response) { - if ($response instanceof View) { - $result[] = $response->toArray(); - } elseif (\is_array($response)) { - $result[] = $response; - } elseif (\is_scalar($response)) { - $result[] = $response; - } elseif ($response instanceof \JsonSerializable) { - $result[] = $response->jsonSerialize(); - } elseif ($response === null) { - continue; - } else { - throw new \Exception('Wrong response type'); - } + foreach ($this->response as $response) { + if ($response instanceof View) { + $result[] = $response->toArray(); + } elseif (\is_array($response) || \is_scalar($response)) { + $result[] = $response; + } elseif ($response instanceof \JsonSerializable) { + $result[] = $response->jsonSerialize(); + } elseif ($response === null) { + continue; + } else { + FileLogger::getInstance('', false) + ->error( + FileLogger::MSG_FULL, [ + 'message' => 'Unknown type.', + 'line' => __LINE__, + 'file' => self::class, + ] + ); } - } catch (\Exception $e) { - FileLogger::getInstance('', false) - ->error( - FileLogger::MSG_FULL, [ - 'message' => $e->getMessage(), - 'line' => __LINE__, - 'file' => self::class, - ] - ); - - $result = []; - } finally { - return $result; } + + return $result; } } diff --git a/Module/ModuleAbstract.php b/Module/ModuleAbstract.php index 426b56590..d8808de64 100644 --- a/Module/ModuleAbstract.php +++ b/Module/ModuleAbstract.php @@ -27,8 +27,8 @@ use phpOMS\System\MimeType; * @link https://orange-management.org * @since 1.0.0 * - * @todo: maybe move to Modules because this is very project specific and not general enough for a framework - * @todo: maybe move all of the Module\classes parts to the Modules\? + * @todo Orange-Management/Modules#113 + * Don't use name but id for identification */ abstract class ModuleAbstract { diff --git a/Module/ModuleManager.php b/Module/ModuleManager.php index 94d4ca5fa..879d6b866 100644 --- a/Module/ModuleManager.php +++ b/Module/ModuleManager.php @@ -31,6 +31,9 @@ use phpOMS\System\File\PathException; * @license OMS License 1.0 * @link https://orange-management.org * @since 1.0.0 + * + * @todo Orange-Management/Modules#113 + * Don't use name but id for identification */ final class ModuleManager { diff --git a/Router/WebRouter.php b/Router/WebRouter.php index 22f011714..98ce0453d 100644 --- a/Router/WebRouter.php +++ b/Router/WebRouter.php @@ -21,6 +21,26 @@ namespace phpOMS\Router; * @license OMS License 1.0 * @link https://orange-management.org * @since 1.0.0 + * + * @todo Orange-Management/phpOMS#191 + * Implement routing parameters + * Most routing implementations have parameters in their route e.g. + * 'route' => '/your/url/{@id}/something' + * This is very easy to read but slows down performance. + * 'route' => [ + * 'match' => '/your/url/.*?/something', + * 'parameters'=> [ + * 'id' => ['type' => 'path', 'index' => 2] + * ] + * ] + * The parameters should then be passed to the method in the $data = [] variable. + * + * @todo Orange-Management/phpOMS#192 + * Implement form/api data validation + * Similar to permission validation it could be possible to add data constraints which are expected for certain routes which then could be checked during routing and dispatching. + * For example it would be possible to define required data fields, their type, their pattern etc. + * This would make the routing definitions much bigger but also dramatically reduce the work which needs to be done in the controllers. + * It could even be written in a way which hardly effects performance. */ final class WebRouter implements RouterInterface { diff --git a/Stdlib/Graph/BinaryTree.php b/Stdlib/Graph/BinaryTree.php index 115f0c965..de5f06122 100644 --- a/Stdlib/Graph/BinaryTree.php +++ b/Stdlib/Graph/BinaryTree.php @@ -21,8 +21,6 @@ namespace phpOMS\Stdlib\Graph; * @license OMS License 1.0 * @link https://orange-management.org * @since 1.0.0 - * - * @todo : there is a bug with Hungary ibans since they have two k (checksums) in their definition */ class BinaryTree extends Tree { diff --git a/Stdlib/Graph/Node.php b/Stdlib/Graph/Node.php index 9324633c0..fe962dcc6 100644 --- a/Stdlib/Graph/Node.php +++ b/Stdlib/Graph/Node.php @@ -21,8 +21,6 @@ namespace phpOMS\Stdlib\Graph; * @license OMS License 1.0 * @link https://orange-management.org * @since 1.0.0 - * - * @todo : there is a bug with Hungary ibans since they have two k (checksums) in their definition */ class Node { diff --git a/Utils/ArrayUtils.php b/Utils/ArrayUtils.php index b530c76fb..395ee9cae 100644 --- a/Utils/ArrayUtils.php +++ b/Utils/ArrayUtils.php @@ -21,6 +21,11 @@ namespace phpOMS\Utils; * @license OMS License 1.0 * @link https://orange-management.org * @since 1.0.0 + * + * @todo Orange-Management/phpOMS#154 + * Create excel operations on arrays + * In many cases there are values stored inside of arrays which need simple math operators performed on them. + * Instead of writing the expression it should be possible to do this in good old excel fasion. */ final class ArrayUtils { @@ -386,6 +391,9 @@ final class ArrayUtils * * @return array * + * @todo Orange-Management/phpOMS#223 + * In the ArrayUtils class the power* functions should be combined once union types become available. + * * @since 1.0.0 */ public static function powerFloat(array $values, float $exp = 2.0) : array @@ -407,6 +415,9 @@ final class ArrayUtils * * @return array * + * @todo Orange-Management/phpOMS#223 + * In the ArrayUtils class the power* functions should be combined once union types become available. + * * @since 1.0.0 */ public static function powerInt(array $values, int $exp = 2) : array diff --git a/Utils/Parser/Markdown/Markdown.php b/Utils/Parser/Markdown/Markdown.php index 4c043f2ad..44bdeef39 100644 --- a/Utils/Parser/Markdown/Markdown.php +++ b/Utils/Parser/Markdown/Markdown.php @@ -210,8 +210,6 @@ class Markdown /** * Some definition data for elements * - * @todo: figure out what it is for - * * @var string[] * @since 1.0.0 */ diff --git a/Utils/StringUtils.php b/Utils/StringUtils.php index e0b4d3289..e261687b6 100644 --- a/Utils/StringUtils.php +++ b/Utils/StringUtils.php @@ -26,6 +26,10 @@ use phpOMS\Contract\RenderableInterface; * @link https://orange-management.org * @since 1.0.0 * + * @todo Orange-Management/phpOMS#119 + * Create jaro winkler distance + * https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance + * * @SuppressWarnings(PHPMD.CamelCaseMethodName) */ final class StringUtils diff --git a/tests/DataStorage/Database/DataMapperAbstractTest.php b/tests/DataStorage/Database/DataMapperAbstractTest.php index 088890102..498966ad8 100644 --- a/tests/DataStorage/Database/DataMapperAbstractTest.php +++ b/tests/DataStorage/Database/DataMapperAbstractTest.php @@ -202,7 +202,10 @@ class DataMapperAbstractTest extends \PHPUnit\Framework\TestCase self::assertEquals($this->model->datetime->format('Y-m-d'), $modelR->datetime->format('Y-m-d')); self::assertNull($modelR->datetime_null); - // todo implement these + /** + * @todo Orange-Management/phpOMS#227 + * Serializable and JsonSerializable data can be inserted and updated in the database but it's not possible to correctly populate a model with the data in its original format. + */ //self::assertEquals('123', $modelR->serializable); //self::assertEquals($this->model->json, $modelR->json); //self::assertEquals([1, 2, 3], $modelR->jsonSerializable); @@ -281,7 +284,10 @@ class DataMapperAbstractTest extends \PHPUnit\Framework\TestCase self::assertEquals($modelR->datetime->format('Y-m-d'), $modelR2->datetime->format('Y-m-d')); self::assertNull($modelR2->datetime_null); - // todo test update relations + /** + * @todo Orange-Management/phpOMS#226 + * Test the update of a model with relations (update relations). + */ } /** @@ -313,7 +319,10 @@ class DataMapperAbstractTest extends \PHPUnit\Framework\TestCase self::assertEquals($modelR['datetime']->format('Y-m-d'), $modelR2['datetime']->format('Y-m-d')); self::assertNull($modelR2['datetime_null']); - // todo test update relations + /** + * @todo Orange-Management/phpOMS#226 + * Test the update of a model with relations (update relations). + */ } /** @@ -329,6 +338,9 @@ class DataMapperAbstractTest extends \PHPUnit\Framework\TestCase self::assertInstanceOf('phpOMS\tests\DataStorage\Database\TestModel\NullBaseModel', $modelR); - // todo test if relations also deleted + /** + * @todo Orange-Management/phpOMS#225 + * Test the deletion of a model with relations (deleting relations). + */ } } diff --git a/tests/DataStorage/Database/Query/BuilderTest.php b/tests/DataStorage/Database/Query/BuilderTest.php index 521edf587..05d52c3de 100644 --- a/tests/DataStorage/Database/Query/BuilderTest.php +++ b/tests/DataStorage/Database/Query/BuilderTest.php @@ -59,15 +59,6 @@ class BuilderTest extends \PHPUnit\Framework\TestCase $sql = 'SELECT `a`.`test`, `b`.`test` FROM `a`, `b` WHERE `a`.`test` = \'' . $datetime->format('Y-m-d H:i:s') . '\';'; self::assertEquals($sql, $query->select('a.test', 'b.test')->from('a', 'b')->where('a.test', '=', $datetime)->toSql()); - $query = new Builder($this->con); - $sql = 'SELECT `a`.`test`, `b`.`test` FROM `a`, `b` WHERE `a`.`test` = \'abc\' AND `b`.`test` = 2;'; - $systemIdentifier = '`'; - self::assertEquals($sql, $query->select('a.test', function () { - return '`b`.`test`'; - })->from('a', function () use ($systemIdentifier) { - return $systemIdentifier . 'b' . $systemIdentifier; - })->where(['a.test', 'b.test'], ['=', '='], ['abc', 2], ['and', 'and'])->toSql()); - $query = new Builder($this->con); $sql = 'SELECT `a`.`test`, `b`.`test` FROM `a`, `b` WHERE `a`.`test` = \'abc\' ORDER BY `a`.`test` ASC, `b`.`test` DESC;'; self::assertEquals($sql, diff --git a/tests/Math/Matrix/MatrixTest.php b/tests/Math/Matrix/MatrixTest.php index debaeef21..5889271c2 100644 --- a/tests/Math/Matrix/MatrixTest.php +++ b/tests/Math/Matrix/MatrixTest.php @@ -269,7 +269,12 @@ class MatrixTest extends \PHPUnit\Framework\TestCase ]); self::markTestIncomplete(); - // todo: result column 0 and 1 are swapped. why? still correct? + + /** + * @todo Orange-Management/phpOMS#179 + * Create unit test for inverse. + * It seems like some columns are ordered in a different way + */ /*self::assertEquals([ [-0.9, -0.5, 2.2], [0.7, 0.5, -1.6], diff --git a/tests/Message/Http/RequestTest.php b/tests/Message/Http/RequestTest.php index e337ae130..91c5462e1 100644 --- a/tests/Message/Http/RequestTest.php +++ b/tests/Message/Http/RequestTest.php @@ -45,7 +45,7 @@ class RequestTest extends \PHPUnit\Framework\TestCase self::assertEquals(BrowserType::UNKNOWN, $request->getBrowser()); self::assertEquals(OSType::UNKNOWN, $request->getOS()); self::assertEquals('127.0.0.1', $request->getOrigin()); - self::assertFalse($request->isHttps()); + self::assertFalse(Request::isHttps()); self::assertEquals([], $request->getHash()); self::assertEmpty($request->getBody()); self::assertEmpty($request->getFiles()); diff --git a/tests/Utils/ArrayUtilsTest.php b/tests/Utils/ArrayUtilsTest.php index c220ef728..2a56d3cb0 100644 --- a/tests/Utils/ArrayUtilsTest.php +++ b/tests/Utils/ArrayUtilsTest.php @@ -215,6 +215,10 @@ class ArrayUtilsTest extends \PHPUnit\Framework\TestCase /** * @testdox All array values in an array can be potentiated by an integer * @covers phpOMS\Utils\ArrayUtils + * + * @todo Orange-Management/phpOMS#223 + * In the ArrayUtils class the power* functions should be combined once union types become available. + * * @group framework */ public function testPowerInt() : void @@ -227,7 +231,9 @@ class ArrayUtilsTest extends \PHPUnit\Framework\TestCase * @testdox All array values in an array can be potentiated by a float * @covers phpOMS\Utils\ArrayUtils * - * @todo combine with int as soon as union types exist + * @todo Orange-Management/phpOMS#223 + * In the ArrayUtils class the power* functions should be combined once union types become available. + * * @group framework */ public function testPowerFloat() : void diff --git a/tests/Utils/Git/RepositoryTest.php b/tests/Utils/Git/RepositoryTest.php index 4d9d11860..afbb5acec 100644 --- a/tests/Utils/Git/RepositoryTest.php +++ b/tests/Utils/Git/RepositoryTest.php @@ -20,7 +20,6 @@ use phpOMS\Utils\Git\Repository; * @testdox phpOMS\tests\Utils\Git\RepositoryTest: Git repository * * @internal - * @todo create tests for other functions */ class RepositoryTest extends \PHPUnit\Framework\TestCase { diff --git a/tests/Utils/TaskSchedule/ScheduleTest.php b/tests/Utils/TaskSchedule/ScheduleTest.php index 8daef0f5a..5057c1dee 100644 --- a/tests/Utils/TaskSchedule/ScheduleTest.php +++ b/tests/Utils/TaskSchedule/ScheduleTest.php @@ -38,7 +38,9 @@ class ScheduleTest extends \PHPUnit\Framework\TestCase /** * @testdox A task can be created from an array and rendered * @covers phpOMS\Utils\TaskSchedule\Schedule + * * @todo the interval has to be implemented! + * * @group framework */ public function testCreateJobWithData() : void diff --git a/tests/Utils/TaskSchedule/SchedulerFactoryTest.php b/tests/Utils/TaskSchedule/SchedulerFactoryTest.php index 17d9a261f..7e1f85653 100644 --- a/tests/Utils/TaskSchedule/SchedulerFactoryTest.php +++ b/tests/Utils/TaskSchedule/SchedulerFactoryTest.php @@ -33,10 +33,5 @@ class SchedulerFactoryTest extends \PHPUnit\Framework\TestCase public function testCreate() : void { self::assertTrue((SchedulerFactory::create() instanceof Cron) || (SchedulerFactory::create() instanceof TaskScheduler)); - - // todo: make full test here by defining schtask or crontab path - // todo: create task - // todo: get task - // todo: remove task } }