diff --git a/.gitignore b/.gitignore index fbc76ff..8fc20cd 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ .php_cs.cache *.idea .php_cs.cache +.phpunit.result.cache /vendor diff --git a/.travis.yml b/.travis.yml index 1bad6b3..788ed16 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: php php: - - 7.1 + - 7.3 services: - mysql before_install: @@ -8,4 +8,4 @@ before_install: install: composer install --dev before_script: - mysql -u root -e 'create database activecollab_database_object_test' -script: vendor/bin/phpunit +script: php vendor/bin/phpunit diff --git a/README.md b/README.md index 8b26258..4607bb9 100644 --- a/README.md +++ b/README.md @@ -163,10 +163,7 @@ use ActiveCollab\DatabaseObject\Entity\Entity; class StatsSnapshot extends Entity { - /** - * {@inheritdoc} - */ - protected function configure() + protected function configure(): void { $this->setGeneratedFieldsValueCaster(new ValueCaster([ 'is_used_on_day' => ValueCasterInterface::CAST_BOOL, @@ -182,4 +179,5 @@ Entity class also refreshes the values of these fields on object save so fresh v ## To Do 1. Caching, -1. Remove deprecated `ObjectInterface` and `Object` class. +2. Add support for PHP enums +3. Remove deprecated `ObjectInterface` and `Object` class. diff --git a/composer.json b/composer.json index 8d96cab..ea22462 100644 --- a/composer.json +++ b/composer.json @@ -15,23 +15,32 @@ "email": "ilija.studen@activecollab.com" } ], + "config": { + "platform": { + "php": "8.2.0" + } + }, "require": { - "php": ">=7.1", - "activecollab/databaseconnection": "^3.0", - "activecollab/etag": "^1.0", + "php": ">=8.2", + "activecollab/databaseconnection": "^5.0", + "activecollab/etag": "^2.0", "activecollab/object": "^1.0", - "doctrine/inflector": "^1.0", + "doctrine/inflector": "^2.0", "psr/log": "^1.0.0" }, "require-dev": { + "ext-mysqli": "*", "friendsofphp/php-cs-fixer": "^2.0", "monolog/monolog": "^1.0", - "phpunit/phpunit": "~5.0", - "pimple/pimple": "~3.0.0" + "phpunit/phpunit": "~9.0" }, "autoload": { "psr-4": { - "ActiveCollab\\DatabaseObject\\": "src", + "ActiveCollab\\DatabaseObject\\": "src" + } + }, + "autoload-dev": { + "psr-4": { "ActiveCollab\\DatabaseObject\\Test\\": "test/src" } } diff --git a/composer.lock b/composer.lock index 32cb299..fc61ec4 100644 --- a/composer.lock +++ b/composer.lock @@ -4,28 +4,28 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0b7a6a190365162173cd286c42a1a6ee", + "content-hash": "7906381b6b26f85f5202623fcf7805e2", "packages": [ { "name": "activecollab/containeraccess", - "version": "1.0.4", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/activecollab/containeraccess.git", - "reference": "30bf92724df248f77f7b0debd93eca3e7097513a" + "reference": "950deccdec3dd6484b2149fae48ce346c3afe0b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/activecollab/containeraccess/zipball/30bf92724df248f77f7b0debd93eca3e7097513a", - "reference": "30bf92724df248f77f7b0debd93eca3e7097513a", + "url": "https://api.github.com/repos/activecollab/containeraccess/zipball/950deccdec3dd6484b2149fae48ce346c3afe0b7", + "reference": "950deccdec3dd6484b2149fae48ce346c3afe0b7", "shasum": "" }, "require": { - "container-interop/container-interop": "^1.2.0", - "php": ">=5.6.0" + "php": ">=7.3", + "psr/container": "^1.0" }, "require-dev": { - "phpunit/phpunit": "~5.3" + "phpunit/phpunit": "^7.0" }, "type": "library", "autoload": { @@ -51,34 +51,39 @@ "ioc", "service-container" ], - "time": "2017-11-12T16:38:02+00:00" + "support": { + "issues": "https://github.com/activecollab/containeraccess/issues", + "source": "https://github.com/activecollab/containeraccess/tree/2.0.0" + }, + "time": "2019-12-21T13:14:15+00:00" }, { "name": "activecollab/databaseconnection", - "version": "3.0.0", + "version": "5.1.6", "source": { "type": "git", "url": "https://github.com/activecollab/databaseconnection.git", - "reference": "9824e8dd4368f55f72146cac71d6d60f1ac61167" + "reference": "5f5ff2ce8fbe7b94b64027d446735499de71c040" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/activecollab/databaseconnection/zipball/9824e8dd4368f55f72146cac71d6d60f1ac61167", - "reference": "9824e8dd4368f55f72146cac71d6d60f1ac61167", + "url": "https://api.github.com/repos/activecollab/databaseconnection/zipball/5f5ff2ce8fbe7b94b64027d446735499de71c040", + "reference": "5f5ff2ce8fbe7b94b64027d446735499de71c040", "shasum": "" }, "require": { - "activecollab/containeraccess": "^1.0", + "activecollab/containeraccess": "^2.0", "activecollab/datevalue": "^2.0", "ext-json": "*", + "ext-mbstring": "*", "ext-mysqli": "*", - "php": ">=7.1", + "php": ">=8.0", "psr/log": "^1.0.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^2.0", - "phpunit/phpunit": "~5.0", - "pimple/pimple": "~3.0.0" + "phpunit/phpunit": "~9.0", + "pimple/pimple": "~3.5.0" }, "type": "library", "autoload": { @@ -103,30 +108,34 @@ "activecollab", "mysql" ], - "time": "2019-06-23T17:02:50+00:00" + "support": { + "issues": "https://github.com/activecollab/databaseconnection/issues", + "source": "https://github.com/activecollab/databaseconnection/tree/5.1.6" + }, + "time": "2023-09-24T06:25:56+00:00" }, { "name": "activecollab/datevalue", - "version": "2.0.0", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/activecollab/datevalue.git", - "reference": "a69670b4938d44a27e2baa0e66cf335a3ad5d511" + "reference": "075bea63dc3cbaab9505459b7d5844eeaaad78ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/activecollab/datevalue/zipball/a69670b4938d44a27e2baa0e66cf335a3ad5d511", - "reference": "a69670b4938d44a27e2baa0e66cf335a3ad5d511", + "url": "https://api.github.com/repos/activecollab/datevalue/zipball/075bea63dc3cbaab9505459b7d5844eeaaad78ae", + "reference": "075bea63dc3cbaab9505459b7d5844eeaaad78ae", "shasum": "" }, "require": { "ext-json": "*", "nesbot/carbon": "~2.0", - "php": ">=7.1" + "php": ">=8.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^2.0", - "phpunit/phpunit": "^5.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "autoload": { @@ -152,27 +161,31 @@ "date", "datetime" ], - "time": "2019-06-23T16:19:52+00:00" + "support": { + "issues": "https://github.com/activecollab/datevalue/issues", + "source": "https://github.com/activecollab/datevalue/tree/2.1.0" + }, + "time": "2022-08-10T07:26:18+00:00" }, { "name": "activecollab/etag", - "version": "1.0.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/activecollab/etag.git", - "reference": "98d8ef105d00c722afa7424cfea80ae7d25a2984" + "reference": "b1d8882fb889a2854e23fc4397e7c2191a56809b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/activecollab/etag/zipball/98d8ef105d00c722afa7424cfea80ae7d25a2984", - "reference": "98d8ef105d00c722afa7424cfea80ae7d25a2984", + "url": "https://api.github.com/repos/activecollab/etag/zipball/b1d8882fb889a2854e23fc4397e7c2191a56809b", + "reference": "b1d8882fb889a2854e23fc4397e7c2191a56809b", "shasum": "" }, "require": { - "php": ">=5.6.0" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "~4.8" + "phpunit/phpunit": "~10.0" }, "type": "library", "autoload": { @@ -197,7 +210,11 @@ "Etag", "activecollab" ], - "time": "2015-11-09T09:18:16+00:00" + "support": { + "issues": "https://github.com/activecollab/etag/issues", + "source": "https://github.com/activecollab/etag/tree/2.0.0" + }, + "time": "2024-03-09T08:26:40+00:00" }, { "name": "activecollab/object", @@ -242,68 +259,110 @@ "keywords": [ "activecollab" ], + "support": { + "issues": "https://github.com/activecollab/object/issues", + "source": "https://github.com/activecollab/object/tree/1.0.0" + }, "time": "2016-07-14T19:59:07+00:00" }, { - "name": "container-interop/container-interop", - "version": "1.2.0", + "name": "carbonphp/carbon-doctrine-types", + "version": "3.2.0", "source": { "type": "git", - "url": "https://github.com/container-interop/container-interop.git", - "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8" + "url": "https://github.com/CarbonPHP/carbon-doctrine-types.git", + "reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8", - "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8", + "url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/18ba5ddfec8976260ead6e866180bd5d2f71aa1d", + "reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d", "shasum": "" }, "require": { - "psr/container": "^1.0" + "php": "^8.1" + }, + "conflict": { + "doctrine/dbal": "<4.0.0 || >=5.0.0" + }, + "require-dev": { + "doctrine/dbal": "^4.0.0", + "nesbot/carbon": "^2.71.0 || ^3.0.0", + "phpunit/phpunit": "^10.3" }, "type": "library", "autoload": { "psr-4": { - "Interop\\Container\\": "src/Interop/Container/" + "Carbon\\Doctrine\\": "src/Carbon/Doctrine/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", - "homepage": "https://github.com/container-interop/container-interop", - "time": "2017-02-14T19:40:03+00:00" + "authors": [ + { + "name": "KyleKatarn", + "email": "kylekatarnls@gmail.com" + } + ], + "description": "Types to use Carbon in Doctrine", + "keywords": [ + "carbon", + "date", + "datetime", + "doctrine", + "time" + ], + "support": { + "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues", + "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/3.2.0" + }, + "funding": [ + { + "url": "https://github.com/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", + "type": "tidelift" + } + ], + "time": "2024-02-09T16:56:22+00:00" }, { "name": "doctrine/inflector", - "version": "v1.3.0", + "version": "2.0.10", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "5527a48b7313d15261292c149e55e26eae771b0a" + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/5527a48b7313d15261292c149e55e26eae771b0a", - "reference": "5527a48b7313d15261292c149e55e26eae771b0a", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^7.2 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^6.2" + "doctrine/coding-standard": "^11.0", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.3", + "phpunit/phpunit": "^8.5 || ^9.5", + "vimeo/psalm": "^4.25 || ^5.4" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, "autoload": { "psr-4": { - "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" + "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" } }, "notification-url": "https://packagist.org/downloads/", @@ -311,6 +370,10 @@ "MIT" ], "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, { "name": "Roman Borschel", "email": "roman@code-factory.org" @@ -319,10 +382,6 @@ "name": "Benjamin Eberlei", "email": "kontakt@beberlei.de" }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, { "name": "Jonathan Wage", "email": "jonwage@gmail.com" @@ -332,49 +391,97 @@ "email": "schmittjoh@gmail.com" } ], - "description": "Common String Manipulations with regard to casing and singular/plural rules.", - "homepage": "http://www.doctrine-project.org", + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", "keywords": [ "inflection", - "pluralize", - "singularize", - "string" + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" + ], + "support": { + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/2.0.10" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "type": "tidelift" + } ], - "time": "2018-01-09T20:05:19+00:00" + "time": "2024-02-18T20:23:39+00:00" }, { "name": "nesbot/carbon", - "version": "2.19.2", + "version": "2.72.3", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "adcad3f3af52d0ad4ad7b05f43aa58243b6ca67b" + "reference": "0c6fd108360c562f6e4fd1dedb8233b423e91c83" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/adcad3f3af52d0ad4ad7b05f43aa58243b6ca67b", - "reference": "adcad3f3af52d0ad4ad7b05f43aa58243b6ca67b", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/0c6fd108360c562f6e4fd1dedb8233b423e91c83", + "reference": "0c6fd108360c562f6e4fd1dedb8233b423e91c83", "shasum": "" }, "require": { + "carbonphp/carbon-doctrine-types": "*", "ext-json": "*", "php": "^7.1.8 || ^8.0", - "symfony/translation": "^3.4 || ^4.0" + "psr/clock": "^1.0", + "symfony/polyfill-mbstring": "^1.0", + "symfony/polyfill-php80": "^1.16", + "symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0" + }, + "provide": { + "psr/clock-implementation": "1.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.14 || ^3.0", - "kylekatarnls/multi-tester": "^1.1", - "phpmd/phpmd": "^2.6", - "phpstan/phpstan": "^0.11", - "phpunit/phpunit": "^7.5 || ^8.0", + "doctrine/dbal": "^2.0 || ^3.1.4 || ^4.0", + "doctrine/orm": "^2.7 || ^3.0", + "friendsofphp/php-cs-fixer": "^3.0", + "kylekatarnls/multi-tester": "^2.0", + "ondrejmirtes/better-reflection": "*", + "phpmd/phpmd": "^2.9", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12.99 || ^1.7.14", + "phpunit/php-file-iterator": "^2.0.5 || ^3.0.6", + "phpunit/phpunit": "^7.5.20 || ^8.5.26 || ^9.5.20", "squizlabs/php_codesniffer": "^3.4" }, + "bin": [ + "bin/carbon" + ], "type": "library", "extra": { + "branch-alias": { + "dev-3.x": "3.x-dev", + "dev-master": "2.x-dev" + }, "laravel": { "providers": [ "Carbon\\Laravel\\ServiceProvider" ] + }, + "phpstan": { + "includes": [ + "extension.neon" + ] } }, "autoload": { @@ -390,41 +497,107 @@ { "name": "Brian Nesbitt", "email": "brian@nesbot.com", - "homepage": "http://nesbot.com" + "homepage": "https://markido.com" + }, + { + "name": "kylekatarnls", + "homepage": "https://github.com/kylekatarnls" } ], - "description": "A simple API extension for DateTime.", - "homepage": "http://carbon.nesbot.com", + "description": "An API extension for DateTime that supports 281 different languages.", + "homepage": "https://carbon.nesbot.com", "keywords": [ "date", "datetime", "time" ], - "time": "2019-06-07T09:56:45+00:00" + "support": { + "docs": "https://carbon.nesbot.com/docs", + "issues": "https://github.com/briannesbitt/Carbon/issues", + "source": "https://github.com/briannesbitt/Carbon" + }, + "funding": [ + { + "url": "https://github.com/sponsors/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon#sponsor", + "type": "opencollective" + }, + { + "url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme", + "type": "tidelift" + } + ], + "time": "2024-01-25T10:35:09+00:00" }, { - "name": "psr/container", + "name": "psr/clock", "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": "^7.0 || ^8.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, + { + "name": "psr/container", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" }, + "type": "library", "autoload": { "psr-4": { "Psr\\Container\\": "src/" @@ -437,7 +610,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common Container Interface (PHP FIG PSR-11)", @@ -449,20 +622,24 @@ "container-interop", "psr" ], - "time": "2017-02-14T16:28:37+00:00" + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.2" + }, + "time": "2021-11-05T16:50:12+00:00" }, { "name": "psr/log", - "version": "1.1.0", + "version": "1.1.4", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd" + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", - "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", "shasum": "" }, "require": { @@ -471,7 +648,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.1.x-dev" } }, "autoload": { @@ -486,7 +663,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for logging libraries", @@ -496,40 +673,41 @@ "psr", "psr-3" ], - "time": "2018-11-20T15:27:04+00:00" + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.4" + }, + "time": "2021-05-03T11:20:27+00:00" }, { - "name": "symfony/polyfill-mbstring", - "version": "v1.11.0", + "name": "symfony/deprecation-contracts", + "version": "v3.4.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "fe5e94c604826c35a32fa832f35bd036b6799609" + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609", - "reference": "fe5e94c604826c35a32fa832f35bd036b6799609", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", "shasum": "" }, "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-mbstring": "For best performance" + "php": ">=8.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-main": "3.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, "files": [ - "bootstrap.php" + "function.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -546,74 +724,64 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for the Mbstring extension", + "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2023-05-23T14:45:45+00:00" }, { - "name": "symfony/translation", - "version": "v4.3.1", + "name": "symfony/polyfill-mbstring", + "version": "v1.29.0", "source": { "type": "git", - "url": "https://github.com/symfony/translation.git", - "reference": "5dda505e5f65d759741dfaf4e54b36010a4b57aa" + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/5dda505e5f65d759741dfaf4e54b36010a4b57aa", - "reference": "5dda505e5f65d759741dfaf4e54b36010a4b57aa", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", "shasum": "" }, "require": { - "php": "^7.1.3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/translation-contracts": "^1.1.2" - }, - "conflict": { - "symfony/config": "<3.4", - "symfony/dependency-injection": "<3.4", - "symfony/yaml": "<3.4" + "php": ">=7.1" }, "provide": { - "symfony/translation-implementation": "1.0" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~3.4|~4.0", - "symfony/console": "~3.4|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/finder": "~2.8|~3.0|~4.0", - "symfony/http-kernel": "~3.4|~4.0", - "symfony/intl": "~3.4|~4.0", - "symfony/service-contracts": "^1.1.2", - "symfony/var-dumper": "~3.4|~4.0", - "symfony/yaml": "~3.4|~4.0" + "ext-mbstring": "*" }, "suggest": { - "psr/log-implementation": "To use logging capability in translator", - "symfony/config": "", - "symfony/yaml": "" + "ext-mbstring": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "4.3-dev" + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Component\\Translation\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Symfony\\Polyfill\\Mbstring\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -621,54 +789,86 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Translation Component", + "description": "Symfony polyfill for the Mbstring extension", "homepage": "https://symfony.com", - "time": "2019-06-03T20:27:40+00:00" + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" }, { - "name": "symfony/translation-contracts", - "version": "v1.1.5", + "name": "symfony/polyfill-php80", + "version": "v1.29.0", "source": { "type": "git", - "url": "https://github.com/symfony/translation-contracts.git", - "reference": "cb4b18ad7b92a26e83b65dde940fab78339e6f3c" + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/cb4b18ad7b92a26e83b65dde940fab78339e6f3c", - "reference": "cb4b18ad7b92a26e83b65dde940fab78339e6f3c", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", "shasum": "" }, "require": { - "php": "^7.1.3" - }, - "suggest": { - "symfony/translation-implementation": "" + "php": ">=7.1" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.1-dev" + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Contracts\\Translation\\": "" - } + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" @@ -678,51 +878,92 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Generic abstractions related to translation", + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" + "compatibility", + "polyfill", + "portable", + "shim" ], - "time": "2019-06-13T11:15:36+00:00" - } - ], - "packages-dev": [ + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, { - "name": "composer/semver", - "version": "1.5.0", + "name": "symfony/translation", + "version": "v6.4.4", "source": { "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "46d9139568ccb8d9e7cdd4539cab7347568a5e2e" + "url": "https://github.com/symfony/translation.git", + "reference": "bce6a5a78e94566641b2594d17e48b0da3184a8e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/46d9139568ccb8d9e7cdd4539cab7347568a5e2e", - "reference": "46d9139568ccb8d9e7cdd4539cab7347568a5e2e", + "url": "https://api.github.com/repos/symfony/translation/zipball/bce6a5a78e94566641b2594d17e48b0da3184a8e", + "reference": "bce6a5a78e94566641b2594d17e48b0da3184a8e", "shasum": "" }, "require": { - "php": "^5.3.2 || ^7.0" + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2.5|^3.0" + }, + "conflict": { + "symfony/config": "<5.4", + "symfony/console": "<5.4", + "symfony/dependency-injection": "<5.4", + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<5.4", + "symfony/service-contracts": "<2.5", + "symfony/twig-bundle": "<5.4", + "symfony/yaml": "<5.4" + }, + "provide": { + "symfony/translation-implementation": "2.3|3.0" }, "require-dev": { - "phpunit/phpunit": "^4.5 || ^5.0.5", - "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" + "nikic/php-parser": "^4.18|^5.0", + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/http-client-contracts": "^2.5|^3.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/intl": "^5.4|^6.0|^7.0", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/routing": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^5.4|^6.0|^7.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, "autoload": { + "files": [ + "Resources/functions.php" + ], "psr-4": { - "Composer\\Semver\\": "src" - } + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -730,17 +971,235 @@ ], "authors": [ { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { - "name": "Rob Bast", + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to internationalize your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/translation/tree/v6.4.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-02-20T13:16:58+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v3.4.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "06450585bf65e978026bda220cdebca3f867fde7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/06450585bf65e978026bda220cdebca3f867fde7", + "reference": "06450585bf65e978026bda220cdebca3f867fde7", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/translation-contracts/tree/v3.4.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-12-26T14:02:43+00:00" + } + ], + "packages-dev": [ + { + "name": "composer/pcre", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/67a32d7d6f9f560b726ab25a061b38ff3a80c560", + "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.3", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/1.0.1" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-01-21T20:24:37+00:00" + }, + { + "name": "composer/semver", + "version": "3.4.0", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32", + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", "email": "rob.bast@gmail.com", "homepage": "http://robbast.nl" } @@ -752,28 +1211,50 @@ "validation", "versioning" ], - "time": "2019-03-19T17:25:45+00:00" + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.0" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2023-08-31T09:50:34+00:00" }, { "name": "composer/xdebug-handler", - "version": "1.3.3", + "version": "2.0.5", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", - "reference": "46867cbf8ca9fb8d60c506895449eb799db1184f" + "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/46867cbf8ca9fb8d60c506895449eb799db1184f", - "reference": "46867cbf8ca9fb8d60c506895449eb799db1184f", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/9e36aeed4616366d2b690bdce11f71e9178c579a", + "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a", "shasum": "" }, "require": { - "php": "^5.3.2 || ^7.0", - "psr/log": "^1.0" + "composer/pcre": "^1", + "php": "^5.3.2 || ^7.0 || ^8.0", + "psr/log": "^1 || ^2 || ^3" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0" }, "type": "library", "autoload": { @@ -791,41 +1272,64 @@ "email": "john-stevenson@blueyonder.co.uk" } ], - "description": "Restarts a process without xdebug.", + "description": "Restarts a process without Xdebug.", "keywords": [ "Xdebug", "performance" ], - "time": "2019-05-27T17:52:04+00:00" + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/2.0.5" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-02-24T20:20:32+00:00" }, { "name": "doctrine/annotations", - "version": "v1.6.1", + "version": "1.14.3", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "53120e0eb10355388d6ccbe462f1fea34ddadb24" + "reference": "fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/53120e0eb10355388d6ccbe462f1fea34ddadb24", - "reference": "53120e0eb10355388d6ccbe462f1fea34ddadb24", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af", + "reference": "fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af", "shasum": "" }, "require": { - "doctrine/lexer": "1.*", - "php": "^7.1" + "doctrine/lexer": "^1 || ^2", + "ext-tokenizer": "*", + "php": "^7.1 || ^8.0", + "psr/cache": "^1 || ^2 || ^3" }, "require-dev": { - "doctrine/cache": "1.*", - "phpunit/phpunit": "^6.4" + "doctrine/cache": "^1.11 || ^2.0", + "doctrine/coding-standard": "^9 || ^10", + "phpstan/phpstan": "~1.4.10 || ^1.8.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "symfony/cache": "^4.4 || ^5.4 || ^6", + "vimeo/psalm": "^4.10" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6.x-dev" - } + "suggest": { + "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" }, + "type": "library", "autoload": { "psr-4": { "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" @@ -836,6 +1340,10 @@ "MIT" ], "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, { "name": "Roman Borschel", "email": "roman@code-factory.org" @@ -844,10 +1352,6 @@ "name": "Benjamin Eberlei", "email": "kontakt@beberlei.de" }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, { "name": "Jonathan Wage", "email": "jonwage@gmail.com" @@ -858,46 +1362,93 @@ } ], "description": "Docblock Annotations Parser", - "homepage": "http://www.doctrine-project.org", + "homepage": "https://www.doctrine-project.org/projects/annotations.html", "keywords": [ "annotations", "docblock", "parser" ], - "time": "2019-03-25T19:12:02+00:00" + "support": { + "issues": "https://github.com/doctrine/annotations/issues", + "source": "https://github.com/doctrine/annotations/tree/1.14.3" + }, + "time": "2023-02-01T09:20:38+00:00" + }, + { + "name": "doctrine/deprecations", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/1.1.3" + }, + "time": "2024-01-30T19:34:25+00:00" }, { "name": "doctrine/instantiator", - "version": "1.2.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "a2c590166b2133a4633738648b6b064edae0814a" + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/a2c590166b2133a4633738648b6b064edae0814a", - "reference": "a2c590166b2133a4633738648b6b064edae0814a", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^6.0", + "doctrine/coding-standard": "^11", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.13", - "phpstan/phpstan-phpunit": "^0.11", - "phpstan/phpstan-shim": "^0.11", - "phpunit/phpunit": "^7.0" + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^5.4" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, "autoload": { "psr-4": { "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" @@ -911,7 +1462,7 @@ { "name": "Marco Pivetta", "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" + "homepage": "https://ocramius.github.io/" } ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", @@ -920,37 +1471,55 @@ "constructor", "instantiate" ], - "time": "2019-03-17T17:37:11+00:00" + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2022-12-30T00:23:10+00:00" }, { "name": "doctrine/lexer", - "version": "1.0.2", + "version": "2.1.1", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8" + "reference": "861c870e8b75f7c8f69c146c7f89cc1c0f1b49b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/1febd6c3ef84253d7c815bed85fc622ad207a9f8", - "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/861c870e8b75f7c8f69c146c7f89cc1c0f1b49b6", + "reference": "861c870e8b75f7c8f69c146c7f89cc1c0f1b49b6", "shasum": "" }, "require": { - "php": ">=5.3.2" + "doctrine/deprecations": "^1.0", + "php": "^7.1 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^4.5" + "doctrine/coding-standard": "^9 || ^12", + "phpstan/phpstan": "^1.3", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^4.11 || ^5.21" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, "autoload": { "psr-4": { - "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + "Doctrine\\Common\\Lexer\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -958,14 +1527,14 @@ "MIT" ], "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, { "name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com" }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com" @@ -980,55 +1549,77 @@ "parser", "php" ], - "time": "2019-06-08T11:03:04+00:00" + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/2.1.1" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2024-02-05T11:35:39+00:00" }, { "name": "friendsofphp/php-cs-fixer", - "version": "v2.15.1", + "version": "v2.19.3", "source": { "type": "git", "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "20064511ab796593a3990669eff5f5b535001f7c" + "reference": "75ac86f33fab4714ea5a39a396784d83ae3b5ed8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/20064511ab796593a3990669eff5f5b535001f7c", - "reference": "20064511ab796593a3990669eff5f5b535001f7c", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/75ac86f33fab4714ea5a39a396784d83ae3b5ed8", + "reference": "75ac86f33fab4714ea5a39a396784d83ae3b5ed8", "shasum": "" }, "require": { - "composer/semver": "^1.4", - "composer/xdebug-handler": "^1.2", + "composer/semver": "^1.4 || ^2.0 || ^3.0", + "composer/xdebug-handler": "^1.2 || ^2.0", "doctrine/annotations": "^1.2", "ext-json": "*", "ext-tokenizer": "*", - "php": "^5.6 || ^7.0", + "php": "^5.6 || ^7.0 || ^8.0", "php-cs-fixer/diff": "^1.3", - "symfony/console": "^3.4.17 || ^4.1.6", - "symfony/event-dispatcher": "^3.0 || ^4.0", - "symfony/filesystem": "^3.0 || ^4.0", - "symfony/finder": "^3.0 || ^4.0", - "symfony/options-resolver": "^3.0 || ^4.0", + "symfony/console": "^3.4.43 || ^4.1.6 || ^5.0", + "symfony/event-dispatcher": "^3.0 || ^4.0 || ^5.0", + "symfony/filesystem": "^3.0 || ^4.0 || ^5.0", + "symfony/finder": "^3.0 || ^4.0 || ^5.0", + "symfony/options-resolver": "^3.0 || ^4.0 || ^5.0", "symfony/polyfill-php70": "^1.0", "symfony/polyfill-php72": "^1.4", - "symfony/process": "^3.0 || ^4.0", - "symfony/stopwatch": "^3.0 || ^4.0" + "symfony/process": "^3.0 || ^4.0 || ^5.0", + "symfony/stopwatch": "^3.0 || ^4.0 || ^5.0" }, "require-dev": { - "johnkary/phpunit-speedtrap": "^1.1 || ^2.0 || ^3.0", "justinrainbow/json-schema": "^5.0", - "keradus/cli-executor": "^1.2", + "keradus/cli-executor": "^1.4", "mikey179/vfsstream": "^1.6", - "php-coveralls/php-coveralls": "^2.1", + "php-coveralls/php-coveralls": "^2.4.2", "php-cs-fixer/accessible-object": "^1.0", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.1", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.1", - "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1", - "phpunitgoodpractices/traits": "^1.8", - "symfony/phpunit-bridge": "^4.3" + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", + "phpspec/prophecy-phpunit": "^1.1 || ^2.0", + "phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.13 || ^9.5", + "phpunitgoodpractices/polyfill": "^1.5", + "phpunitgoodpractices/traits": "^1.9.1", + "sanmai/phpunit-legacy-adapter": "^6.4 || ^8.2.1", + "symfony/phpunit-bridge": "^5.2.1", + "symfony/yaml": "^3.0 || ^4.0 || ^5.0" }, "suggest": { - "ext-mbstring": "For handling non-UTF8 characters in cache signature.", + "ext-dom": "For handling output formats in XML", + "ext-mbstring": "For handling non-UTF8 characters.", "php-cs-fixer/phpunit-constraint-isidenticalstring": "For IsIdenticalString constraint.", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "For XmlMatchesXsd constraint.", "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." @@ -1037,6 +1628,11 @@ "php-cs-fixer" ], "type": "application", + "extra": { + "branch-alias": { + "dev-master": "2.19-dev" + } + }, "autoload": { "psr-4": { "PhpCsFixer\\": "src/" @@ -1050,6 +1646,8 @@ "tests/Test/IntegrationCaseFactory.php", "tests/Test/IntegrationCaseFactoryInterface.php", "tests/Test/InternalIntegrationCaseFactory.php", + "tests/Test/IsIdenticalConstraint.php", + "tests/Test/TokensWithObservedTransformers.php", "tests/TestCase.php" ] }, @@ -1058,30 +1656,40 @@ "MIT" ], "authors": [ - { - "name": "Dariusz RumiÅ„ski", - "email": "dariusz.ruminski@gmail.com" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Dariusz RumiÅ„ski", + "email": "dariusz.ruminski@gmail.com" } ], "description": "A tool to automatically fix PHP code style", - "time": "2019-06-01T10:32:12+00:00" + "support": { + "issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues", + "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v2.19.3" + }, + "funding": [ + { + "url": "https://github.com/keradus", + "type": "github" + } + ], + "time": "2021-11-15T17:17:55+00:00" }, { "name": "monolog/monolog", - "version": "1.24.0", + "version": "1.27.1", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266" + "reference": "904713c5929655dc9b97288b69cfeedad610c9a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266", - "reference": "bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/904713c5929655dc9b97288b69cfeedad610c9a1", + "reference": "904713c5929655dc9b97288b69cfeedad610c9a1", "shasum": "" }, "require": { @@ -1095,11 +1703,10 @@ "aws/aws-sdk-php": "^2.4.9 || ^3.0", "doctrine/couchdb": "~1.0@dev", "graylog2/gelf-php": "~1.0", - "jakub-onderka/php-parallel-lint": "0.9", "php-amqplib/php-amqplib": "~2.4", "php-console/php-console": "^3.1.3", + "phpstan/phpstan": "^0.12.59", "phpunit/phpunit": "~4.5", - "phpunit/phpunit-mock-objects": "2.3.0", "ruflin/elastica": ">=0.90 <3.0", "sentry/sentry": "^0.13", "swiftmailer/swiftmailer": "^5.3|^6.0" @@ -1118,11 +1725,6 @@ "sentry/sentry": "Allow sending log messages to a Sentry server" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, "autoload": { "psr-4": { "Monolog\\": "src/Monolog" @@ -1146,41 +1748,56 @@ "logging", "psr-3" ], - "time": "2018-11-05T09:00:11+00:00" + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/1.27.1" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } + ], + "time": "2022-06-09T08:53:42+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.9.1", + "version": "1.11.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72" + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", - "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^7.1 || ^8.0" }, - "replace": { - "myclabs/deep-copy": "self.version" + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" }, "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^7.1" + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", "autoload": { - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - }, "files": [ "src/DeepCopy/deep_copy.php" - ] + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1194,72 +1811,213 @@ "object", "object graph" ], - "time": "2019-04-07T13:18:21+00:00" + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2023-03-08T13:26:56+00:00" }, { - "name": "paragonie/random_compat", - "version": "v9.99.99", + "name": "nikic/php-parser", + "version": "v5.0.2", "source": { "type": "git", - "url": "https://github.com/paragonie/random_compat.git", - "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95" + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", - "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/139676794dc1e9231bf7bcd123cfc0c99182cb13", + "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13", "shasum": "" }, "require": { - "php": "^7" + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" }, "require-dev": { - "phpunit/phpunit": "4.*|5.*", - "vimeo/psalm": "^1" - }, - "suggest": { - "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" }, + "bin": [ + "bin/php-parse" + ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com" + "name": "Nikita Popov" } ], - "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "description": "A PHP parser written in PHP", "keywords": [ - "csprng", - "polyfill", - "pseudorandom", - "random" + "parser", + "php" ], - "time": "2018-07-02T15:55:56+00:00" + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.2" + }, + "time": "2024-03-05T20:51:40+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" }, { "name": "php-cs-fixer/diff", - "version": "v1.3.0", + "version": "v1.3.1", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/diff.git", - "reference": "78bb099e9c16361126c86ce82ec4405ebab8e756" + "reference": "dbd31aeb251639ac0b9e7e29405c1441907f5759" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/78bb099e9c16361126c86ce82ec4405ebab8e756", - "reference": "78bb099e9c16361126c86ce82ec4405ebab8e756", + "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/dbd31aeb251639ac0b9e7e29405c1441907f5759", + "reference": "dbd31aeb251639ac0b9e7e29405c1441907f5759", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^5.6 || ^7.0 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^5.7.23 || ^6.4.3", + "phpunit/phpunit": "^5.7.23 || ^6.4.3 || ^7.0", "symfony/process": "^3.3" }, "type": "library", @@ -1273,14 +2031,14 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, { "name": "SpacePossum" } @@ -1290,351 +2048,560 @@ "keywords": [ "diff" ], - "time": "2018-02-15T16:58:55+00:00" + "support": { + "issues": "https://github.com/PHP-CS-Fixer/diff/issues", + "source": "https://github.com/PHP-CS-Fixer/diff/tree/v1.3.1" + }, + "abandoned": true, + "time": "2020-10-14T08:39:05+00:00" }, { - "name": "phpdocumentor/reflection-common", - "version": "1.0.1", + "name": "phpunit/php-code-coverage", + "version": "9.2.31", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/48c34b5d8d983006bd2adc2d0de92963b9155965", + "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965", "shasum": "" }, "require": { - "php": ">=5.5" + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.3", + "phpunit/php-text-template": "^2.0.2", + "sebastian/code-unit-reverse-lookup": "^2.0.2", + "sebastian/complexity": "^2.0", + "sebastian/environment": "^5.1.2", + "sebastian/lines-of-code": "^1.0.3", + "sebastian/version": "^3.0.1", + "theseer/tokenizer": "^1.2.0" }, "require-dev": { - "phpunit/phpunit": "^4.6" + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "9.2-dev" } }, "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" - ] - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.31" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2017-09-11T18:02:19+00:00" + "time": "2024-03-02T06:37:42+00:00" }, { - "name": "phpdocumentor/reflection-docblock", - "version": "4.3.1", + "name": "phpunit/php-file-iterator", + "version": "3.0.6", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c" + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", - "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", "shasum": "" }, "require": { - "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0", - "phpdocumentor/type-resolver": "^0.4.0", - "webmozart/assert": "^1.0" + "php": ">=7.3" }, "require-dev": { - "doctrine/instantiator": "~1.0.5", - "mockery/mockery": "^1.0", - "phpunit/phpunit": "^6.4" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2019-04-30T17:48:53+00:00" + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-12-02T12:48:52+00:00" }, { - "name": "phpdocumentor/type-resolver", - "version": "0.4.0", + "name": "phpunit/php-invoker", + "version": "3.1.1", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", "shasum": "" }, "require": { - "php": "^5.5 || ^7.0", - "phpdocumentor/reflection-common": "^1.0" + "php": ">=7.3" }, "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcntl": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.1-dev" } }, "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" } ], - "time": "2017-07-14T14:27:02+00:00" + "time": "2020-09-28T05:58:55+00:00" }, { - "name": "phpspec/prophecy", - "version": "1.8.1", + "name": "phpunit/php-text-template", + "version": "2.0.4", "source": { "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76" + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/1927e75f4ed19131ec9bcc3b002e07fb1173ee76", - "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", - "sebastian/comparator": "^1.1|^2.0|^3.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0" + "php": ">=7.3" }, "require-dev": { - "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.8.x-dev" + "dev-master": "2.0-dev" } }, "autoload": { - "psr-4": { - "Prophecy\\": "src/Prophecy" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + }, + "funding": [ { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" + "url": "https://github.com/sebastianbergmann", + "type": "github" } ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", + "time": "2020-10-26T05:33:50+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "5.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2019-06-13T12:50:23+00:00" + "time": "2020-10-26T13:16:10+00:00" }, { - "name": "phpunit/php-code-coverage", - "version": "4.0.8", + "name": "phpunit/phpunit", + "version": "9.6.17", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "1a156980d78a6666721b7e8e8502fe210b587fcd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1a156980d78a6666721b7e8e8502fe210b587fcd", + "reference": "1a156980d78a6666721b7e8e8502fe210b587fcd", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.3.1 || ^2", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=7.3", + "phpunit/php-code-coverage": "^9.2.28", + "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.3", + "phpunit/php-timer": "^5.0.2", + "sebastian/cli-parser": "^1.0.1", + "sebastian/code-unit": "^1.0.6", + "sebastian/comparator": "^4.0.8", + "sebastian/diff": "^4.0.3", + "sebastian/environment": "^5.1.3", + "sebastian/exporter": "^4.0.5", + "sebastian/global-state": "^5.0.1", + "sebastian/object-enumerator": "^4.0.3", + "sebastian/resource-operations": "^3.0.3", + "sebastian/type": "^3.2", + "sebastian/version": "^3.0.2" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.6-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.17" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2024-02-23T13:14:51+00:00" + }, + { + "name": "psr/cache", + "version": "3.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d" + "url": "https://github.com/php-fig/cache.git", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d", - "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d", + "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-xmlwriter": "*", - "php": "^5.6 || ^7.0", - "phpunit/php-file-iterator": "^1.3", - "phpunit/php-text-template": "^1.2", - "phpunit/php-token-stream": "^1.4.2 || ^2.0", - "sebastian/code-unit-reverse-lookup": "^1.0", - "sebastian/environment": "^1.3.2 || ^2.0", - "sebastian/version": "^1.0 || ^2.0" - }, - "require-dev": { - "ext-xdebug": "^2.1.4", - "phpunit/phpunit": "^5.7" - }, - "suggest": { - "ext-xdebug": "^2.5.1" + "php": ">=8.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Psr\\Cache\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "description": "Common interface for caching libraries", "keywords": [ - "coverage", - "testing", - "xunit" + "cache", + "psr", + "psr-6" ], - "time": "2017-04-02T07:44:40+00:00" + "support": { + "source": "https://github.com/php-fig/cache/tree/3.0.0" + }, + "time": "2021-02-03T23:26:27+00:00" }, { - "name": "phpunit/php-file-iterator", - "version": "1.4.5", + "name": "psr/event-dispatcher", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.2.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "description": "Standard interfaces for event handling.", "keywords": [ - "filesystem", - "iterator" + "events", + "psr", + "psr-14" ], - "time": "2017-11-27T13:52:08+00:00" + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" }, { - "name": "phpunit/php-text-template", - "version": "1.2.1", + "name": "sebastian/cli-parser", + "version": "1.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -1651,32 +2618,39 @@ "role": "lead" } ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2015-06-21T13:50:34+00:00" + "time": "2024-03-02T06:27:43+00:00" }, { - "name": "phpunit/php-timer", - "version": "1.0.9", + "name": "sebastian/code-unit", + "version": "1.0.8", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { @@ -1696,37 +2670,43 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2017-02-26T11:10:40+00:00" + "time": "2020-10-26T13:08:54+00:00" }, { - "name": "phpunit/php-token-stream", - "version": "2.0.2", + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "791198a2c6254db10131eecfe8c06670700904db" + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", - "reference": "791198a2c6254db10131eecfe8c06670700904db", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": "^7.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^6.2.4" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { @@ -1749,68 +2729,46 @@ "email": "sebastian@phpunit.de" } ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2017-11-27T05:48:46+00:00" + "time": "2020-09-28T05:30:19+00:00" }, { - "name": "phpunit/phpunit", - "version": "5.7.27", + "name": "sebastian/comparator", + "version": "4.0.8", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c" + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c", - "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "myclabs/deep-copy": "~1.3", - "php": "^5.6 || ^7.0", - "phpspec/prophecy": "^1.6.2", - "phpunit/php-code-coverage": "^4.0.4", - "phpunit/php-file-iterator": "~1.4", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": "^3.2", - "sebastian/comparator": "^1.2.4", - "sebastian/diff": "^1.4.3", - "sebastian/environment": "^1.3.4 || ^2.0", - "sebastian/exporter": "~2.0", - "sebastian/global-state": "^1.1", - "sebastian/object-enumerator": "~2.0", - "sebastian/resource-operations": "~1.0", - "sebastian/version": "^1.0.6|^2.0.1", - "symfony/yaml": "~2.1|~3.0|~4.0" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "3.0.2" + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" }, "require-dev": { - "ext-pdo": "*" + "phpunit/phpunit": "^9.3" }, - "suggest": { - "ext-xdebug": "*", - "phpunit/php-invoker": "~1.1" - }, - "bin": [ - "phpunit" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "5.7.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -1825,52 +2783,65 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" } ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", "keywords": [ - "phpunit", - "testing", - "xunit" + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2018-02-01T05:50:59+00:00" + "time": "2022-09-14T12:41:17+00:00" }, { - "name": "phpunit/phpunit-mock-objects", - "version": "3.4.4", + "name": "sebastian/complexity", + "version": "2.0.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "a23b761686d50a560cc56233b9ecf49597cc9118" + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118", - "reference": "a23b761686d50a560cc56233b9ecf49597cc9118", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.6 || ^7.0", - "phpunit/php-text-template": "^1.2", - "sebastian/exporter": "^1.2 || ^2.0" - }, - "conflict": { - "phpunit/phpunit": "<5.4.0" + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^5.4" - }, - "suggest": { - "ext-soap": "*" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2.x-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -1885,89 +2856,117 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "abandoned": true, - "time": "2017-06-30T09:13:00+00:00" + "time": "2023-12-22T06:19:30+00:00" }, { - "name": "pimple/pimple", - "version": "v3.0.2", + "name": "sebastian/diff", + "version": "4.0.6", "source": { "type": "git", - "url": "https://github.com/silexphp/Pimple.git", - "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a" + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/silexphp/Pimple/zipball/a30f7d6e57565a2e1a316e1baf2a483f788b258a", - "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { - "psr-0": { - "Pimple": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" } ], - "description": "Pimple, a simple Dependency Injection Container", - "homepage": "http://pimple.sensiolabs.org", + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ - "container", - "dependency injection" + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2015-09-11T15:10:35+00:00" + "time": "2024-03-02T06:30:58+00:00" }, { - "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.1", + "name": "sebastian/environment", + "version": "5.1.5", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.0" + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-posix": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "5.1-dev" } }, "autoload": { @@ -1985,36 +2984,51 @@ "email": "sebastian@phpunit.de" } ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2017-03-04T06:30:41+00:00" + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:03:51+00:00" }, { - "name": "sebastian/comparator", - "version": "1.2.4", + "name": "sebastian/exporter", + "version": "4.0.6", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", "shasum": "" }, "require": { - "php": ">=5.3.3", - "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2 || ~2.0" + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "ext-mbstring": "*", + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -2027,6 +3041,10 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" @@ -2036,47 +3054,62 @@ "email": "github@wallbash.com" }, { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" + "name": "Adam Harvey", + "email": "aharvey@php.net" }, { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ - "comparator", - "compare", - "equality" + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2017-01-29T09:50:25+00:00" + "time": "2024-03-02T06:33:00+00:00" }, { - "name": "sebastian/diff", - "version": "1.4.3", + "name": "sebastian/global-state", + "version": "5.0.7", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + "ext-dom": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-uopz": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -2089,46 +3122,53 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", "keywords": [ - "diff" + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2017-05-22T07:24:03+00:00" + "time": "2024-03-02T06:35:11+00:00" }, { - "name": "sebastian/environment", - "version": "2.0.0", + "name": "sebastian/lines-of-code", + "version": "1.0.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", - "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^5.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "1.0-dev" } }, "autoload": { @@ -2143,44 +3183,50 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2016-11-26T07:53:53+00:00" + "time": "2023-12-22T06:20:34+00:00" }, { - "name": "sebastian/exporter", - "version": "2.0.0", + "name": "sebastian/object-enumerator", + "version": "4.0.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", - "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", "shasum": "" }, "require": { - "php": ">=5.3.3", - "sebastian/recursion-context": "~2.0" + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" }, "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -2193,62 +3239,49 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" } ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2016-11-19T08:54:04+00:00" + "time": "2020-10-26T13:12:34+00:00" }, { - "name": "sebastian/global-state", - "version": "1.1.1", + "name": "sebastian/object-reflector", + "version": "2.0.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "suggest": { - "ext-uopz": "*" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -2266,38 +3299,44 @@ "email": "sebastian@phpunit.de" } ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2015-10-12T03:26:01+00:00" + "time": "2020-10-26T13:14:26+00:00" }, { - "name": "sebastian/object-enumerator", - "version": "2.0.1", + "name": "sebastian/recursion-context", + "version": "4.0.5", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7" + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7", - "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", "shasum": "" }, "require": { - "php": ">=5.6", - "sebastian/recursion-context": "~2.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "~5" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -2313,36 +3352,54 @@ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" } ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2017-02-18T15:18:39+00:00" + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:07:39+00:00" }, { - "name": "sebastian/recursion-context", - "version": "2.0.0", + "name": "sebastian/resource-operations", + "version": "3.0.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", - "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -2355,44 +3412,49 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" - }, + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + }, + "funding": [ { - "name": "Adam Harvey", - "email": "aharvey@php.net" + "url": "https://github.com/sebastianbergmann", + "type": "github" } ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2016-11-19T07:33:16+00:00" + "time": "2020-09-28T06:45:17+00:00" }, { - "name": "sebastian/resource-operations", - "version": "1.0.0", + "name": "sebastian/type", + "version": "3.2.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", "shasum": "" }, "require": { - "php": ">=5.6.0" + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -2407,34 +3469,45 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2015-07-28T20:34:47+00:00" + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:13:03+00:00" }, { "name": "sebastian/version", - "version": "2.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + "reference": "c6c1022351a901512170118436c764e473f6de8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", "shasum": "" }, "require": { - "php": ">=5.6" + "php": ">=7.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -2455,44 +3528,60 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-10-03T07:35:21+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:39:44+00:00" }, { "name": "symfony/console", - "version": "v4.3.1", + "version": "v5.4.36", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "d50bbeeb0e17e6dd4124ea391eff235e932cbf64" + "reference": "39f75d9d73d0c11952fdcecf4877b4d0f62a8f6e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/d50bbeeb0e17e6dd4124ea391eff235e932cbf64", - "reference": "d50bbeeb0e17e6dd4124ea391eff235e932cbf64", + "url": "https://api.github.com/repos/symfony/console/zipball/39f75d9d73d0c11952fdcecf4877b4d0f62a8f6e", + "reference": "39f75d9d73d0c11952fdcecf4877b4d0f62a8f6e", "shasum": "" }, "require": { - "php": "^7.1.3", + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.8", - "symfony/service-contracts": "^1.1" + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.1|^6.0" }, "conflict": { - "symfony/dependency-injection": "<3.4", - "symfony/event-dispatcher": "<4.3", - "symfony/process": "<3.3" + "psr/log": ">=3", + "symfony/dependency-injection": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/event-dispatcher": "<4.4", + "symfony/lock": "<4.4", + "symfony/process": "<4.4" }, "provide": { - "psr/log-implementation": "1.0" + "psr/log-implementation": "1.0|2.0" }, "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~3.4|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/event-dispatcher": "^4.3", - "symfony/lock": "~3.4|~4.0", - "symfony/process": "~3.4|~4.0", - "symfony/var-dumper": "^4.3" + "psr/log": "^1|^2", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/lock": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/var-dumper": "^4.4|^5.0|^6.0" }, "suggest": { "psr/log": "For using the console logger", @@ -2501,11 +3590,6 @@ "symfony/process": "" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.3-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\Console\\": "" @@ -2528,54 +3612,75 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Console Component", + "description": "Eases the creation of beautiful and testable command line interfaces", "homepage": "https://symfony.com", - "time": "2019-06-05T13:25:51+00:00" + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v5.4.36" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-02-20T16:33:57+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v4.3.1", + "version": "v5.4.35", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "4e6c670af81c4fb0b6c08b035530a9915d0b691f" + "reference": "7a69a85c7ea5bdd1e875806a99c51a87d3a74b38" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/4e6c670af81c4fb0b6c08b035530a9915d0b691f", - "reference": "4e6c670af81c4fb0b6c08b035530a9915d0b691f", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/7a69a85c7ea5bdd1e875806a99c51a87d3a74b38", + "reference": "7a69a85c7ea5bdd1e875806a99c51a87d3a74b38", "shasum": "" }, "require": { - "php": "^7.1.3", - "symfony/event-dispatcher-contracts": "^1.1" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/event-dispatcher-contracts": "^2|^3", + "symfony/polyfill-php80": "^1.16" }, "conflict": { - "symfony/dependency-injection": "<3.4" + "symfony/dependency-injection": "<4.4" }, "provide": { "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "1.1" + "symfony/event-dispatcher-implementation": "2.0" }, "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~3.4|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/expression-language": "~3.4|~4.0", - "symfony/http-foundation": "^3.4|^4.0", - "symfony/service-contracts": "^1.1", - "symfony/stopwatch": "~3.4|~4.0" + "psr/log": "^1|^2|^3", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/http-foundation": "^4.4|^5.0|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/stopwatch": "^4.4|^5.0|^6.0" }, "suggest": { "symfony/dependency-injection": "", "symfony/http-kernel": "" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.3-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\EventDispatcher\\": "" @@ -2598,35 +3703,53 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony EventDispatcher Component", + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", - "time": "2019-05-30T16:10:05+00:00" + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.35" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-23T13:51:25+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v1.1.5", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "c61766f4440ca687de1084a5c00b08e167a2575c" + "reference": "a76aed96a42d2b521153fb382d418e30d18b59df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c61766f4440ca687de1084a5c00b08e167a2575c", - "reference": "c61766f4440ca687de1084a5c00b08e167a2575c", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df", + "reference": "a76aed96a42d2b521153fb382d418e30d18b59df", "shasum": "" }, "require": { - "php": "^7.1.3" - }, - "suggest": { - "psr/event-dispatcher": "", - "symfony/event-dispatcher-implementation": "" + "php": ">=8.1", + "psr/event-dispatcher": "^1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-main": "3.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -2658,35 +3781,176 @@ "interoperability", "standards" ], - "time": "2019-06-20T06:46:26+00:00" + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-05-23T14:45:45+00:00" }, { "name": "symfony/filesystem", - "version": "v4.3.1", + "version": "v5.4.35", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "bf2af40d738dec5e433faea7b00daa4431d0a4cf" + "reference": "5a553607d4ffbfa9c0ab62facadea296c9db7086" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/bf2af40d738dec5e433faea7b00daa4431d0a4cf", - "reference": "bf2af40d738dec5e433faea7b00daa4431d0a4cf", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/5a553607d4ffbfa9c0ab62facadea296c9db7086", + "reference": "5a553607d4ffbfa9c0ab62facadea296c9db7086", "shasum": "" }, "require": { - "php": "^7.1.3", - "symfony/polyfill-ctype": "~1.8" + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8", + "symfony/polyfill-php80": "^1.16" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.3-dev" + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v5.4.35" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-23T13:51:25+00:00" + }, + { + "name": "symfony/finder", + "version": "v5.4.35", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "abe6d6f77d9465fed3cd2d029b29d03b56b56435" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/abe6d6f77d9465fed3cd2d029b29d03b56b56435", + "reference": "abe6d6f77d9465fed3cd2d029b29d03b56b56435", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v5.4.35" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } + ], + "time": "2024-01-23T13:51:25+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v5.4.21", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", + "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php73": "~1.0", + "symfony/polyfill-php80": "^1.16" }, + "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\Filesystem\\": "" + "Symfony\\Component\\OptionsResolver\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -2698,48 +3962,77 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "support": { + "source": "https://github.com/symfony/options-resolver/tree/v5.4.21" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "description": "Symfony Filesystem Component", - "homepage": "https://symfony.com", - "time": "2019-06-03T20:27:40+00:00" + "time": "2023-02-14T08:03:56+00:00" }, { - "name": "symfony/finder", - "version": "v4.3.1", + "name": "symfony/polyfill-ctype", + "version": "v1.29.0", "source": { "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "b3d4f4c0e4eadfdd8b296af9ca637cfbf51d8176" + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/b3d4f4c0e4eadfdd8b296af9ca637cfbf51d8176", - "reference": "b3d4f4c0e4eadfdd8b296af9ca637cfbf51d8176", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", "shasum": "" }, "require": { - "php": "^7.1.3" + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "4.3-dev" + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Symfony\\Polyfill\\Ctype\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2747,48 +4040,75 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Finder Component", + "description": "Symfony polyfill for ctype functions", "homepage": "https://symfony.com", - "time": "2019-05-26T20:47:49+00:00" + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" }, { - "name": "symfony/options-resolver", - "version": "v4.3.1", + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.29.0", "source": { "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "914e0edcb7cd0c9f494bc023b1d47534f4542332" + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/914e0edcb7cd0c9f494bc023b1d47534f4542332", - "reference": "914e0edcb7cd0c9f494bc023b1d47534f4542332", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", "shasum": "" }, "require": { - "php": "^7.1.3" + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "4.3-dev" + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2796,55 +4116,79 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony OptionsResolver Component", + "description": "Symfony polyfill for intl's grapheme_* functions", "homepage": "https://symfony.com", "keywords": [ - "config", - "configuration", - "options" + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } ], - "time": "2019-05-10T05:38:46+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { - "name": "symfony/polyfill-ctype", - "version": "v1.11.0", + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.29.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "82ebae02209c21113908c229e9883c419720738a" + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a", - "reference": "82ebae02209c21113908c229e9883c419720738a", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.1" }, "suggest": { - "ext-ctype": "For best performance" + "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.11-dev" + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, "files": [ "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", @@ -2853,58 +4197,69 @@ ], "authors": [ { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for ctype functions", + "description": "Symfony polyfill for intl's Normalizer class and related functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "ctype", + "intl", + "normalizer", "polyfill", - "portable" + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-php70", - "version": "v1.11.0", + "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "bc4858fb611bda58719124ca079baff854149c89" + "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/bc4858fb611bda58719124ca079baff854149c89", - "reference": "bc4858fb611bda58719124ca079baff854149c89", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/5f03a781d984aae42cebd18e7912fa80f02ee644", + "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644", "shasum": "" }, "require": { - "paragonie/random_compat": "~1.0|~2.0|~9.99", - "php": ">=5.3.3" + "php": ">=7.1" }, - "type": "library", + "type": "metapackage", "extra": { "branch-alias": { - "dev-master": "1.11-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php70\\": "" + "dev-main": "1.20-dev" }, - "files": [ - "bootstrap.php" - ], - "classmap": [ - "Resources/stubs" - ] + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2928,38 +4283,56 @@ "portable", "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "support": { + "source": "https://github.com/symfony/polyfill-php70/tree/v1.20.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-10-23T14:02:19+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.11.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "ab50dcf166d5f577978419edd37aa2bb8eabce0c" + "reference": "861391a8da9a04cbad2d232ddd9e4893220d6e25" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/ab50dcf166d5f577978419edd37aa2bb8eabce0c", - "reference": "ab50dcf166d5f577978419edd37aa2bb8eabce0c", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/861391a8da9a04cbad2d232ddd9e4893220d6e25", + "reference": "861391a8da9a04cbad2d232ddd9e4893220d6e25", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.1" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.11-dev" + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" - }, "files": [ "bootstrap.php" - ] + ], + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2983,38 +4356,56 @@ "portable", "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "support": { + "source": "https://github.com/symfony/polyfill-php72/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.11.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "d1fb4abcc0c47be136208ad9d68bf59f1ee17abd" + "reference": "21bd091060673a1177ae842c0ef8fe30893114d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/d1fb4abcc0c47be136208ad9d68bf59f1ee17abd", - "reference": "d1fb4abcc0c47be136208ad9d68bf59f1ee17abd", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/21bd091060673a1177ae842c0ef8fe30893114d2", + "reference": "21bd091060673a1177ae842c0ef8fe30893114d2", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.1" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.11-dev" + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" - }, "files": [ "bootstrap.php" ], + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, "classmap": [ "Resources/stubs" ] @@ -3041,31 +4432,44 @@ "portable", "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/process", - "version": "v4.3.1", + "version": "v5.4.36", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "856d35814cf287480465bb7a6c413bb7f5f5e69c" + "reference": "4fdf34004f149cc20b2f51d7d119aa500caad975" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/856d35814cf287480465bb7a6c413bb7f5f5e69c", - "reference": "856d35814cf287480465bb7a6c413bb7f5f5e69c", + "url": "https://api.github.com/repos/symfony/process/zipball/4fdf34004f149cc20b2f51d7d119aa500caad975", + "reference": "4fdf34004f149cc20b2f51d7d119aa500caad975", "shasum": "" }, "require": { - "php": "^7.1.3" + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.3-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\Process\\": "" @@ -3088,41 +4492,65 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Process Component", + "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", - "time": "2019-05-30T16:10:05+00:00" + "support": { + "source": "https://github.com/symfony/process/tree/v5.4.36" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-02-12T15:49:53+00:00" }, { "name": "symfony/service-contracts", - "version": "v1.1.5", + "version": "v3.4.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d" + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d", - "reference": "f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", "shasum": "" }, "require": { - "php": "^7.1.3", - "psr/container": "^1.0" + "php": ">=8.1", + "psr/container": "^1.1|^2.0" }, - "suggest": { - "symfony/service-implementation": "" + "conflict": { + "ext-psr": "<1.1|>=2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-main": "3.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3148,32 +4576,44 @@ "interoperability", "standards" ], - "time": "2019-06-13T11:15:36+00:00" + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-12-26T14:02:43+00:00" }, { "name": "symfony/stopwatch", - "version": "v4.3.1", + "version": "v5.4.35", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "6b100e9309e8979cf1978ac1778eb155c1f7d93b" + "reference": "887762aa99ff16f65dc8b48aafead415f942d407" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/6b100e9309e8979cf1978ac1778eb155c1f7d93b", - "reference": "6b100e9309e8979cf1978ac1778eb155c1f7d93b", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/887762aa99ff16f65dc8b48aafead415f942d407", + "reference": "887762aa99ff16f65dc8b48aafead415f942d407", "shasum": "" }, "require": { - "php": "^7.1.3", - "symfony/service-contracts": "^1.0" + "php": ">=7.2.5", + "symfony/service-contracts": "^1|^2|^3" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.3-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\Stopwatch\\": "" @@ -3196,46 +4636,65 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Stopwatch Component", + "description": "Provides a way to profile code", "homepage": "https://symfony.com", - "time": "2019-05-27T08:16:38+00:00" + "support": { + "source": "https://github.com/symfony/stopwatch/tree/v5.4.35" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-23T13:51:25+00:00" }, { - "name": "symfony/yaml", - "version": "v4.3.1", + "name": "symfony/string", + "version": "v6.4.4", "source": { "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "c60ecf5ba842324433b46f58dc7afc4487dbab99" + "url": "https://github.com/symfony/string.git", + "reference": "4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/c60ecf5ba842324433b46f58dc7afc4487dbab99", - "reference": "c60ecf5ba842324433b46f58dc7afc4487dbab99", + "url": "https://api.github.com/repos/symfony/string/zipball/4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9", + "reference": "4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9", "shasum": "" }, "require": { - "php": "^7.1.3", - "symfony/polyfill-ctype": "~1.8" + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/console": "<3.4" + "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/console": "~3.4|~4.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/intl": "^6.2|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^5.4|^6.0|^7.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.3-dev" - } - }, "autoload": { + "files": [ + "Resources/functions.php" + ], "psr-4": { - "Symfony\\Component\\Yaml\\": "" + "Symfony\\Component\\String\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -3247,68 +4706,92 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Yaml Component", + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", "homepage": "https://symfony.com", - "time": "2019-04-06T14:04:46+00:00" + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v6.4.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-02-01T13:16:41+00:00" }, { - "name": "webmozart/assert", - "version": "1.4.0", + "name": "theseer/tokenizer", + "version": "1.2.3", "source": { "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9" + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9", - "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0", - "symfony/polyfill-ctype": "^1.8" - }, - "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3-dev" - } - }, "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" } ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } ], - "time": "2018-12-25T11:19:39+00:00" + "time": "2024-03-03T12:36:25+00:00" } ], "aliases": [], @@ -3317,7 +4800,13 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=7.1" + "php": ">=8.2" + }, + "platform-dev": { + "ext-mysqli": "*" + }, + "platform-overrides": { + "php": "8.2.0" }, - "platform-dev": [] + "plugin-api-version": "2.6.0" } diff --git a/phpunit.xml b/phpunit.xml index 8879566..62daf8a 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,27 +1,17 @@ - - - - ./test/src - - - - - - - - ./src - - + + + + + ./src + + + + + + + + ./test/src + + + diff --git a/src/Collection.php b/src/Collection.php index fae5820..163598b 100644 --- a/src/Collection.php +++ b/src/Collection.php @@ -6,6 +6,8 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject; use ActiveCollab\DatabaseConnection\ConnectionInterface; @@ -14,46 +16,20 @@ use LogicException; use Psr\Log\LoggerInterface; -/** - * @package ActiveCollab\DatabaseObject - */ abstract class Collection implements CollectionInterface { use EtagInterfaceImplementation; - /** - * @var ConnectionInterface - */ - protected $connection; - - /** - * @var PoolInterface - */ - protected $pool; - - /** - * @var LoggerInterface - */ - protected $log; - - /** - * @param ConnectionInterface $connection - * @param PoolInterface $pool - * @param LoggerInterface $log - */ - public function __construct(ConnectionInterface $connection, PoolInterface $pool, LoggerInterface $log) + public function __construct( + protected ConnectionInterface $connection, + protected PoolInterface $pool, + protected LoggerInterface $logger, + ) { - $this->connection = $connection; - $this->pool = $pool; - $this->log = $log; - $this->configure(); } - /** - * Pre-configure the collection when it is created. - */ - protected function configure() + protected function configure(): void { } @@ -61,36 +37,20 @@ protected function configure() * Return true if ready. * * If collection declares that it is not ready, but execute methods get called, we should throw an exception - * - * @return bool */ - protected function isReady() + protected function isReady(): bool { return true; } - /** - * @var string - */ - private $application_identifier = 'APPv1.0'; + private string $application_identifier = 'APPv1.0'; - /** - * Return application identifier. - * - * @return string - */ - public function getApplicationIdentifier() + public function getApplicationIdentifier(): string { return $this->application_identifier; } - /** - * Set application identifier. - * - * @param string $value - * @return $this - */ - public function &setApplicationIdentifier($value) + public function setApplicationIdentifier(string $value): static { $this->application_identifier = $value; @@ -99,45 +59,41 @@ public function &setApplicationIdentifier($value) /** * Prepare collection tag from bits of information. - * - * @param string $additional_identifier - * @param string $visitor_identifier - * @param string $hash - * @return string */ - protected function prepareTagFromBits($additional_identifier, $visitor_identifier, $hash) + protected function prepareTagFromBits( + string $additional_identifier, + string $visitor_identifier, + string $hash + ): string { - return implode(',', [$this->getApplicationIdentifier(), 'collection', get_class($this), $additional_identifier, $visitor_identifier, $hash]); + return implode( + ',', + [ + $this->getApplicationIdentifier(), + 'collection', + get_class($this), + $additional_identifier, + $visitor_identifier, + $hash, + ] + ); } - /** - * Return true if this object can be tagged and cached on client side. - * - * @return bool|null - */ - public function canBeTagged() + public function canBeTagged(): bool { return true; } - // --------------------------------------------------- - // Pagination - // --------------------------------------------------- - - /** - * Set pagination configuration. - * - * @param int $current_page - * @param int $items_per_page - * @return $this - */ - public function &pagination($current_page = 1, $items_per_page = 100) + public function pagination( + int $current_page = 1, + int $items_per_page = 100, + ): static { $this->is_paginated = true; $this->currentPage($current_page); - $this->items_per_page = (int) $items_per_page; + $this->items_per_page = $items_per_page; if ($this->items_per_page < 1) { $this->items_per_page = 100; @@ -146,38 +102,17 @@ public function &pagination($current_page = 1, $items_per_page = 100) return $this; } - /** - * @var bool - */ - private $is_paginated = false; + private bool $is_paginated = false; - /** - * Return true if collection is paginated. - * - * @return bool - */ - public function isPaginated() + public function isPaginated(): bool { return $this->is_paginated; } - /** - * @var int|null - */ - private $current_page = null; - - /** - * @var int|null - */ - private $items_per_page = null; + private ?int $current_page = null; + private ?int $items_per_page = null; - /** - * Set current page. - * - * @param int $value - * @return $this - */ - public function ¤tPage($value) + public function currentPage(?int $value): static { if (!$this->is_paginated) { throw new LogicException('Page can be set only for paginated collections'); @@ -192,41 +127,31 @@ public function ¤tPage($value) return $this; } - /** - * Return current page #. - * - * @return int|null - */ - public function getCurrentPage() + public function getCurrentPage(): ?int { return $this->current_page; } - /** - * Return number of items that are displayed per page. - * - * @return int|null - */ - public function getItemsPerPage() + public function getItemsPerPage(): ?int { return $this->items_per_page; } /** * Return array or property => value pairs that describes this object. - * - * @return array */ - public function jsonSerialize() + public function jsonSerialize(): mixed { $result = $this->execute(); if ($result instanceof ResultInterface) { return $result->jsonSerialize(); - } elseif ($result === null) { + } + + if ($result === null) { return []; - } else { - return $result; } + + return $result; } } diff --git a/src/Collection/Composite.php b/src/Collection/Composite.php index 649c863..7e8f2cb 100644 --- a/src/Collection/Composite.php +++ b/src/Collection/Composite.php @@ -6,13 +6,12 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Collection; use ActiveCollab\DatabaseObject\Collection; -/** - * @package ActiveCollab\DatabaseObject\Collection - */ abstract class Composite extends Collection { } diff --git a/src/Collection/Type.php b/src/Collection/Type.php index 50c6d5f..13772ba 100644 --- a/src/Collection/Type.php +++ b/src/Collection/Type.php @@ -6,44 +6,38 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Collection; use ActiveCollab\DatabaseConnection\Result\ResultInterface; use ActiveCollab\DatabaseObject\Collection; use ActiveCollab\DatabaseObject\Entity\EntityInterface; -use Doctrine\Common\Inflector\Inflector; +use Doctrine\Inflector\InflectorFactory; use InvalidArgumentException; use LogicException; -/** - * @package ActiveCollab\DatabaseObject\Collection - */ abstract class Type extends Collection { - /** - * @var string - */ - private $registered_type; + private ?string $registered_type = null; /** * Return type that this collection works with. - * - * @return string */ - abstract public function getType(); + abstract public function getType(): string; /** * Return registered type. - * - * @return string */ - protected function getRegisteredType() + protected function getRegisteredType(): string { - if (empty($this->registered_type)) { + if ($this->registered_type === null) { $this->registered_type = $this->pool->getRegisteredType($this->getType()); if (empty($this->registered_type)) { - throw new InvalidArgumentException("Type '" . $this->getType() . "' is not registered"); + throw new InvalidArgumentException( + sprintf("Type '%s' is not registered", $this->getType()) + ); } } @@ -56,62 +50,51 @@ protected function getRegisteredType() /** * Return true if this object can be tagged and cached on client side. - * - * @return bool|null */ - public function canBeEtagged() + public function canBeEtagged(): bool { return (bool) $this->getTimestampField(); } /** * Cached tag value. - * - * @var string */ - private $tag = false; + private ?string $tag = null; /** * Return collection etag. - * - * @param string $visitor_identifier - * @param bool $use_cache - * @return string */ - public function getEtag($visitor_identifier, $use_cache = true) + public function getEtag( + string $visitor_identifier, + bool $use_cache = true + ): string { $timestamp_field = $this->getTimestampField(); - if ($timestamp_field && ($this->tag === false || !$use_cache)) { - $this->tag = $this->prepareTagFromBits($this->getAdditionalIdentifier(), $visitor_identifier, $this->getTimestampHash($timestamp_field)); + if ($timestamp_field && ($this->tag === null || !$use_cache)) { + $this->tag = $this->prepareTagFromBits( + $this->getAdditionalIdentifier(), + $visitor_identifier, + $this->getTimestampHash($timestamp_field), + ); } return $this->tag; } - /** - * @return string - */ - protected function getAdditionalIdentifier() + protected function getAdditionalIdentifier(): string { return 'na'; } /** * Cached time stamp field name. - * - * @var string|bool */ - private $timestamp_field = null; + private string|false $timestamp_field = ''; - /** - * Return timestamp field name. - * - * @return string|bool - */ - public function getTimestampField() + public function getTimestampField(): string|false { - if ($this->timestamp_field === null) { + if ($this->timestamp_field === '') { $fields = $this->pool->getTypeFields($this->getRegisteredType()); if (in_array('updated_at', $fields)) { @@ -128,11 +111,8 @@ public function getTimestampField() /** * Return timestamp hash. - * - * @param string $timestamp_field - * @return string */ - public function getTimestampHash($timestamp_field) + public function getTimestampHash(string $timestamp_field): string { if (!$this->isReady()) { throw new LogicException('Collection is not ready'); @@ -143,13 +123,21 @@ public function getTimestampHash($timestamp_field) if ($this->count() > 0) { if ($join_expression = $this->getJoinExpression()) { - return sha1($this->connection->executeFirstCell("SELECT GROUP_CONCAT($table_name.$timestamp_field ORDER BY $table_name.id SEPARATOR ',') AS 'timestamp_hash' FROM $table_name $join_expression $conditions")); - } else { - return sha1($this->connection->executeFirstCell("SELECT GROUP_CONCAT($table_name.$timestamp_field ORDER BY id SEPARATOR ',') AS 'timestamp_hash' FROM $table_name $conditions")); + return sha1( + $this->connection->executeFirstCell( + "SELECT GROUP_CONCAT($table_name.$timestamp_field ORDER BY $table_name.id SEPARATOR ',') AS 'timestamp_hash' FROM $table_name $join_expression $conditions", + ), + ); } + + return sha1( + $this->connection->executeFirstCell( + "SELECT GROUP_CONCAT($table_name.$timestamp_field ORDER BY id SEPARATOR ',') AS 'timestamp_hash' FROM $table_name $conditions" + ), + ); } - return sha1(get_class($this)); + return sha1($this::class); } // --------------------------------------------------- @@ -161,7 +149,7 @@ public function getTimestampHash($timestamp_field) * * @return ResultInterface|EntityInterface[] */ - public function execute() + public function execute(): ?iterable { if (!$this->isReady()) { throw new LogicException('Collection is not ready'); @@ -169,44 +157,45 @@ public function execute() if (is_callable($this->pre_execute_callback)) { $ids = $this->executeIds(); + $ids_count = count($ids); - if ($ids_count = count($ids)) { - call_user_func($this->pre_execute_callback, $ids); + if ($ids_count === 0) { + return null; + } - if ($ids_count > 1000) { - $sql = $this->getSelectSql(); // Don't escape more than 1000 ID-s using DB::escape(), let MySQL do the dirty work instead of PHP - } else { - $escaped_ids = $this->connection->escapeValue($ids); + call_user_func($this->pre_execute_callback, $ids); - $sql = "SELECT * FROM {$this->getTableName()} WHERE id IN ($escaped_ids) ORDER BY FIELD (id, $escaped_ids)"; - } - - return $this->pool->findBySql($this->getType(), $sql); + if ($ids_count > 1000) { + $sql = $this->getSelectSql(); // Don't escape more than 1000 ID-s using DB::escape(), let MySQL do the dirty work instead of PHP + } else { + $escaped_ids = $this->connection->escapeValue($ids); + + $sql = sprintf( + "SELECT * FROM %s WHERE `id` IN (%s) ORDER BY FIELD (`id`, %s)", + $this->getTableName(), + $escaped_ids, + $escaped_ids, + ); } - return null; - } else { - return $this->pool->findBySql($this->getType(), $this->getSelectSql()); + return $this->pool->findBySql($this->getType(), $sql); } + + return $this->pool->findBySql($this->getType(), $this->getSelectSql()); } - /** - * @var int[] - */ - private $ids = false; + private ?array $ids = null; /** * Return ID-s of matching records. - * - * @return array */ - public function executeIds() + public function executeIds(): array { if (!$this->isReady()) { throw new LogicException('Collection is not ready'); } - if ($this->ids === false) { + if ($this->ids === null) { $this->ids = $this->connection->executeFirstColumn($this->getSelectSql(false)); if (empty($this->ids)) { @@ -219,10 +208,8 @@ public function executeIds() /** * Return number of items that will be displayed on the current page of paginated collection (or total, if collection is not paginated). - * - * @return int */ - public function countIds() + public function countIds(): int { return count($this->executeIds()); } @@ -257,10 +244,8 @@ private function getSelectSql($all_fields = true) /** * Return number of records that match conditions set by the collection. - * - * @return int */ - public function count() + public function count(): int { if (!$this->isReady()) { throw new LogicException('Collection is not ready'); @@ -276,19 +261,12 @@ public function count() } } - /** - * Return model table name. - * - * @var string - */ - private $table_name; + private ?string $table_name = null; /** * Return model table name. - * - * @return mixed */ - public function getTableName() + public function getTableName(): string { if (empty($this->table_name)) { $this->table_name = $this->pool->getTypeTable($this->getRegisteredType()); @@ -433,7 +411,7 @@ public function getJoinTable() * * If $join_field is null, join field will be based on model name. There are two ways to specify it: * - * 1. As string, where value is for target field and it will map with ID column of the source table, + * 1. As string, where value is for target field, and it will map with ID column of the source table, * 2. As array, where first element is ID in the source table and second element is field in target table * * @param string $table_name @@ -457,10 +435,18 @@ public function &setJoinTable($table_name, $join_field = null) } else { $registered_type = $this->getRegisteredType(); + $inflector = InflectorFactory::create()->build(); + if (($pos = strrpos($registered_type, '\\')) !== false) { - $this->target_join_field = Inflector::singularize(Inflector::tableize(substr($registered_type, $pos + 1))) . '_id'; + $this->target_join_field = sprintf( + '%s_id', + $inflector->singularize($inflector->tableize(substr($registered_type, $pos + 1))) + ); } else { - $this->target_join_field = Inflector::singularize(Inflector::tableize($registered_type)) . '_id'; + $this->target_join_field = sprintf( + '%s_id', + $inflector->singularize($inflector->tableize($registered_type)) + ); } } } diff --git a/src/CollectionInterface.php b/src/CollectionInterface.php index e252525..126cc83 100644 --- a/src/CollectionInterface.php +++ b/src/CollectionInterface.php @@ -6,6 +6,8 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject; use ActiveCollab\DatabaseConnection\Result\ResultInterface; @@ -13,82 +15,54 @@ use ActiveCollab\Etag\EtagInterface; use JsonSerializable; -/** - * @package ActiveCollab\DatabaseObject\Collection - */ interface CollectionInterface extends EtagInterface, JsonSerializable { - /** - * Return application identifier. - * - * @return string - */ - public function getApplicationIdentifier(); - - /** - * Set application identifier. - * - * @param string $value - * @return $this - */ - public function &setApplicationIdentifier($value); + public function getApplicationIdentifier(): string; + public function setApplicationIdentifier(string $value): static; + public function canBeTagged(): bool; /** * Run the query and return DB result. * * @return ResultInterface|EntityInterface[] */ - public function execute(); + public function execute(): ?iterable; /** * Return ID-s of matching records. - * - * @return array */ - public function executeIds(); + public function executeIds(): array; /** * Return number of records that match conditions set by the collection. - * - * @return int */ - public function count(); + public function count(): int; /** * Set pagination configuration. - * - * @param int $current_page - * @param int $items_per_page - * @return $this */ - public function &pagination($current_page = 1, $items_per_page = 100); + public function pagination( + int $current_page = 1, + int $items_per_page = 100, + ): static; /** * Return true if collection is paginated. - * - * @return bool */ - public function isPaginated(); + public function isPaginated(): bool; /** * Set current page. - * - * @param int $value - * @return $this */ - public function ¤tPage($value); + public function currentPage(?int $value): static; /** * Return current page #. - * - * @return int|null */ - public function getCurrentPage(); + public function getCurrentPage(): ?int; /** * Return number of items that are displayed per page. - * - * @return int|null */ - public function getItemsPerPage(); + public function getItemsPerPage(): ?int; } diff --git a/src/Entity/Entity.php b/src/Entity/Entity.php index 28ae7ae..55b4cc1 100644 --- a/src/Entity/Entity.php +++ b/src/Entity/Entity.php @@ -6,14 +6,14 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Entity; use ActiveCollab\ContainerAccess\ContainerAccessInterface; use ActiveCollab\ContainerAccess\ContainerAccessInterface\Implementation as ContainerAccessInterfaceImplementation; use ActiveCollab\DatabaseConnection\ConnectionInterface; use ActiveCollab\DatabaseConnection\Record\ValueCasterInterface; -use ActiveCollab\DatabaseObject\Exception\ValidationException; -use ActiveCollab\DatabaseObject\Pool; use ActiveCollab\DatabaseObject\PoolInterface; use ActiveCollab\DatabaseObject\Validator; use ActiveCollab\DatabaseObject\ValidatorInterface; @@ -22,91 +22,62 @@ use ActiveCollab\DateValue\DateValue; use ActiveCollab\DateValue\DateValueInterface; use DateTime; -use Doctrine\Common\Inflector\Inflector; +use Doctrine\Inflector\InflectorFactory; use InvalidArgumentException; use LogicException; use Psr\Log\LoggerInterface; +use ReturnTypeWillChange; -/** - * @package ActiveCollab\DatabaseObject - */ abstract class Entity implements EntityInterface, ContainerAccessInterface { use ContainerAccessInterfaceImplementation; - /** - * @var ConnectionInterface - */ - protected $connection; - - /** - * @var Pool - */ - protected $pool; - - /** - * @var LoggerInterface - */ - protected $log; - /** * Name of the table. - * - * @var string */ - protected $table_name; + protected string $table_name = ''; /** * Primary key fields. - * - * @var array */ - protected $primary_key = 'id'; + protected string $primary_key = 'id'; /** * Name of autoincrement field (if exists). - * - * @var string */ - protected $auto_increment = 'id'; + protected string $auto_increment = 'id'; /** * @var string[] */ - protected $order_by = ['id']; + protected array $order_by = ['id']; /** * Table fields that are managed by this entity. - * - * @var array */ - protected $fields = []; + protected array $entity_fields = []; /** - * Generated fields that are loaded, but not managed by the entity. - * - * @var array + * Table fields prepared for SELECT SQL query. */ - protected $generated_fields = []; + protected array $sql_read_statements = []; /** - * List of default field values. - * - * @var array + * Generated fields that are loaded, but not managed by the entity. */ - protected $default_field_values = []; + protected array $generated_entity_fields = []; /** - * @param ConnectionInterface $connection - * @param PoolInterface $pool - * @param LoggerInterface|null $log + * List of default field values. */ - public function __construct(ConnectionInterface $connection, PoolInterface $pool, LoggerInterface &$log = null) - { - $this->connection = $connection; - $this->pool = $pool; - $this->log = $log; + protected array $default_entity_field_values = []; + public function __construct( + protected ConnectionInterface $connection, + protected PoolInterface $pool, + protected LoggerInterface $logger + ) + { if ($traits = $pool->getTraitNamesByType(get_class($this))) { foreach ($traits as $trait) { $trait_constructor = str_replace('\\', '', $trait); @@ -123,7 +94,7 @@ public function __construct(ConnectionInterface $connection, PoolInterface $pool /** * Execute post-construction configuration. */ - protected function configure() + protected function configure(): void { } @@ -133,24 +104,18 @@ protected function configure() /** * Indicates if this is new object (not saved). - * - * @var bool */ - private $is_new = true; + private bool $is_new = true; /** * This flag is set to true when data from row are inserted into fields. - * - * @var bool */ - private $is_loading = false; + private bool $is_loading = false; /** * Field values. - * - * @var array */ - private $values = []; + private array $values = []; /** * Array of modified field values. @@ -158,100 +123,78 @@ protected function configure() * Elements of this array are populated on setter call. Real name is * resolved, old value is saved here (if exists) and new one is set. Keys * used in this array are real field names only! - * - * @var array - */ - private $old_values = []; - - /** - * Array of modified fiels. - * - * @var array */ - private $modified_fields = []; + private array $old_values = []; /** - * @var array + * Array of modified fields. */ - private $modified_attributes = []; + private array $modified_fields = []; + private array $modified_attributes = []; /** * Primary key is updated. - * - * @var bool */ - private $primary_key_modified = false; + private bool $primary_key_modified = false; /** * Validate object properties before object is saved. * * This method is called before the item is saved and can be used to fetch - * errors in data before we really save it database. $errors is instance of - * ValidationErrors class that is used for error collection. If collection + * errors in data before we really save it to the database. $errors is instance + * of ValidationErrors class that is used for error collection. If collection * is empty object is considered valid and save process will continue - * - * @param ValidatorInterface $validator */ - public function validate(ValidatorInterface &$validator) + public function validate(ValidatorInterface $validator): ValidatorInterface { $this->triggerEvent('on_validate', [&$validator]); + + return $validator; } - /** - * {@inheritdoc} - */ - public function is($object) + public function is(mixed $object): bool { - if ($object instanceof EntityInterface) { - if ($this->isLoaded()) { - return $object->isLoaded() && get_class($this) == get_class($object) && $this->getId() == $object->getId(); - } else { - foreach ($this->getFields() as $field_name) { - if (!$object->fieldExists($field_name) || - !$this->areFieldValuesSame( - $this->getFieldValue($field_name), - $object->getFieldValue($field_name) - )) { - return false; - } - } + if (!$object instanceof EntityInterface) { + return false; + } - return true; + if ($this->isLoaded()) { + return $object->isLoaded() && get_class($this) == get_class($object) && $this->getId() == $object->getId(); + } + + foreach ($this->getEntityFields() as $field_name) { + if (!$object->entityFieldExists($field_name) || + !$this->areFieldValuesSame( + $this->getFieldValue($field_name), + $object->getFieldValue($field_name) + )) { + return false; } } - return false; + return true; } /** * Return true if field values match. - * - * @param mixed $value_1 - * @param mixed $value_2 - * @return bool */ - private function areFieldValuesSame($value_1, $value_2) + private function areFieldValuesSame(mixed $value_1, mixed $value_2): bool { if (($value_1 instanceof DateValueInterface && $value_2 instanceof DateValueInterface) - || ($value_1 instanceof DateTimeValueInterface && $value_2 instanceof DateTimeValueInterface)) { + || ($value_1 instanceof DateTimeValueInterface && $value_2 instanceof DateTimeValueInterface) + ) { return $value_1->getTimestamp() == $value_2->getTimestamp(); - } else { - return $value_1 === $value_2; } + + return $value_1 === $value_2; } - /** - * {@inheritdoc} - */ - public function getPrimaryKey() + public function getPrimaryKey(): string { return $this->primary_key; } - /** - * {@inheritdoc} - */ - public function getTableName() + public function getTableName(): string { return $this->table_name; } @@ -263,12 +206,9 @@ public function getTableName() /** * Load data from database row. * - * If $cache_row is set to true row data will be added to cache - * - * @param array $row - * @throws InvalidArgumentException + * If $cache_row is set to true row data will be added to cache. */ - public function loadFromRow(array $row) + public function loadFromRow(array $row): static { if (empty($row)) { throw new InvalidArgumentException('Database row expected'); @@ -281,7 +221,7 @@ public function loadFromRow(array $row) foreach ($row as $k => $v) { if ($this->isGeneratedField($k)) { $found_generated_fields[] = $k; - } elseif ($this->fieldExists($k)) { + } elseif ($this->entityFieldExists($k)) { $this->setFieldValue($k, $v); } } @@ -303,22 +243,21 @@ public function loadFromRow(array $row) } $this->doneLoading(); + + return $this; } /** * Save object into database (insert or update). - * - * @return $this - * @throws ValidationException */ - public function &save() + public function save(): static { // --------------------------------------------------- // Populate defaults // --------------------------------------------------- if ($this->isNew()) { - foreach ($this->default_field_values as $field_name => $field_value) { + foreach ($this->default_entity_field_values as $field_name => $field_value) { if (empty($this->values[$field_name]) && !array_key_exists($field_name, $this->values)) { $this->setFieldValue($field_name, $field_value); } @@ -340,7 +279,7 @@ public function &save() $values_to_validate = $this->values; - foreach ($this->fields as $field_name) { + foreach ($this->entity_fields as $field_name) { if (empty($values_to_validate[$field_name]) && !array_key_exists($field_name, $values_to_validate)) { $values_to_validate[$field_name] = null; } @@ -354,7 +293,7 @@ public function &save() $values_to_validate ); - $this->validate($validator); + $validator = $this->validate($validator); if ($validator->hasErrors()) { throw $validator->createException(); @@ -378,12 +317,9 @@ public function &save() } /** - * Delete specific object (and related objects if neccecery). - * - * @param bool $bulk - * @return $this + * Delete specific object (and related objects if necessary). */ - public function &delete($bulk = false) + public function delete(bool $bulk = false): static { if ($this->isLoaded()) { $this->connection->transact(function () use ($bulk) { @@ -401,18 +337,14 @@ public function &delete($bulk = false) /** * Create a copy of this object and optionally save it. - * - * @param bool $save - * @return object */ - public function copy($save = false) + public function copy(bool $save = false): static { $object_class = get_class($this); - /** @var EntityInterface $copy */ - $copy = new $object_class($this->connection, $this->pool, $this->log); + $copy = new $object_class($this->connection, $this->pool, $this->logger); - foreach ($this->getFields() as $field) { + foreach ($this->getEntityFields() as $field) { if ($this->isPrimaryKey($field)) { continue; } @@ -433,20 +365,16 @@ public function copy($save = false) /** * Return value of $is_new variable. - * - * @return bool */ - public function isNew() + public function isNew(): bool { - return (bool) $this->is_new; + return $this->is_new; } /** * Returns true if this object have row in database. - * - * @return bool */ - public function isLoaded() + public function isLoaded(): bool { return !$this->is_new; } @@ -454,7 +382,7 @@ public function isLoaded() /** * Mark start of loading from row. */ - private function startLoading() + private function startLoading(): void { $this->is_loading = true; } @@ -462,7 +390,7 @@ private function startLoading() /** * Done loading from row. */ - private function doneLoading() + private function doneLoading(): void { if ($this->is_loading) { $this->is_loading = false; @@ -474,7 +402,7 @@ private function doneLoading() /** * Set loaded stamp value. */ - private function setAsLoaded() + private function setAsLoaded(): void { $this->is_new = false; $this->resetModifiedFlags(); @@ -483,10 +411,8 @@ private function setAsLoaded() /** * Returns true if this object is in the middle of hydration process * (loading values from database row). - * - * @return bool */ - protected function isLoading() + protected function isLoading(): bool { return $this->is_loading; } @@ -497,21 +423,16 @@ protected function isLoading() /** * Return object ID. - * - * @return int */ - public function getId() + public function getId(): ?int { return $this->getFieldValue('id'); } /** * Set value of id field. - * - * @param int $value - * @return $this */ - public function &setId($value) + public function setId(?int $value): static { $this->setFieldValue('id', $value); @@ -520,26 +441,18 @@ public function &setId($value) /** * Check if this object has modified columns. - * - * @return bool */ - public function isModified() + public function isModified(): bool { return !empty($this->modified_fields) || !empty($this->modified_attributes); } - /** - * {@inheritdoc} - */ - public function getModifiedFields() + public function getModifiedFields(): array { return $this->modified_fields; } - /** - * {@inheritdoc} - */ - public function getModifications() + public function getModifications(): array { $result = []; @@ -559,45 +472,34 @@ public function getModifications() /** * Returns true if specific field is modified. - * - * @param string $field - * @return bool */ - public function isModifiedField($field) + public function isModifiedField(string $field): bool { return in_array($field, $this->modified_fields); } /** * Return true if primary key is modified. - * - * @return bool */ - public function isPrimaryKeyModified() + public function isPrimaryKeyModified(): bool { return $this->primary_key_modified; } - /** - * @return array - */ - public function getModifiedAttributes() + public function getModifiedAttributes(): array { return $this->modified_attributes; } /** * Return true if $attribute is modified. - * - * @param string $attribute - * @return bool */ - public function isModifiedAttribute($attribute) + public function isModifiedAttribute(string $attribute): bool { return in_array($attribute, $this->modified_attributes); } - protected function recordModifiedAttribute($attribute) + protected function recordModifiedAttribute(string $attribute): void { if (!in_array($attribute, $this->modified_attributes)) { $this->modified_attributes[] = $attribute; @@ -606,107 +508,75 @@ protected function recordModifiedAttribute($attribute) /** * Revert field to old value. - * - * @param $field */ - public function revertField($field) + public function revertField(string $field): void { if ($this->isModifiedField($field)) { $this->setFieldValue($field, $this->getOldFieldValue($field)); // revert field value - if (($key = array_search($field, $this->modified_fields)) !== false) { - unset($this->modified_fields[$field]); // remove modified flag + if (array_key_exists($field, $this->modified_fields)) { + unset($this->modified_fields[$field]); } } } /** * Check if selected field is primary key. - * - * @param string $field Field that need to be checked - * @return bool */ - public function isPrimaryKey($field) + public function isPrimaryKey(string $field): bool { return $field === 'id'; } - /** - * {@inheritdoc} - */ - public function getFields() + public function getEntityFields(): array { - return $this->fields; + return $this->entity_fields; } - /** - * {@inheritdoc} - */ - public function fieldExists($field) + public function entityFieldExists(string $entity_field): bool { - return in_array($field, $this->fields) || in_array($field, $this->generated_fields); + return in_array($entity_field, $this->entity_fields) || in_array($entity_field, $this->generated_entity_fields); } - /** - * {@inheritdoc} - */ - public function getGeneratedFields() + public function getGeneratedFields(): array { - return $this->generated_fields; + return $this->generated_entity_fields; } - /** - * {@inheritdoc} - */ - public function generatedFieldExists($field) + public function generatedFieldExists(string $field): bool { - return in_array($field, $this->generated_fields); + return in_array($field, $this->generated_entity_fields); } - /** - * {@inheritdoc} - */ - public function isGeneratedField($field) + public function isGeneratedField(string $field): bool { return $this->generatedFieldExists($field); } - /** - * @var ValueCasterInterface - */ - private $generated_fields_value_caster; + private ?ValueCasterInterface $generated_fields_value_caster = null; - /** - * @return ValueCasterInterface - */ - private function getGeneratedFieldsValueCaster() + private function getGeneratedFieldsValueCaster(): ?ValueCasterInterface { return $this->generated_fields_value_caster; } /** * Set generated fields value caster. - * - * @param ValueCasterInterface|null $value_caster - * @return $this */ - protected function &setGeneratedFieldsValueCaster(ValueCasterInterface $value_caster = null) + protected function setGeneratedFieldsValueCaster(ValueCasterInterface $value_caster = null): static { $this->generated_fields_value_caster = $value_caster; return $this; } - /** - * {@inheritdoc} - */ - public function getFieldValue($field, $default = null) + public function getFieldValue(string $field, mixed $default = null): mixed { if (empty($this->values[$field]) && !array_key_exists($field, $this->values)) { - return empty($this->default_field_values[$field]) - && !array_key_exists($field, $this->default_field_values) ? + return empty($this->default_entity_field_values[$field]) + && !array_key_exists($field, $this->default_entity_field_values) ? $default : - $this->default_field_values[$field]; + $this->default_entity_field_values[$field]; } else { return $this->values[$field]; } @@ -714,23 +584,22 @@ public function getFieldValue($field, $default = null) /** * Return old field values, before fields were updated. - * - * @return array */ - public function getOldValues() + public function getOldValues(): array { return $this->old_values; } /** - * Return all field value. - * - * @param string $field - * @return mixed + * Return old field value. */ - public function getOldFieldValue($field) + public function getOldFieldValue(string $field): mixed { - return isset($this->old_values[$field]) ? $this->old_values[$field] : null; + if (array_key_exists($field, $this->old_values)) { + return $this->old_values[$field]; + } + + return null; } /** @@ -739,20 +608,15 @@ public function getOldFieldValue($field) * Set value of the $field. This function will make sure that everything * runs fine - modifications are saved, in case of primary key old value * will be remembered in case we need to update the row and so on - * - * @param string $field - * @param mixed $value - * @return $this - * @throws InvalidArgumentException */ - public function &setFieldValue($field, $value) + public function setFieldValue(string $field, mixed $value): static { - if ($this->fieldExists($field)) { + if ($this->entityFieldExists($field)) { if ($field === 'id') { $value = $value === null ? null : (int) $value; } - if ($value === null && array_key_exists($field, $this->default_field_values)) { + if ($value === null && array_key_exists($field, $this->default_entity_field_values)) { throw new InvalidArgumentException("Value of '$field' can't be null"); } @@ -797,33 +661,24 @@ public function &setFieldValue($field, $value) /** * Return a list of attributes that this object supports. - * - * @return array */ - protected function getAttributes() + protected function getAttributes(): array { return []; } /** * Return setter method name for the given attribute. - * - * @param string $attribute - * @return string */ - private function getAttributeSetter($attribute) + private function getAttributeSetter(string $attribute): string { - return 'set' . Inflector::classify($attribute); + return sprintf('set%s', InflectorFactory::create()->build()->classify($attribute)); } /** * Set non-field value during DataManager::create() and DataManager::update() calls. - * - * @param string $attribute - * @param mixed $value - * @return $this */ - public function &setAttribute($attribute, $value) + public function setAttribute(string $attribute, mixed $value): static { if (in_array($attribute, $this->getAttributes())) { $setter = $this->getAttributeSetter($attribute); @@ -840,36 +695,34 @@ public function &setAttribute($attribute, $value) /** * Use input $value and return a valid DateValue instance. - * - * @param mixed $value - * @return DateValue|null */ - protected function getDateValueInstanceFrom($value) + protected function getDateValueInstanceFrom(mixed $value): ?DateValueInterface { if ($value === null) { return null; - } elseif ($value instanceof DateTime) { + } + + if ($value instanceof DateTime) { return new DateValue($value->format('Y-m-d')); - } else { - return new DateValue($value); } + + return new DateValue($value); } /** * Use input $value and return a valid DateTimeValue instance. - * - * @param mixed $value - * @return DateTimeValue|null */ - protected function getDateTimeValueInstanceFrom($value) + protected function getDateTimeValueInstanceFrom(mixed $value): ?DateTimeValueInterface { if ($value === null) { return null; - } elseif ($value instanceof DateTime) { + } + + if ($value instanceof DateTime) { return new DateTimeValue($value->format('Y-m-d H:i:s'), 'UTC'); - } else { - return new DateTimeValue($value, 'UTC'); } + + return new DateTimeValue($value, 'UTC'); } // --------------------------------------------------- @@ -879,7 +732,7 @@ protected function getDateTimeValueInstanceFrom($value) /** * Insert record in the database. */ - private function insert() + private function insert(): void { $last_insert_id = $this->connection->insert($this->table_name, $this->values); @@ -894,46 +747,45 @@ private function insert() /** * Update database record. */ - private function update() + private function update(): void { - if (count($this->modified_fields)) { - $updates = []; + if (empty($this->modified_fields)) { + return; + } - foreach ($this->modified_fields as $modified_field) { - $updates[$modified_field] = $this->values[$modified_field]; - } + $updates = []; - if ($this->primary_key_modified) { - $old_id = isset($this->old_values['id']) ? $this->old_values['id'] : $this->getId(); + foreach ($this->modified_fields as $modified_field) { + $updates[$modified_field] = $this->values[$modified_field]; + } - if ($this->pool->exists(get_class($this), $this->getId())) { - throw new LogicException('Object #' . $this->getId() . " can't be overwritten"); - } else { - $this->connection->update($this->table_name, $updates, $this->getWherePartById($old_id)); - } + if ($this->primary_key_modified) { + $old_id = $this->old_values['id'] ?? $this->getId(); + + if ($this->pool->exists(get_class($this), $this->getId())) { + throw new LogicException('Object #' . $this->getId() . " can't be overwritten"); } else { - $this->connection->update($this->table_name, $updates, $this->getWherePartById($this->getId())); + $this->connection->update($this->table_name, $updates, $this->getWherePartById($old_id)); } - - $this->values = array_merge($this->values, $this->refreshGeneratedFieldValues($this->getId())); - $this->setAsLoaded(); + } else { + $this->connection->update($this->table_name, $updates, $this->getWherePartById($this->getId())); } + + $this->values = array_merge($this->values, $this->refreshGeneratedFieldValues($this->getId())); + $this->setAsLoaded(); } /** * Return an array with potentially refreshed values of generated fields. - * - * @param int $id - * @return array */ - private function refreshGeneratedFieldValues($id) + private function refreshGeneratedFieldValues(int $id): array { $result = []; - if (!empty($this->generated_fields)) { + if (!empty($this->generated_entity_fields)) { $result = $this->connection->selectFirstRow( $this->getTableName(), - $this->generated_fields, + $this->generated_entity_fields, $this->getWherePartById($id) ); @@ -953,13 +805,10 @@ private function refreshGeneratedFieldValues($id) /** * Return where part of query. - * - * @param int $id - * @return string */ - private function getWherePartById($id) + private function getWherePartById(int $id): string { - if (empty($id)) { + if ($id < 1) { throw new InvalidArgumentException("Value '$id' is not a valid ID"); } @@ -967,13 +816,13 @@ private function getWherePartById($id) } /** - * Reset modification idicators. + * Reset modification indicators. * - * Useful when you use setXXX functions but you dont want to modify + * Useful when you use setXXX functions, but you don't want to modify * anything (just loading data from database in fresh object using * setFieldValue function) */ - private function resetModifiedFlags() + private function resetModifiedFlags(): void { $this->modified_fields = []; $this->modified_attributes = []; @@ -987,41 +836,33 @@ private function resetModifiedFlags() /** * Registered event handlers. - * - * @var array */ - private $event_handlers = []; + private array $event_handlers = []; /** * Register an internal event handler. - * - * @param string $event - * @param callable $handler */ - protected function registerEventHandler($event, callable $handler) + protected function registerEventHandler(string $event, callable $handler): void { if (empty($event)) { throw new InvalidArgumentException('Event name is required'); } - if (is_callable($handler)) { - if (empty($this->event_handlers[$event])) { - $this->event_handlers[$event] = []; - } - - $this->event_handlers[$event][] = $handler; - } else { + if (!is_callable($handler)) { throw new InvalidArgumentException('Handler not callable'); } + + if (empty($this->event_handlers[$event])) { + $this->event_handlers[$event] = []; + } + + $this->event_handlers[$event][] = $handler; } /** * Trigger an internal event. - * - * @param string $event - * @param array $event_parameters */ - protected function triggerEvent($event, array $event_parameters = []) + protected function triggerEvent(string $event, array $event_parameters = []): void { if (isset($this->event_handlers[$event])) { foreach ($this->event_handlers[$event] as $handler) { @@ -1030,9 +871,7 @@ protected function triggerEvent($event, array $event_parameters = []) } } - /** - * {@inheritdoc} - */ + #[ReturnTypeWillChange] public function jsonSerialize() { $result = [ @@ -1045,10 +884,7 @@ public function jsonSerialize() return $result; } - /** - * {@inheritdoc} - */ - public function jsonSerializeDetails() + public function jsonSerializeDetails(): array { return []; } diff --git a/src/Entity/EntityInterface.php b/src/Entity/EntityInterface.php index 90c714d..b0f6e2a 100644 --- a/src/Entity/EntityInterface.php +++ b/src/Entity/EntityInterface.php @@ -6,79 +6,64 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Entity; use ActiveCollab\DatabaseConnection\Record\LoadFromRow; -use ActiveCollab\DatabaseObject\Exception\ValidationException; use ActiveCollab\DatabaseObject\ValidatorInterface; use ActiveCollab\Object\ObjectInterface; -use InvalidArgumentException; use JsonSerializable; -/** - * @package ActiveCollab\DatabaseObject - */ interface EntityInterface extends ObjectInterface, LoadFromRow, JsonSerializable { /** * Load data from database row. * - * If $cache_row is set to true row data will be added to cache - * - * @param array $row - * @throws InvalidArgumentException + * If $cache_row is set to true row data will be added to cache. */ - public function loadFromRow(array $row); + public function loadFromRow(array $row): static; /** * Validate object properties before object is saved. * * This method is called before the item is saved and can be used to fetch - * errors in data before we really save it database. $errors is instance of - * ValidationErrors class that is used for error collection. If collection + * errors in data before we really save it to the database. $errors is instance + * of ValidationErrors class that is used for error collection. If collection * is empty object is considered valid and save process will continue - * - * @param ValidatorInterface $validator */ - public function validate(ValidatorInterface &$validator); + public function validate(ValidatorInterface $validator): ValidatorInterface; + + /** + * Return true if $object is the same as this object (of same type, and + * with the same ID). + */ + public function is(mixed $object): bool; /** * Save object into database (insert or update). - * - * @return $this - * @throws ValidationException */ - public function &save(); + public function save(): static; /** * Create a copy of this object and optionally save it. - * - * @param bool $save - * @return EntityInterface */ - public function copy($save = false); + public function copy(bool $save = false): static; /** - * Delete specific object (and related objects if neccecery). - * - * @param bool $bulk - * @return $this + * Delete specific object (and related objects if necessary). */ - public function &delete($bulk = false); + public function delete(bool $bulk = false): static; /** * Return primary key columns. - * - * @return string */ - public function getPrimaryKey(); + public function getPrimaryKey(): string; /** * Return value of table name. - * - * @return string */ - public function getTableName(); + public function getTableName(): string; // --------------------------------------------------- // Flags @@ -86,157 +71,109 @@ public function getTableName(); /** * Return value of $is_new variable. - * - * @return bool */ - public function isNew(); + public function isNew(): bool; /** * Returns true if this object have row in database. - * - * @return bool */ - public function isLoaded(); + public function isLoaded(): bool; // --------------------------------------------------- // Fields // --------------------------------------------------- + public function getId(): ?int; + /** * Set value of id field. - * - * @param int $value - * @return $this */ - public function &setId($value); + public function setId(?int $value): static; /** * Check if this object has modified columns. - * - * @return bool */ - public function isModified(); + public function isModified(): bool; /** - * Return modificications indexed by field name, with value composed of an old and new value. - * - * @return array + * Return modifications indexed by field name, with value composed of an old and new value. */ - public function getModifications(); + public function getModifications(): array; /** * Return array of modified fields. - * - * @return array */ - public function getModifiedFields(); + public function getModifiedFields(): array; /** * Returns true if specific field is modified. - * - * @param string $field - * @return bool */ - public function isModifiedField($field); + public function isModifiedField(string $field): bool; /** * Return a list of modified attributes. - * - * @return array */ - public function getModifiedAttributes(); + public function getModifiedAttributes(): array; /** * Return true if $attribute is modified. - * - * @param string $attribute - * @return bool */ - public function isModifiedAttribute($attribute); + public function isModifiedAttribute(string $attribute): bool; /** * Return a list of fields that are managed by this entity. - * - * @return array */ - public function getFields(); + public function getEntityFields(): array; /** * Return true if $field exists (both generated and non-generated fields are checked). - * - * @param string $field Field name - * @return bool */ - public function fieldExists($field); + public function entityFieldExists(string $entity_field): bool; /** * Return a list of fields that this entity is aware of, but does not manage. - * - * @return array */ - public function getGeneratedFields(); + public function getGeneratedFields(): array; /** * Check if generated field exists. - * - * @param string $field Field name - * @return bool */ - public function generatedFieldExists($field); + public function generatedFieldExists(string $field): bool; /** * Return true if $field is generated field. - * - * @param string $field - * @return bool */ - public function isGeneratedField($field); + public function isGeneratedField(string $field): bool; /** * Check if selected field is primary key. - * - * @param string $field Field that need to be checked - * @return bool */ - public function isPrimaryKey($field); + public function isPrimaryKey(string $field): bool; /** * Return true if primary key is modified. - * - * @return bool */ - public function isPrimaryKeyModified(); + public function isPrimaryKeyModified(): bool; /** - * Return value of specific field and typecast it... - * - * @param string $field Field value - * @param mixed $default Default value that is returned in case of any error - * @return mixed + * Return value of specific field and typecast it. */ - public function getFieldValue($field, $default = null); + public function getFieldValue(string $field, mixed $default = null): mixed; /** * Return old field values, before fields were updated. - * - * @return array */ - public function getOldValues(); + public function getOldValues(): array; /** * Return all field value. - * - * @param string $field - * @return mixed */ - public function getOldFieldValue($field); + public function getOldFieldValue(string $field): mixed; /** * Revert field to old value. - * - * @param string $field */ - public function revertField($field); + public function revertField(string $field): void; /** * Set specific field value. @@ -244,27 +181,16 @@ public function revertField($field); * Set value of the $field. This function will make sure that everything * runs fine - modifications are saved, in case of primary key old value * will be remembered in case we need to update the row and so on - * - * @param string $field - * @param mixed $value - * @return mixed - * @throws InvalidArgumentException */ - public function &setFieldValue($field, $value); + public function setFieldValue(string $field, mixed $value): static; /** * Set non-field value during DataManager::create() and DataManager::update() calls. - * - * @param string $attribute - * @param mixed $value - * @return $this */ - public function &setAttribute($attribute, $value); + public function setAttribute(string $attribute, mixed $value): static; /** * Return an array of object properties that are needed to fully display this object on a page. - * - * @return array */ - public function jsonSerializeDetails(); + public function jsonSerializeDetails(): array; } diff --git a/src/Entity/Manager.php b/src/Entity/Manager.php index 851df01..0c09a14 100644 --- a/src/Entity/Manager.php +++ b/src/Entity/Manager.php @@ -6,41 +6,21 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Entity; use ActiveCollab\DatabaseConnection\ConnectionInterface; use ActiveCollab\DatabaseObject\PoolInterface; use Psr\Log\LoggerInterface; -/** - * @package ActiveCollab\DatabaseObject\Entity - */ abstract class Manager implements ManagerInterface { - /** - * @var ConnectionInterface - */ - protected $connection; - - /** - * @var PoolInterface - */ - protected $pool; - - /** - * @var LoggerInterface - */ - protected $log; - - /** - * @param PoolInterface $pool - * @param ConnectionInterface $connection - * @param LoggerInterface|null $log - */ - public function __construct(ConnectionInterface $connection, PoolInterface $pool, LoggerInterface &$log = null) + public function __construct( + protected ConnectionInterface $connection, + protected PoolInterface $pool, + protected LoggerInterface $logger, + ) { - $this->connection = $connection; - $this->pool = $pool; - $this->log = $log; } } diff --git a/src/Entity/ManagerInterface.php b/src/Entity/ManagerInterface.php index a48adee..7185b75 100644 --- a/src/Entity/ManagerInterface.php +++ b/src/Entity/ManagerInterface.php @@ -6,17 +6,11 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Entity; -/** - * @package ActiveCollab\DatabaseObject\Entity - */ interface ManagerInterface { - /** - * Return type that this manager works with. - * - * @return string - */ - public function getType(); + public function getType(): string; } diff --git a/src/Exception/ObjectNotFoundException.php b/src/Exception/ObjectNotFoundException.php index 52ce385..bf96299 100644 --- a/src/Exception/ObjectNotFoundException.php +++ b/src/Exception/ObjectNotFoundException.php @@ -6,23 +6,25 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Exception; use Exception; use RuntimeException; -/** - * @package ActiveCollab\DatabaseObject\Exception - */ class ObjectNotFoundException extends RuntimeException { - /** - * @param string $type - * @param int $id - * @param Exception|null $previous - */ - public function __construct($type, $id, Exception $previous = null) + public function __construct( + string $type, + int $id, + Exception $previous = null, + ) { - parent::__construct("{$type} #{$id} not found", 0, $previous); + parent::__construct( + sprintf("%s #%d not found", $type, $id), + 0, + $previous, + ); } } diff --git a/src/Exception/ValidationException.php b/src/Exception/ValidationException.php index ea591c9..9b90fe8 100644 --- a/src/Exception/ValidationException.php +++ b/src/Exception/ValidationException.php @@ -6,154 +6,81 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Exception; use ActiveCollab\DatabaseObject\Entity\EntityInterface; use Exception; -/** - * @package ActiveCollab\DatabaseObject\Exception - */ class ValidationException extends Exception { const ANY_FIELD = '-- any --'; - /** - * Object instance. - * - * @var EntityInterface - */ - private $object; + private ?EntityInterface $object = null; + private array $errors = []; - /** - * Errors array. - * - * @var array - */ - private $errors = []; - - public function __construct($message = 'Validation failed', int $code = 0, Exception $previous = null) + public function __construct( + string $message = 'Validation failed', + int $code = 0, + Exception $previous = null, + ) { parent::__construct($message, $code, $previous); } - /** - * Return parent object instance. - * - * @return object - */ - public function getObject() + public function getObject(): ?EntityInterface { return $this->object; } - /** - * @param EntityInterface $object - */ - public function setObject(EntityInterface $object) + public function setObject(EntityInterface $object): static { $this->object = $object; + + return $this; } - /** - * Return array or property => value pairs that describes this object. - * - * @return array - */ - public function jsonSerialize() + public function getErrors(): ?array { - $result = [ - 'message' => $this->getMessage(), - 'type' => get_class($this), - 'field_errors' => [] - ]; - - foreach ($this->getErrors() as $field => $messages) { - foreach ($messages as $message) { - if (empty($result['field_errors'][$field])) { - $result['field_errors'][$field] = []; - } - - $result['field_errors'][$field][] = $message; - } - } - - if ($this->object instanceof EntityInterface) { - $result['object_class'] = get_class($this->object); + if (empty($this->errors)) { + return null; } - return $result; - } - - // --------------------------------------------------- - // Utility methods - // --------------------------------------------------- - - /** - * Return number of errors from specific form. - * - * @return array - */ - public function getErrors() - { - return count($this->errors) ? $this->errors : null; + return $this->errors; } /** * Set errors. * * Key is field name, value is array of error messages for the given field - * - * @param array $errors - * @return $this */ - public function &setErrors(array $errors) + public function setErrors(array $errors): static { $this->errors = $errors; return $this; } - /** - * Return field errors. - * - * @param string $field - * @return array - */ - public function getFieldErrors($field) + public function getFieldErrors(string $field): ?array { - return isset($this->errors[$field]) ? $this->errors[$field] : null; + return $this->errors[$field] ?? null; } - /** - * Returns true if there are error messages reported. - * - * @return bool - */ - public function hasErrors() + public function hasErrors(): bool { return (bool) count($this->errors); } - /** - * Check if a specific field has reported errors. - * - * @param string $field - * @return bool - */ - public function hasError($field) + public function hasError(string $field): bool { return !empty($this->errors[$field]); } - /** - * Add error to array. - * - * @param string $error - * @param string $field - * @return $this - */ - public function &addError(string $error, string $field = self::ANY_FIELD) + public function addError( + string $error, + string $field = self::ANY_FIELD, + ): static { if (empty($field)) { $field = self::ANY_FIELD; @@ -167,4 +94,29 @@ public function &addError(string $error, string $field = self::ANY_FIELD) return $this; } + + public function jsonSerialize(): array + { + $result = [ + 'message' => $this->getMessage(), + 'type' => get_class($this), + 'field_errors' => [] + ]; + + foreach ($this->getErrors() as $field => $messages) { + foreach ($messages as $message) { + if (empty($result['field_errors'][$field])) { + $result['field_errors'][$field] = []; + } + + $result['field_errors'][$field][] = $message; + } + } + + if ($this->object instanceof EntityInterface) { + $result['object_class'] = get_class($this->object); + } + + return $result; + } } diff --git a/src/Finder.php b/src/Finder.php index b5d8e8d..f455fad 100644 --- a/src/Finder.php +++ b/src/Finder.php @@ -6,84 +6,41 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject; use ActiveCollab\ContainerAccess\ContainerAccessInterface; use ActiveCollab\ContainerAccess\ContainerAccessInterface\Implementation as ContainerAccessInterfaceImplementation; use ActiveCollab\DatabaseConnection\ConnectionInterface; use ActiveCollab\DatabaseObject\Entity\EntityInterface; -use Doctrine\Common\Inflector\Inflector; -use InvalidArgumentException; +use Doctrine\Inflector\InflectorFactory; use Psr\Log\LoggerInterface; -/** - * @package ActiveCollab\DatabaseObject - */ class Finder implements FinderInterface, ContainerAccessInterface { use ContainerAccessInterfaceImplementation; - /** - * @var ConnectionInterface - */ - private $connection; - - /** - * @var PoolInterface - */ - private $pool; - - /** - * @var LoggerInterface - */ - private $log; - - /** - * @var string - */ - private $type; - - /** - * @var string[] - */ - private $where = []; - - /** - * @var string - */ - private $order_by; - - /** - * @var int|null - */ - private $offset; - - /** - * @var int|null - */ - private $limit; - - /** - * @var string - */ - private $join; + private ConnectionInterface $connection; + private PoolInterface $pool; + private LoggerInterface $logger; + private string $type; + private array $where = []; + private string $order_by; + private ?int $offset = null; + private ?int $limit = null; + private ?string $join = null; - /** - * @param PoolInterface $pool - * @param ConnectionInterface $connection - * @param LoggerInterface|null $log - * @param string $type - */ public function __construct( ConnectionInterface $connection, PoolInterface $pool, - LoggerInterface &$log = null, + LoggerInterface $logger, string $type ) { $this->connection = $connection; $this->pool = $pool; - $this->log = $log; + $this->logger = $logger; $this->type = $type; $this->order_by = $this->pool->getEscapedTypeOrderBy($type); } @@ -95,7 +52,7 @@ public function getType(): string public function getSelectSql(): string { - return $this->getSelectFieldsSql($this->pool->getEscapedTypeFields($this->type)); + return $this->getSelectFieldsSql($this->pool->getTypeFieldsReadStatement($this->type)); } public function getSelectIdsSql(): string @@ -112,19 +69,8 @@ public function __toString(): string // Configuration // --------------------------------------------------- - /** - * Set finder . - * - * @param string|array $pattern - * @param mixed ...$arguments - * @return FinderInterface|$this - */ - public function &where($pattern, ...$arguments): FinderInterface + public function where(string $pattern, mixed ...$arguments): static { - if (!is_string($pattern)) { - throw new InvalidArgumentException('Conditions pattern needs to be string'); - } - $conditions_to_prepare = [$pattern]; if (!empty($arguments)) { @@ -141,35 +87,27 @@ public function &where($pattern, ...$arguments): FinderInterface */ private function getWhere(): string { - switch (count($this->where)) { - case 0: - return ''; - case 1: - return $this->where[0]; - default: - return implode(' AND ', array_map(function ($condition) { - return "($condition)"; - }, $this->where)); - } + return match (count($this->where)) { + 0 => '', + 1 => $this->where[0], + default => implode( + ' AND ', + array_map( + fn ($condition) => sprintf("(%s)", $condition), + $this->where, + ), + ), + }; } - /** - * @param string $order_by - * @return FinderInterface|$this - */ - public function &orderBy($order_by): FinderInterface + public function orderBy(string $order_by): static { $this->order_by = $order_by; return $this; } - /** - * @param int $offset - * @param int $limit - * @return FinderInterface|$this - */ - public function &limit($offset, $limit): FinderInterface + public function limit(int $offset, int $limit): static { $this->offset = $offset; $this->limit = $limit; @@ -177,25 +115,20 @@ public function &limit($offset, $limit): FinderInterface return $this; } - /** - * @param string $type - * @param string $field_name - * @return FinderInterface|$this - */ - public function &join($type, $field_name = null): FinderInterface + public function join(string $type, string $field_name = null): static { return $this->joinTable($this->pool->getTypeTable($type), $field_name); } - /** - * @param string $table_name - * @param string $field_name - * @return FinderInterface|$this - */ - public function &joinTable($table_name, $field_name = null): FinderInterface + public function joinTable( + string $table_name, + string $field_name = null, + ): static { $join_table = $this->connection->escapeTableName($table_name); - $join_field = $this->connection->escapeFieldName($field_name ? $field_name : $this->getJoinFieldNameFromType()); + $join_field = $this->connection->escapeFieldName( + $field_name ?: $this->getJoinFieldNameFromType() + ); $this->join = "LEFT JOIN $join_table ON {$this->getEscapedTableName()}.`id` = $join_table.$join_field"; @@ -210,7 +143,7 @@ private function getJoinFieldNameFromType(): string $type = substr($this->getType(), $pos + 1); } - return Inflector::tableize($type) . '_id'; + return sprintf('%s_id', InflectorFactory::create()->build()->tableize($type)); } // --------------------------------------------------- @@ -221,7 +154,10 @@ public function count(): int { $table_name = $this->getEscapedTableName(); - $sql = "SELECT COUNT($table_name.`id`) AS 'row_count' FROM $table_name"; + $sql = sprintf("SELECT COUNT(%s.`id`) AS 'row_count' FROM %s", + $table_name, + $table_name + ); if ($this->join) { $sql .= " $this->join"; @@ -234,6 +170,16 @@ public function count(): int return $this->connection->executeFirstCell($sql); } + public function exists(): bool + { + return $this->count() > 0; + } + + public function existsOne(): bool + { + return $this->count() === 1; + } + /** * {@inheritdoc} */ @@ -270,10 +216,7 @@ public function ids(): ?iterable return empty($ids) ? [] : $ids; } - /** - * {@inheritdoc} - */ - public function execute() + public function execute(): mixed { $select_sql = $this->getSelectSql(); @@ -295,7 +238,7 @@ public function execute() [ &$this->connection, &$this->pool, - &$this->log, + &$this->logger, ], $this->getContainer() ); @@ -309,7 +252,7 @@ public function execute() [ &$this->connection, &$this->pool, - &$this->log, + &$this->logger, ] ); } @@ -319,9 +262,9 @@ public function execute() // Utilities // --------------------------------------------------- - private $load_by_type_field; + private ?bool $load_by_type_field = null; - private function loadByTypeField(): string + private function loadByTypeField(): bool { if ($this->load_by_type_field === null) { $this->load_by_type_field = in_array('type', $this->pool->getTypeFields($this->type)); @@ -330,9 +273,13 @@ private function loadByTypeField(): string return $this->load_by_type_field; } - private function getSelectFieldsSql(string $escaped_field_names): string + private function getSelectFieldsSql(string $fields_read_statement): string { - $result = "SELECT $escaped_field_names FROM " . $this->getEscapedTableName(); + $result = sprintf( + 'SELECT %s FROM %s', + $fields_read_statement, + $this->getEscapedTableName() + ); if ($this->join) { $result .= " $this->join"; @@ -353,7 +300,7 @@ private function getSelectFieldsSql(string $escaped_field_names): string return $result; } - private $escaped_table_name; + private ?string $escaped_table_name = null; private function getEscapedTableName(): string { diff --git a/src/FinderFactory/FinderFactory.php b/src/FinderFactory/FinderFactory.php index 4b7e534..e271647 100644 --- a/src/FinderFactory/FinderFactory.php +++ b/src/FinderFactory/FinderFactory.php @@ -18,22 +18,19 @@ class FinderFactory implements FinderFactoryInterface { - private $connection; - private $pool; - private $logger; - public function __construct( - ConnectionInterface $connection, - PoolInterface $pool, - LoggerInterface $logger = null + private ConnectionInterface $connection, + private PoolInterface $pool, + private LoggerInterface $logger, ) { - $this->connection = $connection; - $this->pool = $pool; - $this->logger = $logger; } - public function produceFinder(string $type, string $where_pattern = null, ...$where_arguments): FinderInterface + public function produceFinder( + string $type, + string $where_pattern = null, + mixed ...$where_arguments, + ): FinderInterface { $finder = new Finder( $this->connection, diff --git a/src/FinderFactory/FinderFactoryInterface.php b/src/FinderFactory/FinderFactoryInterface.php index 9027743..0f00dc7 100644 --- a/src/FinderFactory/FinderFactoryInterface.php +++ b/src/FinderFactory/FinderFactoryInterface.php @@ -14,5 +14,9 @@ interface FinderFactoryInterface { - public function produceFinder(string $type, string $where_pattern = null, ...$where_arguments): FinderInterface; + public function produceFinder( + string $type, + string $where_pattern = null, + mixed ...$where_arguments, + ): FinderInterface; } diff --git a/src/FinderInterface.php b/src/FinderInterface.php index 8474412..dd2c7ab 100644 --- a/src/FinderInterface.php +++ b/src/FinderInterface.php @@ -6,14 +6,13 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject; use ActiveCollab\DatabaseConnection\Result\ResultInterface; use ActiveCollab\DatabaseObject\Entity\EntityInterface; -/** - * @package ActiveCollab\DatabaseObject - */ interface FinderInterface { public function getType(): string; @@ -25,41 +24,11 @@ public function __toString(): string; // Configuration // --------------------------------------------------- - /** - * Set finder conditions. - * - * @param string $pattern - * @param mixed ...$arguments - * @return FinderInterface - */ - public function &where($pattern, ...$arguments): FinderInterface; - - /** - * @param string $order_by - * @return FinderInterface - */ - public function &orderBy($order_by): FinderInterface; - - /** - * @param int $offset - * @param int $limit - * @return FinderInterface - */ - public function &limit($offset, $limit): FinderInterface; - - /** - * @param string $type - * @param string $field_name - * @return FinderInterface - */ - public function &join($type, $field_name = null): FinderInterface; - - /** - * @param string $table_name - * @param string $field_name - * @return FinderInterface - */ - public function &joinTable($table_name, $field_name = null): FinderInterface; + public function where(string $pattern, mixed ...$arguments): static; + public function orderBy(string $order_by): static; + public function limit(int $offset, int $limit): static; + public function join(string $type, string $field_name = null): static; + public function joinTable(string $table_name, string $field_name = null): static; // --------------------------------------------------- // Execution @@ -72,6 +41,9 @@ public function &joinTable($table_name, $field_name = null): FinderInterface; */ public function count(): int; + public function exists(): bool; + public function existsOne(): bool; + /** * Return all records that match the given criteria. * @@ -95,8 +67,6 @@ public function ids(): ?iterable; /** * Prepare SQL and load one or more records. - * - * @return mixed */ - public function execute(); + public function execute(): mixed; } diff --git a/src/Object.php b/src/Object.php deleted file mode 100644 index 1302e44..0000000 --- a/src/Object.php +++ /dev/null @@ -1,18 +0,0 @@ -. All rights reserved. - */ - -namespace ActiveCollab\DatabaseObject; - -use ActiveCollab\DatabaseObject\Entity\Entity; - -/** - * @package ActiveCollab\DatabaseObject - */ -abstract class Object extends Entity -{ -} diff --git a/src/Pool.php b/src/Pool.php index 7e65e5c..d86cb96 100644 --- a/src/Pool.php +++ b/src/Pool.php @@ -6,6 +6,8 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject; use ActiveCollab\ContainerAccess\ContainerAccessInterface; @@ -21,72 +23,48 @@ use ReflectionClass; use RuntimeException; -/** - * @package ActiveCollab\DatabaseObject - */ class Pool implements PoolInterface, ProducerInterface, ContainerAccessInterface { use ContainerAccessInterfaceImplementation; - /** - * @var ConnectionInterface - */ - protected $connection; - - /** - * @var LoggerInterface - */ - protected $log; + protected ConnectionInterface $connection; + protected LoggerInterface $logger; /** * @var EntityInterface[] */ - private $objects_pool = []; + private array $objects_pool = []; - /** - * @param ConnectionInterface $connection - * @param LoggerInterface|null $log - */ - public function __construct(ConnectionInterface $connection, LoggerInterface &$log = null) + public function __construct(ConnectionInterface $connection, LoggerInterface $logger) { $this->connection = $connection; - $this->log = $log; + $this->logger = $logger; } - /** - * Produce new instance of $type. - * - * @param string $type - * @param array|null $attributes - * @param bool $save - * @return EntityInterface - */ - public function &produce($type, array $attributes = null, $save = true) + public function produce( + string $type, + array $attributes = null, + bool $save = true, + ): EntityInterface { $registered_type = $this->requireRegisteredType($type); - $object = $this->getProducerForRegisteredType($registered_type)->produce($type, $attributes, $save); - - if ($object instanceof EntityInterface) { - if ($object->isLoaded()) { - $this->objects_pool[$registered_type][$object->getId()] = $object; - } + $object = $this + ->getProducerForRegisteredType($registered_type) + ->produce($type, $attributes, $save); - return $object; - } else { - throw new RuntimeException("Failed to produce an instance of '$type'"); + if ($object->isLoaded()) { + $this->objects_pool[$registered_type][$object->getId()] = $object; } + + return $object; } - /** - * Update an instance. - * - * @param EntityInterface $instance - * @param array|null $attributes - * @param bool $save - * @return EntityInterface - */ - public function &modify(EntityInterface &$instance, array $attributes = null, $save = true) + public function modify( + EntityInterface $instance, + array $attributes = null, + bool $save = true, + ): EntityInterface { if ($instance->isNew()) { throw new RuntimeException('Only objects that are saved to database can be modified'); @@ -94,23 +72,19 @@ public function &modify(EntityInterface &$instance, array $attributes = null, $s $registered_type = $this->requireRegisteredType(get_class($instance)); - $instance = $this->getProducerForRegisteredType($registered_type)->modify($instance, $attributes, $save); + $instance = $this + ->getProducerForRegisteredType($registered_type) + ->modify($instance, $attributes, $save); - if ($instance instanceof EntityInterface) { - $this->objects_pool[$registered_type][$instance->getId()] = $instance; - } + $this->objects_pool[$registered_type][$instance->getId()] = $instance; return $instance; } - /** - * Scrap an instance (move it to trash, if object supports, or delete it). - * - * @param EntityInterface $instance - * @param bool $force_delete - * @return EntityInterface - */ - public function &scrap(EntityInterface &$instance, $force_delete = false) + public function scrap( + EntityInterface $instance, + bool $force_delete = false, + ): EntityInterface { if ($instance->isNew()) { throw new RuntimeException('Only objects that are saved to database can be modified'); @@ -128,22 +102,16 @@ public function &scrap(EntityInterface &$instance, $force_delete = false) return $instance; } - private $default_producer_class = Producer::class; + private string $default_producer_class = Producer::class; - /** - * {@inheritdoc} - */ - public function getDefaultProducerClass() + public function getDefaultProducerClass(): string { return $this->default_producer_class; } - /** - * {@inheritdoc} - */ - public function &setDefaultProducerClass($default_producer_class) + public function setDefaultProducerClass(string $default_producer_class): PoolInterface { - if (!class_exists($default_producer_class, true)) { + if (!class_exists($default_producer_class)) { throw new InvalidArgumentException('Producer class not found.'); } @@ -157,20 +125,14 @@ public function &setDefaultProducerClass($default_producer_class) return $this; } - /** - * @var ProducerInterface - */ - private $default_producer; + private ?ProducerInterface $default_producer = null; - /** - * {@inheritdoc} - */ - public function &getDefaultProducer(): ProducerInterface + public function getDefaultProducer(): ProducerInterface { if (empty($this->default_producer)) { $default_producer_class = $this->getDefaultProducerClass(); - $this->default_producer = new $default_producer_class($this->connection, $this); + $this->default_producer = new $default_producer_class($this->connection, $this, $this->logger); if ($this->default_producer instanceof ContainerAccessInterface && $this->hasContainer()) { $this->default_producer->setContainer($this->getContainer()); @@ -180,10 +142,7 @@ public function &getDefaultProducer(): ProducerInterface return $this->default_producer; } - /** - * {@inheritdoc} - */ - public function &setDefaultProducer(ProducerInterface $producer) + public function setDefaultProducer(ProducerInterface $producer): PoolInterface { $this->default_producer = $producer; @@ -193,30 +152,18 @@ public function &setDefaultProducer(ProducerInterface $producer) /** * @var ProducerInterface[] */ - private $producers = []; + private array $producers = []; - /** - * Return producer for registered type. - * - * @param string $registered_type - * @return ProducerInterface - */ - protected function &getProducerForRegisteredType($registered_type) + protected function getProducerForRegisteredType(string $registered_type): ProducerInterface { if (empty($this->producers[$registered_type])) { return $this->getDefaultProducer(); - } else { - return $this->producers[$registered_type]; } + + return $this->producers[$registered_type]; } - /** - * Register producer instance for the given type. - * - * @param string $type - * @param ProducerInterface $producer - */ - public function registerProducer($type, ProducerInterface $producer) + public function registerProducer(string $type, ProducerInterface $producer): PoolInterface { $registered_type = $this->requireRegisteredType($type); @@ -227,85 +174,61 @@ public function registerProducer($type, ProducerInterface $producer) $this->producers[$registered_type] = $producer; } else { - throw new LogicException("Producer for '$type' is already registered"); + throw new LogicException(sprintf("Producer for '%s' is already registered", $type)); } + + return $this; } - /** - * Register producerby providing a producer class name. - * - * @param string $type - * @param string $producer_class - */ - public function registerProducerByClass($type, $producer_class) + public function registerProducerByClass(string $type, string $producer_class): PoolInterface { if (class_exists($producer_class)) { $producer_class_reflection = new ReflectionClass($producer_class); if ($producer_class_reflection->implementsInterface(ProducerInterface::class)) { - $this->registerProducer($type, new $producer_class($this->connection, $this)); + $this->registerProducer($type, new $producer_class($this->connection, $this, $this->logger)); } else { - throw new InvalidArgumentException("Class '$producer_class' does not implement '" . ProducerInterface::class . "' interface"); + throw new InvalidArgumentException( + sprintf( + "Class '%s' does not implement '%s' interface", + $producer_class, + ProducerInterface::class + ) + ); } } + + return $this; } - /** - * Return object from object pool by the given type and ID; if object is not found, return NULL. - * - * @param string $type - * @param int $id - * @param bool $use_cache - * @return object - * @throws InvalidArgumentException - */ - public function &getById($type, $id, $use_cache = true) + public function getById(string $type, int $id, bool $use_cache = true): ?EntityInterface { $registered_type = $this->requireRegisteredType($type); - $id = (int) $id; - if ($id < 1) { throw new InvalidArgumentException('ID is expected to be a number larger than 0'); } if (isset($this->objects_pool[$registered_type][$id]) && $use_cache) { return $this->objects_pool[$registered_type][$id]; - } else { - $type_fields = $this->getTypeFields($registered_type); - - if ($row = $this->connection->executeFirstRow($this->getSelectOneByType($registered_type), [$id])) { - $object_class = in_array('type', $type_fields) ? $row['type'] : $type; - - /** @var object|EntityInterface $object */ - $object = new $object_class($this->connection, $this, $this->log); + } - if ($object instanceof ContainerAccessInterface && $this->hasContainer()) { - $object->setContainer($this->getContainer()); - } + $row = $this->connection->executeFirstRow($this->getSelectOneByType($registered_type), [$id]); - $object->loadFromRow($row); + if (empty($row)) { + $object = null; - return $this->addToObjectPool($registered_type, $id, $object); - } else { - $object = null; - - return $this->addToObjectPool($registered_type, $id, $object); - } + return $this->addToObjectPool($registered_type, $id, $object); } + + return $this->getObjectFromRow( + $type, + $registered_type, + $row, + ); } - /** - * Return object from object pool by the given type and ID; if object is not found, raise an exception. - * - * @param string $type - * @param int $id - * @param bool $use_cache - * @return object - * @throws ObjectNotFoundException - * @throws InvalidArgumentException - */ - public function &mustGetById($type, $id, $use_cache = true) + public function mustGetById(string $type, int $id, bool $use_cache = true): EntityInterface { $result = $this->getById($type, $id, $use_cache); @@ -316,31 +239,65 @@ public function &mustGetById($type, $id, $use_cache = true) return $result; } - /** - * Reload an object of the give type with the given ID. - * - * @param string $type - * @param int $id - * @return object - */ - public function &reload($type, $id) + public function getFirstBy(string $type, string $where, mixed ...$arguments): ?EntityInterface + { + if (empty($where)) { + throw new LogicException('Conditions are required'); + } + + $registered_type = $this->requireRegisteredType($type); + + $row = $this->connection->executeFirstRow( + sprintf( + 'SELECT %s FROM %s WHERE %s LIMIT 0, 1', + $this->getTypeFieldsReadStatement($type), + $this->getTypeTable($type, true), + $this->connection->prepare($where, $arguments), + ) + ); + + if (empty($row)) { + return null; + } + + return $this->getObjectFromRow( + $type, + $registered_type, + $row, + ); + } + + private function getObjectFromRow( + string $type, + string $registered_type, + array $row, + ): EntityInterface + { + $object_class = in_array('type', $this->getTypeFields($registered_type)) + ? $row['type'] + : $type; + + /** @var object|EntityInterface $object */ + $object = new $object_class($this->connection, $this, $this->logger); + + if ($object instanceof ContainerAccessInterface && $this->hasContainer()) { + $object->setContainer($this->getContainer()); + } + + $object->loadFromRow($row); + + return $this->addToObjectPool($registered_type, $object->getId(), $object); + } + + public function reload(string $type, int $id): ?EntityInterface { return $this->getById($type, $id, false); } - /** - * Check if object #ID of $type is in the pool. - * - * @param string $type - * @param int $id - * @return bool - */ - public function isInPool($type, $id) + public function isInPool(string $type, int $id): bool { $this->requireRegisteredType($type); - $id = (int) $id; - if ($id < 1) { throw new InvalidArgumentException('ID is expected to be a number larger than 0'); } @@ -348,15 +305,11 @@ public function isInPool($type, $id) return isset($this->objects_pool[$type][$id]); } - /** - * Add object to the object pool. - * - * @param string $registered_type - * @param int $id - * @param EntityInterface|null $value_to_store - * @return EntityInterface - */ - private function &addToObjectPool($registered_type, $id, &$value_to_store) + private function &addToObjectPool( + string $registered_type, + int $id, + ?EntityInterface $value_to_store + ): ?EntityInterface { if (empty($this->objects_pool[$registered_type])) { $this->objects_pool[$registered_type] = []; @@ -367,32 +320,23 @@ private function &addToObjectPool($registered_type, $id, &$value_to_store) return $this->objects_pool[$registered_type][$id]; } - /** - * Add object to the pool. - * - * @param EntityInterface $object - */ - public function remember(EntityInterface &$object) + public function remember(EntityInterface $object): void { - if ($object->isLoaded()) { - $this->addToObjectPool($this->requireRegisteredType(get_class($object)), $object->getId(), $object); - } else { + if (!$object->isLoaded()) { throw new InvalidArgumentException('Object needs to be saved in the database to be remembered'); } - } - /** - * {@inheritdoc} - */ - public function forget($type, $id) + $this->addToObjectPool( + $this->requireRegisteredType(get_class($object)), + $object->getId(), + $object + ); + } + public function forget(string $type, int ...$ids_to_forget): void { $this->requireRegisteredType($type); - $ids_to_forget = (array) $id; - foreach ($ids_to_forget as $id_to_forget) { - $id_to_forget = (int) $id_to_forget; - if ($id_to_forget < 1) { throw new InvalidArgumentException('ID is expected to be a number larger than 0'); } @@ -406,19 +350,26 @@ public function forget($type, $id) /** * Return number of records of the given type that match the given conditions. * - * @param string $type - * @param array|string|null $conditions - * @return int + * @param array|string|null $conditions */ - public function count($type, $conditions = null) + public function count(string $type, mixed $conditions = null): int { $this->requireRegisteredType($type); - if ($conditions = $this->connection->prepareConditions($conditions)) { - return $this->connection->executeFirstCell('SELECT COUNT(`id`) AS "row_count" FROM ' . $this->getTypeTable($type, true) . " WHERE $conditions"); - } else { - return $this->connection->executeFirstCell('SELECT COUNT(`id`) AS "row_count" FROM ' . $this->getTypeTable($type, true)); + $conditions = $this->connection->prepareConditions($conditions); + + if ($conditions) { + return $this->connection->executeFirstCell( + sprintf('SELECT COUNT(`id`) AS "row_count" FROM %s WHERE %s', + $this->getTypeTable($type, true), + $conditions + ) + ); } + + return $this->connection->executeFirstCell( + sprintf('SELECT COUNT(`id`) AS "row_count" FROM %s', $this->getTypeTable($type, true)) + ); } /** @@ -428,7 +379,7 @@ public function count($type, $conditions = null) * @param int $id * @return bool */ - public function exists($type, $id) + public function exists(string $type, int $id): bool { return (bool) $this->count($type, ['`id` = ?', $id]); } @@ -439,14 +390,14 @@ public function exists($type, $id) * @param string $type * @return Finder */ - public function find($type) + public function find(string $type): FinderInterface { $registered_type = $this->requireRegisteredType($type); $default_finder_class = $this->getDefaultFinderClass(); /** @var Finder $finder */ - $finder = new $default_finder_class($this->connection, $this, $this->log, $registered_type); + $finder = new $default_finder_class($this->connection, $this, $this->logger, $registered_type); if ($finder instanceof ContainerAccessInterface && $this->hasContainer()) { $finder->setContainer($this->getContainer()); @@ -455,18 +406,12 @@ public function find($type) return $finder; } - /** - * @return string - */ - public function getDefaultFinderClass() + public function getDefaultFinderClass(): string { return Finder::class; } - /** - * {@inheritdoc} - */ - public function findBySql($type, $sql, ...$arguments) + public function findBySql(string $type, string $sql, mixed ...$arguments): mixed { if (empty($type)) { throw new InvalidArgumentException('Type is required'); @@ -487,16 +432,36 @@ public function findBySql($type, $sql, ...$arguments) } if ($this->hasContainer()) { - return $this->connection->advancedExecute($sql, $arguments, ConnectionInterface::LOAD_ALL_ROWS, $return_by, $return_by_value, [&$this->connection, &$this, &$this->log], $this->getContainer()); - } else { - return $this->connection->advancedExecute($sql, $arguments, ConnectionInterface::LOAD_ALL_ROWS, $return_by, $return_by_value, [&$this->connection, &$this, &$this->log]); - } - } - - /** - * {@inheritdoc} - */ - public function getTypeTable($type, $escaped = false) + return $this->connection->advancedExecute( + $sql, + $arguments, + ConnectionInterface::LOAD_ALL_ROWS, + $return_by, + $return_by_value, + [ + &$this->connection, + &$this, + &$this->logger, + ], + $this->getContainer() + ); + } + + return $this->connection->advancedExecute( + $sql, + $arguments, + ConnectionInterface::LOAD_ALL_ROWS, + $return_by, + $return_by_value, + [ + &$this->connection, + &$this, + &$this->logger, + ] + ); + } + + public function getTypeTable(string $type, bool $escaped = false): string { $registered_type = $this->requireRegisteredType($type); @@ -511,31 +476,22 @@ public function getTypeTable($type, $escaped = false) } } - /** - * {@inheritdoc} - */ - public function getTypeFields($type) + public function getTypeFields(string $type): array { return $this->types[$this->requireRegisteredType($type)]['fields']; } - /** - * {@inheritdoc} - */ - public function getGeneratedTypeFields($type) + public function getGeneratedTypeFields(string $type): array { return $this->types[$this->requireRegisteredType($type)]['generated_fields']; } - /** - * Get a particular type property, and make it (using $callback) if it is not set already. - * - * @param string $type - * @param string $property - * @param callable $callback - * @return mixed - */ - public function getTypeProperty($type, $property, callable $callback) + public function getTypeSqlReadStatements(string $type): array + { + return $this->types[$this->requireRegisteredType($type)]['sql_read_statements']; + } + + public function getTypeProperty(string $type, string $property, callable $callback): mixed { $registered_type = $this->requireRegisteredType($type); @@ -548,103 +504,112 @@ public function getTypeProperty($type, $property, callable $callback) /** * Return select by ID-s query for the given type. - * - * @param string $type - * @return string */ - private function getSelectOneByType($type) + private function getSelectOneByType(string $type): string { if (empty($this->types[$type]['sql_select_by_ids'])) { - $this->types[$type]['sql_select_by_ids'] = 'SELECT ' . $this->getEscapedTypeFields($type) . ' FROM ' . $this->getTypeTable($type, true) . ' WHERE `id` IN ? ORDER BY `id`'; + $this->types[$type]['sql_select_by_ids'] = sprintf( + 'SELECT %s FROM %s WHERE `id` IN ? ORDER BY `id`', + $this->getTypeFieldsReadStatement($type), + $this->getTypeTable($type, true) + ); } return $this->types[$type]['sql_select_by_ids']; } - /** - * Return a list of escaped field names for the given type. - * - * @param string $type - * @return string - */ - public function getEscapedTypeFields($type) + public function getEscapedTypeFields(string $type): string { - return $this->getTypeProperty($type, 'escaped_fields', function () use ($type) { - $table_name = $this->getTypeTable($type, true); + return $this->getTypeProperty( + $type, + 'escaped_fields', + function () use ($type) { + $table_name = $this->getTypeTable($type, true); - $escaped_field_names = []; + $escaped_field_names = []; - foreach ($this->getTypeFields($type) as $field_name) { - $escaped_field_names[] = $table_name . '.' . $this->connection->escapeFieldName($field_name); - } + foreach ($this->getTypeFields($type) as $field_name) { + $escaped_field_names[] = $table_name . '.' . $this->connection->escapeFieldName($field_name); + } - foreach ($this->getGeneratedTypeFields($type) as $field_name) { - $escaped_field_names[] = $table_name . '.' . $this->connection->escapeFieldName($field_name); + foreach ($this->getGeneratedTypeFields($type) as $field_name) { + $escaped_field_names[] = $table_name . '.' . $this->connection->escapeFieldName($field_name); + } + + return implode(',', $escaped_field_names); } + ); + } - return implode(',', $escaped_field_names); - }); + public function getTypeFieldsReadStatement(string $type): string + { + return $this->getTypeProperty( + $type, + 'field_read_statements', + function () use ($type) { + $table_name = $this->getTypeTable($type, true); + + $field_read_statements = []; + + foreach ($this->getTypeSqlReadStatements($type) as $sql_read_statement) { + $field_read_statements[] = $sql_read_statement; + } + + foreach ($this->getGeneratedTypeFields($type) as $field_name) { + $field_read_statements[] = $table_name . '.' . $this->connection->escapeFieldName($field_name); + } + + return implode(',', $field_read_statements); + } + ); } - /** - * Return default order by for the given type. - * - * @param string $type - * @return string[] - */ - public function getTypeOrderBy($type) + public function getTypeOrderBy(string $type): array { return $this->types[$this->requireRegisteredType($type)]['order_by']; } - /** - * Return escaped list of fields that we can order by. - * - * @param string $type - * @return string - */ - public function getEscapedTypeOrderBy($type) + public function getEscapedTypeOrderBy(string $type): string { - return $this->getTypeProperty($type, 'escaped_order_by', function () use ($type) { - $table_name = $this->getTypeTable($type, true); + return $this->getTypeProperty( + $type, + 'escaped_order_by', + function () use ($type) { + $table_name = $this->getTypeTable($type, true); - return implode(',', array_map(function ($field_name) use ($table_name) { - if (substr($field_name, 0, 1) == '!') { - return $table_name . '.' . $this->connection->escapeFieldName(substr($field_name, 1)) . ' DESC'; - } else { - return $table_name . '.' . $this->connection->escapeFieldName($field_name); - } - }, $this->getTypeOrderBy($type))); - }); + return implode( + ',', + array_map( + function ($field_name) use ($table_name) { + if (str_starts_with($field_name, '!')) { + return $table_name . '.' . $this->connection->escapeFieldName(substr($field_name, 1)) . ' DESC'; + } + + return $table_name . '.' . $this->connection->escapeFieldName($field_name); + }, + $this->getTypeOrderBy($type) + ) + ); + } + ); } - /** - * @var array - */ - private $types = []; + private array $types = []; - /** - * @return array - */ - public function getRegisteredTypes() + public function getRegisteredTypes(): array { return array_keys($this->types); } /** * Cached type to registered type map. - * - * @var array */ - private $known_types = []; + private array $known_types = []; /** * Return registered type for the given $type. This function is subclassing aware. - * - * @param string $type - * @return string|null */ - public function getRegisteredType($type) + public function getRegisteredType(string $type): ?string { $type = ltrim($type, '\\'); @@ -652,13 +617,13 @@ public function getRegisteredType($type) if (isset($this->types[$type])) { $this->known_types[$type] = $type; } else { - if (class_exists($type, true)) { + if (class_exists($type)) { $reflection_class = new ReflectionClass($type); if ($reflection_class->implementsInterface(EntityInterface::class)) { foreach ($this->types as $registered_type => $registered_type_properties) { if ($reflection_class->isSubclassOf($registered_type)) { - $this->known_types[ $type ] = $registered_type; + $this->known_types[$type] = $registered_type; break; } } @@ -674,64 +639,42 @@ public function getRegisteredType($type) return $this->known_types[$type]; } - /** - * {@inheritdoc} - */ - public function requireRegisteredType($type) + public function requireRegisteredType(string $type): string { - if ($registered_type = $this->getRegisteredType($type)) { - return $registered_type; - } else { + $registered_type = $this->getRegisteredType($type); + + if (empty($registered_type)) { throw new InvalidArgumentException("Type '$type' is not registered"); } + + return $registered_type; } - /** - * Return true if $type is registered. - * - * @param string $type - * @return bool - */ - public function isTypeRegistered($type) + public function isTypeRegistered(string $type): bool { return (bool) $this->getRegisteredType($type); } - /** - * @var string|null - */ - private $polymorph_type_interface; + private ?string $polymorph_type_interface = null; - /** - * {@inheritdoc} - */ - public function getPolymorphTypeInterface() + public function getPolymorphTypeInterface(): ?string { return $this->polymorph_type_interface; } - /** - * {@inheritdoc} - */ - public function &setPolymorphTypeInterface($value) + public function &setPolymorphTypeInterface(?string $value): PoolInterface { $this->polymorph_type_interface = $value; return $this; } - /** - * @var array - */ - private $polymorph_types = []; + private array $polymorph_types = []; /** * Return true if $type is polymorph (has type column that is used to figure out a class of individual record). - * - * @param string $type - * @return bool */ - public function isTypePolymorph($type) + public function isTypePolymorph(string $type): bool { $registered_type = $this->getRegisteredType($type); @@ -751,48 +694,48 @@ public function isTypePolymorph($type) return $this->polymorph_types[$registered_type]; } - /** - * @param string[] $types - */ - public function registerType(...$types) + public function registerType(string ...$types): PoolInterface { foreach ($types as $type) { $type = ltrim($type, '\\'); - if (class_exists($type, true)) { - $reflection = new ReflectionClass($type); + if (!class_exists($type)) { + throw new InvalidArgumentException(sprintf("Type '%s' is not defined.", $type)); + } - if ($reflection->implementsInterface(EntityInterface::class)) { - $default_properties = $reflection->getDefaultProperties(); + $reflection = new ReflectionClass($type); - if (empty($default_properties['order_by'])) { - $default_properties['order_by'] = ''; - } + if (!$reflection->implementsInterface(EntityInterface::class)) { + throw new InvalidArgumentException( + sprintf( + "Type '%s' does not implement '%s' interface.", + $type, + EntityInterface::class + ) + ); + } - $this->types[$type] = [ - 'table_name' => $default_properties['table_name'], - 'fields' => $default_properties['fields'], - 'generated_fields' => $default_properties['generated_fields'], - 'order_by' => $default_properties['order_by'], - ]; - } else { - throw new InvalidArgumentException("Type '$type' does not implement '" . EntityInterface::class . "' interface"); - } - } else { - throw new InvalidArgumentException("Type '$type' is not defined"); + $default_properties = $reflection->getDefaultProperties(); + + if (empty($default_properties['order_by'])) { + $default_properties['order_by'] = ''; } + + $this->types[$type] = [ + 'table_name' => $default_properties['table_name'], + 'fields' => $default_properties['entity_fields'], + 'generated_fields' => $default_properties['generated_entity_fields'], + 'sql_read_statements' => $default_properties['sql_read_statements'], + 'order_by' => $default_properties['order_by'], + ]; } + + return $this; } - /** - * @var TraitsResolverInterface - */ - private $traits_resolver; + private ?TraitsResolverInterface $traits_resolver = null; - /** - * @return TraitsResolverInterface - */ - private function &getTraitsResolver() + private function getTraitsResolver(): TraitsResolverInterface { if (empty($this->traits_resolver)) { $this->traits_resolver = new TraitsResolver(); @@ -805,12 +748,9 @@ private function &getTraitsResolver() * Return trait names by object. * * Note: $type does not need to be directly registered, because we need to support subclasses, which call can have - * different traits impelemnted! - * - * @param string $type - * @return array + * different traits implemented! */ - public function getTraitNamesByType($type) + public function getTraitNamesByType(string $type): array { return $this->getTraitsResolver()->getClassTraits($type); } diff --git a/src/PoolInterface.php b/src/PoolInterface.php index 63183d9..443c94e 100644 --- a/src/PoolInterface.php +++ b/src/PoolInterface.php @@ -6,155 +6,73 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject; use ActiveCollab\DatabaseConnection\Result\ResultInterface; use ActiveCollab\DatabaseObject\Entity\EntityInterface; -/** - * @package ActiveCollab\DatabaseObject - */ interface PoolInterface { /** - * Produce new instance of $type. - * - * @param string $type - * @param array|null $attributes - * @param bool $save - * @return EntityInterface - */ - public function &produce($type, array $attributes = null, $save = true); - - /** - * Update an instance. - * - * @param EntityInterface $instance - * @param array|null $attributes - * @param bool $save - * @return EntityInterface - */ - public function &modify(EntityInterface &$instance, array $attributes = null, $save = true); - - /** - * Scrap an instance (move it to trash, if object supports, or delete it). - * - * @param EntityInterface $instance - * @param bool $force_delete - * @return EntityInterface - */ - public function &scrap(EntityInterface &$instance, $force_delete = false); - - /** - * @return string + * @template TClassName + * @param class-string $type + * @return TClassName */ - public function getDefaultProducerClass(); + public function produce(string $type, array $attributes = null, bool $save = true): EntityInterface; + public function modify(EntityInterface $instance, array $attributes = null, bool $save = true): EntityInterface; + public function scrap(EntityInterface $instance, bool $force_delete = false): EntityInterface; - /** - * @return ProducerInterface - */ - public function &getDefaultProducer(): ProducerInterface; + public function getDefaultProducerClass(): string; + public function getDefaultProducer(): ProducerInterface; + public function setDefaultProducer(ProducerInterface $producer): PoolInterface; + public function setDefaultProducerClass(string $default_producer_class): PoolInterface; + public function registerProducer(string $type, ProducerInterface $producer): PoolInterface; + public function registerProducerByClass(string $type, string $producer_class): PoolInterface; /** - * @param ProducerInterface $producer - * @return $this - */ - public function &setDefaultProducer(ProducerInterface $producer); - - /** - * Set default producer class. - * - * @param string $default_producer_class - * @return $this + * @template TClassName + * @param class-string $type + * @return ?TClassName */ - public function setDefaultProducerClass($default_producer_class); + public function getById(string $type, int $id, bool $use_cache = true): ?EntityInterface; /** - * Register producer instance for the given type. - * - * @param string $type - * @param ProducerInterface $producer + * @template TClassName + * @param class-string $type + * @return TClassName */ - public function registerProducer($type, ProducerInterface $producer); + public function mustGetById(string $type, int $id, bool $use_cache = true): EntityInterface; /** - * Register producerby providing a producer class name. - * - * @param string $type - * @param string $producer_class + * @template TClassName + * @param class-string $type + * @return ?TClassName */ - public function registerProducerByClass($type, $producer_class); + public function getFirstBy(string $type, string $where, mixed ...$arguments): ?EntityInterface; /** - * Return object from object pool by the given type and ID; if object is not found, return NULL. - * - * @param string $type - * @param int $id - * @param bool $use_cache - * @return object|null + * @template TClassName + * @param class-string $type + * @return ?TClassName */ - public function &getById($type, $id, $use_cache = true); - - /** - * Return object from object pool by the given type and ID; if object is not found, raise an exception. - * - * @param string $type - * @param int $id - * @param bool $use_cache - * @return object - */ - public function &mustGetById($type, $id, $use_cache = true); - - /** - * Reload an object of the give type with the given ID. - * - * @param string $type - * @param int $id - * @return object - */ - public function &reload($type, $id); - - /** - * Check if object #ID of $type is in the pool. - * - * @param string $type - * @param int $id - * @return bool - */ - public function isInPool($type, $id); - - /** - * Add object to the pool. - * - * @param EntityInterface $object - */ - public function remember(EntityInterface &$object); - - /** - * Forget object if it is loaded in memory. - * - * @param string $type - * @param array|int $id - */ - public function forget($type, $id); + public function reload(string $type, int $id): ?EntityInterface; + public function isInPool(string $type, int $id): bool; + public function remember(EntityInterface $object): void; + public function forget(string $type, int ...$ids_to_forget): void; /** * Return number of records of the given type that match the given conditions. * - * @param string $type * @param array|string|null $conditions - * @return int */ - public function count($type, $conditions = null); + public function count(string $type, mixed $conditions = null): int; /** * Return true if object of the given type with the given ID exists. - * - * @param string $type - * @param int $id - * @return bool */ - public function exists($type, $id); + public function exists(string $type, int $id): bool; /** * Find records by type. @@ -162,26 +80,15 @@ public function exists($type, $id); * @param string $type * @return Finder */ - public function find($type); + public function find(string $type): FinderInterface; /** * Return result by a prepared SQL statement. * - * @param string $type - * @param string $sql - * @param mixed $arguments * @return ResultInterface|EntityInterface[]|null */ - public function findBySql($type, $sql, ...$arguments); - - /** - * Return table name by type. - * - * @param string $type - * @param bool $escaped - * @return string - */ - public function getTypeTable($type, $escaped = false); + public function findBySql(string $type, string $sql, mixed ...$arguments): mixed; + public function getTypeTable(string $type, bool $escaped = false): string; /** * Return a list of fields that are managed by the type. @@ -189,85 +96,28 @@ public function getTypeTable($type, $escaped = false); * @param string $type * @return array */ - public function getTypeFields($type); - - /** - * Return a list of generated type fields that $type is aware of. - * - * @param string $type - * @return array - */ - public function getGeneratedTypeFields($type); + public function getTypeFields(string $type): array; + public function getGeneratedTypeFields(string $type): array; /** * Get a particular type property, and make it (using $callback) if it is not set already. - * - * @param string $type - * @param string $property - * @param callable $callback - * @return mixed - */ - public function getTypeProperty($type, $property, callable $callback); - - /** - * Return a list of escaped field names for the given type. - * - * @param string $type - * @return string - */ - public function getEscapedTypeFields($type); - - /** - * Return default order by for the given type. - * - * @param string $type - * @return string[] - */ - public function getTypeOrderBy($type); - - /** - * Return escaped list of fields that we can order by. - * - * @param string $type - * @return string - */ - public function getEscapedTypeOrderBy($type); - - /** - * @return array */ - public function getRegisteredTypes(); - - /** - * Return registered type for the given $type. This function is subclassing aware. - * - * @param string $type - * @return string|null - */ - public function getRegisteredType($type); - - /** - * Get registered type's class, or throw an execption if type is not regiestered. - * - * @param string $type - * @return string - */ - public function requireRegisteredType($type); - - /** - * Return true if $type is registered. - * - * @param string $type - * @return bool - */ - public function isTypeRegistered($type); + public function getTypeProperty(string $type, string $property, callable $callback): mixed; + public function getEscapedTypeFields(string $type): string; + public function getTypeFieldsReadStatement(string $type): string; + public function getTypeOrderBy(string $type): array; + public function getEscapedTypeOrderBy(string $type): string; + public function getRegisteredTypes(): array; + public function getRegisteredType(string $type): ?string; + public function requireRegisteredType(string $type): string; + public function isTypeRegistered(string $type): bool; /** * Return interface that is used to detect if type is polymorph. * * @return string|null */ - public function getPolymorphTypeInterface(); + public function getPolymorphTypeInterface(): ?string; /** * Set interface that is used to detect if type is polymorph. @@ -275,7 +125,7 @@ public function getPolymorphTypeInterface(); * @param string|null $value * @return $this */ - public function &setPolymorphTypeInterface($value); + public function &setPolymorphTypeInterface(?string $value): PoolInterface; /** * Return true if $type is polymorph (has type column that is used to figure out a class of individual record). @@ -283,23 +133,9 @@ public function &setPolymorphTypeInterface($value); * @param string $type * @return bool */ - public function isTypePolymorph($type); + public function isTypePolymorph(string $type): bool; + public function registerType(string ...$types): PoolInterface; - /** - * @param string[] $types - */ - public function registerType(...$types); - - /** - * Return trait names by object. - * - * @param string $type - * @return array - */ - public function getTraitNamesByType($type); - - /** - * @return string - */ - public function getDefaultFinderClass(); + public function getTraitNamesByType(string $type): array; + public function getDefaultFinderClass(): string; } diff --git a/src/Producer.php b/src/Producer.php index a756483..d46d273 100644 --- a/src/Producer.php +++ b/src/Producer.php @@ -6,6 +6,8 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject; use ActiveCollab\ContainerAccess\ContainerAccessInterface; @@ -14,47 +16,26 @@ use ActiveCollab\DatabaseObject\Entity\EntityInterface; use Psr\Log\LoggerInterface; -/** - * @package ActiveCollab\DatabaseObject - */ class Producer implements ProducerInterface, ContainerAccessInterface { use ContainerAccessInterfaceImplementation; - /** - * @var ConnectionInterface - */ - protected $connection; - - /** - * @var PoolInterface - */ - protected $pool; - - /** - * @var LoggerInterface - */ - protected $log; - - /** - * @param ConnectionInterface $connection - * @param PoolInterface $pool - * @param LoggerInterface|null $log - */ - public function __construct(ConnectionInterface &$connection, PoolInterface &$pool, LoggerInterface &$log = null) + public function __construct( + protected ConnectionInterface $connection, + protected PoolInterface $pool, + protected LoggerInterface $logger + ) { - $this->connection = $connection; - $this->pool = $pool; - $this->log = $log; } - /** - * {@inheritdoc} - */ - public function &produce($type, array $attributes = null, $save = true) + public function produce( + string $type, + array $attributes = null, + bool $save = true, + ): EntityInterface { - /** @var object|EntityInterface $object */ - $object = new $type($this->connection, $this->pool, $this->log); + /** @var EntityInterface $object */ + $object = new $type($this->connection, $this->pool, $this->logger); if ($object instanceof ContainerAccessInterface && $this->hasContainer()) { $object->setContainer($this->getContainer()); @@ -62,7 +43,7 @@ public function &produce($type, array $attributes = null, $save = true) if ($attributes) { foreach ($attributes as $k => $v) { - if ($object->fieldExists($k)) { + if ($object->entityFieldExists($k)) { $object->setFieldValue($k, $v); } else { $object->setAttribute($k, $v); @@ -77,14 +58,15 @@ public function &produce($type, array $attributes = null, $save = true) return $object; } - /** - * {@inheritdoc} - */ - public function &modify(EntityInterface &$instance, array $attributes = null, $save = true) + public function modify( + EntityInterface $instance, + array $attributes = null, + bool $save = true, + ): EntityInterface { if ($attributes) { foreach ($attributes as $k => $v) { - if ($instance->fieldExists($k)) { + if ($instance->entityFieldExists($k)) { $instance->setFieldValue($k, $v); } else { $instance->setAttribute($k, $v); @@ -99,15 +81,15 @@ public function &modify(EntityInterface &$instance, array $attributes = null, $s return $instance; } - /** - * {@inheritdoc} - */ - public function &scrap(EntityInterface &$instance, $force_delete = false) + public function scrap( + EntityInterface $instance, + bool $force_delete = false, + ): EntityInterface { if (!$force_delete && $instance instanceof ScrapInterface) { return $instance->scrap(); - } else { - return $instance->delete(); } + + return $instance->delete(); } } diff --git a/src/ProducerInterface.php b/src/ProducerInterface.php index c79e21a..fee5828 100644 --- a/src/ProducerInterface.php +++ b/src/ProducerInterface.php @@ -6,41 +6,28 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject; use ActiveCollab\DatabaseObject\Entity\EntityInterface; -/** - * @package ActiveCollab\DatabaseObject - */ interface ProducerInterface { - /** - * Produce new instance of $type. - * - * @param string $type - * @param array|null $attributes - * @param bool $save - * @return EntityInterface - */ - public function &produce($type, array $attributes = null, $save = true); + public function produce( + string $type, + array $attributes = null, + bool $save = true, + ): EntityInterface; - /** - * Update an instance. - * - * @param EntityInterface $instance - * @param array|null $attributes - * @param bool $save - * @return EntityInterface - */ - public function &modify(EntityInterface &$instance, array $attributes = null, $save = true); + public function modify( + EntityInterface $instance, + array $attributes = null, + bool $save = true, + ): EntityInterface; - /** - * Scrap an instance (move it to trash, if object supports, or delete it). - * - * @param EntityInterface $instance - * @param bool $force_delete - * @return EntityInterface - */ - public function &scrap(EntityInterface &$instance, $force_delete = false); + public function scrap( + EntityInterface $instance, + bool $force_delete = false, + ): EntityInterface; } diff --git a/src/ScrapInterface.php b/src/ScrapInterface.php index d315a7b..3b8d6b8 100644 --- a/src/ScrapInterface.php +++ b/src/ScrapInterface.php @@ -6,18 +6,13 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject; -/** - * @package ActiveCollab\DatabaseObject - */ +use ActiveCollab\DatabaseObject\Entity\EntityInterface; + interface ScrapInterface { - /** - * Scrap the object, instead of permanently deleting it. - * - * @param bool|false $bulk - * @return $this - */ - public function &scrap($bulk = false); + public function scrap(bool $bulk = false): EntityInterface; } diff --git a/src/TraitsResolver/TraitsResolver.php b/src/TraitsResolver/TraitsResolver.php index 85be552..14d185b 100644 --- a/src/TraitsResolver/TraitsResolver.php +++ b/src/TraitsResolver/TraitsResolver.php @@ -6,25 +6,24 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\TraitsResolver; use ReflectionClass; class TraitsResolver implements TraitsResolverInterface { - private $type_traits = []; + private array $type_traits = []; - /** - * {@inheritdoc} - */ - public function getClassTraits($class_name) + public function getClassTraits(string $class_name): array { if (empty($this->type_traits[$class_name])) { $this->type_traits[$class_name] = []; $this->recursiveGetClassTraits( new ReflectionClass($class_name), - $this->type_traits[$class_name] + $this->type_traits[$class_name], ); } @@ -33,11 +32,8 @@ public function getClassTraits($class_name) /** * Recursively get trait names for the given class name. - * - * @param ReflectionClass $class - * @param array $trait_names */ - private function recursiveGetClassTraits(ReflectionClass $class, array &$trait_names) + private function recursiveGetClassTraits(ReflectionClass $class, array &$trait_names): void { $trait_names = array_merge($trait_names, $class->getTraitNames()); diff --git a/src/TraitsResolver/TraitsResolverInterface.php b/src/TraitsResolver/TraitsResolverInterface.php index 68596bb..129e8ab 100644 --- a/src/TraitsResolver/TraitsResolverInterface.php +++ b/src/TraitsResolver/TraitsResolverInterface.php @@ -6,15 +6,14 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\TraitsResolver; interface TraitsResolverInterface { /** * Return trait names for the given class. - * - * @param string $class_name - * @return array */ - public function getClassTraits($class_name); + public function getClassTraits(string $class_name): array; } diff --git a/src/Validator.php b/src/Validator.php index 9e4b820..9d74b5a 100644 --- a/src/Validator.php +++ b/src/Validator.php @@ -6,97 +6,70 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject; use ActiveCollab\DatabaseConnection\ConnectionInterface; use ActiveCollab\DatabaseObject\Exception\ValidationException; use InvalidArgumentException; -/** - * @package ActiveCollab\DatabaseObject - */ class Validator implements ValidatorInterface { - /** - * @var array - */ - private $errors = []; - - /** - * @var ConnectionInterface - */ - private $connection; - - /** - * @var string - */ - private $table_name; - - /** - * @var int|null - */ - private $object_id; - - /** - * @var int|null - */ - private $old_object_id; - - /** - * @var array - */ - private $field_values; - - /** - * @param ConnectionInterface $connection - * @param string $table_name - * @param int|null $object_id - * @param int|null $old_object_id - * @param array $field_values - */ - public function __construct(ConnectionInterface $connection, $table_name, $object_id, $old_object_id, array $field_values) + private array $errors = []; + + public function __construct( + private ConnectionInterface $connection, + private string $table_name, + private ?int $object_id, + private ?int $old_object_id, + private array $field_values, + ) { - $this->connection = $connection; - $this->table_name = $table_name; - $this->object_id = $object_id; - $this->old_object_id = $old_object_id; - $this->field_values = $field_values; } /** * Check if value of $field_name is present. * - * Note: strings are trimmed prior to check, and values that empty() would return true for (like '0') are consdiered - * to be present (because we check strlen(trim($value)). - * - * @param string $field_name - * @return bool + * Note: strings are trimmed prior to check, and values that empty() would return true for (like '0') are considered + * to be present (because we check strlen(trim($value))). */ - public function present($field_name) + public function present( + string $field_name, + bool $allow_empty = false, + ): bool { if (empty($field_name)) { - throw new InvalidArgumentException("Value '$field_name' is not a valid field name"); + throw new InvalidArgumentException( + sprintf("Value '%s' is not a valid field name", $field_name), + ); } - if (array_key_exists($field_name, $this->field_values)) { - if (is_string($this->field_values[$field_name])) { - if (mb_strlen(trim($this->field_values[$field_name])) > 0) { - return true; - } else { - return $this->failPresenceValidation($field_name); - } - } elseif (is_bool($this->field_values[$field_name])) { + if (!array_key_exists($field_name, $this->field_values)) { + return $this->failPresenceValidation($field_name); + } + + if ($allow_empty && empty($this->field_values[$field_name])) { + return true; + } + + if (is_string($this->field_values[$field_name])) { + if (mb_strlen(trim($this->field_values[$field_name])) > 0) { return true; - } else { - if (empty($this->field_values[$field_name])) { - return $this->failPresenceValidation($field_name); - } else { - return true; - } } - } else { + + return $this->failPresenceValidation($field_name); + } + + if (is_bool($this->field_values[$field_name])) { + return true; + } + + if (empty($this->field_values[$field_name])) { return $this->failPresenceValidation($field_name); } + + return true; } /** @@ -105,47 +78,51 @@ public function present($field_name) * @param string $field_name * @return bool */ - private function failPresenceValidation($field_name) + private function failPresenceValidation(string $field_name): bool { - $this->addFieldError($field_name, "Value of '$field_name' is required"); + $this->addFieldError($field_name, sprintf("Value of '%s' is required.", $field_name)); return false; } - /** - * {@inheritdoc} - */ - public function lowerThan($field_name, $reference_value, $allow_null = false) + public function lowerThan( + string $field_name, + int $reference_value, + bool $allow_null = false + ): bool { return $this->compareValues($field_name, $reference_value, $allow_null, function ($a, $b) { return $a < $b; }, "Value of '$field_name' is not lower than $reference_value"); } - /** - * {@inheritdoc} - */ - public function lowerThanOrEquals($field_name, $reference_value, $allow_null = false) + public function lowerThanOrEquals( + string $field_name, + int $reference_value, + bool $allow_null = false + ): bool { return $this->compareValues($field_name, $reference_value, $allow_null, function ($a, $b) { return $a <= $b; }, "Value of '$field_name' is not lower than or equal to $reference_value"); } - /** - * {@inheritdoc} - */ - public function greaterThan($field_name, $reference_value, $allow_null = false) + public function greaterThan( + string $field_name, + int $reference_value, + bool $allow_null = false + ): bool { return $this->compareValues($field_name, $reference_value, $allow_null, function ($a, $b) { return $a > $b; }, "Value of '$field_name' is not greater than $reference_value"); } - /** - * {@inheritdoc} - */ - public function greaterThanOrEquals($field_name, $reference_value, $allow_null = false) + public function greaterThanOrEquals( + string $field_name, + int $reference_value, + bool $allow_null = false + ): bool { return $this->compareValues($field_name, $reference_value, $allow_null, function ($a, $b) { return $a >= $b; @@ -154,15 +131,14 @@ public function greaterThanOrEquals($field_name, $reference_value, $allow_null = /** * Validate field value by comparing it to a reference value using a closure. - * - * @param string $field_name - * @param mixed $reference_value - * @param bool $allow_null - * @param callable $compare_with - * @param string $validation_failed_message - * @return bool */ - protected function compareValues($field_name, $reference_value, $allow_null, callable $compare_with, $validation_failed_message) + protected function compareValues( + string $field_name, + mixed $reference_value, + bool $allow_null, + callable $compare_with, + string $validation_failed_message + ): bool { if (empty($field_name)) { throw new InvalidArgumentException("Value '$field_name' is not a valid field name"); @@ -189,10 +165,10 @@ protected function compareValues($field_name, $reference_value, $allow_null, cal } } - /** - * {@inheritdoc} - */ - public function inArray($field_name, array $array_of_values, $allow_null = false) + public function inArray( + string $field_name, + array $array_of_values, bool $allow_null = false + ): bool { if (empty($field_name)) { throw new InvalidArgumentException("Value '$field_name' is not a valid field name"); @@ -210,7 +186,7 @@ public function inArray($field_name, array $array_of_values, $allow_null = false if (in_array($this->field_values[$field_name], $array_of_values)) { return true; } else { - $this->addFieldError($field_name, "Value of '$field_name' is not present in the list of supported values"); + $this->addFieldError($field_name, "Value of '$field_name' is not present in the list of supported values."); return false; } @@ -219,109 +195,198 @@ public function inArray($field_name, array $array_of_values, $allow_null = false } } - /** - * {@inheritdoc} - */ - public function unique($field_name, ...$context) + public function unique(string $field_name, string ...$context): bool { return $this->uniqueWhere($field_name, '', ...$context); } - /** - * {@inheritdoc} - */ - public function uniqueWhere($field_name, $where, ...$context) + public function uniqueWhere( + string $field_name, + mixed $where, + string ...$context + ): bool { - if (empty($field_name)) { - throw new InvalidArgumentException("Value '$field_name' is not a valid field name"); - } + $field_names = $this->mustGetFieldNames($field_name, $context); if (empty($context) && (!array_key_exists($field_name, $this->field_values) || $this->field_values[$field_name] === null)) { return true; // NULL is always good for single column keys because MySQL does not check NULL for uniqueness } - $field_names = [$field_name]; - - if (count($context)) { - $field_names = array_merge($field_names, $context); + if ($this->connection->executeFirstCell($this->prepareUniquenessValidatorSql($field_names, $where)) === 0) { + return true; } - // Check if we have existsing columns - foreach ($field_names as $v) { - if (!array_key_exists($v, $this->field_values)) { - throw new InvalidArgumentException("Field '$v' is not known"); - } + if (empty($context)) { + $this->addFieldError( + $field_name, + sprintf("Value of '%s' needs to be unique.", $field_name) + ); + + return false; } - $table_name = $this->connection->escapeTableName($this->table_name); + $this->addFieldError( + $field_name, + sprintf( + "Value of '%s' needs to be unique in context of %s.", + $field_name, + $this->implodeFieldNames($context) + ) + ); - $conditions = []; + return false; + } - if ($where) { - $conditions[] = $this->connection->prepareConditions($where); + public function presentAndUnique(string $field_name, string ...$context): bool + { + if ($this->present($field_name)) { + return $this->unique($field_name, ...$context); } - foreach ($field_names as $v) { - $escaped_field_name = $this->connection->escapeFieldName($v); + return false; + } - if ($this->field_values[$v] === null) { - $conditions[] = "$escaped_field_name IS NULL"; - } else { - $conditions[] = $this->connection->prepare("$escaped_field_name = ?", $this->field_values[$v]); - } + public function presentAndUniqueWhere( + string $field_name, + mixed $where, + string ...$context + ): bool + { + if ($this->present($field_name)) { + return $this->uniqueWhere($field_name, $where, ...$context); } - $conditions = implode(' AND ', $conditions); + return false; + } - if (empty($this->object_id)) { - $sql = "SELECT COUNT(`id`) AS 'row_count' FROM {$table_name} WHERE {$conditions}"; - } else { - $sql = $this->connection->prepare("SELECT COUNT(`id`) AS 'row_count' FROM $table_name WHERE ($conditions) AND (`id` != ?)", ($this->old_object_id ? $this->old_object_id : $this->object_id)); + public function onlyOne( + string $field_name, + mixed $field_value, + string ...$context + ): bool + { + return $this->onlyOneWhere($field_name, $field_value, '', ...$context); + } + + public function onlyOneWhere( + string $field_name, + mixed $field_value, + mixed $where, + string ...$context + ): bool + { + if (empty($field_name)) { + throw new InvalidArgumentException( + sprintf("Value '%s' is not a valid field name", $field_name) + ); } - if ($this->connection->executeFirstCell($sql) > 0) { - if (empty($context)) { - $this->addFieldError($field_name, "Value of '$field_name' needs to be unique"); - } else { - $this->addFieldError($field_name, "Value of '$field_name' needs to be unique in context of " . implode(', ', array_map(function ($field_name) { - return "'$field_name'"; - }, $context))); - } + $field_names = $this->mustGetFieldNames($field_name, $context); + + // No need to check value if it's not the one that we're looking for. + if ($this->field_values[$field_name] !== $field_value) { + return true; + } + + if ($this->connection->executeFirstCell($this->prepareUniquenessValidatorSql($field_names, $where)) === 0) { + return true; + } + + if (empty($context)) { + $this->addFieldError( + $field_name, + sprintf("Only one record with field '%s' set to '%s' is allowed.", $field_name, $field_value) + ); return false; } - return true; + $this->addFieldError( + $field_name, + sprintf( + "Only one record with field '%s' set to '%s' is allowed in context of %s.", + $field_name, + $field_value, + $this->implodeFieldNames($context) + ) + ); + + return false; } - /** - * {@inheritdoc} - */ - public function presentAndUnique($field_name, ...$context) + private function mustGetFieldNames(string $field_name, array $context): array { - if ($this->present($field_name)) { - return $this->unique($field_name, ...$context); + $result = [ + $field_name, + ]; + + if (!empty($context)) { + $result = array_merge($result, $context); } - return false; + // Check if we have existing columns. + foreach ($result as $v) { + if (!array_key_exists($v, $this->field_values)) { + throw new InvalidArgumentException("Field '$v' is not known"); + } + } + + return $result; } - /** - * {@inheritdoc} - */ - public function presentAndUniqueWhere($field_name, $where, ...$context) + private function implodeFieldNames(array $field_names): string { - if ($this->present($field_name)) { - return $this->uniqueWhere($field_name, $where, ...$context); + return implode( + ', ', + array_map( + function ($field_name) { + return "'$field_name'"; + }, + $field_names + ) + ); + } + + private function prepareUniquenessValidatorSql(array $field_names, mixed $where): string + { + $conditions = []; + + if ($where) { + $conditions[] = $this->connection->prepareConditions($where); } - return false; + foreach ($field_names as $v) { + $escaped_field_name = $this->connection->escapeFieldName($v); + + if ($this->field_values[$v] === null) { + $conditions[] = "$escaped_field_name IS NULL"; + } else { + $conditions[] = $this->connection->prepare("$escaped_field_name = ?", $this->field_values[$v]); + } + } + + if (empty($this->object_id)) { + return sprintf( + "SELECT COUNT(`id`) AS 'row_count' FROM %s WHERE %s", + $this->connection->escapeTableName($this->table_name), + implode(' AND ', $conditions) + ); + } + + return $this->connection->prepare( + sprintf( + "SELECT COUNT(`id`) AS 'row_count' FROM %s WHERE `id` != ? AND (%s)", + $this->connection->escapeTableName($this->table_name), + implode(' AND ', $conditions) + ), + $this->old_object_id ?? $this->object_id + ); } - /** - * {@inheritdoc} - */ - public function email($field_name, $allow_null = false) + public function email( + string $field_name, + bool $allow_null = false + ): bool { if (array_key_exists($field_name, $this->field_values)) { if ($this->field_values[$field_name] === null) { @@ -335,7 +400,7 @@ public function email($field_name, $allow_null = false) if (filter_var($this->field_values[$field_name], FILTER_VALIDATE_EMAIL)) { return true; } else { - $this->addFieldError($field_name, "Value of '$field_name' is not a valid email address"); + $this->addFieldError($field_name, "Value of '$field_name' is not a valid email address."); return false; } @@ -344,10 +409,10 @@ public function email($field_name, $allow_null = false) } } - /** - * {@inheritdoc} - */ - public function url($field_name, $allow_null = false) + public function url( + string $field_name, + bool $allow_null = false + ): bool { if (array_key_exists($field_name, $this->field_values)) { if ($this->field_values[$field_name] === null) { @@ -361,7 +426,7 @@ public function url($field_name, $allow_null = false) if (filter_var($this->field_values[$field_name], FILTER_VALIDATE_URL)) { return true; } else { - $this->addFieldError($field_name, "Value of '$field_name' is not a valid URL"); + $this->addFieldError($field_name, "Value of '$field_name' is not a valid URL."); return false; } @@ -370,34 +435,22 @@ public function url($field_name, $allow_null = false) } } - /** - * {@inheritdoc} - */ - public function getErrors() + public function getErrors(): array { return $this->errors; } - /** - * {@inheritdoc} - */ - public function hasErrors() + public function hasErrors(): bool { return count($this->errors) > 0; } - /** - * {@inheritdoc} - */ - public function getFieldErrors($field_name) + public function getFieldErrors(string $field_name): array { - return isset($this->errors[$field_name]) ? $this->errors[$field_name] : []; + return $this->errors[$field_name] ?? []; } - /** - * {@inheritdoc} - */ - public function addFieldError($field_name, $error_message) + public function addFieldError(string $field_name, string $error_message): void { if (empty($this->errors[$field_name])) { $this->errors[$field_name] = []; @@ -406,17 +459,14 @@ public function addFieldError($field_name, $error_message) $this->errors[$field_name][] = $error_message; } - /** - * @return ValidationException - */ - public function createException() + public function createException(): ValidationException { $message = 'Validation failed'; $first_messages = []; $counter = 0; - foreach ($this->errors as $field => $error_messages) { + foreach ($this->errors as $error_messages) { foreach ($error_messages as $error_message) { $first_messages[] = $error_message; ++$counter; diff --git a/src/ValidatorInterface.php b/src/ValidatorInterface.php index 00eb1b8..f26e5f5 100644 --- a/src/ValidatorInterface.php +++ b/src/ValidatorInterface.php @@ -6,139 +6,132 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject; use ActiveCollab\DatabaseObject\Exception\ValidationException; -/** - * @package ActiveCollab\DatabaseObject - */ interface ValidatorInterface { /** - * Check if value of $field_name is present. - * - * @param string $field_name - * @return bool + * Check if value of $field_name is present (not-empty). */ - public function present($field_name); + public function present(string $field_name): bool; - /** - * @param string $field_name - * @param int $reference_value - * @param bool|false $allow_null - * @return bool - */ - public function lowerThan($field_name, $reference_value, $allow_null = false); + public function lowerThan( + string $field_name, + int $reference_value, + bool $allow_null = false + ): bool; - /** - * @param string $field_name - * @param int $reference_value - * @param bool|false $allow_null - * @return bool - */ - public function lowerThanOrEquals($field_name, $reference_value, $allow_null = false); + public function lowerThanOrEquals( + string $field_name, + int $reference_value, + bool $allow_null = false + ): bool; + + public function greaterThan( + string $field_name, + int $reference_value, + bool $allow_null = false + ): bool; + + public function greaterThanOrEquals( + string $field_name, + int $reference_value, + bool $allow_null = false + ): bool; + + public function inArray( + string $field_name, + array $array_of_values, bool $allow_null = false + ): bool; /** - * @param string $field_name - * @param int $reference_value - * @param bool|false $allow_null - * @return bool + * Check if value that we are trying to save is unique in the given context. */ - public function greaterThan($field_name, $reference_value, $allow_null = false); + public function unique(string $field_name, string ...$context): bool; /** - * @param string $field_name - * @param int $reference_value - * @param bool|false $allow_null - * @return bool + * Check if value that we are trying to save is unique in the given context, with extra filtering. */ - public function greaterThanOrEquals($field_name, $reference_value, $allow_null = false); + public function uniqueWhere( + string $field_name, + mixed $where, + string ...$context + ): bool; /** - * @param string $field_name - * @param array $array_of_values - * @param bool|false $allow_null - * @return bool + * Field value needs to be present and unique. */ - public function inArray($field_name, array $array_of_values, $allow_null = false); + public function presentAndUnique(string $field_name, string ...$context): bool; /** - * @param string $field_name - * @param string[] $context - * @return bool + * Present and unique, with the given condition. */ - public function unique($field_name, ...$context); + public function presentAndUniqueWhere( + string $field_name, + mixed $where, + string ...$context + ): bool; /** - * Check if value that we are trying to save is unique in the given context. + * Make sure that that only one record with the given value in the given context exists. * - * @param string $field_name - * @param array|string $where - * @param string[] $context + * Note: Difference with unique() validation is that there can other non-unique values, as long as there's not more + * than one record with the given value. */ - public function uniqueWhere($field_name, $where, ...$context); + public function onlyOne( + string $field_name, + mixed $field_value, + string ...$context + ): bool; /** - * Field value needs to be present and unique. - * - * @param string $field_name - * @param string[] $context - * @return bool + * Make sure that that only one record with the given value in the given context exists, with extra filtering. */ - public function presentAndUnique($field_name, ...$context); + public function onlyOneWhere( + string $field_name, + mixed $field_value, + mixed $where, + string ...$context + ): bool; /** - * Present and unique, with the given condition. - * - * @param string $field_name - * @param array|string $where - * @param string[] $context - * @return bool + * Validate email address value. */ - public function presentAndUniqueWhere($field_name, $where, ...$context); + public function email( + string $field_name, + bool $allow_null = false + ): bool; /** - * Validate email address value. - * - * @param string $field_name - * @param bool|false $allow_null - * @return bool + * Validate URL value. */ - public function email($field_name, $allow_null = false); + public function url( + string $field_name, + bool $allow_null = false + ): bool; /** * Return array of validation messages, indexed by field name. - * - * @return array */ - public function getErrors(); + public function getErrors(): array; /** * Return true if there are error. - * - * @return bool */ - public function hasErrors(); + public function hasErrors(): bool; /** * Return field errors. - * - * @param string $field_name - * @return array */ - public function getFieldErrors($field_name); + public function getFieldErrors(string $field_name): array; /** * Report an error for the given field. - * - * @param string $field_name - * @param string $error_message - */ - public function addFieldError($field_name, $error_message); - - /** - * @return ValidationException */ - public function createException(); + public function addFieldError(string $field_name, string $error_message): void; + public function createException(): ValidationException; } diff --git a/test/src/AutoloaderTest.php b/test/src/AutoloaderTest.php index 6cc45a1..01077b3 100644 --- a/test/src/AutoloaderTest.php +++ b/test/src/AutoloaderTest.php @@ -6,18 +6,14 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseObject\Test\Base\TestCase; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class AutoloaderTest extends TestCase { - /** - * Test if classes are properly loaded. - */ public function testAutoloader() { $this->assertTrue(class_exists('\ActiveCollab\DatabaseObject\Entity\Entity')); diff --git a/test/src/Base/TestCase.php b/test/src/Base/TestCase.php index eb11766..3964682 100644 --- a/test/src/Base/TestCase.php +++ b/test/src/Base/TestCase.php @@ -6,67 +6,63 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test\Base; -use ActiveCollab\DatabaseConnection\Connection; use ActiveCollab\DatabaseConnection\Connection\MysqliConnection; +use ActiveCollab\DatabaseConnection\ConnectionInterface; use ActiveCollab\DatabaseObject\Pool; +use ActiveCollab\DatabaseObject\PoolInterface; use Monolog\Handler\TestHandler; use Monolog\Logger; use mysqli; +use PHPUnit\Framework\MockObject\MockObject; use Psr\Log\LoggerInterface; +use PHPUnit\Framework\TestCase as BaseTestCase; +use RuntimeException; -/** - * @package ActiveCollab\DatabaseObject\Test\Base - */ -abstract class TestCase extends \PHPUnit_Framework_TestCase +abstract class TestCase extends BaseTestCase { - /** - * @var mysqli - */ - protected $link; - - /** - * @var Connection - */ - protected $connection; - - /** - * @var Pool - */ - protected $pool; - - /** - * @var LoggerInterface - */ - protected $logger; + protected mysqli $link; + protected ConnectionInterface $connection; + protected PoolInterface $pool; + protected LoggerInterface $logger; - public function setUp() + public function setUp(): void { parent::setUp(); - $this->link = new \MySQLi('localhost', 'root', '', 'activecollab_database_object_test'); + $this->link = new \MySQLi( + 'localhost', + 'root', + $this->getValidMySqlPassword(), + 'activecollab_database_object_test' + ); if ($this->link->connect_error) { - throw new \RuntimeException('Failed to connect to database. MySQL said: ' . $this->link->connect_error); + throw new RuntimeException('Failed to connect to database. MySQL said: ' . $this->link->connect_error); } + /** @var LoggerInterface|MockObject $logger */ + $logger = $this->createMock(LoggerInterface::class); + $this->connection = new MysqliConnection($this->link); - $this->pool = new Pool($this->connection); + $this->pool = new Pool($this->connection, $logger); $this->logger = new Logger('DatabaseObject test'); $this->logger->pushHandler(new TestHandler()); } - /** - * Tear down test environment. - */ - public function tearDown() + public function tearDown(): void { - $this->connection = null; - $this->pool = null; $this->link->close(); parent::tearDown(); } + + protected function getValidMySqlPassword(): string + { + return (string) getenv('DATABASE_CONNECTION_TEST_PASSWORD'); + } } diff --git a/test/src/Base/WritersTypeTestCase.php b/test/src/Base/WritersTypeTestCase.php index f91e697..0d179f8 100644 --- a/test/src/Base/WritersTypeTestCase.php +++ b/test/src/Base/WritersTypeTestCase.php @@ -11,15 +11,9 @@ use ActiveCollab\DatabaseObject\Test\Fixtures\Writers\Writer; use ActiveCollab\DateValue\DateValue; -/** - * @package ActiveCollab\DatabaseObject\Test\Base - */ abstract class WritersTypeTestCase extends TestCase { - /** - * Set up test environment. - */ - public function setUp() + public function setUp(): void { parent::setUp(); @@ -53,10 +47,7 @@ public function setUp() $this->assertTrue($this->pool->isTypeRegistered(Writer::class)); } - /** - * Tear down test environment. - */ - public function tearDown() + public function tearDown(): void { if ($this->connection->tableExists('writers')) { $this->connection->dropTable('writers'); diff --git a/test/src/ContainerPropagatesToFinderTest.php b/test/src/ContainerPropagatesToFinderTest.php index b8330ec..b0036c0 100644 --- a/test/src/ContainerPropagatesToFinderTest.php +++ b/test/src/ContainerPropagatesToFinderTest.php @@ -6,43 +6,41 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseObject\Finder; use ActiveCollab\DatabaseObject\Test\Base\TestCase; -use ActiveCollab\DatabaseObject\Test\Fixtures\Container; use ActiveCollab\DatabaseObject\Test\Fixtures\Writers\Writer; +use Psr\Container\ContainerInterface; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class ContainerPropagatesToFinderTest extends TestCase { - /** - * Set up test environment. - */ - public function setUp() + public function setUp(): void { parent::setUp(); - $container = new Container(['dependency' => 'it works!']); - - $this->pool->setContainer($container); - $this->assertTrue($this->pool->hasContainer()); - $this->assertInstanceOf(Container::class, $this->pool->getContainer()); - $this->pool->registerType(Writer::class); } /** - * Test if container propages to finder. + * Test if container propagates to finder. */ - public function testCustomFinderRecivesContainer() + public function testCustomFinderReceivesContainer() { + $container = $this->createMock(ContainerInterface::class); + $container + ->expects($this->once()) + ->method('has') + ->with('dependency') + ->willReturn(true); + + $this->pool->setContainer($container); + /** @var Finder $finder */ $finder = $this->pool->find(Writer::class); - $this->assertInstanceOf(Container::class, $finder->getContainer()); $this->assertTrue($finder->getContainer()->has('dependency')); } @@ -51,15 +49,26 @@ public function testCustomFinderRecivesContainer() */ public function testCustomFinderInstantination() { + $container = $this->createMock(ContainerInterface::class); + $container + ->expects($this->once()) + ->method('has') + ->with('dependency') + ->willReturn(true); + $container + ->expects($this->once()) + ->method('get') + ->with('dependency') + ->willReturn('it works!'); + + $this->pool->setContainer($container); + /** @var Finder $finder */ $finder = $this->pool->find(Writer::class); $this->assertInstanceOf(Finder::class, $finder); - if (isset($finder->dependency)) { - $this->assertEquals('it works!', $finder->dependency); - } else { - $this->fail('Dependency property not set in Finder'); - } + $this->assertTrue(isset($finder->dependency)); + $this->assertEquals('it works!', $finder->dependency); } } diff --git a/test/src/ContainerPropagatesToObjectTest.php b/test/src/ContainerPropagatesToObjectTest.php index 17703ba..cc6e3e9 100644 --- a/test/src/ContainerPropagatesToObjectTest.php +++ b/test/src/ContainerPropagatesToObjectTest.php @@ -6,38 +6,36 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseConnection\Result\ResultInterface; use ActiveCollab\DatabaseObject\Test\Base\WritersTypeTestCase; -use ActiveCollab\DatabaseObject\Test\Fixtures\Container; use ActiveCollab\DatabaseObject\Test\Fixtures\Writers\Writer; +use Psr\Container\ContainerInterface; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class ContainerPropagatesToObjectTest extends WritersTypeTestCase { - /** - * Set up test environment. - */ - public function setUp() + public function setUp(): void { parent::setUp(); - $container = new Container(['is_special' => true]); + $container = $this->createMock(ContainerInterface::class); + $container + ->expects($this->once()) + ->method('get') + ->with('is_special') + ->willReturn(true); $this->pool->setContainer($container); - $this->assertTrue($this->pool->hasContainer()); - $this->assertInstanceOf(Container::class, $this->pool->getContainer()); } /** - * Test instantination via getById() method. + * Test instantiation via getById() method. */ public function testGetByIdInstantination() { - /** @var Writer $special_writer */ $special_writer = $this->pool->getById(Writer::class, 1); $this->assertInstanceOf(Writer::class, $special_writer); @@ -45,6 +43,16 @@ public function testGetByIdInstantination() $this->assertTrue($special_writer->is_special); } + public function testGetFirstByInstantination() + { + /** @var Writer $special_writer */ + $special_writer = $this->pool->getFirstBy(Writer::class, '`name` = ?', 'Leo Tolstoy'); + + $this->assertInstanceOf(Writer::class, $special_writer); + $this->assertTrue($special_writer->hasContainer()); + $this->assertTrue($special_writer->is_special); + } + /** * Test instantination via finder. */ @@ -63,10 +71,13 @@ public function testFindIdInstantination() public function testInstantinationUsingProducer() { /** @var Writer $special_writer */ - $special_writer = $this->pool->produce(Writer::class, [ - 'name' => 'Special Writer', - 'birthday' => '2013-10-02', - ]); + $special_writer = $this->pool->produce( + Writer::class, + [ + 'name' => 'Special Writer', + 'birthday' => '2013-10-02', + ] + ); $this->assertInstanceOf(Writer::class, $special_writer); $this->assertTrue($special_writer->is_special); diff --git a/test/src/CrudTest.php b/test/src/CrudTest.php index 23e7f4c..bfe5fd2 100644 --- a/test/src/CrudTest.php +++ b/test/src/CrudTest.php @@ -6,16 +6,19 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; +use ActiveCollab\DatabaseObject\Exception\ObjectNotFoundException; +use ActiveCollab\DatabaseObject\Exception\ValidationException; use ActiveCollab\DatabaseObject\Test\Base\WritersTypeTestCase; use ActiveCollab\DatabaseObject\Test\Fixtures\Writers\AwesomeWriter; use ActiveCollab\DatabaseObject\Test\Fixtures\Writers\Writer; use ActiveCollab\DateValue\DateValue; +use InvalidArgumentException; +use LogicException; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class CrudTest extends WritersTypeTestCase { /** @@ -23,26 +26,22 @@ class CrudTest extends WritersTypeTestCase */ public function testNewInstancesGetDefaultFieldValues() { - $unknown_writer = new Writer($this->connection, $this->pool); + $unknown_writer = new Writer($this->connection, $this->pool, $this->logger); $this->assertEquals('Unknown Writer', $unknown_writer->getName()); } - /** - * @expectedException \InvalidArgumentException - */ public function testFieldsWithDefaultValueCantBeNull() { - $unknown_writer = new Writer($this->connection, $this->pool); + $this->expectException(InvalidArgumentException::class); + $unknown_writer = new Writer($this->connection, $this->pool, $this->logger); $unknown_writer->setName(null); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Database row expected - */ public function testCantLoadFromEmptyRow() { - $writer = new Writer($this->connection, $this->pool); + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage("Database row expected"); + $writer = new Writer($this->connection, $this->pool, $this->logger); $writer->loadFromRow([]); } @@ -51,7 +50,7 @@ public function testCantLoadFromEmptyRow() */ public function testIdIsPrimaryKey() { - $unknown_writer = new Writer($this->connection, $this->pool); + $unknown_writer = new Writer($this->connection, $this->pool, $this->logger); $this->assertSame('id', $unknown_writer->getPrimaryKey()); $this->assertTrue($unknown_writer->isPrimaryKey('id')); @@ -73,12 +72,10 @@ public function testGetById() $this->assertSame('1828-09-09', $tolstoy->getBirthday()->format('Y-m-d')); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage ID is expected to be a number larger than 0 - */ public function testGetByIdOnInvalidIdException() { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage("ID is expected to be a number larger than 0"); $this->pool->getById(Writer::class, 0); } @@ -93,11 +90,10 @@ public function testGetByIdForNonExistingRecord() /** * Test if Pool::mustGetById() throws an exception when record was not found. - * - * @expectedException \ActiveCollab\DatabaseObject\Exception\ObjectNotFoundException */ public function testMustGetByIdThrowsAnException() { + $this->expectException(ObjectNotFoundException::class); $this->assertFalse($this->pool->exists(Writer::class, 890)); $this->assertNull($this->pool->mustGetById(Writer::class, 890)); } @@ -117,11 +113,9 @@ public function testSublassingAwareGetById() $this->assertSame('1828-09-09', $tolstoy->getBirthday()->format('Y-m-d')); } - /** - * @expectedException \InvalidArgumentException - */ public function testGetByIdThrowsAnExceptionOnUnregisteredType() { + $this->expectException(InvalidArgumentException::class); $this->pool->getById(DateValue::class, 1); } @@ -130,7 +124,7 @@ public function testGetByIdThrowsAnExceptionOnUnregisteredType() */ public function testCreate() { - $chekhov = new Writer($this->connection, $this->pool); + $chekhov = new Writer($this->connection, $this->pool, $this->logger); $chekhov->setName('Anton Chekhov'); $chekhov->setBirthday(new DateValue('1860-01-29')); @@ -143,13 +137,11 @@ public function testCreate() $this->assertEquals('1860-01-29', $chekhov->getBirthday()->format('Y-m-d')); } - /** - * @expectedException \ActiveCollab\DatabaseObject\Exception\ValidationException - * @expectedExceptionMessage Value of 'birthday' is required - */ public function testExceptionOnInvalidCreate() { - (new Writer($this->connection, $this->pool)) + $this->expectException(ValidationException::class); + $this->expectExceptionMessage("Value of 'birthday' is required"); + (new Writer($this->connection, $this->pool, $this->logger)) ->setName('Anton Chekhov') ->save(); } @@ -184,12 +176,12 @@ public function testModifications() /** @var Writer $tolstoy */ $tolstoy = $this->pool->getById(Writer::class, 1); - $this->assertInternalType('array', $tolstoy->getModifications()); + $this->assertIsArray($tolstoy->getModifications()); $this->assertEmpty($tolstoy->getModifications()); $tolstoy->setName('Lev Nikolayevich Tolstoy')->setBirthday(new DateValue('1828-09-10')); - $this->assertInternalType('array', $tolstoy->getModifications()); + $this->assertIsArray($tolstoy->getModifications()); $this->assertCount(2, $tolstoy->getModifications()); $this->assertEquals('Leo Tolstoy', $tolstoy->getModifications()['name'][0]); @@ -200,7 +192,7 @@ public function testModifications() $tolstoy->save(); - $this->assertInternalType('array', $tolstoy->getModifications()); + $this->assertIsArray($tolstoy->getModifications()); $this->assertEmpty($tolstoy->getModifications()); } @@ -209,7 +201,7 @@ public function testModifications() */ public function testChangeIdToNewRecord() { - $chekhov = new Writer($this->connection, $this->pool); + $chekhov = new Writer($this->connection, $this->pool, $this->logger); $chekhov->setName('Anton Chekhov'); $chekhov->setBirthday(new DateValue('1860-01-29')); @@ -233,12 +225,10 @@ public function testChangeIdToNewRecord() $this->assertEquals(1, $this->connection->executeFirstCell('SELECT COUNT(`id`) AS "row_count" FROM `writers` WHERE `id` = ?', 18)); } - /** - * @expectedException \LogicException - */ public function testChangeIdToExistingRecord() { - $chekhov = new Writer($this->connection, $this->pool); + $this->expectException(LogicException::class); + $chekhov = new Writer($this->connection, $this->pool, $this->logger); $chekhov->setName('Anton Chekhov'); $chekhov->setBirthday(new DateValue('1860-01-29')); @@ -277,7 +267,7 @@ public function testDelete() */ public function testSetAttributeWithEventHandler() { - $writer = new Writer($this->connection, $this->pool); + $writer = new Writer($this->connection, $this->pool, $this->logger); $this->assertNull($writer->custom_attribute_value); $writer->setAttribute('custom_attribute', 13.5); $this->assertSame(13.5, $writer->custom_attribute_value); @@ -288,7 +278,7 @@ public function testSetAttributeWithEventHandler() */ public function testSetAttributeWithSetter() { - $writer = new Writer($this->connection, $this->pool); + $writer = new Writer($this->connection, $this->pool, $this->logger); $this->assertNull($writer->getCustomFieldValue()); $writer->setAttribute('custom_field_value', 12); $this->assertSame(12, $writer->getCustomFieldValue()); @@ -299,7 +289,7 @@ public function testSetAttributeWithSetter() */ public function testSetAttributeIgnoresUnknownAttributes() { - $writer = new Writer($this->connection, $this->pool); + $writer = new Writer($this->connection, $this->pool, $this->logger); $this->assertEquals('protected', $writer->getProtectedCustomFieldValue()); $writer->setAttribute('protected_custom_field_value', 12); $this->assertEquals('protected', $writer->getProtectedCustomFieldValue()); @@ -310,7 +300,7 @@ public function testSetAttributeIgnoresUnknownAttributes() */ public function testUnknownAttributeDoesNotProduceAnError() { - $writer = new Writer($this->connection, $this->pool); + $writer = new Writer($this->connection, $this->pool, $this->logger); $writer->setAttribute('unknown_attribute', 12); } } diff --git a/test/src/DefaultProducerTest.php b/test/src/DefaultProducerTest.php index 66d528f..5464139 100644 --- a/test/src/DefaultProducerTest.php +++ b/test/src/DefaultProducerTest.php @@ -13,6 +13,7 @@ use ActiveCollab\DatabaseObject\Test\Base\TestCase; use ActiveCollab\DatabaseObject\Test\Fixtures\CustomProducer; use ActiveCollab\DatabaseObject\Validator; +use InvalidArgumentException; /** * @package ActiveCollab\DatabaseObject\Test @@ -27,7 +28,7 @@ public function testDefaultProducer() public function testDefaultProducerCanBeSet() { $this->assertInstanceOf(Producer::class, $this->pool->getDefaultProducer()); - $this->pool->setDefaultProducer(new CustomProducer($this->connection, $this->pool)); + $this->pool->setDefaultProducer(new CustomProducer($this->connection, $this->pool, $this->logger)); $this->assertInstanceOf(CustomProducer::class, $this->pool->getDefaultProducer()); } @@ -38,21 +39,17 @@ public function testCustomProducerCanBeSetByClassName() $this->assertInstanceOf(CustomProducer::class, $this->pool->getDefaultProducer()); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Producer class not found. - */ public function testUnknownClassCantBeSetAsDefaultProducer() { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage("Producer class not found."); $this->pool->setDefaultProducerClass('Unknown class'); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Producer class does not implement producer interface. - */ public function testDefaultProducerClassNeedsToImlementProducerInterface() { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage("Producer class does not implement producer interface."); $this->pool->setDefaultProducerClass(Validator::class); } } diff --git a/test/src/EmailValidatorTest.php b/test/src/EmailValidatorTest.php index 2135c03..d8caf58 100644 --- a/test/src/EmailValidatorTest.php +++ b/test/src/EmailValidatorTest.php @@ -20,7 +20,7 @@ class EmailValidatorTest extends TestCase /** * Set up test environment. */ - public function setUp() + public function setUp(): void { parent::setUp(); @@ -42,7 +42,7 @@ public function testValidEmailAddressPassesValidation() $email_errors = $validator->getFieldErrors('email'); - $this->assertInternalType('array', $email_errors); + $this->assertIsArray($email_errors); $this->assertCount(0, $email_errors); } @@ -60,7 +60,7 @@ public function testInvalidEmailAddressFailsValidation() $email_errors = $validator->getFieldErrors('email'); - $this->assertInternalType('array', $email_errors); + $this->assertIsArray($email_errors); $this->assertCount(1, $email_errors); } @@ -78,7 +78,7 @@ public function testNullPassesValidationWhenAllowed() $email_errors = $validator->getFieldErrors('email'); - $this->assertInternalType('array', $email_errors); + $this->assertIsArray($email_errors); $this->assertCount(0, $email_errors); } @@ -96,7 +96,7 @@ public function testNullFailsValidationWhenNotAllowed() $email_errors = $validator->getFieldErrors('email'); - $this->assertInternalType('array', $email_errors); + $this->assertIsArray($email_errors); $this->assertCount(1, $email_errors); } } diff --git a/test/src/EntityCopyTest.php b/test/src/EntityCopyTest.php index 1966eb1..5f8d424 100644 --- a/test/src/EntityCopyTest.php +++ b/test/src/EntityCopyTest.php @@ -6,6 +6,8 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseObject\Entity\EntityInterface; @@ -14,9 +16,6 @@ use ActiveCollab\DateValue\DateTimeValueInterface; use ActiveCollab\DateValue\DateValueInterface; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class EntityCopyTest extends WritersTypeTestCase { /** @@ -27,7 +26,7 @@ class EntityCopyTest extends WritersTypeTestCase /** * {@inheritdoc} */ - public function setUp() + public function setUp(): void { parent::setUp(); @@ -43,7 +42,7 @@ public function testCopyWithSave() $this->assertTrue($writer_copy->isLoaded()); $this->assertNotEquals($this->writer->getId(), $writer_copy->getId()); - foreach ($writer_copy->getFields() as $field) { + foreach ($writer_copy->getEntityFields() as $field) { if ($writer_copy->isPrimaryKey($field)) { continue; } @@ -67,7 +66,7 @@ public function testCopyWithoutSave() $this->assertFalse($writer_copy->isLoaded()); $this->assertEmpty($writer_copy->getId()); - foreach ($writer_copy->getFields() as $field) { + foreach ($writer_copy->getEntityFields() as $field) { if ($writer_copy->isPrimaryKey($field)) { continue; } diff --git a/test/src/EntityIsTest.php b/test/src/EntityIsTest.php index 141b398..6b63e0a 100644 --- a/test/src/EntityIsTest.php +++ b/test/src/EntityIsTest.php @@ -6,15 +6,14 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseObject\Entity\EntityInterface; use ActiveCollab\DatabaseObject\Test\Base\WritersTypeTestCase; use ActiveCollab\DatabaseObject\Test\Fixtures\Writers\Writer; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class EntityIsTest extends WritersTypeTestCase { /** @@ -25,7 +24,7 @@ class EntityIsTest extends WritersTypeTestCase /** * {@inheritdoc} */ - public function setUp() + public function setUp(): void { parent::setUp(); @@ -42,7 +41,7 @@ public function testFailWhenNotAllFieldsAreTheSame() { $field_values = []; - foreach ($this->writer->getFields() as $field_name) { + foreach ($this->writer->getEntityFields() as $field_name) { $field_values[$field_name] = $this->writer->getFieldValue($field_name); } @@ -57,7 +56,7 @@ public function testPassWhenAllFieldsAreTheSame() { $writer_field_values = []; - foreach ($this->writer->getFields() as $field_name) { + foreach ($this->writer->getEntityFields() as $field_name) { $writer_field_values[$field_name] = $this->writer->getFieldValue($field_name); } @@ -65,7 +64,7 @@ public function testPassWhenAllFieldsAreTheSame() $new_writer_field_values = []; - foreach ($new_writer->getFields() as $field_name) { + foreach ($new_writer->getEntityFields() as $field_name) { $new_writer_field_values[$field_name] = $new_writer->getFieldValue($field_name); } diff --git a/test/src/EntityModifyFieldsTest.php b/test/src/EntityModifyFieldsTest.php index 6745402..1639583 100644 --- a/test/src/EntityModifyFieldsTest.php +++ b/test/src/EntityModifyFieldsTest.php @@ -6,15 +6,15 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseObject\Entity\EntityInterface; use ActiveCollab\DatabaseObject\Test\Base\WritersTypeTestCase; use ActiveCollab\DatabaseObject\Test\Fixtures\Writers\Writer; +use InvalidArgumentException; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class EntityModifyFieldsTest extends WritersTypeTestCase { /** @@ -25,7 +25,7 @@ class EntityModifyFieldsTest extends WritersTypeTestCase /** * {@inheritdoc} */ - public function setUp() + public function setUp(): void { parent::setUp(); @@ -33,12 +33,10 @@ public function setUp() $this->assertInstanceOf(Writer::class, $this->writer); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage 'not a field' is not a known field - */ public function testMissingFieldCantBeSet() { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage("'not a field' is not a known field"); $this->writer->setFieldValue('not a field', 'yes, a value'); } diff --git a/test/src/EscapedTypeFieldsTest.php b/test/src/EscapedTypeFieldsTest.php new file mode 100644 index 0000000..06cb368 --- /dev/null +++ b/test/src/EscapedTypeFieldsTest.php @@ -0,0 +1,40 @@ +. All rights reserved. + */ + +declare(strict_types=1); + +namespace ActiveCollab\DatabaseObject\Test; + +use ActiveCollab\DatabaseObject\Test\Base\TestCase; +use ActiveCollab\DatabaseObject\Test\Fixtures\SpatialEntity\Base\SpatialEntity; + +class EscapedTypeFieldsTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + + $this->pool->registerType(SpatialEntity::class); + } + + public function testWillEscapeFieldNames(): void + { + $this->assertSame( + '`spatial_entities`.`id`,`spatial_entities`.`name`,`spatial_entities`.`polygon`', + $this->pool->getEscapedTypeFields(SpatialEntity::class) + ); + } + + public function testWillPrepareTypeSqlReadStatement(): void + { + $this->assertSame( + "`spatial_entities`.`id`,`spatial_entities`.`name`,ST_GEOMFROMTEXT(`spatial_entities`.`polygon`) AS 'polygon'", + $this->pool->getTypeFieldsReadStatement(SpatialEntity::class) + ); + } +} diff --git a/test/src/FindJoinTest.php b/test/src/FindJoinTest.php index a336167..e65b05b 100644 --- a/test/src/FindJoinTest.php +++ b/test/src/FindJoinTest.php @@ -6,21 +6,20 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseConnection\Result\Result; use ActiveCollab\DatabaseObject\Test\Base\WritersTypeTestCase; use ActiveCollab\DatabaseObject\Test\Fixtures\Writers\Writer; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class FindJoinTest extends WritersTypeTestCase { /** * Set up test environment. */ - public function setUp() + public function setUp(): void { parent::setUp(); @@ -45,7 +44,7 @@ public function setUp() /** * Tear down test environment. */ - public function tearDown() + public function tearDown(): void { if ($this->connection->tableExists('writer_groups')) { $this->connection->dropTable('writer_groups'); @@ -122,19 +121,19 @@ public function testFindAllIds() { $ids = $this->pool->find(Writer::class)->orderBy('`id`')->ids(); - $this->assertInternalType('array', $ids); + $this->assertIsArray($ids); $this->assertCount(3, $ids); $this->assertEquals([1, 2, 3], $ids); $ids = $this->pool->find(Writer::class)->orderBy('`id`')->joinTable('writer_groups')->where('`writer_groups`.`group_id` = ?', 1)->ids(); - $this->assertInternalType('array', $ids); + $this->assertIsArray($ids); $this->assertCount(2, $ids); $this->assertEquals([1, 2], $ids); $ids = $this->pool->find(Writer::class)->orderBy('`id`')->joinTable('writer_groups')->where('`writer_groups`.`group_id` = ?', 2)->ids(); - $this->assertInternalType('array', $ids); + $this->assertIsArray($ids); $this->assertCount(1, $ids); $this->assertEquals([3], $ids); } diff --git a/test/src/FindTest.php b/test/src/FindTest.php index ee811f4..5066b13 100644 --- a/test/src/FindTest.php +++ b/test/src/FindTest.php @@ -6,6 +6,8 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseConnection\Result\Result; @@ -14,25 +16,20 @@ use ActiveCollab\DatabaseObject\Test\Base\WritersTypeTestCase; use ActiveCollab\DatabaseObject\Test\Fixtures\Writers\Writer; use ActiveCollab\DateValue\DateValue; +use InvalidArgumentException; +use TypeError; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class FindTest extends WritersTypeTestCase { - /** - * Test count all. - */ public function testCount() { $this->assertEquals(3, $this->pool->count(Writer::class)); } - /** - * @expectedException \InvalidArgumentException - */ public function testCountThrowsAnExceptionOnUnregisteredType() { + $this->expectException(InvalidArgumentException::class); + $this->pool->count(DateValue::class); } @@ -41,7 +38,10 @@ public function testCountThrowsAnExceptionOnUnregisteredType() */ public function testCountWithConditions() { - $this->assertEquals(2, $this->pool->count(Writer::class, ['birthday > ?', new DateValue('1800-01-01')])); + $this->assertEquals( + 2, + $this->pool->count(Writer::class, ['birthday > ?', new DateValue('1800-01-01')]) + ); } /** @@ -99,7 +99,7 @@ public function testFindAllIds() { $ids = $this->pool->find(Writer::class)->ids(); - $this->assertInternalType('array', $ids); + $this->assertIsArray($ids); $this->assertCount(3, $ids); } @@ -110,7 +110,7 @@ public function testFindIdsAlwaysReturnsArray() { $ids = $this->pool->find(Writer::class)->where('id = ?', -1)->ids(); - $this->assertInternalType('array', $ids); + $this->assertIsArray($ids); $this->assertCount(0, $ids); } @@ -122,6 +122,28 @@ public function testCountUsingFinder() $this->assertEquals(3, $this->pool->find(Writer::class)->count()); } + public function testExistsUsingFinder() + { + $this->assertEquals(3, $this->pool->find(Writer::class)->count()); + + $this->assertTrue($this->pool->find(Writer::class)->exists()); + $this->assertFalse($this->pool->find(Writer::class)->existsOne()); + + $this->connection->execute('DELETE FROM `writers` WHERE `name` != ?', 'Leo Tolstoy'); + + $this->assertEquals(1, $this->pool->find(Writer::class)->count()); + + $this->assertTrue($this->pool->find(Writer::class)->exists()); + $this->assertTrue($this->pool->find(Writer::class)->existsOne()); + + $this->connection->execute('DELETE FROM `writers`'); + + $this->assertEquals(0, $this->pool->find(Writer::class)->count()); + + $this->assertFalse($this->pool->find(Writer::class)->exists()); + $this->assertFalse($this->pool->find(Writer::class)->existsOne()); + } + /** * Test find by conditions. */ @@ -141,7 +163,7 @@ public function testFindByConditions() public function testFindByMultipleConditions() { $finder_1 = $this->pool->find(Writer::class)->where('`birthday` > ?', '1800-01-01'); - $this->assertContains("WHERE `birthday` > '1800-01-01'", (string) $finder_1); + $this->assertStringContainsString("WHERE `birthday` > '1800-01-01'", (string) $finder_1); /* @var Writer[] $should_be_fyodor */ $should_be_fyodor_and_leo = $finder_1->all(); @@ -153,7 +175,7 @@ public function testFindByMultipleConditions() ->where('`birthday` > ?', '1800-01-01') ->where('`birthday` < ?', '1825-01-01'); - $this->assertContains("WHERE (`birthday` > '1800-01-01') AND (`birthday` < '1825-01-01')", (string) $finder_2); + $this->assertStringContainsString("WHERE (`birthday` > '1800-01-01') AND (`birthday` < '1825-01-01')", (string) $finder_2); /** @var Writer[] $should_be_fyodor */ $should_be_fyodor = $finder_2->all(); @@ -165,11 +187,10 @@ public function testFindByMultipleConditions() $this->assertEquals('Fyodor Dostoyevsky', $should_be_fyodor[0]->getName()); } - /** - * @expectedException \InvalidArgumentException - */ public function testConditionsPatternNeedsToBeString() { + $this->expectException(TypeError::class); + $this->pool->find(Writer::class)->where(['`name` LIKE ?', '%Leo%']); } @@ -188,7 +209,7 @@ public function testFindIdsByCondition() { $ids = $this->pool->find(Writer::class)->where('`name` LIKE ?', '%Leo%')->ids(); - $this->assertInternalType('array', $ids); + $this->assertIsArray($ids); $this->assertCount(1, $ids); $this->assertSame(1, $ids[0]); } @@ -234,27 +255,21 @@ public function testHydratedObjectsAreFullyFunctional() $this->assertEquals('Lev Nikolayevich Tolstoy', $should_be_leo->getName()); } - /** - * @expectedException \InvalidArgumentException - */ public function testFindBySqlRequiresType() { + $this->expectException(InvalidArgumentException::class); $this->pool->findBySql('', 'SELECT * FROM `writers` ORDER BY `name`'); } - /** - * @expectedException \InvalidArgumentException - */ public function testFindBySqlRequiresRegisteredType() { + $this->expectException(InvalidArgumentException::class); $this->pool->findBySql(DateValue::class, 'SELECT * FROM `writers` ORDER BY `name`'); } - /** - * @expectedException \InvalidArgumentException - */ public function testFindBySqlRequiresSqlStatement() { + $this->expectException(InvalidArgumentException::class); $this->pool->findBySql(Writer::class, ''); } diff --git a/test/src/FinderFactoryTest.php b/test/src/FinderFactoryTest.php index c4d6144..f9ab4f9 100644 --- a/test/src/FinderFactoryTest.php +++ b/test/src/FinderFactoryTest.php @@ -21,7 +21,8 @@ public function testFinderFactoryProducesFinder() { $finder = (new FinderFactory( $this->connection, - $this->pool + $this->pool, + $this->logger ))->produceFinder(Writer::class); $this->assertInstanceOf(FinderInterface::class, $finder); @@ -32,12 +33,13 @@ public function testFinderFactoryCanSetWhere() { $finder = (new FinderFactory( $this->connection, - $this->pool + $this->pool, + $this->logger ))->produceFinder(Writer::class, '`name` = ?', 'Leo Tolstoy'); $this->assertInstanceOf(FinderInterface::class, $finder); $this->assertSame(Writer::class, $finder->getType()); - $this->assertContains("`name` = 'Leo Tolstoy'", (string) $finder); + $this->assertStringContainsString("`name` = 'Leo Tolstoy'", (string) $finder); } } diff --git a/test/src/Fixtures/Container.php b/test/src/Fixtures/Container.php deleted file mode 100644 index c8e8e12..0000000 --- a/test/src/Fixtures/Container.php +++ /dev/null @@ -1,49 +0,0 @@ -. All rights reserved. - */ - -namespace ActiveCollab\DatabaseObject\Test\Fixtures; - -use Interop\Container\ContainerInterface; -use InvalidArgumentException; - -/** - * @package ActiveCollab\DatabaseObject\Test\Fixtures - */ -class Container extends \Pimple\Container implements ContainerInterface -{ - /** - * Finds an entry of the container by its identifier and returns it. - * - * @param string $id Identifier of the entry to look for - * - * @throws InvalidArgumentException No entry was found for this identifier - * - * @return mixed Entry - */ - public function get($id) - { - if (!$this->offsetExists($id)) { - throw new InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id)); - } - - return $this->offsetGet($id); - } - - /** - * Returns true if the container can return an entry for the given identifier. - * Returns false otherwise. - * - * @param string $id Identifier of the entry to look for - * - * @return bool - */ - public function has($id) - { - return $this->offsetExists($id); - } -} diff --git a/test/src/Fixtures/CustomObject/CustomObjectPool.php b/test/src/Fixtures/CustomObject/CustomObjectPool.php index 83f7fa6..7212bf0 100644 --- a/test/src/Fixtures/CustomObject/CustomObjectPool.php +++ b/test/src/Fixtures/CustomObject/CustomObjectPool.php @@ -6,13 +6,12 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test\Fixtures\CustomObject; use ActiveCollab\DatabaseObject\Pool; -/** - * @package ActiveCollab\DatabaseObject\Test\Fixtures\CustomObject - */ class CustomObjectPool extends Pool { } diff --git a/test/src/Fixtures/CustomProducer.php b/test/src/Fixtures/CustomProducer.php index a05ffbb..48a9cdd 100644 --- a/test/src/Fixtures/CustomProducer.php +++ b/test/src/Fixtures/CustomProducer.php @@ -6,26 +6,21 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test\Fixtures; use ActiveCollab\DatabaseObject\Entity\EntityInterface; use ActiveCollab\DatabaseObject\Producer; use ActiveCollab\DatabaseObject\Test\Fixtures\Writers\Writer; -/** - * @package ActiveCollab\DatabaseObject\Test\Fixtures\Users - */ class CustomProducer extends Producer { - /** - * Produce new instance of $type. - * - * @param string $type - * @param array|null $attributes - * @param bool $save - * @return EntityInterface - */ - public function &produce($type, array $attributes = null, $save = true) + public function produce( + string $type, + array $attributes = null, + bool $save = true, + ): EntityInterface { $object = parent::produce($type, $attributes, $save); @@ -36,15 +31,11 @@ public function &produce($type, array $attributes = null, $save = true) return $object; } - /** - * Update an instance. - * - * @param EntityInterface $instance - * @param array|null $attributes - * @param bool $save - * @return EntityInterface - */ - public function &modify(EntityInterface &$instance, array $attributes = null, $save = true) + public function modify( + EntityInterface $instance, + array $attributes = null, + bool $save = true, + ): EntityInterface { $instance = parent::modify($instance, $attributes, $save); @@ -55,14 +46,10 @@ public function &modify(EntityInterface &$instance, array $attributes = null, $s return $instance; } - /** - * Scrap an instance (move it to trash, if object can be trashed, or delete it). - * - * @param EntityInterface $instance - * @param bool $force_delete - * @return EntityInterface - */ - public function &scrap(EntityInterface &$instance, $force_delete = false) + public function scrap( + EntityInterface $instance, + bool $force_delete = false, + ): EntityInterface { $instance = parent::scrap($instance, $force_delete); diff --git a/test/src/Fixtures/SpatialEntity/Base/SpatialEntity.php b/test/src/Fixtures/SpatialEntity/Base/SpatialEntity.php new file mode 100644 index 0000000..08d8879 --- /dev/null +++ b/test/src/Fixtures/SpatialEntity/Base/SpatialEntity.php @@ -0,0 +1,230 @@ +. All rights reserved. + */ + +declare(strict_types=1); + +namespace ActiveCollab\DatabaseObject\Test\Fixtures\SpatialEntity\Base; + +use ActiveCollab\DatabaseConnection\Record\ValueCaster; +use ActiveCollab\DatabaseConnection\Record\ValueCasterInterface; +use ActiveCollab\DatabaseObject\Entity\Entity; +use ActiveCollab\DatabaseObject\ValidatorInterface; + +abstract class SpatialEntity extends Entity +{ + /** + * Name of the table where records are stored. + */ + protected string $table_name = 'spatial_entities'; + + /** + * Table fields that are managed by this entity. + */ + protected array $entity_fields = [ + 'id', + 'name', + 'polygon', + ]; + + /** + * Table fields prepared for SELECT SQL query. + */ + protected array $sql_read_statements = [ + '`spatial_entities`.`id`', + '`spatial_entities`.`name`', + 'ST_GEOMFROMTEXT(`spatial_entities`.`polygon`) AS \'polygon\'', + ]; + + /** + * Generated fields that are loaded, but not managed by the entity. + * + * @var array + */ + protected array $generated_entity_fields = []; + + /** + * List of default field values. + */ + protected array $default_entity_field_values = []; + + /** + * Return value of name field. + * + * @return string + */ + public function getName() + { + return $this->getFieldValue('name'); + } + + /** + * Set value of name field. + * + * @param string $value + * @return $this + */ + public function &setName($value) + { + $this->setFieldValue('name', $value); + + return $this; + } + + /** + * Return value of day field. + * + * @return \ActiveCollab\DateValue\DateValueInterface|null + */ + public function getDay() + { + return $this->getFieldValue('day'); + } + + /** + * Set value of day field. + * + * @param \ActiveCollab\DateValue\DateValueInterface|null $value + * @return $this + */ + public function &setDay($value) + { + $this->setFieldValue('day', $value); + + return $this; + } + + /** + * Return value of is_used_on_day field. + * + * @return bool + */ + public function isUsedOnDay() + { + return $this->getFieldValue('is_used_on_day'); + } + + /** + * Return value of is_used_on_day field. + * + * @return bool + * @deprecated use isUsedOnDay() + */ + public function getIsUsedOnDay() + { + return $this->getFieldValue('is_used_on_day'); + } + + /** + * Return value of plan_name field. + * + * @return string + */ + public function getPlanName() + { + return $this->getFieldValue('plan_name'); + } + + /** + * Return value of number_of_users field. + * + * @return int + */ + public function getNumberOfUsers() + { + return $this->getFieldValue('number_of_users'); + } + + /** + * Return value of stats field. + * + * @return mixed + */ + public function getStats() + { + return $this->getFieldValue('stats'); + } + + /** + * Set value of stats field. + * + * @param mixed $value + * @return $this + */ + public function &setStats($value) + { + $this->setFieldValue('stats', $value); + + return $this; + } + + public function getFieldValue(string $field, mixed $default = null): mixed + { + $value = parent::getFieldValue($field, $default); + + if ($value === null) { + return null; + } else { + switch ($field) { + case 'stats': + return json_decode($value, true); + } + + return $value; + } + } + + public function setFieldValue(string $field, mixed $value): static + { + if ($value === null) { + parent::setFieldValue($field, null); + } else { + switch ($field) { + case 'id': + case 'name': + return parent::setFieldValue($field, (string) $value); + case 'day': + return parent::setFieldValue($field, $this->getDateTimeValueInstanceFrom($value)); + case 'stats': + return parent::setFieldValue($field, $this->isLoading() ? $value : json_encode($value)); + default: + if ($this->isLoading()) { + return parent::setFieldValue($field, $value); + } else { + if ($this->isGeneratedField($field)) { + throw new \LogicException("Generated field $field cannot be set by directly assigning a value"); + } else { + throw new \InvalidArgumentException("Field $field does not exist in this table"); + } + } + } + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function jsonSerialize() + { + return array_merge(parent::jsonSerialize(), [ + 'account_id' => $this->getAccountId(), + 'day' => $this->getDay(), + 'is_used_on_day' => $this->getIsUsedOnDay(), + 'stats' => $this->getStats(), + ]); + } + + public function validate(ValidatorInterface $validator): ValidatorInterface + { + $validator->present('day'); + $validator->present('account_id'); + + return parent::validate($validator); + } +} diff --git a/test/src/Fixtures/SpatialEntity/SpatialEntity.php b/test/src/Fixtures/SpatialEntity/SpatialEntity.php new file mode 100644 index 0000000..4f6628f --- /dev/null +++ b/test/src/Fixtures/SpatialEntity/SpatialEntity.php @@ -0,0 +1,15 @@ +. All rights reserved. + */ + +declare(strict_types=1); + +namespace ActiveCollab\DatabaseObject\Test\Fixtures\SpatialEntity; + +class SpatialEntity extends Base\SpatialEntity +{ +} diff --git a/test/src/Fixtures/StatSnapshots/Base/StatsSnapshot.php b/test/src/Fixtures/StatSnapshots/Base/StatsSnapshot.php index 2f4fc06..a117cc7 100644 --- a/test/src/Fixtures/StatSnapshots/Base/StatsSnapshot.php +++ b/test/src/Fixtures/StatSnapshots/Base/StatsSnapshot.php @@ -6,6 +6,8 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test\Fixtures\StatSnapshots\Base; use ActiveCollab\DatabaseConnection\Record\ValueCaster; @@ -13,49 +15,53 @@ use ActiveCollab\DatabaseObject\Entity\Entity; use ActiveCollab\DatabaseObject\ValidatorInterface; -/** - * @package ActiveCollab\DatabaseObject\Test\Fixtures\StatSnapshots\Base - */ abstract class StatsSnapshot extends Entity { /** * Name of the table where records are stored. - * - * @var string */ - protected $table_name = 'stats_snapshots'; + protected string $table_name = 'stats_snapshots'; /** * Table fields that are managed by this entity. * * @var array */ - protected $fields = ['id', 'account_id', 'day', 'stats']; + protected array $entity_fields = ['id', 'account_id', 'day', 'stats']; /** - * Generated fields that are loaded, but not managed by the entity. - * - * @var array + * Table fields prepared for SELECT SQL query. */ - protected $generated_fields = ['is_used_on_day', 'plan_name', 'number_of_users']; + protected array $sql_read_statements = [ + '`stats_snapshots`.`id`', + '`stats_snapshots`.`account_id`', + '`stats_snapshots`.`day`', + '`stats_snapshots`.`stats`', + ]; /** - * List of default field values. + * Generated fields that are loaded, but not managed by the entity. * * @var array */ - protected $default_field_values = []; + protected array $generated_entity_fields = ['is_used_on_day', 'plan_name', 'number_of_users']; /** - * {@inheritdoc} + * List of default field values. */ - protected function configure() + protected array $default_entity_field_values = []; + + protected function configure(): void { - $this->setGeneratedFieldsValueCaster(new ValueCaster([ - 'is_used_on_day' => ValueCasterInterface::CAST_BOOL, - 'plan_name' => ValueCasterInterface::CAST_STRING, - 'number_of_users' => ValueCasterInterface::CAST_INT, - ])); + $this->setGeneratedFieldsValueCaster( + new ValueCaster( + [ + 'is_used_on_day' => ValueCasterInterface::CAST_BOOL, + 'plan_name' => ValueCasterInterface::CAST_STRING, + 'number_of_users' => ValueCasterInterface::CAST_INT, + ] + ) + ); } /** @@ -168,10 +174,7 @@ public function &setStats($value) return $this; } - /** - * {@inheritdoc} - */ - public function getFieldValue($field, $default = null) + public function getFieldValue(string $field, mixed $default = null): mixed { $value = parent::getFieldValue($field, $default); @@ -187,30 +190,27 @@ public function getFieldValue($field, $default = null) } } - /** - * {@inheritdoc} - */ - public function &setFieldValue($name, $value) + public function setFieldValue(string $field, mixed $value): static { if ($value === null) { - parent::setFieldValue($name, null); + parent::setFieldValue($field, null); } else { - switch ($name) { + switch ($field) { case 'id': case 'account_id': - return parent::setFieldValue($name, (int) $value); + return parent::setFieldValue($field, (int) $value); case 'day': - return parent::setFieldValue($name, $this->getDateTimeValueInstanceFrom($value)); + return parent::setFieldValue($field, $this->getDateTimeValueInstanceFrom($value)); case 'stats': - return parent::setFieldValue($name, $this->isLoading() ? $value : json_encode($value)); + return parent::setFieldValue($field, $this->isLoading() ? $value : json_encode($value)); default: if ($this->isLoading()) { - return parent::setFieldValue($name, $value); + return parent::setFieldValue($field, $value); } else { - if ($this->isGeneratedField($name)) { - throw new \LogicException("Generated field $name cannot be set by directly assigning a value"); + if ($this->isGeneratedField($field)) { + throw new \LogicException("Generated field $field cannot be set by directly assigning a value"); } else { - throw new \InvalidArgumentException("Field $name does not exist in this table"); + throw new \InvalidArgumentException("Field $field does not exist in this table"); } } } @@ -232,14 +232,11 @@ public function jsonSerialize() ]); } - /** - * {@inheritdoc} - */ - public function validate(ValidatorInterface &$validator) + public function validate(ValidatorInterface $validator): ValidatorInterface { $validator->present('day'); $validator->present('account_id'); - parent::validate($validator); + return parent::validate($validator); } } diff --git a/test/src/Fixtures/StatSnapshots/StatsSnapshot.php b/test/src/Fixtures/StatSnapshots/StatsSnapshot.php index 7a5eeea..04c6ab0 100644 --- a/test/src/Fixtures/StatSnapshots/StatsSnapshot.php +++ b/test/src/Fixtures/StatSnapshots/StatsSnapshot.php @@ -6,11 +6,10 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test\Fixtures\StatSnapshots; -/** - * @package ActiveCollab\Shepherd\Model - */ class StatsSnapshot extends Base\StatsSnapshot { /** diff --git a/test/src/Fixtures/Users/Base/User.php b/test/src/Fixtures/Users/Base/User.php index ffc2bae..b239c34 100644 --- a/test/src/Fixtures/Users/Base/User.php +++ b/test/src/Fixtures/Users/Base/User.php @@ -6,36 +6,44 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test\Fixtures\Users\Base; use ActiveCollab\DatabaseObject\Entity\Entity; use ActiveCollab\DatabaseObject\ValidatorInterface; -/** - * @package ActiveCollab\DatabaseObject\Test\Fixtures\Users\Base - */ abstract class User extends Entity { /** * Name of the table where records are stored. - * - * @var string */ - protected $table_name = 'users'; + protected string $table_name = 'users'; /** * All table fields. * * @var array */ - protected $fields = ['id', 'type', 'first_name', 'last_name', 'email', 'homepage_url', 'password']; + protected array $entity_fields = ['id', 'type', 'first_name', 'last_name', 'email', 'homepage_url', 'password']; + + /** + * Table fields prepared for SELECT SQL query. + */ + protected array $sql_read_statements = [ + '`users`.`id`', + '`users`.`type`', + '`users`.`first_name`', + '`users`.`last_name`', + '`users`.`email`', + '`users`.`homepage_url`', + '`users`.`password`', + ]; /** * List of default field values. - * - * @var array */ - protected $default_field_values = [ + protected array $default_entity_field_values = [ 'type' => 'ActiveCollab\DatabaseObject\Test\Fixtures\Users\User', 'first_name' => '', 'last_name' => '', @@ -181,29 +189,24 @@ public function &setPassword($value) /** * Set value of specific field. - * - * @param string $name - * @param mixed $value - * @return $this - * @throws \InvalidArgumentException */ - public function &setFieldValue($name, $value) + public function setFieldValue(string $field, mixed $value): static { if ($value === null) { - parent::setFieldValue($name, null); + parent::setFieldValue($field, null); } else { - switch ($name) { + switch ($field) { case 'id': - return parent::setFieldValue($name, (int) $value); + return parent::setFieldValue($field, (int) $value); case 'type': case 'first_name': case 'last_name': case 'email': case 'homepage_url': case 'password': - return parent::setFieldValue($name, (string) $value); + return parent::setFieldValue($field, (string) $value); default: - throw new \InvalidArgumentException("Field $name does not exist in this table"); + throw new \InvalidArgumentException("Field $field does not exist in this table"); } } @@ -212,14 +215,12 @@ public function &setFieldValue($name, $value) /** * Validate object properties before object is saved. - * - * @param ValidatorInterface $validator */ - public function validate(ValidatorInterface &$validator) + public function validate(ValidatorInterface $validator): ValidatorInterface { $validator->presentAndUnique('email'); $validator->present('password'); - parent::validate($validator); + return parent::validate($validator); } } diff --git a/test/src/Fixtures/Users/User.php b/test/src/Fixtures/Users/User.php index a22889b..de3f962 100644 --- a/test/src/Fixtures/Users/User.php +++ b/test/src/Fixtures/Users/User.php @@ -6,13 +6,12 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test\Fixtures\Users; use ActiveCollab\DatabaseObject\Test\Fixtures\Users\Base\User as BaseUser; -/** - * @package ActiveCollab\DatabaseObject\Test\Fixtures\Users - */ class User extends BaseUser { } diff --git a/test/src/Fixtures/Writers/AwesomeWriter.php b/test/src/Fixtures/Writers/AwesomeWriter.php index 29c0a9c..4bb671e 100644 --- a/test/src/Fixtures/Writers/AwesomeWriter.php +++ b/test/src/Fixtures/Writers/AwesomeWriter.php @@ -6,11 +6,10 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test\Fixtures\Writers; -/** - * @package ActiveCollab\DatabaseObject\Test\Fixtures\Writers - */ class AwesomeWriter extends Writer { } diff --git a/test/src/Fixtures/Writers/BaseWriter.php b/test/src/Fixtures/Writers/BaseWriter.php index 5fe71a4..d0c27d8 100644 --- a/test/src/Fixtures/Writers/BaseWriter.php +++ b/test/src/Fixtures/Writers/BaseWriter.php @@ -9,47 +9,52 @@ namespace ActiveCollab\DatabaseObject\Test\Fixtures\Writers; use ActiveCollab\DatabaseObject\Entity\Entity; -use ActiveCollab\DatabaseObject\Entity\EntityInterface; use ActiveCollab\DateValue\DateValueInterface; use InvalidArgumentException; -/** - * @package ActiveCollab\DatabaseObject\Test\Fixtures\Writers - */ -abstract class BaseWriter extends Entity implements EntityInterface +abstract class BaseWriter extends Entity implements WriterInterface { /** * Name of the table where records are stored. - * - * @var string */ - protected $table_name = 'writers'; + protected string $table_name = 'writers'; /** * All table fields. * * @var array */ - protected $fields = ['id', 'name', 'birthday', 'created_at', 'updated_at']; + protected array $entity_fields = ['id', 'name', 'birthday', 'created_at', 'updated_at']; + + /** + * Table fields prepared for SELECT SQL query. + */ + protected array $sql_read_statements = [ + '`writers`.`id`', + '`writers`.`name`', + '`writers`.`birthday`', + '`writers`.`created_at`', + '`writers`.`updated_at`', + ]; /** * List of default field values. * * @var array */ - protected $default_field_values = ['name' => 'Unknown Writer']; + protected array $default_entity_field_values = ['name' => 'Unknown Writer']; /** * Name of AI field (if any). * * @var string */ - protected $auto_increment = 'id'; + protected string $auto_increment = 'id'; /** * @var string[] */ - protected $order_by = ['!id']; + protected array $order_by = ['!id']; /** * Return value of name field. @@ -145,32 +150,27 @@ public function &setUpdatedAt($value) /** * Set value of specific field. - * - * @param string $name - * @param mixed $value - * @return mixed - * @throws InvalidArgumentException */ - public function &setFieldValue($name, $value) + public function setFieldValue(string $field, mixed $value): static { if ($value === null) { - parent::setFieldValue($name, null); + parent::setFieldValue($field, null); } else { - switch ($name) { + switch ($field) { case 'id': - parent::setFieldValue($name, (int) $value); + parent::setFieldValue($field, (int) $value); break; case 'name': - parent::setFieldValue($name, (string) $value); + parent::setFieldValue($field, (string) $value); break; case 'birthday': - parent::setFieldValue($name, $this->getDateValueInstanceFrom($value)); + parent::setFieldValue($field, $this->getDateValueInstanceFrom($value)); break; case 'created_at': case 'updated_at': - return parent::setFieldValue($name, $this->getDateTimeValueInstanceFrom($value)); + return parent::setFieldValue($field, $this->getDateTimeValueInstanceFrom($value)); default: - throw new InvalidArgumentException("'$name' is not a known field"); + throw new InvalidArgumentException("'$field' is not a known field"); } } diff --git a/test/src/Fixtures/Writers/Collection.php b/test/src/Fixtures/Writers/Collection.php index 3b9d69c..2073636 100644 --- a/test/src/Fixtures/Writers/Collection.php +++ b/test/src/Fixtures/Writers/Collection.php @@ -6,65 +6,44 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test\Fixtures\Writers; use ActiveCollab\DatabaseObject\Collection\Type; -/** - * @package ActiveCollab\DatabaseObject\Test\Fixtures\Writers - */ class Collection extends Type { - /** - * Return type that this collection manages. - * - * @return string - */ - public function getType() + public function getType(): string { return Writer::class; } - private $is_ready = true; + private bool $is_ready = true; - /** - * {@inheritdoc} - */ - protected function isReady() + protected function isReady(): bool { return $this->is_ready; } /** * Set collection as not ready. - * - * @return $this */ - public function &setAsNotReady() + public function setAsNotReady(): static { $this->is_ready = false; return $this; } - /** - * @var string - */ - private $additional_identifier = 'na'; + private string $additional_identifier = 'na'; - /** - * @return string - */ - protected function getAdditionalIdentifier() + protected function getAdditionalIdentifier(): string { return $this->additional_identifier; } - /** - * @param string $value - * @return $this - */ - public function &setAdditionalIdenfitifier($value) + public function setAdditionalIdentifier(string $value): static { $this->additional_identifier = $value; diff --git a/test/src/Fixtures/Writers/PreconfiguredCollection.php b/test/src/Fixtures/Writers/PreconfiguredCollection.php index 0e00ec0..4303fdf 100644 --- a/test/src/Fixtures/Writers/PreconfiguredCollection.php +++ b/test/src/Fixtures/Writers/PreconfiguredCollection.php @@ -6,29 +6,20 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test\Fixtures\Writers; use ActiveCollab\DatabaseObject\Collection\Type; -/** - * @package ActiveCollab\DatabaseObject\Test\Fixtures\Writers - */ class PreconfiguredCollection extends Type { - /** - * Return type that this collection manages. - * - * @return string - */ - public function getType() + public function getType(): string { return Writer::class; } - /** - * Configure the collection when it is created. - */ - protected function configure() + protected function configure(): void { $this->where('`name` LIKE ?', 'A%')->orderBy('`name`'); } diff --git a/test/src/Fixtures/Writers/Traits/ClassicWriter.php b/test/src/Fixtures/Writers/Traits/ClassicWriter.php index cd1d64d..b3a1b46 100644 --- a/test/src/Fixtures/Writers/Traits/ClassicWriter.php +++ b/test/src/Fixtures/Writers/Traits/ClassicWriter.php @@ -6,21 +6,14 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test\Fixtures\Writers\Traits; -/** - * @package ActiveCollab\DatabaseObject\Test\Fixtures\Writers\Traits - */ trait ClassicWriter { - /** - * @var bool - */ - public $is_classic_writer = false; + public bool $is_classic_writer = false; - /** - * Call when object is created. - */ public function ActiveCollabDatabaseObjectTestFixturesWritersTraitsClassicWriter() { $this->is_classic_writer = true; diff --git a/test/src/Fixtures/Writers/Traits/Russian.php b/test/src/Fixtures/Writers/Traits/Russian.php index 6651ff1..43b964c 100644 --- a/test/src/Fixtures/Writers/Traits/Russian.php +++ b/test/src/Fixtures/Writers/Traits/Russian.php @@ -6,17 +6,13 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test\Fixtures\Writers\Traits; -/** - * @package ActiveCollab\DatabaseObject\Test\Fixtures\Writers\Traits - */ trait Russian { - /** - * @var bool - */ - public $is_russian = false; + public bool $is_russian = false; /** * Call when object is created. diff --git a/test/src/Fixtures/Writers/Writer.php b/test/src/Fixtures/Writers/Writer.php index 93b8baf..fed1eec 100644 --- a/test/src/Fixtures/Writers/Writer.php +++ b/test/src/Fixtures/Writers/Writer.php @@ -6,9 +6,12 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test\Fixtures\Writers; use ActiveCollab\DatabaseConnection\ConnectionInterface; +use ActiveCollab\DatabaseObject\Entity\EntityInterface; use ActiveCollab\DatabaseObject\PoolInterface; use ActiveCollab\DatabaseObject\ScrapInterface; use ActiveCollab\DatabaseObject\Test\Fixtures\Writers\Traits\ClassicWriter; @@ -18,8 +21,6 @@ /** * @property string $is_special - * - * @package ActiveCollab\DatabaseObject\Test\Fixtures\Writers */ class Writer extends BaseWriter implements ScrapInterface { @@ -29,47 +30,33 @@ class Writer extends BaseWriter implements ScrapInterface * @var mixed */ public $custom_attribute_value; + public bool $modified_using_custom_producer = false; + public bool $is_scrapped = false; + public bool $scrapped_using_custom_producer = false; - /** - * @var bool - */ - public $modified_using_custom_producer = false; - - /** - * @var bool - */ - public $is_scrapped = false; - - /** - * @var bool - */ - public $scrapped_using_custom_producer = false; - - /** - * @param ConnectionInterface $connection - * @param PoolInterface $pool - * @param LoggerInterface|null $log - */ - public function __construct(ConnectionInterface &$connection, PoolInterface &$pool, LoggerInterface &$log = null) + public function __construct(ConnectionInterface &$connection, PoolInterface &$pool, LoggerInterface $logger) { - parent::__construct($connection, $pool, $log); - - $this->registerEventHandler('on_set_attribute', function ($attribute, $value) { - if ($attribute == 'custom_attribute') { - $this->custom_attribute_value = $value; - } - }); - - $this->registerEventHandler('on_json_serialize', function (array &$result) { - $result['name'] = $this->getName(); - $result['birthday'] = $this->getBirthday(); - }); + parent::__construct($connection, $pool, $logger); + + $this->registerEventHandler( + 'on_set_attribute', + function ($attribute, $value) { + if ($attribute == 'custom_attribute') { + $this->custom_attribute_value = $value; + } + }, + ); + + $this->registerEventHandler( + 'on_json_serialize', + function (array &$result) { + $result['name'] = $this->getName(); + $result['birthday'] = $this->getBirthday(); + }, + ); } - /** - * {@inheritdoc} - */ - protected function getAttributes() + protected function getAttributes(): array { return array_merge(parent::getAttributes(), ['custom_field_value']); } @@ -133,21 +120,15 @@ public function &setProtectedCustomFieldValue($value) /** * @param ValidatorInterface $validator */ - public function validate(ValidatorInterface &$validator) + public function validate(ValidatorInterface $validator): ValidatorInterface { $validator->present('name'); $validator->present('birthday'); - parent::validate($validator); + return parent::validate($validator); } - /** - * Scrap the object, instead of permanently deleting it. - * - * @param bool|false $bulk - * @return $this - */ - public function &scrap($bulk = false) + public function scrap(bool $bulk = false): EntityInterface { $this->is_scrapped = true; diff --git a/src/ObjectInterface.php b/test/src/Fixtures/Writers/WriterInterface.php similarity index 57% rename from src/ObjectInterface.php rename to test/src/Fixtures/Writers/WriterInterface.php index ccb5442..9ae25d8 100644 --- a/src/ObjectInterface.php +++ b/test/src/Fixtures/Writers/WriterInterface.php @@ -6,14 +6,12 @@ * (c) A51 doo . All rights reserved. */ -namespace ActiveCollab\DatabaseObject; +declare(strict_types=1); + +namespace ActiveCollab\DatabaseObject\Test\Fixtures\Writers; use ActiveCollab\DatabaseObject\Entity\EntityInterface; -/** - * @package ActiveCollab\DatabaseObject - * @deprecated - */ -interface ObjectInterface extends EntityInterface +interface WriterInterface extends EntityInterface { } diff --git a/test/src/GeneratedFieldsTest.php b/test/src/GeneratedFieldsTest.php index f424c93..427bdb0 100644 --- a/test/src/GeneratedFieldsTest.php +++ b/test/src/GeneratedFieldsTest.php @@ -6,6 +6,8 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseObject\Entity\EntityInterface; @@ -14,16 +16,14 @@ use ActiveCollab\DateValue\DateTimeValue; use ActiveCollab\DateValue\DateValue; use ActiveCollab\DateValue\DateValueInterface; +use LogicException; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class GeneratedFieldsTest extends TestCase { /** * {@inheritdoc} */ - public function setUp() + public function setUp(): void { parent::setUp(); @@ -46,7 +46,7 @@ public function setUp() $this->pool->registerType(StatsSnapshot::class); } - public function tearDown() + public function tearDown(): void { $this->connection->dropTable('stats_snapshots'); $this->connection->execute('DROP TRIGGER IF EXISTS `insert_stats_snapshots`'); @@ -64,8 +64,8 @@ public function testFieldsVsGeneratedFieldsChecks() { $snapshot = $this->produceSnapshot(); - $this->assertTrue($snapshot->fieldExists('account_id')); - $this->assertTrue($snapshot->fieldExists('is_used_on_day')); + $this->assertTrue($snapshot->entityFieldExists('account_id')); + $this->assertTrue($snapshot->entityFieldExists('is_used_on_day')); $this->assertFalse($snapshot->generatedFieldExists('account_id')); $this->assertTrue($snapshot->generatedFieldExists('is_used_on_day')); @@ -80,12 +80,10 @@ public function testIsUsedOnDayIsGeneratedField() $this->assertContains('is_used_on_day', $this->pool->getGeneratedTypeFields(StatsSnapshot::class)); } - /** - * @expectedException \LogicException - * @expectedExceptionMessage Generated field is_used_on_day cannot be set by directly assigning a value - */ public function testGeneratedFieldCantBeSetDuringProduction() { + $this->expectException(LogicException::class); + $this->expectExceptionMessage("Generated field is_used_on_day cannot be set by directly assigning a value"); $this->pool->produce(StatsSnapshot::class, [ 'account_id' => 1, 'day' => new DateValue(), @@ -96,12 +94,10 @@ public function testGeneratedFieldCantBeSetDuringProduction() ]); } - /** - * @expectedException \LogicException - * @expectedExceptionMessage Generated field is_used_on_day cannot be set by directly assigning a value - */ public function testGeneratedFieldCantBeSetUsingSetField() { + $this->expectException(LogicException::class); + $this->expectExceptionMessage("Generated field is_used_on_day cannot be set by directly assigning a value"); $this->produceSnapshot()->setFieldValue('is_used_on_day', true); } @@ -114,12 +110,16 @@ public function testPoolUsesTheCorrectListOfGeneratedFields() public function testPoolIncludesGeneratedFieldsInTypeFieldsList() { $generated_type_fields = $this->pool->getGeneratedTypeFields(StatsSnapshot::class); - $this->assertInternalType('array', $generated_type_fields); + $this->assertIsArray($generated_type_fields); $this->assertContains('is_used_on_day', $generated_type_fields); $escaped_type_fields = $this->pool->getEscapedTypeFields(StatsSnapshot::class); - $this->assertInternalType('string', $escaped_type_fields); - $this->assertContains('is_used_on_day', $escaped_type_fields); + $this->assertIsString($escaped_type_fields); + $this->assertStringContainsString('is_used_on_day', $escaped_type_fields); + + $type_fields_read_statement = $this->pool->getTypeFieldsReadStatement(StatsSnapshot::class); + $this->assertIsString($type_fields_read_statement); + $this->assertStringContainsString('is_used_on_day', $type_fields_read_statement); } public function testGeneratedFieldsAreHydrated() @@ -134,7 +134,7 @@ public function testGeneratedFieldsAreHydrated() $this->assertSame(1, $insert_id); $row = $this->connection->executeFirstRow('SELECT * FROM stats_snapshots WHERE id = ?', $insert_id); - $this->assertInternalType('array', $row); + $this->assertIsArray($row); $this->assertArrayHasKey('is_used_on_day', $row); $this->assertTrue($row['is_used_on_day']); diff --git a/test/src/GreaterThanOrEqualsValidatorTest.php b/test/src/GreaterThanOrEqualsValidatorTest.php index 3d2c18e..cbeb2c8 100644 --- a/test/src/GreaterThanOrEqualsValidatorTest.php +++ b/test/src/GreaterThanOrEqualsValidatorTest.php @@ -6,15 +6,15 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseObject\Test\Base\TestCase; use ActiveCollab\DatabaseObject\Test\Fixtures\Users\User; use ActiveCollab\DatabaseObject\Validator; +use InvalidArgumentException; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class GreaterThanOrEqualsValidatorTest extends TestCase { /** @@ -25,7 +25,7 @@ class GreaterThanOrEqualsValidatorTest extends TestCase /** * Set up test environment. */ - public function setUp() + public function setUp(): void { parent::setUp(); @@ -33,12 +33,10 @@ public function setUp() $this->assertTrue($this->pool->isTypeRegistered(User::class)); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Value '' is not a valid field name - */ public function testFieldNameIsRequired() { + $this->expectExceptionMessage("Value '' is not a valid field name"); + $this->expectException(InvalidArgumentException::class); $validator = new Validator($this->connection, 'users', null, null, []); $validator->greaterThanOrEquals('', 123); } @@ -57,7 +55,7 @@ public function testValueGreaterThanPassesValidation() $age_errors = $validator->getFieldErrors('age'); - $this->assertInternalType('array', $age_errors); + $this->assertIsArray($age_errors); $this->assertCount(0, $age_errors); } @@ -75,7 +73,7 @@ public function testEqualValueThanPassesValidation() $age_errors = $validator->getFieldErrors('age'); - $this->assertInternalType('array', $age_errors); + $this->assertIsArray($age_errors); $this->assertCount(0, $age_errors); } @@ -93,7 +91,7 @@ public function testValueNotInArrayFailsValidation() $age_errors = $validator->getFieldErrors('age'); - $this->assertInternalType('array', $age_errors); + $this->assertIsArray($age_errors); $this->assertCount(1, $age_errors); } @@ -111,7 +109,7 @@ public function testNullPassesValidationWhenAllowed() $age_errors = $validator->getFieldErrors('age'); - $this->assertInternalType('array', $age_errors); + $this->assertIsArray($age_errors); $this->assertCount(0, $age_errors); } @@ -129,7 +127,7 @@ public function testNullFailsValidationWhenNotAllowed() $age_errors = $validator->getFieldErrors('age'); - $this->assertInternalType('array', $age_errors); + $this->assertIsArray($age_errors); $this->assertCount(1, $age_errors); } } diff --git a/test/src/GreaterThanValidatorTest.php b/test/src/GreaterThanValidatorTest.php index 1f4eae4..16e2277 100644 --- a/test/src/GreaterThanValidatorTest.php +++ b/test/src/GreaterThanValidatorTest.php @@ -6,15 +6,15 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseObject\Test\Base\TestCase; use ActiveCollab\DatabaseObject\Test\Fixtures\Users\User; use ActiveCollab\DatabaseObject\Validator; +use InvalidArgumentException; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class GreaterThanValidatorTest extends TestCase { /** @@ -25,7 +25,7 @@ class GreaterThanValidatorTest extends TestCase /** * Set up test environment. */ - public function setUp() + public function setUp(): void { parent::setUp(); @@ -33,12 +33,10 @@ public function setUp() $this->assertTrue($this->pool->isTypeRegistered(User::class)); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Value '' is not a valid field name - */ public function testFieldNameIsRequired() { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage("Value '' is not a valid field name"); $validator = new Validator($this->connection, 'users', null, null, []); $validator->greaterThan('', 123); } @@ -57,7 +55,7 @@ public function testValueGreaterThanPassesValidation() $age_errors = $validator->getFieldErrors('age'); - $this->assertInternalType('array', $age_errors); + $this->assertIsArray($age_errors); $this->assertCount(0, $age_errors); } @@ -75,7 +73,7 @@ public function testValueNotInArrayFailsValidation() $age_errors = $validator->getFieldErrors('age'); - $this->assertInternalType('array', $age_errors); + $this->assertIsArray($age_errors); $this->assertCount(1, $age_errors); } @@ -93,7 +91,7 @@ public function testNullPassesValidationWhenAllowed() $age_errors = $validator->getFieldErrors('age'); - $this->assertInternalType('array', $age_errors); + $this->assertIsArray($age_errors); $this->assertCount(0, $age_errors); } @@ -111,7 +109,7 @@ public function testNullFailsValidationWhenNotAllowed() $age_errors = $validator->getFieldErrors('age'); - $this->assertInternalType('array', $age_errors); + $this->assertIsArray($age_errors); $this->assertCount(1, $age_errors); } } diff --git a/test/src/InArrayValidatorTest.php b/test/src/InArrayValidatorTest.php index 88d80ee..3a62391 100644 --- a/test/src/InArrayValidatorTest.php +++ b/test/src/InArrayValidatorTest.php @@ -6,26 +6,30 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseObject\Test\Base\TestCase; use ActiveCollab\DatabaseObject\Test\Fixtures\Users\User; use ActiveCollab\DatabaseObject\Validator; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class InArrayValidatorTest extends TestCase { - /** - * @var array - */ - private $continents = ['Asia', 'Africa', 'North America', 'South America', 'Antarctica', 'Europe', 'Australia']; + private array $continents = [ + 'Asia', + 'Africa', + 'North America', + 'South America', + 'Antarctica', + 'Europe', + 'Australia', + ]; /** * Set up test environment. */ - public function setUp() + public function setUp(): void { parent::setUp(); @@ -47,7 +51,7 @@ public function testValueInArrayPassesValidation() $continent_errors = $validator->getFieldErrors('continent'); - $this->assertInternalType('array', $continent_errors); + $this->assertIsArray($continent_errors); $this->assertCount(0, $continent_errors); } @@ -65,7 +69,7 @@ public function testValueNotInArrayFailsValidation() $continent_errors = $validator->getFieldErrors('continent'); - $this->assertInternalType('array', $continent_errors); + $this->assertIsArray($continent_errors); $this->assertCount(1, $continent_errors); } @@ -83,7 +87,7 @@ public function testNullPassesValidationWhenAllowed() $continent_errors = $validator->getFieldErrors('continent'); - $this->assertInternalType('array', $continent_errors); + $this->assertIsArray($continent_errors); $this->assertCount(0, $continent_errors); } @@ -101,7 +105,7 @@ public function testNullFailsValidationWhenNotAllowed() $continent_errors = $validator->getFieldErrors('continent'); - $this->assertInternalType('array', $continent_errors); + $this->assertIsArray($continent_errors); $this->assertCount(1, $continent_errors); } } diff --git a/test/src/LowerThanOrEqualsValidatorTest.php b/test/src/LowerThanOrEqualsValidatorTest.php index d10b825..507fdd5 100644 --- a/test/src/LowerThanOrEqualsValidatorTest.php +++ b/test/src/LowerThanOrEqualsValidatorTest.php @@ -6,26 +6,23 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseObject\Test\Base\TestCase; use ActiveCollab\DatabaseObject\Test\Fixtures\Users\User; use ActiveCollab\DatabaseObject\Validator; +use InvalidArgumentException; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class LowerThanOrEqualsValidatorTest extends TestCase { - /** - * @var int - */ - private $max_age = 125; + private int $max_age = 125; /** * Set up test environment. */ - public function setUp() + public function setUp(): void { parent::setUp(); @@ -33,12 +30,10 @@ public function setUp() $this->assertTrue($this->pool->isTypeRegistered(User::class)); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Value '' is not a valid field name - */ public function testFieldNameIsRequired() { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage("Value '' is not a valid field name"); $validator = new Validator($this->connection, 'users', null, null, []); $validator->lowerThanOrEquals('', 123); } @@ -57,7 +52,7 @@ public function testValueLowerThanPassesValidation() $age_errors = $validator->getFieldErrors('age'); - $this->assertInternalType('array', $age_errors); + $this->assertIsArray($age_errors); $this->assertCount(0, $age_errors); } @@ -75,7 +70,7 @@ public function testEqualValuePassesValidation() $age_errors = $validator->getFieldErrors('age'); - $this->assertInternalType('array', $age_errors); + $this->assertIsArray($age_errors); $this->assertCount(0, $age_errors); } @@ -93,7 +88,7 @@ public function testValueNotInArrayFailsValidation() $age_errors = $validator->getFieldErrors('age'); - $this->assertInternalType('array', $age_errors); + $this->assertIsArray($age_errors); $this->assertCount(1, $age_errors); } @@ -111,7 +106,7 @@ public function testNullPassesValidationWhenAllowed() $age_errors = $validator->getFieldErrors('age'); - $this->assertInternalType('array', $age_errors); + $this->assertIsArray($age_errors); $this->assertCount(0, $age_errors); } @@ -129,7 +124,7 @@ public function testNullFailsValidationWhenNotAllowed() $age_errors = $validator->getFieldErrors('age'); - $this->assertInternalType('array', $age_errors); + $this->assertIsArray($age_errors); $this->assertCount(1, $age_errors); } } diff --git a/test/src/LowerThanValidatorTest.php b/test/src/LowerThanValidatorTest.php index 18e22ac..356658f 100644 --- a/test/src/LowerThanValidatorTest.php +++ b/test/src/LowerThanValidatorTest.php @@ -6,15 +6,15 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseObject\Test\Base\TestCase; use ActiveCollab\DatabaseObject\Test\Fixtures\Users\User; use ActiveCollab\DatabaseObject\Validator; +use InvalidArgumentException; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class LowerThanValidatorTest extends TestCase { /** @@ -25,7 +25,7 @@ class LowerThanValidatorTest extends TestCase /** * Set up test environment. */ - public function setUp() + public function setUp(): void { parent::setUp(); @@ -33,12 +33,10 @@ public function setUp() $this->assertTrue($this->pool->isTypeRegistered(User::class)); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Value '' is not a valid field name - */ public function testFieldNameIsRequired() { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage("Value '' is not a valid field name"); $validator = new Validator($this->connection, 'users', null, null, []); $validator->lowerThan('', 123); } @@ -57,7 +55,7 @@ public function testValueLowerThanPassesValidation() $age_errors = $validator->getFieldErrors('age'); - $this->assertInternalType('array', $age_errors); + $this->assertIsArray($age_errors); $this->assertCount(0, $age_errors); } @@ -75,7 +73,7 @@ public function testValueNotInArrayFailsValidation() $age_errors = $validator->getFieldErrors('age'); - $this->assertInternalType('array', $age_errors); + $this->assertIsArray($age_errors); $this->assertCount(1, $age_errors); } @@ -93,7 +91,7 @@ public function testNullPassesValidationWhenAllowed() $age_errors = $validator->getFieldErrors('age'); - $this->assertInternalType('array', $age_errors); + $this->assertIsArray($age_errors); $this->assertCount(0, $age_errors); } @@ -111,7 +109,7 @@ public function testNullFailsValidationWhenNotAllowed() $age_errors = $validator->getFieldErrors('age'); - $this->assertInternalType('array', $age_errors); + $this->assertIsArray($age_errors); $this->assertCount(1, $age_errors); } } diff --git a/test/src/OnlyOneValidatorTest.php b/test/src/OnlyOneValidatorTest.php new file mode 100644 index 0000000..65bce6c --- /dev/null +++ b/test/src/OnlyOneValidatorTest.php @@ -0,0 +1,123 @@ +. All rights reserved. + */ + +declare(strict_types=1); + +namespace ActiveCollab\DatabaseObject\Test; + +use ActiveCollab\DatabaseObject\Test\Base\WritersTypeTestCase; +use ActiveCollab\DatabaseObject\Validator; + +class OnlyOneValidatorTest extends WritersTypeTestCase +{ + public function testRecordWithDifferentFieldValueIsValidated(): void + { + $validator = new Validator( + $this->connection, + 'writers', + null, + null, + [ + 'name' => 'Alexander Pushkin', + ] + ); + + $is_only_one = $validator->onlyOne('name', 'Not Alexander Pushkin'); + + $this->assertTrue($is_only_one); + $this->assertEmpty($validator->getFieldErrors('name')); + } + + public function testWillValidateMatchingValueThatDoesNotExist(): void + { + $validator = new Validator( + $this->connection, + 'writers', + null, + null, + [ + 'name' => 'Anton Chekhov', + ] + ); + + $is_only_one = $validator->onlyOne('name', 'Alexander Pushkin'); + + $this->assertTrue($is_only_one); + $this->assertEmpty($validator->getFieldErrors('name')); + } + + public function testWillInvalidateMatchingValueThatAlreadyExists(): void + { + $validator = new Validator( + $this->connection, + 'writers', + null, + null, + [ + 'name' => 'Alexander Pushkin', + ] + ); + + $is_only_one = $validator->onlyOne('name', 'Alexander Pushkin'); + + $this->assertFalse($is_only_one); + + $name_errors = $validator->getFieldErrors('name'); + $this->assertNotEmpty($name_errors); + $this->assertSame( + "Only one record with field 'name' set to 'Alexander Pushkin' is allowed.", + $name_errors[0] + ); + } + + public function testWillValidateMatchingValueWhenContextIsNotTheSame(): void + { + $validator = new Validator( + $this->connection, + 'writers', + null, + null, + [ + 'name' => 'Alexander Pushkin', + + // Same writer, different birthday (Pushkin's birthday is '1799-06-06'). + 'birthday' => '1821-11-11', + ] + ); + + $is_only_one = $validator->onlyOne('name', 'Alexander Pushkin', 'birthday'); + + $this->assertTrue($is_only_one); + $this->assertEmpty($validator->getFieldErrors('name')); + } + + public function testWillInvalidateMatchingValueThatAlreadyExistsInGivenContext(): void + { + $validator = new Validator( + $this->connection, + 'writers', + null, + null, + [ + 'name' => 'Alexander Pushkin', + 'birthday' => '1799-06-06', + ] + ); + + $is_only_one = $validator->onlyOne('name', 'Alexander Pushkin', 'birthday'); + + $this->assertFalse($is_only_one); + + $name_errors = $validator->getFieldErrors('name'); + $this->assertNotEmpty($name_errors); + $this->assertSame( + "Only one record with field 'name' set to 'Alexander Pushkin' is allowed in context of 'birthday'.", + $name_errors[0] + ); + } +} diff --git a/test/src/PoolProduceTest.php b/test/src/PoolProduceTest.php index 184ada6..dab4a37 100644 --- a/test/src/PoolProduceTest.php +++ b/test/src/PoolProduceTest.php @@ -6,6 +6,8 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseObject\Test\Base\WritersTypeTestCase; @@ -13,10 +15,8 @@ use ActiveCollab\DatabaseObject\Test\Fixtures\Writers\Writer; use ActiveCollab\DatabaseObject\Validator; use ActiveCollab\DateValue\DateValue; +use InvalidArgumentException; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class PoolProduceTest extends WritersTypeTestCase { /** @@ -146,19 +146,15 @@ public function testProducedObjectUpdateIsSavedToPool() $this->assertEquals('Anton Pavlovich Chekhov', $object_from_pool_second_take->getName()); } - /** - * @expectedException \InvalidArgumentException - */ public function testExceptionOnUnknonwClass() { + $this->expectException(InvalidArgumentException::class); $this->pool->produce('Definitely not a Class'); } - /** - * @expectedException \InvalidArgumentException - */ public function testExceptionOnNonObjectClass() { + $this->expectException(InvalidArgumentException::class); $this->pool->produce(Validator::class); } } diff --git a/test/src/PresenceValidatorTest.php b/test/src/PresenceValidatorTest.php index 3b12429..4525811 100644 --- a/test/src/PresenceValidatorTest.php +++ b/test/src/PresenceValidatorTest.php @@ -6,22 +6,20 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseObject\Test\Base\WritersTypeTestCase; use ActiveCollab\DatabaseObject\Validator; +use InvalidArgumentException; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class PresenceValidatorTest extends WritersTypeTestCase { - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Value '' is not a valid field name - */ public function testFieldNameIsRequired() { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage("Value '' is not a valid field name"); $validator = new Validator($this->connection, 'writers', null, null, []); $validator->present(''); } @@ -40,7 +38,22 @@ public function testPass() $name_errors = $validator->getFieldErrors('name'); - $this->assertInternalType('array', $name_errors); + $this->assertIsArray($name_errors); + $this->assertCount(0, $name_errors); + } + + public function testPassAllowEmpty() + { + $validator = new Validator($this->connection, 'writers', null, null, ['name' => '']); + + $is_present = $validator->present('name', true); + + $this->assertTrue($is_present); + $this->assertFalse($validator->hasErrors()); + + $name_errors = $validator->getFieldErrors('name'); + + $this->assertIsArray($name_errors); $this->assertCount(0, $name_errors); } @@ -58,7 +71,7 @@ public function testFail() $name_errors = $validator->getFieldErrors('name'); - $this->assertInternalType('array', $name_errors); + $this->assertIsArray($name_errors); $this->assertCount(1, $name_errors); } @@ -91,7 +104,7 @@ public function testBooleanPresenceFail() $is_alive_errors = $validator->getFieldErrors('is_alive'); - $this->assertInternalType('array', $is_alive_errors); + $this->assertIsArray($is_alive_errors); $this->assertCount(1, $is_alive_errors); } @@ -109,7 +122,7 @@ public function testFailBecauseTheresNoValue() $name_errors = $validator->getFieldErrors('name'); - $this->assertInternalType('array', $name_errors); + $this->assertIsArray($name_errors); $this->assertCount(1, $name_errors); } @@ -127,7 +140,7 @@ public function testTypeCheck() $name_errors = $validator->getFieldErrors('name'); - $this->assertInternalType('array', $name_errors); + $this->assertIsArray($name_errors); $this->assertCount(0, $name_errors); } } diff --git a/test/src/ProducerTest.php b/test/src/ProducerTest.php index 08082cc..a5f46f6 100644 --- a/test/src/ProducerTest.php +++ b/test/src/ProducerTest.php @@ -6,6 +6,8 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseObject\Test\Base\WritersTypeTestCase; @@ -14,22 +16,25 @@ use ActiveCollab\DatabaseObject\Test\Fixtures\Writers\AwesomeWriter; use ActiveCollab\DatabaseObject\Test\Fixtures\Writers\Writer; use ActiveCollab\DateValue\DateValue; +use InvalidArgumentException; +use LogicException; +use RuntimeException; +use stdClass; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class ProducerTest extends WritersTypeTestCase { /** * Test if default producer is used by default. */ - public function testDefaultProducerIsUsedByDefault() + public function testDefaultProducerIsUsedByDefault(): void { - /** @var Writer $object */ - $object = $this->pool->produce(Writer::class, [ - 'name' => 'Anton Chekhov', - 'birthday' => new DateValue('1860-01-29'), - ]); + $object = $this->pool->produce( + Writer::class, + [ + 'name' => 'Anton Chekhov', + 'birthday' => new DateValue('1860-01-29'), + ], + ); $this->assertInstanceOf(Writer::class, $object); $this->assertNull($object->custom_attribute_value); @@ -40,14 +45,16 @@ public function testDefaultProducerIsUsedByDefault() */ public function testCustomProducerCanBeSetForType() { - $this->pool->registerProducer(Writer::class, new CustomProducer($this->connection, $this->pool)); + $this->pool->registerProducer(Writer::class, new CustomProducer($this->connection, $this->pool, $this->logger)); - /** @var Writer $object */ - $object = $this->pool->produce(Writer::class, [ - 'name' => 'Anton Chekhov', - 'birthday' => new DateValue('1860-01-29'), - 'custom_producer_set_custom_attribute_to' => 1234, - ]); + $object = $this->pool->produce( + Writer::class, + [ + 'name' => 'Anton Chekhov', + 'birthday' => new DateValue('1860-01-29'), + 'custom_producer_set_custom_attribute_to' => 1234, + ], + ); $this->assertInstanceOf(Writer::class, $object); $this->assertSame(1234, $object->custom_attribute_value); @@ -58,14 +65,16 @@ public function testCustomProducerCanBeSetForType() */ public function testCustomProducerCanBeSetForSubtype() { - $this->pool->registerProducer(AwesomeWriter::class, new CustomProducer($this->connection, $this->pool)); + $this->pool->registerProducer(AwesomeWriter::class, new CustomProducer($this->connection, $this->pool, $this->logger)); - /** @var Writer $object */ - $object = $this->pool->produce(AwesomeWriter::class, [ - 'name' => 'Anton Chekhov', - 'birthday' => new DateValue('1860-01-29'), - 'custom_producer_set_custom_attribute_to' => 1234, - ]); + $object = $this->pool->produce( + AwesomeWriter::class, + [ + 'name' => 'Anton Chekhov', + 'birthday' => new DateValue('1860-01-29'), + 'custom_producer_set_custom_attribute_to' => 1234, + ], + ); $this->assertInstanceOf(AwesomeWriter::class, $object); $this->assertSame(1234, $object->custom_attribute_value); @@ -78,49 +87,43 @@ public function testCustomProducerCanBeSetByClassName() { $this->pool->registerProducerByClass(Writer::class, CustomProducer::class); - /** @var Writer $object */ - $object = $this->pool->produce(Writer::class, [ - 'name' => 'Anton Chekhov', - 'birthday' => new DateValue('1860-01-29'), - 'custom_producer_set_custom_attribute_to' => 1234, - ]); + $object = $this->pool->produce( + Writer::class, + [ + 'name' => 'Anton Chekhov', + 'birthday' => new DateValue('1860-01-29'), + 'custom_producer_set_custom_attribute_to' => 1234, + ], + ); $this->assertInstanceOf(Writer::class, $object); $this->assertSame(1234, $object->custom_attribute_value); } - /** - * @expectedException \InvalidArgumentException - */ public function testCustomProducerCantBeSetForUnregisteredType() { + $this->expectException(InvalidArgumentException::class); $this->assertFalse($this->pool->isTypeRegistered(User::class)); - $this->pool->registerProducer(User::class, new CustomProducer($this->connection, $this->pool)); + $this->pool->registerProducer(User::class, new CustomProducer($this->connection, $this->pool, $this->logger)); } - /** - * @expectedException \LogicException - */ public function testCustomProducerCantBeSetTwice() { - $this->pool->registerProducer(Writer::class, new CustomProducer($this->connection, $this->pool)); - $this->pool->registerProducer(AwesomeWriter::class, new CustomProducer($this->connection, $this->pool)); + $this->expectException(LogicException::class); + $this->pool->registerProducer(Writer::class, new CustomProducer($this->connection, $this->pool, $this->logger)); + $this->pool->registerProducer(AwesomeWriter::class, new CustomProducer($this->connection, $this->pool, $this->logger)); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Class 'stdClass' does not implement 'ActiveCollab\DatabaseObject\ProducerInterface' interface - */ public function testCustomProducerRequiresProducerInterface() { - $this->pool->registerProducerByClass(Writer::class, \stdClass::class); + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage("Class 'stdClass' does not implement 'ActiveCollab\DatabaseObject\ProducerInterface' interface"); + $this->pool->registerProducerByClass(Writer::class, stdClass::class); } - /** - * @expectedException \RuntimeException - */ public function testUnsavedObjectsCantBeModified() { + $this->expectException(RuntimeException::class); $object = $this->pool->produce(Writer::class, [ 'name' => 'Anton Chekhov', 'birthday' => new DateValue('1860-01-20'), @@ -184,11 +187,9 @@ public function testModifyUsingCustomProducer() $this->assertTrue($object->modified_using_custom_producer); } - /** - * @expectedException \RuntimeException - */ public function testUnsavedObjectsCantBeScrapped() { + $this->expectException(RuntimeException::class); $object = $this->pool->produce(Writer::class, [ 'name' => 'Anton Chekhov', 'birthday' => new DateValue('1860-01-20'), diff --git a/test/src/SerializeTest.php b/test/src/SerializeTest.php index 3edce1f..dbf4e6b 100644 --- a/test/src/SerializeTest.php +++ b/test/src/SerializeTest.php @@ -6,6 +6,8 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseObject\Entity\EntityInterface; @@ -13,9 +15,6 @@ use ActiveCollab\DatabaseObject\Test\Fixtures\Writers\Writer; use JsonSerializable; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class SerializeTest extends WritersTypeTestCase { /** @@ -26,7 +25,7 @@ class SerializeTest extends WritersTypeTestCase /** * {@inheritdoc} */ - public function setUp() + public function setUp(): void { parent::setUp(); @@ -42,7 +41,7 @@ public function testEntityIsSerializable() public function testSerialization() { $data = json_decode(json_encode($this->writer), true); - $this->assertInternalType('array', $data); + $this->assertIsArray($data); $this->assertArrayHasKey('id', $data); $this->assertSame($this->writer->getId(), $data['id']); @@ -59,7 +58,7 @@ public function testSerialization() public function testExtendedSerializationIsEmptyByDefault() { - $this->assertInternalType('array', $this->writer->jsonSerializeDetails()); + $this->assertIsArray($this->writer->jsonSerializeDetails()); $this->assertEmpty($this->writer->jsonSerializeDetails()); } } diff --git a/test/src/TraitTest.php b/test/src/TraitTest.php index eb72a22..cf1c28a 100644 --- a/test/src/TraitTest.php +++ b/test/src/TraitTest.php @@ -6,6 +6,8 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\ContainerAccess\ContainerAccessInterface\Implementation; @@ -15,15 +17,12 @@ use ActiveCollab\DatabaseObject\Test\Fixtures\Writers\Writer; use ActiveCollab\DatabaseObject\TraitsResolver\TraitsResolver; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class TraitTest extends TestCase { /** * Set up test environment. */ - public function setUp() + public function setUp(): void { parent::setUp(); @@ -35,7 +34,7 @@ public function testClassTraits() { $trait_names = (new TraitsResolver())->getClassTraits(Writer::class); - $this->assertInternalType('array', $trait_names); + $this->assertIsArray($trait_names); $this->assertCount(3, $trait_names); $this->assertContains(Implementation::class, $trait_names); @@ -48,7 +47,7 @@ public function testClassTraits() */ public function testIfTraitsAreCalledWhenNewInstanceIsCreated() { - $unknown_writer = new Writer($this->connection, $this->pool); + $unknown_writer = new Writer($this->connection, $this->pool, $this->logger); $this->assertTrue($unknown_writer->is_russian); $this->assertTrue($unknown_writer->is_classic_writer); diff --git a/test/src/TypeCollectionTest.php b/test/src/TypeCollectionTest.php index 6270707..ec50397 100644 --- a/test/src/TypeCollectionTest.php +++ b/test/src/TypeCollectionTest.php @@ -6,24 +6,23 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseConnection\Result\ResultInterface; use ActiveCollab\DatabaseObject\Test\Base\WritersTypeTestCase; use ActiveCollab\DatabaseObject\Test\Fixtures\Writers\Collection as WritersCollection; use ActiveCollab\DatabaseObject\Test\Fixtures\Writers\Writer; +use InvalidArgumentException; +use LogicException; -/** - * Test data object collection. - * - * @package angie.tests - */ class TypeCollectionTest extends WritersTypeTestCase { /** * Tear down test environment. */ - public function tearDown() + public function tearDown(): void { if ($this->connection->tableExists('favorite_writers')) { $this->connection->dropTable('favorite_writers'); @@ -66,12 +65,10 @@ public function testSetConditionsFromArray() $this->assertEquals($collection->getConditions(), "type = 'File'"); } - /** - * @expectedException \LogicException - * @expectedExceptionMessage When pattern is an array, no extra arguments are allowed - */ public function testSetConditionsFromArrayAcceptsOnlyPatternArgument() { + $this->expectException(LogicException::class); + $this->expectExceptionMessage("When pattern is an array, no extra arguments are allowed"); $collection = new WritersCollection($this->connection, $this->pool, $this->logger); $collection->where(['type = ?', 'File'], 1, 2, 3); @@ -88,30 +85,24 @@ public function testSetConditionsFromArrayOfArguments() $this->assertEquals($collection->getConditions(), "type = 'File'"); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Pattern argument is required - */ public function testEmptyPatternStringThrowsAnException() { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage("Pattern argument is required"); (new WritersCollection($this->connection, $this->pool, $this->logger))->where(''); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Pattern argument is required - */ public function testEmptyPatternArrayThrowsAnException() { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage("Pattern argument is required"); (new WritersCollection($this->connection, $this->pool, $this->logger))->where([]); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Pattern can be string or an array - */ public function testInvalidConditionsTypeThrowsAnException() { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage("Pattern can be string or an array"); (new WritersCollection($this->connection, $this->pool, $this->logger))->where(123); } @@ -137,35 +128,27 @@ public function testSetOrderBy() $this->assertEquals($collection->getOrderBy(), '`writers`.`created_at` DESC'); } - /** - * @expectedException \LogicException - */ public function testCoundShouldNotWorkWhenCollectionIsNotReady() { + $this->expectException(LogicException::class); (new WritersCollection($this->connection, $this->pool, $this->logger))->setAsNotReady()->executeIds(); } - /** - * @expectedException \LogicException - */ public function testExecuteShouldNotWorkWhenCollectionIsNotReady() { + $this->expectException(LogicException::class); (new WritersCollection($this->connection, $this->pool, $this->logger))->setAsNotReady()->execute(); } - /** - * @expectedException \LogicException - */ public function testExecuteIdsShouldNotWorkWhenCollectionIsNotReady() { + $this->expectException(LogicException::class); (new WritersCollection($this->connection, $this->pool, $this->logger))->setAsNotReady()->executeIds(); } - /** - * @expectedException \LogicException - */ public function testGetTagShouldNotWorkWhenCollectionIsNotReady() { + $this->expectException(LogicException::class); (new WritersCollection($this->connection, $this->pool, $this->logger))->setAsNotReady()->getEtag('ilija.studen@activecollab.com'); } @@ -245,11 +228,9 @@ public function testIsPaginated() $this->assertTrue($paginated->isPaginated()); } - /** - * @expectedException \LogicException - */ public function testSetCurrentPageForNonPaginatedCollectionThrowsAnError() { + $this->expectException(LogicException::class); (new WritersCollection($this->connection, $this->pool, $this->logger))->currentPage(1); } @@ -356,11 +337,9 @@ public function testSourceAndTargetJoinFieldsSpecified() $this->assertEquals('target_id', $collection->getTargetJoinField()); } - /** - * @expectedException \InvalidArgumentException - */ public function testInvalidSourceAndTargetJoinFieldException() { + $this->expectException(InvalidArgumentException::class); (new WritersCollection($this->connection, $this->pool, $this->logger)) ->setJoinTable('writes_books', ['invalid', 'number', 'of', 'arguments']); } @@ -506,7 +485,7 @@ public function testEtagCanIncludeAdditionalIdenfitier() { $collection = (new WritersCollection($this->connection, $this->pool, $this->logger)) ->setApplicationIdentifier('MyApp v1.0') - ->setAdditionalIdenfitifier('addidf'); + ->setAdditionalIdentifier('addidf'); $etag = $collection->getEtag('ilija.studen@activecollab.com'); diff --git a/test/src/TypePreconfiguredCollectionTest.php b/test/src/TypePreconfiguredCollectionTest.php index 091563c..e46846f 100644 --- a/test/src/TypePreconfiguredCollectionTest.php +++ b/test/src/TypePreconfiguredCollectionTest.php @@ -6,15 +6,14 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseConnection\Result\ResultInterface; use ActiveCollab\DatabaseObject\Test\Base\WritersTypeTestCase; use ActiveCollab\DatabaseObject\Test\Fixtures\Writers\PreconfiguredCollection; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class TypePreconfiguredCollectionTest extends WritersTypeTestCase { /** diff --git a/test/src/TypeRegistrationTest.php b/test/src/TypeRegistrationTest.php index 27e6dfb..fb67588 100644 --- a/test/src/TypeRegistrationTest.php +++ b/test/src/TypeRegistrationTest.php @@ -6,6 +6,8 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\ContainerAccess\ContainerAccessInterface\Implementation; @@ -17,10 +19,8 @@ use ActiveCollab\DatabaseObject\Test\Fixtures\Writers\Writer; use ActiveCollab\DatabaseObject\Validator; use ActiveCollab\DateValue\DateValue; +use InvalidArgumentException; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class TypeRegistrationTest extends TestCase { /** @@ -40,11 +40,9 @@ public function testRegisterEmptyList() $this->assertSame([], $this->pool->getRegisteredTypes()); } - /** - * @expectedException \InvalidArgumentException - */ public function testExceptionWhenRegisteringInvalidClass() { + $this->expectException(InvalidArgumentException::class); $this->pool->registerType(DateValue::class); } @@ -100,7 +98,7 @@ public function testFieldsForRegisteredTypes() $fileds = $this->pool->getTypeFields(Writer::class); - $this->assertInternalType('array', $fileds); + $this->assertIsArray($fileds); $this->assertContains('id', $fileds); $this->assertContains('name', $fileds); @@ -116,7 +114,7 @@ public function testFieldsForClassThatExtendsRegisteredType() $fileds = $this->pool->getTypeFields(AwesomeWriter::class); - $this->assertInternalType('array', $fileds); + $this->assertIsArray($fileds); $this->assertContains('id', $fileds); $this->assertContains('name', $fileds); @@ -195,7 +193,7 @@ public function testTraitNamesByType() { $trait_names = $this->pool->getTraitNamesByType(Writer::class); - $this->assertInternalType('array', $trait_names); + $this->assertIsArray($trait_names); $this->assertCount(3, $trait_names); $this->assertContains(Implementation::class, $trait_names); diff --git a/test/src/UniqueValidatorTest.php b/test/src/UniqueValidatorTest.php index ef4320b..f8bed3f 100644 --- a/test/src/UniqueValidatorTest.php +++ b/test/src/UniqueValidatorTest.php @@ -6,19 +6,18 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseObject\Test\Base\WritersTypeTestCase; use ActiveCollab\DatabaseObject\Validator; use ActiveCollab\DateValue\DateValue; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class UniqueValidatorTest extends WritersTypeTestCase { /** - * Test if theres no error thrown for NULL even though there are NULL records in the table. + * Test if there's no error thrown for NULL even though there are NULL records in the table. */ public function testNoErrorOnNull() { @@ -35,7 +34,7 @@ public function testNoErrorOnNull() $name_errors = $validator->getFieldErrors('name'); - $this->assertInternalType('array', $name_errors); + $this->assertIsArray($name_errors); $this->assertCount(0, $name_errors); } @@ -44,7 +43,15 @@ public function testNoErrorOnNull() */ public function testNewRecordDoesNotReportAnErrorWhenTheresNoDuplicateValue() { - $validator = new Validator($this->connection, 'writers', null, null, ['name' => 'Anton Chekhov']); + $validator = new Validator( + $this->connection, + 'writers', + null, + null, + [ + 'name' => 'Anton Chekhov', + ] + ); $is_unique = $validator->unique('name'); @@ -53,7 +60,7 @@ public function testNewRecordDoesNotReportAnErrorWhenTheresNoDuplicateValue() $name_errors = $validator->getFieldErrors('name'); - $this->assertInternalType('array', $name_errors); + $this->assertIsArray($name_errors); $this->assertCount(0, $name_errors); } @@ -62,7 +69,15 @@ public function testNewRecordDoesNotReportAnErrorWhenTheresNoDuplicateValue() */ public function testNewRecordReportsAnErrorOnDuplicateValue() { - $validator = new Validator($this->connection, 'writers', null, null, ['name' => 'Leo Tolstoy']); + $validator = new Validator( + $this->connection, + 'writers', + null, + null, + [ + 'name' => 'Leo Tolstoy', + ] + ); $is_unique = $validator->unique('name'); @@ -71,7 +86,7 @@ public function testNewRecordReportsAnErrorOnDuplicateValue() $name_errors = $validator->getFieldErrors('name'); - $this->assertInternalType('array', $name_errors); + $this->assertIsArray($name_errors); $this->assertCount(1, $name_errors); } @@ -80,7 +95,15 @@ public function testNewRecordReportsAnErrorOnDuplicateValue() */ public function testExistingRecordDoesNotReportAnErrorWhenTheresNoDuplicateValue() { - $validator = new Validator($this->connection, 'writers', 1, null, ['name' => 'Leo Tolstoy']); + $validator = new Validator( + $this->connection, + 'writers', + 1, + null, + [ + 'name' => 'Leo Tolstoy', + ] + ); $is_unique = $validator->unique('name'); @@ -89,7 +112,7 @@ public function testExistingRecordDoesNotReportAnErrorWhenTheresNoDuplicateValue $name_errors = $validator->getFieldErrors('name'); - $this->assertInternalType('array', $name_errors); + $this->assertIsArray($name_errors); $this->assertCount(0, $name_errors); } @@ -98,7 +121,15 @@ public function testExistingRecordDoesNotReportAnErrorWhenTheresNoDuplicateValue */ public function testExistingRecordReportsAnErrorOnDuplicateValue() { - $validator = new Validator($this->connection, 'writers', 1, null, ['name' => 'Alexander Pushkin']); + $validator = new Validator( + $this->connection, + 'writers', + 1, + null, + [ + 'name' => 'Alexander Pushkin', + ] + ); $is_unique = $validator->unique('name'); @@ -107,7 +138,7 @@ public function testExistingRecordReportsAnErrorOnDuplicateValue() $name_errors = $validator->getFieldErrors('name'); - $this->assertInternalType('array', $name_errors); + $this->assertIsArray($name_errors); $this->assertCount(1, $name_errors); } @@ -125,7 +156,7 @@ public function testExistingRecordDoesNotReportAnErrorWhenTheresNoDuplicateValue $name_errors = $validator->getFieldErrors('name'); - $this->assertInternalType('array', $name_errors); + $this->assertIsArray($name_errors); $this->assertCount(0, $name_errors); } @@ -143,7 +174,7 @@ public function testExistingRecordReportsAnErrorOnDuplicateValueOnIdChange() $name_errors = $validator->getFieldErrors('name'); - $this->assertInternalType('array', $name_errors); + $this->assertIsArray($name_errors); $this->assertCount(1, $name_errors); } @@ -161,7 +192,7 @@ public function testNoErrorWhenUniqueWhereIsNotMatched() $name_errors = $validator->getFieldErrors('name'); - $this->assertInternalType('array', $name_errors); + $this->assertIsArray($name_errors); $this->assertCount(0, $name_errors); } @@ -179,7 +210,7 @@ public function testErrorWhenUniqueWhereIsMatched() $name_errors = $validator->getFieldErrors('name'); - $this->assertInternalType('array', $name_errors); + $this->assertIsArray($name_errors); $this->assertCount(1, $name_errors); } } diff --git a/test/src/UrlValidatorTest.php b/test/src/UrlValidatorTest.php index 9105779..c034dfa 100644 --- a/test/src/UrlValidatorTest.php +++ b/test/src/UrlValidatorTest.php @@ -6,21 +6,17 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseObject\Test\Base\TestCase; use ActiveCollab\DatabaseObject\Test\Fixtures\Users\User; use ActiveCollab\DatabaseObject\Validator; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class UrlValidatorTest extends TestCase { - /** - * Set up test environment. - */ - public function setUp() + public function setUp(): void { parent::setUp(); @@ -42,7 +38,7 @@ public function testValidUrlAddressPassesValidation() $url_errors = $validator->getFieldErrors('homepage_url'); - $this->assertInternalType('array', $url_errors); + $this->assertIsArray($url_errors); $this->assertCount(0, $url_errors); } @@ -57,9 +53,9 @@ public function testNoUrlFailsValidation() $url_errors = $validator->getFieldErrors('homepage_url'); - $this->assertInternalType('array', $url_errors); + $this->assertIsArray($url_errors); $this->assertCount(1, $url_errors); - $this->assertContains("Value of 'homepage_url' is required", $url_errors); + $this->assertContains("Value of 'homepage_url' is required.", $url_errors); } /** @@ -76,9 +72,9 @@ public function testInvalidUrlAddressFailsValidation() $url_errors = $validator->getFieldErrors('homepage_url'); - $this->assertInternalType('array', $url_errors); + $this->assertIsArray($url_errors); $this->assertCount(1, $url_errors); - $this->assertContains("Value of 'homepage_url' is not a valid URL", $url_errors); + $this->assertContains("Value of 'homepage_url' is not a valid URL.", $url_errors); } /** @@ -95,7 +91,7 @@ public function testNullPassesValidationWhenAllowed() $url_errors = $validator->getFieldErrors('homepage_url'); - $this->assertInternalType('array', $url_errors); + $this->assertIsArray($url_errors); $this->assertCount(0, $url_errors); } @@ -113,8 +109,8 @@ public function testNullFailsValidationWhenNotAllowed() $url_errors = $validator->getFieldErrors('homepage_url'); - $this->assertInternalType('array', $url_errors); + $this->assertIsArray($url_errors); $this->assertCount(1, $url_errors); - $this->assertContains("Value of 'homepage_url' is required", $url_errors); + $this->assertContains("Value of 'homepage_url' is required.", $url_errors); } } diff --git a/test/src/ValidatorTest.php b/test/src/ValidatorTest.php index 57edbbf..1068560 100644 --- a/test/src/ValidatorTest.php +++ b/test/src/ValidatorTest.php @@ -6,15 +6,14 @@ * (c) A51 doo . All rights reserved. */ +declare(strict_types=1); + namespace ActiveCollab\DatabaseObject\Test; use ActiveCollab\DatabaseObject\Exception\ValidationException; use ActiveCollab\DatabaseObject\Test\Base\WritersTypeTestCase; use ActiveCollab\DatabaseObject\Validator; -/** - * @package ActiveCollab\DatabaseObject\Test - */ class ValidatorTest extends WritersTypeTestCase { /** @@ -52,17 +51,17 @@ public function testValidatorReturnsAllErrors() $errors = $validator->getErrors(); - $this->assertInternalType('array', $errors); + $this->assertIsArray($errors); $this->assertCount(2, $errors); $this->assertArrayHasKey('name', $errors); - $this->assertInternalType('array', $errors['name']); + $this->assertIsArray($errors['name']); $this->assertCount(1, $errors['name']); - $this->assertEquals("Value of 'name' needs to be unique", $errors['name'][0]); + $this->assertEquals("Value of 'name' needs to be unique.", $errors['name'][0]); $this->assertArrayHasKey('birthday', $errors); - $this->assertInternalType('array', $errors['birthday']); + $this->assertIsArray($errors['birthday']); $this->assertCount(1, $errors['birthday']); - $this->assertEquals("Value of 'birthday' is required", $errors['birthday'][0]); + $this->assertEquals("Value of 'birthday' is required.", $errors['birthday'][0]); } }