diff --git a/CHANGELOG b/CHANGELOG index fc89404b..7982703f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,8 +1,16 @@ -Version 0.??.? (????-??-??) +Version 0.??.? (2024-??-??) +=========================== + +Bug fixes: +- Do not hang when language files are missing or corrupted + +Version 0.10.5 (2024-01-10) =========================== Changes: - Require PHP 7.3 +- Adapt the Arch package to make using alternative PHP interpreters easier + (see manual for details) - Multiple editorial and stylistic changes to the UNIX manual page Version 0.10.4 (2023-01-24) @@ -79,7 +87,7 @@ Bug fixes: - Further relax Fever HTTP correctness, to fix more clients - Use icons specified in Atom feeds when available - Do not return null as subscription unread count -- Explicitly forbid U+003A COLON and control characters in usernames, for +- Explicitly forbid U+003A COLON and control characters in usernames, for compatibility with RFC 7617 - Never return 401 in response to an OPTIONS request - Accept "t" and "f" as booleans in Tiny Tiny RSS diff --git a/README.md b/README.md index efea0d3d..c9d6db7e 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ The `/dist/` directory, on the other hand, contains general and system-specific The source text for The Arsse's manual can be found in `/docs/`, with pages written in [Markdown](https://spec.commonmark.org/current/) and converted to HTML [with Daux](#building-the-manual). If a static manual is generated its files will appear under `/manual/`. -The Arsse also has a UNIX manual page, also written in Markdown, which can be found under `/manpages/`. [Pandoc](https://pandoc.org/) is needed to convert it to the appropriate format, with the results stored under `/dist/man/`. +The Arsse also has a UNIX manual page written in [mdoc](https://man.archlinux.org/man/extra/mandoc/mandoc_mdoc.7.en) format, which can be found under `/dist/man/`. In addition to the manuals the files `/README.md` (this file), `/CHANGELOG`, `/UPGRADING`, `/LICENSE`, and `/AUTHORS` also document various things about the software, rather than the software itself. diff --git a/RoboFile.php b/RoboFile.php index b0ca1e03..16a1741a 100644 --- a/RoboFile.php +++ b/RoboFile.php @@ -188,9 +188,9 @@ class RoboFile extends \Robo\Tasks { * may not be equivalent due to subsequent changes in the exclude list, or because * of new tooling. */ - public function packageGeneric(string $commit = null): Result { - if (!$this->toolExists("git", "pandoc")) { - throw new \Exception("Git and Pandoc are required in PATH to produce generic release tarballs"); + public function packageGeneric(?string $commit = null): Result { + if (!$this->toolExists("git")) { + throw new \Exception("Git is required in PATH to produce generic release tarballs"); } // establish which commit to package [$commit, $version] = $this->commitVersion($commit); @@ -308,7 +308,7 @@ class RoboFile extends \Robo\Tasks { * or any commit hash. If none is provided on the command line, Robo will prompt * for a commit to package; the default is "HEAD". */ - public function packageDebsrc(string $commit = null): Result { + public function packageDebsrc(?string $commit = null): Result { // establish which commit to package [$commit, $version] = $this->commitVersion($commit); $tarball = BASE."release/$version/arsse-$version.tar.gz"; @@ -362,7 +362,7 @@ class RoboFile extends \Robo\Tasks { * Build Service instances and with slight modification the Arch User Repository. * Use for Launchpad PPAs has not been tested. */ - public function package(string $commit = null): Result { + public function package(?string $commit = null): Result { if (!$this->toolExists("git")) { throw new \Exception("Git is required in PATH to produce packages"); } @@ -517,7 +517,7 @@ class RoboFile extends \Robo\Tasks { } elseif (in_array("item", $expected) && preg_match('/^- (\w.*)$/D', $l, $m)) { $entry[$section][] = $m[1]; $expected = ["item", "continuation", "blank line"]; - } elseif (in_array("continuation", $expected) && preg_match('/^ (\w.*)$/D', $l, $m)) { + } elseif (in_array("continuation", $expected) && preg_match('/^ (\S.*)$/D', $l, $m)) { $last = sizeof($entry[$section]) - 1; $entry[$section][$last] .= "\n".$m[1]; } else { diff --git a/UPGRADING b/UPGRADING index 531e341f..8a5fba6b 100644 --- a/UPGRADING +++ b/UPGRADING @@ -11,10 +11,13 @@ usually prudent: `composer install -o --no-dev` -Upgrading from 0.10.4 to 0.10.? +Upgrading from 0.10.4 to 0.10.5 ============================= - PHP 7.3 is now required +- Web server configuration in the Arch Linux package has been modified to ease + the use of alternative PHP interpreters; please review the sample + configuration files for changes Upgrading from 0.10.2 to 0.10.3 diff --git a/composer.json b/composer.json index 5a6a8ad8..9767c8ee 100644 --- a/composer.json +++ b/composer.json @@ -24,11 +24,12 @@ "ext-hash": "*", "ext-filter": "*", "ext-dom": "*", - "nicolus/picofeed": "dev-patch-3", + "nicolus/picofeed": "dev-php84", "hosteurope/password-generator": "1.*", - "docopt/docopt": "1.*", + "docopt/docopt": "dev-master", "jkingweb/druuid": "3.*", "guzzlehttp/psr7": "2.*", + "laminas/laminas-xml": "dev-fixup as 1.4.0", "laminas/laminas-httphandlerrunner": "2.*" }, "require-dev": { @@ -66,6 +67,15 @@ { "type": "vcs", "url": "https://github.com/JKingweb/picoFeed-1/" + }, + { + "type": "vcs", + "url": "https://github.com/JKingweb/laminas-xml/" + }, + { + "type": "vcs", + "url": "https://github.com/mensbeam/docopt.php/" } + ] } diff --git a/composer.lock b/composer.lock index 0361177d..815f92c2 100644 --- a/composer.lock +++ b/composer.lock @@ -4,32 +4,32 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "8d22dd66c6cde0b1ed4ca0009293bf88", + "content-hash": "149ece489c5ed860109686b09d2293e3", "packages": [ { "name": "docopt/docopt", - "version": "1.0.5", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/docopt/docopt.php.git", - "reference": "0e3db660cf2f2eb07a83253790b7d97cdb398826" + "url": "https://github.com/mensbeam/docopt.php.git", + "reference": "91f3980e42442344d60d5b83e49baddc355e079f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/docopt/docopt.php/zipball/0e3db660cf2f2eb07a83253790b7d97cdb398826", - "reference": "0e3db660cf2f2eb07a83253790b7d97cdb398826", + "url": "https://api.github.com/repos/mensbeam/docopt.php/zipball/91f3980e42442344d60d5b83e49baddc355e079f", + "reference": "91f3980e42442344d60d5b83e49baddc355e079f", "shasum": "" }, "require": { "php": ">=5.3.0" }, + "default-branch": true, "type": "library", "autoload": { "classmap": [ "src/docopt.php" ] }, - "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -48,29 +48,28 @@ "docs" ], "support": { - "issues": "https://github.com/docopt/docopt.php/issues", - "source": "https://github.com/docopt/docopt.php/tree/1.0.5" + "source": "https://github.com/mensbeam/docopt.php/tree/master" }, - "time": "2023-03-22T12:31:48+00:00" + "time": "2024-12-12T02:51:22+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "7.8.0", + "version": "7.9.2", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9" + "reference": "d281ed313b989f213357e3be1a179f02196ac99b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/1110f66a6530a40fe7aea0378fe608ee2b2248f9", - "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b", + "reference": "d281ed313b989f213357e3be1a179f02196ac99b", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0.1", - "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", + "guzzlehttp/promises": "^1.5.3 || ^2.0.3", + "guzzlehttp/psr7": "^2.7.0", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -79,11 +78,11 @@ "psr/http-client-implementation": "1.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", + "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", - "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "guzzle/client-integration-tests": "3.0.2", "php-http/message-factory": "^1.1", - "phpunit/phpunit": "^8.5.29 || ^9.5.23", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { @@ -161,7 +160,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.8.0" + "source": "https://github.com/guzzle/guzzle/tree/7.9.2" }, "funding": [ { @@ -177,28 +176,28 @@ "type": "tidelift" } ], - "time": "2023-08-27T10:20:53+00:00" + "time": "2024-07-24T11:22:20+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.0.1", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "111166291a0f8130081195ac4556a5587d7f1b5d" + "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/111166291a0f8130081195ac4556a5587d7f1b5d", - "reference": "111166291a0f8130081195ac4556a5587d7f1b5d", + "url": "https://api.github.com/repos/guzzle/promises/zipball/f9c436286ab2892c7db7be8c8da4ef61ccf7b455", + "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", - "phpunit/phpunit": "^8.5.29 || ^9.5.23" + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" }, "type": "library", "extra": { @@ -244,7 +243,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.0.1" + "source": "https://github.com/guzzle/promises/tree/2.0.4" }, "funding": [ { @@ -260,20 +259,20 @@ "type": "tidelift" } ], - "time": "2023-08-03T15:11:55+00:00" + "time": "2024-10-17T10:06:22+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.6.1", + "version": "2.7.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727" + "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/be45764272e8873c72dbe3d2edcfdfcc3bc9f727", - "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201", + "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201", "shasum": "" }, "require": { @@ -287,9 +286,9 @@ "psr/http-message-implementation": "1.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", - "http-interop/http-factory-tests": "^0.9", - "phpunit/phpunit": "^8.5.29 || ^9.5.23" + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -360,7 +359,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.6.1" + "source": "https://github.com/guzzle/psr7/tree/2.7.0" }, "funding": [ { @@ -376,7 +375,7 @@ "type": "tidelift" } ], - "time": "2023-08-27T10:13:57+00:00" + "time": "2024-07-18T11:15:46+00:00" }, { "name": "hosteurope/password-generator", @@ -619,16 +618,16 @@ }, { "name": "laminas/laminas-xml", - "version": "1.4.0", + "version": "dev-fixup", "source": { "type": "git", - "url": "https://github.com/laminas/laminas-xml.git", - "reference": "dcadeefdb6d7ed6b39d772b47e3845003d6ea60f" + "url": "https://github.com/JKingweb/laminas-xml.git", + "reference": "3a6903c9f7b61c96355532d90525d04c3a67ba7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-xml/zipball/dcadeefdb6d7ed6b39d772b47e3845003d6ea60f", - "reference": "dcadeefdb6d7ed6b39d772b47e3845003d6ea60f", + "url": "https://api.github.com/repos/JKingweb/laminas-xml/zipball/3a6903c9f7b61c96355532d90525d04c3a67ba7a", + "reference": "3a6903c9f7b61c96355532d90525d04c3a67ba7a", "shasum": "" }, "require": { @@ -651,7 +650,29 @@ "Laminas\\Xml\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "autoload-dev": { + "psr-4": { + "LaminasTest\\Xml\\": "test/" + } + }, + "scripts": { + "check": [ + "@cs-check", + "@test" + ], + "cs-check": [ + "phpcs" + ], + "cs-fix": [ + "phpcbf" + ], + "test": [ + "phpunit --colors=always" + ], + "test-coverage": [ + "phpunit --colors=always --coverage-clover clover.xml" + ] + }, "license": [ "BSD-3-Clause" ], @@ -663,32 +684,26 @@ "xml" ], "support": { - "chat": "https://laminas.dev/chat", - "forum": "https://discourse.laminas.dev", "issues": "https://github.com/laminas/laminas-xml/issues", + "source": "https://github.com/laminas/laminas-xml", "rss": "https://github.com/laminas/laminas-xml/releases.atom", - "source": "https://github.com/laminas/laminas-xml" + "chat": "https://laminas.dev/chat", + "forum": "https://discourse.laminas.dev" }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-11-30T02:16:35+00:00" + "time": "2024-12-16T02:41:12+00:00" }, { "name": "nicolus/picofeed", - "version": "dev-patch-3", + "version": "dev-php84", "source": { "type": "git", "url": "https://github.com/JKingweb/picoFeed-1.git", - "reference": "536911c180651fea79d6e1894a826fff6ab87a52" + "reference": "d25f100fb079a23ec05a3af291e5d97899ede3f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JKingweb/picoFeed-1/zipball/536911c180651fea79d6e1894a826fff6ab87a52", - "reference": "536911c180651fea79d6e1894a826fff6ab87a52", + "url": "https://api.github.com/repos/JKingweb/picoFeed-1/zipball/d25f100fb079a23ec05a3af291e5d97899ede3f2", + "reference": "d25f100fb079a23ec05a3af291e5d97899ede3f2", "shasum": "" }, "require": { @@ -737,9 +752,9 @@ "description": "RSS/Atom parsing library", "homepage": "https://github.com/nicolus/picoFeed", "support": { - "source": "https://github.com/JKingweb/picoFeed-1/tree/patch-3" + "source": "https://github.com/JKingweb/picoFeed-1/tree/php84" }, - "time": "2023-03-23T01:54:27+00:00" + "time": "2024-12-15T22:23:39+00:00" }, { "name": "psr/http-client", @@ -795,20 +810,20 @@ }, { "name": "psr/http-factory", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-factory.git", - "reference": "e616d01114759c4c489f93b099585439f795fe35" + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", - "reference": "e616d01114759c4c489f93b099585439f795fe35", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", "shasum": "" }, "require": { - "php": ">=7.0.0", + "php": ">=7.1", "psr/http-message": "^1.0 || ^2.0" }, "type": "library", @@ -832,7 +847,7 @@ "homepage": "https://www.php-fig.org/" } ], - "description": "Common interfaces for PSR-7 HTTP message factories", + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", "keywords": [ "factory", "http", @@ -844,9 +859,9 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-factory/tree/1.0.2" + "source": "https://github.com/php-fig/http-factory" }, - "time": "2023-04-10T20:10:41+00:00" + "time": "2024-04-15T12:06:14+00:00" }, { "name": "psr/http-message", @@ -1053,16 +1068,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v2.5.2", + "version": "v2.5.4", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" + "reference": "605389f2a7e5625f273b53960dc46aeaf9c62918" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/605389f2a7e5625f273b53960dc46aeaf9c62918", + "reference": "605389f2a7e5625f273b53960dc46aeaf9c62918", "shasum": "" }, "require": { @@ -1100,7 +1115,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.4" }, "funding": [ { @@ -1116,7 +1131,7 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2024-09-25T14:11:13+00:00" } ], "packages-dev": [ @@ -1178,9 +1193,18 @@ "time": "2022-10-31T08:38:03+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "laminas/laminas-xml", + "version": "dev-fixup", + "alias": "1.4.0", + "alias_normalized": "1.4.0.0" + } + ], "minimum-stability": "stable", "stability-flags": { + "docopt/docopt": 20, + "laminas/laminas-xml": 20, "nicolus/picofeed": 20 }, "prefer-stable": false, @@ -1193,7 +1217,7 @@ "ext-filter": "*", "ext-dom": "*" }, - "platform-dev": [], + "platform-dev": {}, "platform-overrides": { "php": "7.3.33" }, diff --git a/dist/apache/arsse-fcgi.conf b/dist/apache/arsse-fcgi.conf new file mode 100644 index 00000000..a7e38421 --- /dev/null +++ b/dist/apache/arsse-fcgi.conf @@ -0,0 +1,5 @@ +ProxyPreserveHost On +ProxyFCGISetEnvIf "true" SCRIPT_FILENAME "/usr/share/arsse/arsse.php" +ProxyFCGISetEnvIf "-n req('Authorization')" HTTP_AUTHORIZATION "%{req:Authorization}" + +ProxyPass "unix:/var/run/php/arsse.sock|fcgi://localhost/usr/share/arsse/" \ No newline at end of file diff --git a/dist/apache/arsse-loc.conf b/dist/apache/arsse-loc.conf index 611c1fc6..51c4247a 100644 --- a/dist/apache/arsse-loc.conf +++ b/dist/apache/arsse-loc.conf @@ -1,34 +1,34 @@ # Nextcloud News protocol - ProxyPass ${ARSSE_PROXY} + Include "/etc/arsse/apache/arsse-fcgi.conf" # Tiny Tiny RSS protocol - ProxyPass ${ARSSE_PROXY} + Include "/etc/arsse/apache/arsse-fcgi.conf" # Tiny Tiny RSS feed icons - ProxyPass ${ARSSE_PROXY} + Include "/etc/arsse/apache/arsse-fcgi.conf" # Fever protocol - ProxyPass ${ARSSE_PROXY} + Include "/etc/arsse/apache/arsse-fcgi.conf" # Miniflux protocol - ProxyPass ${ARSSE_PROXY} + Include "/etc/arsse/apache/arsse-fcgi.conf" # Miniflux version number - ProxyPass ${ARSSE_PROXY} + Include "/etc/arsse/apache/arsse-fcgi.conf" # Miniflux "health check" - ProxyPass ${ARSSE_PROXY} + Include "/etc/arsse/apache/arsse-fcgi.conf" diff --git a/dist/apache/arsse.conf b/dist/apache/arsse.conf index b16c80e8..7d4b47f0 100644 --- a/dist/apache/arsse.conf +++ b/dist/apache/arsse.conf @@ -3,9 +3,4 @@ DocumentRoot "/usr/share/arsse/www" Require all granted -Define ARSSE_PROXY "unix:/var/run/php/arsse.sock|fcgi://localhost/usr/share/arsse/" -ProxyPreserveHost On -ProxyFCGISetEnvIf "true" SCRIPT_FILENAME "/usr/share/arsse/arsse.php" -ProxyFCGISetEnvIf "-n req('Authorization')" HTTP_AUTHORIZATION "%{req:Authorization}" - Include "/etc/arsse/apache/arsse-loc.conf" diff --git a/dist/arch/PKGBUILD b/dist/arch/PKGBUILD index 76afba7d..9b49ec14 100644 --- a/dist/arch/PKGBUILD +++ b/dist/arch/PKGBUILD @@ -7,6 +7,7 @@ pkgdesc="Multi-protocol RSS/Atom newsfeed synchronization server" arch=("any") url="https://thearsse.com/" license=("MIT") +conflicts=("arsse-git") depends=() makedepends=() checkdepends=() @@ -14,44 +15,50 @@ optdepends=("nginx: HTTP server" "apache>=2.4: HTTP server" "percona-server: Alternate database" "postgresql>=10: Alternate database" - "php-pgsql>=7.3: PostgreSQL database support") + "php-pgsql-interpreter>=7.3: PostgreSQL database support") backup=("etc/webapps/arsse/config.php" + "etc/webapps/arsse/systemd-environment" "etc/php/php-fpm.d/arsse.conf" + "etc/php-legacy/php-fpm.d/arsse.conf" "etc/webapps/arsse/nginx/example.conf" "etc/webapps/arsse/nginx/arsse.conf" "etc/webapps/arsse/nginx/arsse-loc.conf" "etc/webapps/arsse/nginx/arsse-fcgi.conf" "etc/webapps/arsse/apache/example.conf" "etc/webapps/arsse/apache/arsse.conf" + "etc/webapps/arsse/apache/arsse-fcgi.conf" "etc/webapps/arsse/apache/arsse-loc.conf") source=("arsse-0.10.4.tar.gz") md5sums=("SKIP") package() { # define runtime dependencies - depends=("php>=7.3" "php-intl>=7.3" "php-sqlite>=7.3" "php-fpm>=7.3") + depends=("php-interpreter>=7.3" "php-sqlite-interpreter>=7.3" "php-fpm-interpreter>=7.3") # create most directories necessary for the final package cd "$pkgdir" - mkdir -p "usr/share/webapps/arsse" "usr/share/doc/arsse" "usr/share/licenses/arsse" "usr/lib/systemd/system" "usr/lib/sysusers.d" "usr/lib/tmpfiles.d" "etc/php/php-fpm.d" "etc/webapps/arsse" + mkdir -p "usr/share/webapps/arsse" "usr/share/doc/arsse" "usr/share/licenses/arsse" "usr/lib/systemd/system" "usr/lib/sysusers.d" "usr/lib/tmpfiles.d" "etc/php/php-fpm.d" "etc/php-legacy/php-fpm.d" "etc/webapps/arsse" # copy requisite files cd "$srcdir/arsse" cp -r lib locale sql vendor www CHANGELOG UPGRADING README.md arsse.php "$pkgdir/usr/share/webapps/arsse" cp -r manual/* "$pkgdir/usr/share/doc/arsse" cp LICENSE AUTHORS "$pkgdir/usr/share/licenses/arsse" - cp dist/systemd/* "$pkgdir/usr/lib/systemd/system" cp dist/sysuser.conf "$pkgdir/usr/lib/sysusers.d/arsse.conf" cp dist/tmpfiles.conf "$pkgdir/usr/lib/tmpfiles.d/arsse.conf" cp dist/php-fpm.conf "$pkgdir/etc/php/php-fpm.d/arsse.conf" cp -r dist/man "$pkgdir/usr/share" cp -r dist/nginx dist/apache config.defaults.php "$pkgdir/etc/webapps/arsse" - cd "$pkgdir" # copy files requiring special permissions - cd "$srcdir/arsse" - install -Dm755 dist/arsse "$pkgdir/usr/bin/arsse" install -Dm640 dist/config.php "$pkgdir/etc/webapps/arsse" # patch generic configuration files to use Arch-specific paths and identifiers - sed -i -se 's/\/\(etc\|usr\/share\)\/arsse\//\/\1\/webapps\/arsse\//g' "$pkgdir/etc/webapps/arsse/nginx/"* "$pkgdir/etc/webapps/arsse/apache/"* "$pkgdir/usr/lib/tmpfiles.d/arsse.conf" "$pkgdir/usr/lib/systemd/system/"* "$pkgdir/usr/bin/"* + sed -i -se 's/\/\(etc\|usr\/share\)\/arsse\//\/\1\/webapps\/arsse\//g' "$pkgdir/etc/webapps/arsse/nginx/"* "$pkgdir/etc/webapps/arsse/apache/"* "$pkgdir/usr/lib/tmpfiles.d/arsse.conf" sed -i -se 's/\/var\/run\/php\//\/run\/php-fpm\//g' "$pkgdir/etc/webapps/arsse/nginx/"* "$pkgdir/etc/webapps/arsse/apache/"* "$pkgdir/etc/php/php-fpm.d/arsse.conf" sed -i -se 's/www-data/http/g' "$pkgdir/etc/php/php-fpm.d/arsse.conf" - sed -i -e 's/^WorkingDirectory=.*$/WorkingDirectory=\/usr\/share\/webapps\/arsse/g' -e 's/^ConfigurationDirectory=.*$/ConfigurationDirectory=webapps\/arsse/g' "$pkgdir/usr/lib/systemd/system/arsse-fetch.service" + # make a duplicate PHP-FPM pool for php-legacy + sed -se 's/php-fpm/php-fpm-legacy/' "$pkgdir/etc/php/php-fpm.d/arsse.conf" > "$pkgdir/etc/php-legacy/php-fpm.d/arsse.conf" + # copy Arch-specific versions of files + install -Dm755 dist/arch/arsse "$pkgdir/usr/bin/arsse" + cp dist/arch/nginx-arsse-fcgi.conf "$pkgdir/etc/webapps/arsse/nginx/arsse-fcgi.conf" + cp dist/arch/apache-arsse-fcgi.conf "$pkgdir/etc/webapps/arsse/apache/arsse-fcgi.conf" + cp dist/arch/*.service "$pkgdir/usr/lib/systemd/system" + cp dist/arch/systemd-environment "$pkgdir/etc/webapps/arsse/systemd-environment" } diff --git a/dist/arch/PKGBUILD-git b/dist/arch/PKGBUILD-git index c366e893..a1baf566 100644 --- a/dist/arch/PKGBUILD-git +++ b/dist/arch/PKGBUILD-git @@ -9,22 +9,25 @@ url="https://thearsse.com/" license=("MIT") provides=("arsse") conflicts=("arsse") -depends=("php>=7.3" "php-intl>=7.3" "php-sqlite>=7.3") -makedepends=("composer" "pandoc") +depends=("php-interpreter>=7.3" "php-intl-interpreter>=7.3" "php-sqlite-interpreter>=7.3") +makedepends=("composer") checkdepends=() optdepends=("nginx: HTTP server" "apache>=2.4: HTTP server" "percona-server: Alternate database" "postgresql>=10: Alternate database" - "php-pgsql>=7.3: PostgreSQL database support") + "php-pgsql-interpreter>=7.3: PostgreSQL database support") backup=("etc/webapps/arsse/config.php" + "etc/webapps/arsse/systemd-environment" "etc/php/php-fpm.d/arsse.conf" + "etc/php-legacy/php-fpm.d/arsse.conf" "etc/webapps/arsse/nginx/example.conf" "etc/webapps/arsse/nginx/arsse.conf" "etc/webapps/arsse/nginx/arsse-loc.conf" "etc/webapps/arsse/nginx/arsse-fcgi.conf" "etc/webapps/arsse/apache/example.conf" "etc/webapps/arsse/apache/arsse.conf" + "etc/webapps/arsse/apache/arsse-fcgi.conf" "etc/webapps/arsse/apache/arsse-loc.conf") source=("git+https://code.mensbeam.com/MensBeam/arsse/") md5sums=("SKIP") @@ -37,7 +40,6 @@ pkgver() { build() { cd "$srcdir/arsse" composer install - ./robo manpage ./robo manual composer install --no-dev -o --no-scripts php arsse.php conf save-defaults config.defaults.php @@ -46,29 +48,32 @@ build() { package() { # define runtime dependencies - depends=("php>=7.3" "php-intl>=7.3" "php-sqlite>=7.3" "php-fpm>=7.3") + depends=("php-interpreter>=7.3" "php-sqlite-interpreter>=7.3" "php-fpm-interpreter>=7.3") # create most directories necessary for the final package cd "$pkgdir" - mkdir -p "usr/share/webapps/arsse" "usr/share/doc/arsse" "usr/share/licenses/arsse" "usr/lib/systemd/system" "usr/lib/sysusers.d" "usr/lib/tmpfiles.d" "etc/php/php-fpm.d" "etc/webapps/arsse" + mkdir -p "usr/share/webapps/arsse" "usr/share/doc/arsse" "usr/share/licenses/arsse" "usr/lib/systemd/system" "usr/lib/sysusers.d" "usr/lib/tmpfiles.d" "etc/php/php-fpm.d" "etc/php-legacy/php-fpm.d" "etc/webapps/arsse" # copy requisite files cd "$srcdir/arsse" cp -r lib locale sql vendor www CHANGELOG UPGRADING README.md arsse.php "$pkgdir/usr/share/webapps/arsse" cp -r manual/* "$pkgdir/usr/share/doc/arsse" cp LICENSE AUTHORS "$pkgdir/usr/share/licenses/arsse" - cp dist/systemd/* "$pkgdir/usr/lib/systemd/system" cp dist/sysuser.conf "$pkgdir/usr/lib/sysusers.d/arsse.conf" cp dist/tmpfiles.conf "$pkgdir/usr/lib/tmpfiles.d/arsse.conf" cp dist/php-fpm.conf "$pkgdir/etc/php/php-fpm.d/arsse.conf" cp -r dist/man "$pkgdir/usr/share" cp -r dist/nginx dist/apache config.defaults.php "$pkgdir/etc/webapps/arsse" - cd "$pkgdir" # copy files requiring special permissions - cd "$srcdir/arsse" - install -Dm755 dist/arsse "$pkgdir/usr/bin/arsse" install -Dm640 dist/config.php "$pkgdir/etc/webapps/arsse" # patch generic configuration files to use Arch-specific paths and identifiers - sed -i -se 's/\/\(etc\|usr\/share\)\/arsse\//\/\1\/webapps\/arsse\//g' "$pkgdir/etc/webapps/arsse/nginx/"* "$pkgdir/etc/webapps/arsse/apache/"* "$pkgdir/usr/lib/tmpfiles.d/arsse.conf" "$pkgdir/usr/lib/systemd/system/"* "$pkgdir/usr/bin/"* + sed -i -se 's/\/\(etc\|usr\/share\)\/arsse\//\/\1\/webapps\/arsse\//g' "$pkgdir/etc/webapps/arsse/nginx/"* "$pkgdir/etc/webapps/arsse/apache/"* "$pkgdir/usr/lib/tmpfiles.d/arsse.conf" sed -i -se 's/\/var\/run\/php\//\/run\/php-fpm\//g' "$pkgdir/etc/webapps/arsse/nginx/"* "$pkgdir/etc/webapps/arsse/apache/"* "$pkgdir/etc/php/php-fpm.d/arsse.conf" sed -i -se 's/www-data/http/g' "$pkgdir/etc/php/php-fpm.d/arsse.conf" - sed -i -e 's/^WorkingDirectory=.*$/WorkingDirectory=\/usr\/share\/webapps\/arsse/g' -e 's/^ConfigurationDirectory=.*$/ConfigurationDirectory=webapps\/arsse/g' "$pkgdir/usr/lib/systemd/system/arsse-fetch.service" + # make a duplicate PHP-FPM pool for php-legacy + sed -se 's/php-fpm/php-fpm-legacy/' "$pkgdir/etc/php/php-fpm.d/arsse.conf" > "$pkgdir/etc/php-legacy/php-fpm.d/arsse.conf" + # copy Arch-specific versions of files + install -Dm755 dist/arch/arsse "$pkgdir/usr/bin/arsse" + cp dist/arch/nginx-arsse-fcgi.conf "$pkgdir/etc/webapps/arsse/nginx/arsse-fcgi.conf" + cp dist/arch/apache-arsse-fcgi.conf "$pkgdir/etc/webapps/arsse/apache/arsse-fcgi.conf" + cp dist/arch/*.service "$pkgdir/usr/lib/systemd/system" + cp dist/arch/systemd-environment "$pkgdir/etc/webapps/arsse/systemd-environment" } diff --git a/dist/arch/apache-arsse-fcgi.conf b/dist/arch/apache-arsse-fcgi.conf new file mode 100644 index 00000000..59562c61 --- /dev/null +++ b/dist/arch/apache-arsse-fcgi.conf @@ -0,0 +1,6 @@ +ProxyPreserveHost On +ProxyFCGISetEnvIf "true" SCRIPT_FILENAME "/usr/share/webapps/arsse/arsse.php" +ProxyFCGISetEnvIf "-n req('Authorization')" HTTP_AUTHORIZATION "%{req:Authorization}" + +# Modify the below line to begin with "unix:/run/php-fpm-legacy/" if using the php-legacy package +ProxyPass "unix:/run/php-fpm/arsse.sock|fcgi://localhost/usr/share/webapps/arsse/" \ No newline at end of file diff --git a/dist/arch/arsse b/dist/arch/arsse new file mode 100644 index 00000000..c099a569 --- /dev/null +++ b/dist/arch/arsse @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +readonly default_php="/usr/bin/php" +php="" + +check_sudo() { + if ! command -v sudo > /dev/null; then + printf "The sudo command is not available.\n" + exit 1 + fi +} + +# allow overriding the php executable +if [ -n "${ARSSE_PHP}" ] && command -v "${ARSSE_PHP}" > /dev/null; then + php="${ARSSE_PHP}" +else + php="${default_php}" +fi + +if [ "$(whoami)" = "arsse" ]; then + "$php" /usr/share/webapps/arsse/arsse "$@" +elif [ "${UID}" -eq 0 ]; then + runuser -u "arsse" -- "$php" /usr/share/webapps/arsse/arsse "$@" +else + check_sudo + sudo -u "arsse" "$php" /usr/share/webapps/arsse/arsse "$@" +fi + diff --git a/dist/arch/arsse-fetch.service b/dist/arch/arsse-fetch.service new file mode 100644 index 00000000..1389165a --- /dev/null +++ b/dist/arch/arsse-fetch.service @@ -0,0 +1,37 @@ +[Unit] +Description=The Arsse newsfeed fetching service +Documentation=https://thearsse.com/manual/ +PartOf=arsse.service + +[Install] +WantedBy=multi-user.target + +[Service] +User=arsse +Group=arsse +Type=simple +WorkingDirectory=/usr/share/webapps/arsse +EnvironmentFile=/etc/webapps/arsse/systemd-environment +ExecStart=/usr/bin/arsse daemon + +ProtectProc=invisible +NoNewPrivileges=true +ProtectSystem=full +ProtectHome=true +StateDirectory=arsse +ConfigurationDirectory=arsse +PrivateTmp=true +PrivateDevices=true +RestrictSUIDSGID=true +StandardOutput=journal +StandardError=journal +SyslogIdentifier=arsse +Restart=on-failure +RestartPreventStatus= + +# These directives can be used for extra security, but are disabled for now for compatibility + +#ReadOnlyPaths=/ +#ReadWriePaths=/var/lib/arsse +#NoExecPaths=/ +#ExecPaths=/usr/bin/php diff --git a/dist/arch/arsse.service b/dist/arch/arsse.service new file mode 100644 index 00000000..9a7e91c6 --- /dev/null +++ b/dist/arch/arsse.service @@ -0,0 +1,13 @@ +[Unit] +Description=The Arsse newsfeed management service +Documentation=https://thearsse.com/manual/ +Requires=arsse-fetch.service +Wants=php-fpm.service php-legacy-fpm.service + +[Install] +WantedBy=multi-user.target + +[Service] +Type=oneshot +RemainAfterExit=true +ExecStart=/usr/bin/true diff --git a/dist/arch/nginx-arsse-fcgi.conf b/dist/arch/nginx-arsse-fcgi.conf new file mode 100644 index 00000000..352168ba --- /dev/null +++ b/dist/arch/nginx-arsse-fcgi.conf @@ -0,0 +1,16 @@ +fastcgi_pass_header Authorization; # required if the Arsse is to perform its own HTTP authentication +fastcgi_pass_request_body on; +fastcgi_pass_request_headers on; +fastcgi_intercept_errors off; +fastcgi_buffering off; +fastcgi_param REQUEST_METHOD $request_method; +fastcgi_param CONTENT_TYPE $content_type; +fastcgi_param CONTENT_LENGTH $content_length; +fastcgi_param REQUEST_URI $uri; +fastcgi_param QUERY_STRING $query_string; +fastcgi_param HTTPS $https if_not_empty; +fastcgi_param REMOTE_USER $remote_user; +fastcgi_param SCRIPT_FILENAME /usr/share/webapps/arsse/arsse.php; + +# Modify the below line to begin with "/run/php-fpm-legacy/" if using the php-legacy package +fastcgi_pass unix:/run/php-fpm/arsse.sock; diff --git a/dist/arch/systemd-environment b/dist/arch/systemd-environment new file mode 100644 index 00000000..085e8164 --- /dev/null +++ b/dist/arch/systemd-environment @@ -0,0 +1 @@ +ARSSE_PHP=/usr/bin/php \ No newline at end of file diff --git a/dist/nginx/arsse-fcgi.conf b/dist/nginx/arsse-fcgi.conf index eb83097f..d7e39f5d 100644 --- a/dist/nginx/arsse-fcgi.conf +++ b/dist/nginx/arsse-fcgi.conf @@ -10,3 +10,6 @@ fastcgi_param REQUEST_URI $uri; fastcgi_param QUERY_STRING $query_string; fastcgi_param HTTPS $https if_not_empty; fastcgi_param REMOTE_USER $remote_user; + +fastcgi_pass unix:/var/run/php/arsse.sock; +fastcgi_param SCRIPT_FILENAME /usr/share/arsse/arsse.php; diff --git a/dist/nginx/arsse.conf b/dist/nginx/arsse.conf index fe5721e8..7949a66c 100644 --- a/dist/nginx/arsse.conf +++ b/dist/nginx/arsse.conf @@ -2,15 +2,11 @@ root /usr/share/arsse/www; location @arsse { # HTTP authentication may be enabled for this location, though this may impact some features - fastcgi_pass unix:/var/run/php/arsse.sock; - fastcgi_param SCRIPT_FILENAME /usr/share/arsse/arsse.php; include /etc/arsse/nginx/arsse-fcgi.conf; } location @arsse_public { # HTTP authentication should not be enabled for this location - fastcgi_pass unix:/var/run/php/arsse.sock; - fastcgi_param SCRIPT_FILENAME /usr/share/arsse/arsse.php; include /etc/arsse/nginx/arsse-fcgi.conf; } diff --git a/dist/tmpfiles.conf b/dist/tmpfiles.conf index f5e6ed18..8e4c86cc 100644 --- a/dist/tmpfiles.conf +++ b/dist/tmpfiles.conf @@ -2,3 +2,4 @@ z /usr/bin/arsse 0755 root arsse - - z /etc/arsse/config.php 0640 root arsse - - L /usr/share/arsse/config.php - root arsse - /etc/arsse/config.php d /var/lib/arsse 0750 arsse arsse - - +L /usr/share/arsse/arsse - root arsse - /usr/share/arsse/arsse.php \ No newline at end of file diff --git a/docs/en/020_Getting_Started/020_Download_and_Installation/010_On_Arch_Linux.md b/docs/en/020_Getting_Started/020_Download_and_Installation/010_On_Arch_Linux.md index e075c1b2..a20c9692 100644 --- a/docs/en/020_Getting_Started/020_Download_and_Installation/010_On_Arch_Linux.md +++ b/docs/en/020_Getting_Started/020_Download_and_Installation/010_On_Arch_Linux.md @@ -35,6 +35,23 @@ LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so No additional set-up is required for Nginx. +# Using an alternative PHP interpreter + +The above instructions assume you will be using the `php` package as your PHP interpreter. If you wish to use `php-legacy` (which is always one feature version behind, for compatibility) a few configuration tweaks are required. The follwoing commands are a short summary: + +```sh +# Enable the necessary PHP extensions; curl is optional but recommended; pdo_sqlite may be used instead of sqlite3, but this is not recommended +sudo sed -i -e 's/^;\(extension=\(curl\|iconv\|intl\|sqlite3\)\)$/\1/' /etc/php-legacy/php.ini +# Modify the system service's environment +sudo sed -i -e 's/^ARSSE_PHP=.*/ARSSE_PHP=\/usr\/bin\/php-legacy/' /etc/webapps/arsse/systemd-environment +# Modify the PAM environment for the administrative CLI +echo "export ARSSE_PHP=/usr/bin/php-legacy" | sudo tee -a /etc/profile.d/arsse >/dev/null +# Modify the Nginx and Apache HTTPD configurations +sudo sed -i -se 's/\/run\/php-fpm\//\/run\/php-fpm-legacy\//' /etc/webapps/arsse/apache/arsse-fcgi.conf /etc/webapps/arsse/nginx/arsse-fcgi.conf +``` + +The above procedure can also be applied to use another PHP version from AUR if so desired. + # Next steps If using a database other than SQLite, you will likely want to [set it up](/en/Getting_Started/Database_Setup) before doing anything else. diff --git a/docs/en/020_Getting_Started/050_Configuration.md b/docs/en/020_Getting_Started/050_Configuration.md index cb5dc26f..dd5376e1 100644 --- a/docs/en/020_Getting_Started/050_Configuration.md +++ b/docs/en/020_Getting_Started/050_Configuration.md @@ -363,7 +363,7 @@ The default value is equal to two megabytes. |---------|---------| | boolean | `true` | -Whether to allow the possibility of fetching full article contents from an article's source, if a newsfeed only provides excerpts. Whether fetching will actually happen is governed by a per-newsfeed toggle (defaulting to `false`) which currently can only be changed by manually editing the database. +Whether to allow the possibility of fetching full article contents from an article's source, if a newsfeed only provides excerpts. Whether fetching will actually happen is governed by a per-newsfeed toggle (defaulting to `false`) which currently can only be changed via the Miniflux protocol. ### fetchUserAgentString diff --git a/lib/AbstractException.php b/lib/AbstractException.php index 20c6c1d4..0748736a 100644 --- a/lib/AbstractException.php +++ b/lib/AbstractException.php @@ -121,7 +121,7 @@ abstract class AbstractException extends \Exception { protected $symbol; protected $params; - public function __construct(string $msgID = "", $vars = null, \Throwable $e = null) { + public function __construct(string $msgID = "", $vars = null, ?\Throwable $e = null) { $this->symbol = $msgID; $this->params = $vars ?? []; if ($msgID === "") { diff --git a/lib/Arsse.php b/lib/Arsse.php index 14c20a37..d520bbe7 100644 --- a/lib/Arsse.php +++ b/lib/Arsse.php @@ -8,7 +8,7 @@ declare(strict_types=1); namespace JKingWeb\Arsse; class Arsse { - public const VERSION = "0.10.4"; + public const VERSION = "0.10.5"; public const REQUIRED_EXTENSIONS = [ "intl", // as this extension is required to prepare formatted messages, its absence will throw a distinct English-only exception "dom", diff --git a/lib/CLI.php b/lib/CLI.php index ec24362d..5a21285f 100644 --- a/lib/CLI.php +++ b/lib/CLI.php @@ -72,7 +72,7 @@ USAGE_TEXT; return ($file === "-" ? null : $file) ?? $stdinOrStdout; } - public function dispatch(array $argv = null): int { + public function dispatch(?array $argv = null): int { $argv = $argv ?? $_SERVER['argv']; $argv0 = array_shift($argv); $args = \Docopt::handle($this->usage($argv0), [ @@ -198,7 +198,7 @@ USAGE_TEXT; return 0; } - protected function userAddOrSetPassword(string $method, string $user, string $password = null, string $oldpass = null): int { + protected function userAddOrSetPassword(string $method, string $user, ?string $password = null, ?string $oldpass = null): int { $passwd = Arsse::$user->$method(...array_slice(func_get_args(), 1)); if (is_null($password)) { echo $passwd.\PHP_EOL; diff --git a/lib/Context/BooleanMembers.php b/lib/Context/BooleanMembers.php index 6cf6b38a..559437f1 100644 --- a/lib/Context/BooleanMembers.php +++ b/lib/Context/BooleanMembers.php @@ -14,23 +14,23 @@ trait BooleanMembers { public $labelled = null; public $annotated = null; - public function unread(bool $spec = null) { + public function unread(?bool $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function starred(bool $spec = null) { + public function starred(?bool $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function hidden(bool $spec = null) { + public function hidden(?bool $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function labelled(bool $spec = null) { + public function labelled(?bool $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function annotated(bool $spec = null) { + public function annotated(?bool $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } } diff --git a/lib/Context/ExclusionContext.php b/lib/Context/ExclusionContext.php index 9e484f18..6b3faf5c 100644 --- a/lib/Context/ExclusionContext.php +++ b/lib/Context/ExclusionContext.php @@ -10,7 +10,7 @@ namespace JKingWeb\Arsse\Context; class ExclusionContext extends AbstractContext { use ExclusionMembers; - public function __construct(Context $parent = null) { + public function __construct(?Context $parent = null) { $this->parent = $parent; } diff --git a/lib/Context/ExclusionMembers.php b/lib/Context/ExclusionMembers.php index 45fbf1a3..b33f65db 100644 --- a/lib/Context/ExclusionMembers.php +++ b/lib/Context/ExclusionMembers.php @@ -83,127 +83,127 @@ trait ExclusionMembers { return array_values(array_unique($spec, \SORT_REGULAR)); } - public function folder(int $spec = null) { + public function folder(?int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function folders(array $spec = null) { + public function folders(?array $spec = null) { if (isset($spec)) { $spec = $this->cleanIdArray($spec, true); } return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function folderShallow(int $spec = null) { + public function folderShallow(?int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function foldersShallow(array $spec = null) { + public function foldersShallow(?array $spec = null) { if (isset($spec)) { $spec = $this->cleanIdArray($spec, true); } return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function tag(int $spec = null) { + public function tag(?int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function tags(array $spec = null) { + public function tags(?array $spec = null) { if (isset($spec)) { $spec = $this->cleanIdArray($spec); } return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function tagName(string $spec = null) { + public function tagName(?string $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function tagNames(array $spec = null) { + public function tagNames(?array $spec = null) { if (isset($spec)) { $spec = $this->cleanStringArray($spec); } return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function subscription(int $spec = null) { + public function subscription(?int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function subscriptions(array $spec = null) { + public function subscriptions(?array $spec = null) { if (isset($spec)) { $spec = $this->cleanIdArray($spec); } return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function edition(int $spec = null) { + public function edition(?int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function article(int $spec = null) { + public function article(?int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function editions(array $spec = null) { + public function editions(?array $spec = null) { if (isset($spec)) { $spec = $this->cleanIdArray($spec); } return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function articles(array $spec = null) { + public function articles(?array $spec = null) { if (isset($spec)) { $spec = $this->cleanIdArray($spec); } return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function label(int $spec = null) { + public function label(?int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function labels(array $spec = null) { + public function labels(?array $spec = null) { if (isset($spec)) { $spec = $this->cleanIdArray($spec); } return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function labelName(string $spec = null) { + public function labelName(?string $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function labelNames(array $spec = null) { + public function labelNames(?array $spec = null) { if (isset($spec)) { $spec = $this->cleanStringArray($spec); } return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function annotationTerms(array $spec = null) { + public function annotationTerms(?array $spec = null) { if (isset($spec)) { $spec = $this->cleanStringArray($spec); } return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function searchTerms(array $spec = null) { + public function searchTerms(?array $spec = null) { if (isset($spec)) { $spec = $this->cleanStringArray($spec); } return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function titleTerms(array $spec = null) { + public function titleTerms(?array $spec = null) { if (isset($spec)) { $spec = $this->cleanStringArray($spec); } return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function authorTerms(array $spec = null) { + public function authorTerms(?array $spec = null) { if (isset($spec)) { $spec = $this->cleanStringArray($spec); } @@ -237,7 +237,7 @@ trait ExclusionMembers { return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function modifiedRanges(array $spec = null) { + public function modifiedRanges(?array $spec = null) { if (isset($spec)) { $spec = $this->cleanDateRangeArray($spec); } @@ -253,7 +253,7 @@ trait ExclusionMembers { return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function markedRanges(array $spec = null) { + public function markedRanges(?array $spec = null) { if (isset($spec)) { $spec = $this->cleanDateRangeArray($spec); } diff --git a/lib/Context/RootContext.php b/lib/Context/RootContext.php index d189d910..f06f330d 100644 --- a/lib/Context/RootContext.php +++ b/lib/Context/RootContext.php @@ -11,11 +11,11 @@ abstract class RootContext extends AbstractContext { public $limit = 0; public $offset = 0; - public function limit(int $spec = null) { + public function limit(?int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } - public function offset(int $spec = null) { + public function offset(?int $spec = null) { return $this->act(__FUNCTION__, func_num_args(), $spec); } } diff --git a/lib/Database.php b/lib/Database.php index 5c53d862..88e21b7c 100644 --- a/lib/Database.php +++ b/lib/Database.php @@ -86,11 +86,16 @@ class Database { /** Returns the bare name of the calling context's calling method, when __FUNCTION__ is not appropriate */ protected function caller(): string { - $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 4); - if ($trace[2]['function'] === "articleQuery") { - return $trace[3]['function']; + $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10); + $out = ""; + foreach ($trace as $step) { + if (($step['class'] ?? "") === __CLASS__) { + $out = $step['function']; + } else { + break; + } } - return $trace[2]['function']; + return $out; } /** Returns the current (actual) schema version of the database; compared against self::SCHEMA_VERSION to know when an upgrade is required */ @@ -408,7 +413,7 @@ class Database { * @param string $user The user who owns the session to be destroyed * @param string|null $id The identifier of the session to destroy */ - public function sessionDestroy(string $user, string $id = null): bool { + public function sessionDestroy(string $user, ?string $id = null): bool { if (is_null($id)) { // delete all sessions and report success unconditionally if no identifier was specified $this->db->prepare("DELETE FROM arsse_sessions where \"user\" = ?", "str")->run($user); @@ -462,7 +467,7 @@ class Database { * @param \DateTimeInterface|null $expires An optional expiry date and time for the token * @param string $data Application-specific data associated with a token */ - public function tokenCreate(string $user, string $class, string $id = null, ?\DateTimeInterface $expires = null, string $data = null): string { + public function tokenCreate(string $user, string $class, ?string $id = null, ?\DateTimeInterface $expires = null, ?string $data = null): string { if (!$this->userExists($user)) { throw new User\ExceptionConflict("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); } @@ -676,7 +681,7 @@ class Database { } /** Ensures an operation to rename and/or move a folder does not result in a conflict or circular dependence, and raises an exception otherwise */ - protected function folderValidateMove(string $user, $id = null, $parent = null, string $name = null): ?int { + protected function folderValidateMove(string $user, $id = null, $parent = null, ?string $name = null): ?int { $errData = ["action" => $this->caller(), "field" => "parent", 'id' => $parent]; if (!$id) { // the root cannot be moved @@ -811,7 +816,7 @@ class Database { * @param boolean $recursive Whether to list subscriptions of descendent folders as well as the selected folder * @param integer|null $id The numeric identifier of a particular subscription; used internally by subscriptionPropertiesGet */ - public function subscriptionList(string $user, $folder = null, bool $recursive = true, int $id = null): Db\Result { + public function subscriptionList(string $user, $folder = null, bool $recursive = true, ?int $id = null): Db\Result { // validate inputs $folder = $this->folderValidateId($user, $folder)['id']; // create a complex query @@ -1051,7 +1056,7 @@ class Database { } /** Returns the time at which any of a user's subscriptions (or a specific subscription) was last refreshed, as a DateTimeImmutable object */ - public function subscriptionRefreshed(string $user, int $id = null): ?\DateTimeImmutable { + public function subscriptionRefreshed(string $user, ?int $id = null): ?\DateTimeImmutable { $q = new Query("SELECT max(arsse_feeds.updated) from arsse_feeds join arsse_subscriptions on arsse_subscriptions.feed = arsse_feeds.id"); $q->setWhere("arsse_subscriptions.owner = ?", "str", $user); if ($id) { @@ -1641,7 +1646,7 @@ class Database { return $q; } - protected function articleFilter(Context $context, QueryFilter $q = null) { + protected function articleFilter(Context $context, ?QueryFilter $q = null) { $q = $q ?? new QueryFilter; $colDefs = $this->articleColumns(); // handle the simple context options @@ -1820,7 +1825,7 @@ class Database { * @param array $fieldss The columns to return in the result set, any of: id, edition, url, title, author, content, guid, fingerprint, folder, subscription, feed, starred, unread, note, published_date, edited_date, modified_date, marked_date, subscription_title, media_url, media_type * @param array $sort The columns to sort the result by eg. "edition desc" in decreasing order of importance */ - public function articleList(string $user, RootContext $context = null, array $fields = ["id"], array $sort = []): Db\Result { + public function articleList(string $user, ?RootContext $context = null, array $fields = ["id"], array $sort = []): Db\Result { // make a base query based on context and output columns $context = $context ?? new Context; $q = $this->articleQuery($user, $context, $fields); @@ -1864,7 +1869,7 @@ class Database { * @param string $user The user whose articles are to be counted * @param RootContext $context The search context */ - public function articleCount(string $user, RootContext $context = null): int { + public function articleCount(string $user, ?RootContext $context = null): int { $context = $context ?? new Context; $q = $this->articleQuery($user, $context, []); return (int) $this->db->prepare($q->getQuery(), $q->getTypes())->run($q->getValues())->getValue(); @@ -1884,7 +1889,7 @@ class Database { * @param RootContext $context The query context to match articles against * @param bool $updateTimestamp Whether to also update the timestamp. This should only be false if a mark is changed as a result of an automated action not taken by the user */ - public function articleMark(string $user, array $data, RootContext $context = null, bool $updateTimestamp = true): int { + public function articleMark(string $user, array $data, ?RootContext $context = null, bool $updateTimestamp = true): int { $data = [ 'read' => $data['read'] ?? null, 'starred' => $data['starred'] ?? null, @@ -2167,7 +2172,7 @@ class Database { } /** Returns the numeric identifier of the most recent edition of an article matching the given context */ - public function editionLatest(string $user, RootContext $context = null): int { + public function editionLatest(string $user, ?RootContext $context = null): int { $context = $context ?? new Context; $q = $this->articleQuery($user, $context, ["latest_edition"]); return (int) $this->db->prepare((string) $q, $q->getTypes())->run($q->getValues())->getValue(); diff --git a/lib/Db/AbstractDriver.php b/lib/Db/AbstractDriver.php index 055fe943..ce550086 100644 --- a/lib/Db/AbstractDriver.php +++ b/lib/Db/AbstractDriver.php @@ -20,7 +20,7 @@ abstract class AbstractDriver implements Driver { abstract protected function unlock(bool $rollback = false): bool; abstract protected static function buildEngineException($code, string $msg): array; - public function schemaUpdate(int $to, string $basePath = null): bool { + public function schemaUpdate(int $to, ?string $basePath = null): bool { $ver = $this->schemaVersion(); if (!Arsse::$conf->dbAutoUpdate) { throw new Exception("updateManual", ['version' => $ver, 'driver_name' => $this->driverName()]); @@ -91,7 +91,7 @@ abstract class AbstractDriver implements Driver { return $this->transDepth; } - public function savepointRelease(int $index = null): bool { + public function savepointRelease(?int $index = null): bool { // assume the most recent savepoint if none was specified $index = $index ?? $this->transDepth; if (array_key_exists($index, $this->transStatus)) { @@ -150,7 +150,7 @@ abstract class AbstractDriver implements Driver { } } - public function savepointUndo(int $index = null): bool { + public function savepointUndo(?int $index = null): bool { $index = $index ?? $this->transDepth; if (array_key_exists($index, $this->transStatus)) { switch ($this->transStatus[$index]) { diff --git a/lib/Db/Driver.php b/lib/Db/Driver.php index 9ca1b7f1..480a5c84 100644 --- a/lib/Db/Driver.php +++ b/lib/Db/Driver.php @@ -39,10 +39,10 @@ interface Driver { public function savepointCreate(): int; /** Manually commits either the latest or a specified nested transaction */ - public function savepointRelease(int $index = null): bool; + public function savepointRelease(?int $index = null): bool; /** Manually rolls back either the latest or a specified nested transaction */ - public function savepointUndo(int $index = null): bool; + public function savepointUndo(?int $index = null): bool; /** Performs an in-place upgrade of the database schema * diff --git a/lib/Db/MySQL/Driver.php b/lib/Db/MySQL/Driver.php index 6f39b2eb..8f3e72e5 100644 --- a/lib/Db/MySQL/Driver.php +++ b/lib/Db/MySQL/Driver.php @@ -99,7 +99,7 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { } } - public function savepointRelease(int $index = null): bool { + public function savepointRelease(?int $index = null): bool { $index = $index ?? $this->transDepth; $out = parent::savepointRelease($index); if ($index == $this->transStart) { @@ -109,7 +109,7 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { return $out; } - public function savepointUndo(int $index = null): bool { + public function savepointUndo(?int $index = null): bool { $index = $index ?? $this->transDepth; $out = parent::savepointUndo($index); if ($index == $this->transStart) { diff --git a/lib/Db/PDODriver.php b/lib/Db/PDODriver.php index bb93741b..814fdacc 100644 --- a/lib/Db/PDODriver.php +++ b/lib/Db/PDODriver.php @@ -10,6 +10,8 @@ namespace JKingWeb\Arsse\Db; trait PDODriver { use PDOError; + protected $db; + public function exec(string $query): bool { try { $this->db->exec($query); diff --git a/lib/Db/PostgreSQL/Driver.php b/lib/Db/PostgreSQL/Driver.php index 70fb21c2..67e02fe4 100644 --- a/lib/Db/PostgreSQL/Driver.php +++ b/lib/Db/PostgreSQL/Driver.php @@ -139,7 +139,7 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { } } - public function savepointRelease(int $index = null): bool { + public function savepointRelease(?int $index = null): bool { $index = $index ?? $this->transDepth; $out = parent::savepointRelease($index); if ($index == $this->transStart) { @@ -149,7 +149,7 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { return $out; } - public function savepointUndo(int $index = null): bool { + public function savepointUndo(?int $index = null): bool { $index = $index ?? $this->transDepth; $out = parent::savepointUndo($index); if ($index == $this->transStart) { diff --git a/lib/Db/SQLite3/AbstractPDODriver.php b/lib/Db/SQLite3/AbstractPDODriver.php index e8fa5e86..1fd4478b 100644 --- a/lib/Db/SQLite3/AbstractPDODriver.php +++ b/lib/Db/SQLite3/AbstractPDODriver.php @@ -11,4 +11,6 @@ abstract class AbstractPDODriver extends Driver { // this class exists solely so SQLite's PDO driver can call methods of the generic PDO driver via parent::method() // if there's a better way to do this, please FIXME ;) use \JKingWeb\Arsse\Db\PDODriver; + + protected $db; } diff --git a/lib/Db/SQLite3/Driver.php b/lib/Db/SQLite3/Driver.php index e50ca525..67181b11 100644 --- a/lib/Db/SQLite3/Driver.php +++ b/lib/Db/SQLite3/Driver.php @@ -131,7 +131,7 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver { } } - public function schemaUpdate(int $to, string $basePath = null): bool { + public function schemaUpdate(int $to, ?string $basePath = null): bool { if ($to == 1) { // if we're initializing the database for the first time, switch to WAL mode $this->exec("PRAGMA journal_mode = wal"); diff --git a/lib/Db/SQLite3/Result.php b/lib/Db/SQLite3/Result.php index 73716f85..15d83bf7 100644 --- a/lib/Db/SQLite3/Result.php +++ b/lib/Db/SQLite3/Result.php @@ -26,7 +26,7 @@ class Result extends \JKingWeb\Arsse\Db\AbstractResult { // constructor/destructor - public function __construct(\SQLite3Result $result, array $changes = [0,0], Statement $statement = null) { + public function __construct(\SQLite3Result $result, array $changes = [0,0], ?Statement $statement = null) { $this->st = $statement; //keeps the statement from being destroyed, invalidating the result set $this->set = $result; $this->rows = $changes[0]; diff --git a/lib/Feed.php b/lib/Feed.php index 2a5cb445..6c463378 100644 --- a/lib/Feed.php +++ b/lib/Feed.php @@ -60,7 +60,7 @@ class Feed { } } - public function __construct(int $feedID = null, string $url, string $lastModified = '', string $etag = '', string $username = '', string $password = '', bool $scrape = false) { + public function __construct(?int $feedID, string $url, string $lastModified = '', string $etag = '', string $username = '', string $password = '', bool $scrape = false) { // fetch the feed [$client, $reader] = self::download($url, $lastModified, $etag, $username, $password); // format the HTTP Last-Modified date returned @@ -288,7 +288,7 @@ class Feed { return $out; } - protected function matchToDatabase(int $feedID = null): void { + protected function matchToDatabase(?int $feedID = null): void { // first perform deduplication on items $items = $this->deduplicateItems($this->items); // if we haven't been given a database feed ID to check against, all items are new diff --git a/lib/Feed/Exception.php b/lib/Feed/Exception.php index 069bed9e..ae444de0 100644 --- a/lib/Feed/Exception.php +++ b/lib/Feed/Exception.php @@ -16,7 +16,7 @@ class Exception extends \JKingWeb\Arsse\AbstractException { protected const CURL_ERROR_MAP = [1 => "invalidUrl",3 => "invalidUrl",5 => "transmissionError","connectionFailed","connectionFailed","transmissionError","forbidden","unauthorized","transmissionError","transmissionError","transmissionError","transmissionError","connectionFailed","connectionFailed","transmissionError","transmissionError","transmissionError","transmissionError","transmissionError","invalidUrl","transmissionError","transmissionError","transmissionError","transmissionError",28 => "timeout","transmissionError","transmissionError","transmissionError","transmissionError","transmissionError",35 => "invalidCertificate","transmissionError","transmissionError","transmissionError","transmissionError",45 => "transmissionError","unauthorized","maxRedirect",52 => "transmissionError","invalidCertificate","invalidCertificate","transmissionError","transmissionError",58 => "invalidCertificate","invalidCertificate","invalidCertificate","transmissionError","invalidUrl","transmissionError","invalidCertificate","transmissionError","invalidCertificate","forbidden","invalidUrl","forbidden","transmissionError",73 => "transmissionError","transmissionError",77 => "invalidCertificate","invalidUrl",90 => "invalidCertificate","invalidCertificate","transmissionError",94 => "unauthorized","transmissionError","connectionFailed"]; protected const HTTP_ERROR_MAP = [401 => "unauthorized",403 => "forbidden",404 => "invalidUrl",408 => "timeout",410 => "invalidUrl",414 => "invalidUrl",451 => "invalidUrl"]; - public function __construct(string $msgID = "", $vars = null, \Throwable $e = null) { + public function __construct(string $msgID = "", $vars = null, ?\Throwable $e = null) { if ($msgID === "") { assert($e !== null, new \Exception("Expecting Picofeed or Guzzle exception when no message specified.")); if ($e instanceof BadResponseException) { @@ -31,7 +31,8 @@ class Exception extends \JKingWeb\Arsse\AbstractException { } elseif (preg_match("/^cURL error (\d+):/", $msg, $match)) { $msgID = self::CURL_ERROR_MAP[(int) $match[1]] ?? "internalError"; } else { - $msgID = "internalError"; + // Fallback for future Guzzle exceptions we may not know about + $msgID = "internalError"; // @codeCoverageIgnore } } elseif ($e instanceof PicoFeedException) { $className = get_class($e); diff --git a/lib/Lang.php b/lib/Lang.php index 37ffb6f3..c437a25a 100644 --- a/lib/Lang.php +++ b/lib/Lang.php @@ -124,7 +124,7 @@ class Lang { return $out; } - public function match(string $locale, array $list = null): string { + public function match(string $locale, ?array $list = null): string { $list = $list ?? $this->listFiles(); $default = ($this->locale === "") ? self::DEFAULT : $this->locale; return \Locale::lookup($list, $locale, true, $default); @@ -161,12 +161,12 @@ class Lang { if (!$this->requirementsMet) { $this->checkRequirements(); } + $this->synched = true; + $this->formatter = null; // if we've requested no locale (""), just load the fallback strings and return if ($this->wanted === "") { $this->strings = self::REQUIRED; $this->locale = $this->wanted; - $this->synched = true; - $this->formatter = null; return true; } // decompose the requested locale from specific to general, building a list of files to load @@ -191,16 +191,14 @@ class Lang { $files[] = $file; } // if we need to load all files, start with the fallback strings - $strings = []; if ($files === $loaded) { - $strings[] = self::REQUIRED; - } else { - // otherwise start with the strings we already have if we're going from e.g. "fr" to "fr_ca" - $strings[] = $this->strings; + $this->strings = self::REQUIRED; + $this->locale = ""; } - // read files in reverse order - $files = array_reverse($files); - foreach ($files as $file) { + $this->loaded = array_diff($loaded, $files); + while ($files) { + // read files in reverse order, from most general to most specific + $file = array_pop($files); if (!file_exists($this->path."$file.php")) { throw new Lang\Exception("fileMissing", $file); } elseif (!is_readable($this->path."$file.php")) { @@ -218,14 +216,10 @@ class Lang { if (!is_array($arr)) { throw new Lang\Exception("fileCorrupt", $file); } - $strings[] = $arr; + $this->strings = array_replace_recursive($this->strings, $arr); + $this->loaded[] = $file; + $this->locale = $file; } - // apply the results and return - $this->strings = call_user_func_array("array_replace_recursive", $strings); - $this->loaded = $loaded; - $this->locale = $this->wanted; - $this->synched = true; - $this->formatter = null; return true; } } diff --git a/lib/Misc/Date.php b/lib/Misc/Date.php index f6232c4a..b865df68 100644 --- a/lib/Misc/Date.php +++ b/lib/Misc/Date.php @@ -8,7 +8,7 @@ declare(strict_types=1); namespace JKingWeb\Arsse\Misc; abstract class Date { - public static function transform($date, string $outFormat = null, string $inFormat = null) { + public static function transform($date, ?string $outFormat = null, ?string $inFormat = null) { $date = ValueInfo::normalize($date, ValueInfo::T_DATE, $inFormat); if (!$date) { return null; @@ -22,7 +22,7 @@ abstract class Date { return $out; } - public static function normalize($date, string $inFormat = null): ?\DateTimeImmutable { + public static function normalize($date, ?string $inFormat = null): ?\DateTimeImmutable { return ValueInfo::normalize($date, ValueInfo::T_DATE, $inFormat); } diff --git a/lib/Misc/URL.php b/lib/Misc/URL.php index e0328ce9..53102b03 100644 --- a/lib/Misc/URL.php +++ b/lib/Misc/URL.php @@ -36,7 +36,7 @@ class URL { * @param string $u Username to add to the URL, replacing any existing credentials * @param string $p Password to add to the URL, if a username is specified */ - public static function normalize(string $url, string $u = null, string $p = null): string { + public static function normalize(string $url, ?string $u = null, ?string $p = null): string { extract(parse_url($url)); $out = ""; if (isset($scheme)) { diff --git a/lib/Misc/ValueInfo.php b/lib/Misc/ValueInfo.php index 942b6892..b64d5373 100644 --- a/lib/Misc/ValueInfo.php +++ b/lib/Misc/ValueInfo.php @@ -60,7 +60,7 @@ class ValueInfo { 'float' => ["U.u", "U.u" ], ]; - public static function normalize($value, int $type, string $dateInFormat = null, $dateOutFormat = null) { + public static function normalize($value, int $type, ?string $dateInFormat = null, $dateOutFormat = null) { $allowNull = ($type & self::M_NULL); $strict = ($type & (self::M_STRICT | self::M_DROP)); $drop = ($type & self::M_DROP); @@ -511,7 +511,7 @@ class ValueInfo { } } - public static function bool($value, bool $default = null): ?bool { + public static function bool($value, ?bool $default = null): ?bool { if (is_null($value) || ValueInfo::str($value) & ValueInfo::WHITE) { return $default; } diff --git a/lib/REST.php b/lib/REST.php index bff419e8..1417025a 100644 --- a/lib/REST.php +++ b/lib/REST.php @@ -76,11 +76,11 @@ class REST { ]; protected $apis = []; - public function __construct(array $apis = null) { + public function __construct(?array $apis = null) { $this->apis = $apis ?? self::API_LIST; } - public function dispatch(ServerRequestInterface $req = null): ResponseInterface { + public function dispatch(?ServerRequestInterface $req = null): ResponseInterface { try { // ensure the require extensions are loaded Arsse::checkExtensions(...Arsse::REQUIRED_EXTENSIONS); @@ -159,12 +159,12 @@ class REST { return $req; } - public function challenge(ResponseInterface $res, string $realm = null): ResponseInterface { + public function challenge(ResponseInterface $res, ?string $realm = null): ResponseInterface { $realm = $realm ?? Arsse::$conf->httpRealm; return $res->withAddedHeader("WWW-Authenticate", 'Basic realm="'.$realm.'", charset="UTF-8"'); } - public function normalizeResponse(ResponseInterface $res, RequestInterface $req = null): ResponseInterface { + public function normalizeResponse(ResponseInterface $res, ?RequestInterface $req = null): ResponseInterface { // if the response code is 401, issue an HTTP authentication challenge if ($res->getStatusCode() == 401) { $res = $this->challenge($res); @@ -203,7 +203,7 @@ class REST { return $res; } - public function corsApply(ResponseInterface $res, RequestInterface $req = null): ResponseInterface { + public function corsApply(ResponseInterface $res, ?RequestInterface $req = null): ResponseInterface { if ($req && $req->getMethod() === "OPTIONS") { if ($res->hasHeader("Allow")) { $res = $res->withHeader("Access-Control-Allow-Methods", $res->getHeaderLine("Allow")); @@ -218,7 +218,7 @@ class REST { return $res->withAddedHeader("Vary", "Origin"); } - public function corsNegotiate(RequestInterface $req, string $allowed = null, string $denied = null): bool { + public function corsNegotiate(RequestInterface $req, ?string $allowed = null, ?string $denied = null): bool { $allowed = trim($allowed ?? Arsse::$conf->httpOriginsAllowed); $denied = trim($denied ?? Arsse::$conf->httpOriginsDenied); // continue if at least one origin is allowed @@ -255,7 +255,7 @@ class REST { return false; } - public function corsNormalizeOrigin(string $origin, array $ports = null): string { + public function corsNormalizeOrigin(string $origin, ?array $ports = null): string { $origin = trim($origin); if ($origin === "null") { // if the origin is the special value "null", use it diff --git a/lib/REST/Fever/User.php b/lib/REST/Fever/User.php index a8354eae..0691168d 100644 --- a/lib/REST/Fever/User.php +++ b/lib/REST/Fever/User.php @@ -11,7 +11,7 @@ use JKingWeb\Arsse\Arsse; use JKingWeb\Arsse\Db\ExceptionInput; class User { - public function register(string $user, string $password = null): string { + public function register(string $user, ?string $password = null): string { $password = $password ?? Arsse::$user->generatePassword(); $hash = md5("$user:$password"); $tr = Arsse::$db->begin(); diff --git a/lib/REST/Miniflux/V1.php b/lib/REST/Miniflux/V1.php index dfcdeef0..09e3a5aa 100644 --- a/lib/REST/Miniflux/V1.php +++ b/lib/REST/Miniflux/V1.php @@ -1028,7 +1028,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler { return ['total' => $count, 'entries' => $out]; } - protected function findEntry(int $id, Context $c = null): array { + protected function findEntry(int $id, ?Context $c = null): array { $c = ($c ?? new Context)->article($id); $tr = Arsse::$db->begin(); $meta = $this->userMeta(Arsse::$user->id); diff --git a/lib/REST/NextcloudNews/V1_2.php b/lib/REST/NextcloudNews/V1_2.php index a13c2eda..fee83a1f 100644 --- a/lib/REST/NextcloudNews/V1_2.php +++ b/lib/REST/NextcloudNews/V1_2.php @@ -135,7 +135,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler { return implode("/", $path); } - protected function normalizeInput(array $data, array $types, string $dateFormat = null, int $mode = 0): array { + protected function normalizeInput(array $data, array $types, ?string $dateFormat = null, int $mode = 0): array { $out = []; foreach ($types as $key => $type) { if (isset($data[$key])) { diff --git a/lib/REST/TinyTinyRSS/Search.php b/lib/REST/TinyTinyRSS/Search.php index c13251d8..bd032442 100644 --- a/lib/REST/TinyTinyRSS/Search.php +++ b/lib/REST/TinyTinyRSS/Search.php @@ -33,7 +33,7 @@ class Search { "" => "searchTerms", ]; - public static function parse(string $search, string $tz, Context $context = null): ?Context { + public static function parse(string $search, string $tz, ?Context $context = null): ?Context { // normalize the input $search = strtolower(trim(preg_replace("<\s+>", " ", $search))); // set initial state @@ -283,7 +283,7 @@ class Search { return $context; } - protected static function processToken(Context $c, string $value, string $tag, bool $neg, string $tz = null): Context { + protected static function processToken(Context $c, string $value, string $tag, bool $neg, ?string $tz = null): Context { if (!strlen($value) && !strlen($tag)) { return $c; } elseif (!strlen($value)) { diff --git a/lib/User.php b/lib/User.php index da8718cc..faa03f18 100644 --- a/lib/User.php +++ b/lib/User.php @@ -35,7 +35,7 @@ class User { /** @var User\Driver */ protected $u; - public function __construct(\JKingWeb\Arsse\User\Driver $driver = null) { + public function __construct(?\JKingWeb\Arsse\User\Driver $driver = null) { $this->u = $driver ?? new Arsse::$conf->userDriver; } diff --git a/lib/User/Driver.php b/lib/User/Driver.php index eb5e8e5b..304fc6af 100644 --- a/lib/User/Driver.php +++ b/lib/User/Driver.php @@ -24,7 +24,7 @@ interface Driver { * @param string $user The username to create * @param string|null $password The cleartext password to assign to the user, or null to generate a random password */ - public function userAdd(string $user, string $password = null): ?string; + public function userAdd(string $user, ?string $password = null): ?string; /** Renames a user * @@ -50,14 +50,14 @@ interface Driver { * @param string|null $password The cleartext password to assign to the user, or null to generate a random password * @param string|null $oldPassword The user's previous password, if known */ - public function userPasswordSet(string $user, ?string $newPassword, string $oldPassword = null): ?string; + public function userPasswordSet(string $user, ?string $newPassword, ?string $oldPassword = null): ?string; /** Removes a user's password; this makes authentication fail unconditionally * * @param string $user The user for whom to change the password * @param string|null $oldPassword The user's previous password, if known */ - public function userPasswordUnset(string $user, string $oldPassword = null): bool; + public function userPasswordUnset(string $user, ?string $oldPassword = null): bool; /** Retrieves metadata about a user * diff --git a/lib/User/Internal/Driver.php b/lib/User/Internal/Driver.php index 5674d004..1181c0cf 100644 --- a/lib/User/Internal/Driver.php +++ b/lib/User/Internal/Driver.php @@ -33,7 +33,7 @@ class Driver implements \JKingWeb\Arsse\User\Driver { return password_verify($password, $hash); } - public function userAdd(string $user, string $password = null): ?string { + public function userAdd(string $user, ?string $password = null): ?string { if (isset($password)) { // only add the user if the password is not null; the user manager will retry with a generated password if null is returned Arsse::$db->userAdd($user, $password); @@ -59,7 +59,7 @@ class Driver implements \JKingWeb\Arsse\User\Driver { return Arsse::$db->userList(); } - public function userPasswordSet(string $user, ?string $newPassword, string $oldPassword = null): ?string { + public function userPasswordSet(string $user, ?string $newPassword, ?string $oldPassword = null): ?string { // do nothing: the internal database is updated regardless of what the driver does (assuming it does not throw an exception) // throw an exception if the user does not exist if (!$this->userExists($user)) { @@ -69,7 +69,7 @@ class Driver implements \JKingWeb\Arsse\User\Driver { } } - public function userPasswordUnset(string $user, string $oldPassword = null): bool { + public function userPasswordUnset(string $user, ?string $oldPassword = null): bool { // do nothing: the internal database is updated regardless of what the driver does (assuming it does not throw an exception) // throw an exception if the user does not exist if (!$this->userExists($user)) { diff --git a/robo b/robo index 223ad9f1..6cc8c077 100755 --- a/robo +++ b/robo @@ -1,14 +1,17 @@ #! /bin/sh base=`dirname "$0"` -roboCommand="$1" +command="$1" +robo="$base/vendor-bin/robo/vendor/bin/robo" +if [ -z "$ARSSE_PHP" ]; then + php="php" +else + php="$ARSSE_PHP" +fi + if [ $# -eq 0 ]; then - "$base/vendor-bin/robo/vendor/bin/robo" + "$php" "$robo" else shift ulimit -n 2048 - if [ "$1" = "clean" ]; then - "$base/vendor-bin/robo/vendor/bin/robo" "$roboCommand" "$@" - else - "$base/vendor-bin/robo/vendor/bin/robo" "$roboCommand" -- "$@" - fi + "$php" "$robo" "$command" -- "$@" fi diff --git a/tests/cases/Database/SeriesArticle.php b/tests/cases/Database/SeriesArticle.php index 30efe91f..9d383b1f 100644 --- a/tests/cases/Database/SeriesArticle.php +++ b/tests/cases/Database/SeriesArticle.php @@ -427,7 +427,15 @@ trait SeriesArticle { unset($this->data, $this->matches, $this->fields, $this->checkTables, $this->user); } - /** @dataProvider provideContextMatches */ + /** + * @dataProvider provideContextMatches + * @covers \JKingWeb\Arsse\Database::articleList + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testListArticlesCheckingContext(RootContext $c, array $exp): void { $ids = array_column($ids = Arsse::$db->articleList("john.doe@example.com", $c, ["id"], ["id"])->getAll(), "id"); sort($ids); @@ -547,6 +555,14 @@ trait SeriesArticle { ]; } + /** + * @covers \JKingWeb\Arsse\Database::editionArticle + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testRetrieveArticleIdsForEditions(): void { $exp = [ 1 => 1, @@ -584,16 +600,40 @@ trait SeriesArticle { $this->assertEquals($exp, Arsse::$db->editionArticle(...range(1, 1001))); } + /** + * @covers \JKingWeb\Arsse\Database::articleList + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testListArticlesOfAMissingFolder(): void { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->articleList($this->user, (new Context)->folder(1)); } + /** + * @covers \JKingWeb\Arsse\Database::articleList + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testListArticlesOfAMissingSubscription(): void { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->articleList($this->user, (new Context)->subscription(1)); } + /** + * @covers \JKingWeb\Arsse\Database::articleList + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testListArticlesCheckingProperties(): void { $this->user = "john.doe@example.org"; // check that the different fieldset groups return the expected columns @@ -607,7 +647,15 @@ trait SeriesArticle { $this->assertEquals($this->fields, $test); } - /** @dataProvider provideOrderedLists */ + /** + * @dataProvider provideOrderedLists + * @covers \JKingWeb\Arsse\Database::articleList + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testListArticlesCheckingOrder(array $sortCols, array $exp): void { $act = ValueInfo::normalize(array_column(iterator_to_array(Arsse::$db->articleList("john.doe@example.com", null, ["id"], $sortCols)), "id"), ValueInfo::T_INT | ValueInfo::M_ARRAY); $this->assertSame($exp, $act); @@ -626,10 +674,26 @@ trait SeriesArticle { ]; } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkNothing(): void { $this->assertSame(0, Arsse::$db->articleMark($this->user, [])); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAllArticlesUnread(): void { Arsse::$db->articleMark($this->user, ['read' => false]); $now = Date::transform(time(), "sql"); @@ -641,6 +705,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAllArticlesRead(): void { Arsse::$db->articleMark($this->user, ['read' => true]); $now = Date::transform(time(), "sql"); @@ -656,6 +728,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAllArticlesUnstarred(): void { Arsse::$db->articleMark($this->user, ['starred' => false]); $now = Date::transform(time(), "sql"); @@ -667,6 +747,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAllArticlesStarred(): void { Arsse::$db->articleMark($this->user, ['starred' => true]); $now = Date::transform(time(), "sql"); @@ -682,6 +770,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAllArticlesUnreadAndUnstarred(): void { Arsse::$db->articleMark($this->user, ['read' => false,'starred' => false]); $now = Date::transform(time(), "sql"); @@ -696,6 +792,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAllArticlesReadAndStarred(): void { Arsse::$db->articleMark($this->user, ['read' => true,'starred' => true]); $now = Date::transform(time(), "sql"); @@ -714,6 +818,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAllArticlesUnreadAndStarred(): void { Arsse::$db->articleMark($this->user, ['read' => false,'starred' => true]); $now = Date::transform(time(), "sql"); @@ -732,6 +844,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAllArticlesReadAndUnstarred(): void { Arsse::$db->articleMark($this->user, ['read' => true,'starred' => false]); $now = Date::transform(time(), "sql"); @@ -750,6 +870,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testSetNoteForAllArticles(): void { Arsse::$db->articleMark($this->user, ['note' => "New note"]); $now = Date::transform(time(), "sql"); @@ -769,6 +897,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkATreeFolder(): void { Arsse::$db->articleMark($this->user, ['read' => true], (new Context)->folder(7)); $now = Date::transform(time(), "sql"); @@ -780,6 +916,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkALeafFolder(): void { Arsse::$db->articleMark($this->user, ['read' => true], (new Context)->folder(8)); $now = Date::transform(time(), "sql"); @@ -789,6 +933,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAMissingFolder(): void { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->articleMark($this->user, ['read' => true], (new Context)->folder(42)); @@ -803,11 +955,27 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAMissingSubscription(): void { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->articleMark($this->user, ['read' => true], (new Context)->folder(2112)); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAnArticle(): void { Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->article(20)); $now = Date::transform(time(), "sql"); @@ -817,6 +985,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkMultipleArticles(): void { Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->articles([2,4,7,20])); $now = Date::transform(time(), "sql"); @@ -827,6 +1003,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkMultipleArticlessUnreadAndStarred(): void { Arsse::$db->articleMark($this->user, ['read' => false,'starred' => true], (new Context)->articles([2,4,7,20])); $now = Date::transform(time(), "sql"); @@ -840,16 +1024,40 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkTooManyMultipleArticles(): void { $setSize = (new \ReflectionClassConstant(Database::class, "LIMIT_SET_SIZE"))->getValue(); $this->assertSame(7, Arsse::$db->articleMark($this->user, ['read' => false,'starred' => true], (new Context)->articles(range(1, $setSize * 3)))); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAMissingArticle(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->article(1)); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAnEdition(): void { Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->edition(1001)); $now = Date::transform(time(), "sql"); @@ -859,6 +1067,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkMultipleEditions(): void { Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->editions([2,4,7,20])); $now = Date::transform(time(), "sql"); @@ -869,12 +1085,28 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkMultipleMissingEditions(): void { $this->assertSame(0, Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->editions([500,501]))); $state = $this->primeExpectations($this->data, $this->checkTables); $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkMultipleEditionsUnread(): void { Arsse::$db->articleMark($this->user, ['read' => false], (new Context)->editions([2,4,7,1001])); $now = Date::transform(time(), "sql"); @@ -886,6 +1118,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkMultipleEditionsUnreadWithStale(): void { Arsse::$db->articleMark($this->user, ['read' => false], (new Context)->editions([2,4,7,20])); $now = Date::transform(time(), "sql"); @@ -895,6 +1135,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkMultipleEditionsUnreadAndStarredWithStale(): void { Arsse::$db->articleMark($this->user, ['read' => false,'starred' => true], (new Context)->editions([2,4,7,20])); $now = Date::transform(time(), "sql"); @@ -907,16 +1155,39 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkTooManyMultipleEditions(): void { $this->assertSame(7, Arsse::$db->articleMark($this->user, ['read' => false,'starred' => true], (new Context)->editions(range(1, 51)))); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAStaleEditionUnread(): void { Arsse::$db->articleMark($this->user, ['read' => false], (new Context)->edition(20)); // no changes occur $state = $this->primeExpectations($this->data, $this->checkTables); $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAStaleEditionStarred(): void { Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->edition(20)); $now = Date::transform(time(), "sql"); @@ -926,6 +1197,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAStaleEditionUnreadAndStarred(): void { Arsse::$db->articleMark($this->user, ['read' => false,'starred' => true], (new Context)->edition(20)); // only starred is changed $now = Date::transform(time(), "sql"); @@ -935,17 +1214,41 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAStaleEditionUnreadAndUnstarred(): void { Arsse::$db->articleMark($this->user, ['read' => false,'starred' => false], (new Context)->edition(20)); // no changes occur $state = $this->primeExpectations($this->data, $this->checkTables); $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAMissingEdition(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->edition(2)); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkByOldestEdition(): void { Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->editionRange(19, null)); $now = Date::transform(time(), "sql"); @@ -957,6 +1260,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkByLatestEdition(): void { Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->editionRange(null, 20)); $now = Date::transform(time(), "sql"); @@ -970,6 +1281,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkByLastMarked(): void { Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->markedRange('2017-01-01T00:00:00Z', null)); $now = Date::transform(time(), "sql"); @@ -981,6 +1300,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkByNotLastMarked(): void { Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->markedRange(null, '2000-01-01T00:00:00Z')); $now = Date::transform(time(), "sql"); @@ -990,6 +1317,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleCount + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testCountArticles(): void { $setSize = (new \ReflectionClassConstant(Database::class, "LIMIT_SET_SIZE"))->getValue(); $this->assertSame(2, Arsse::$db->articleCount("john.doe@example.com", (new Context)->starred(true))); @@ -998,6 +1333,7 @@ trait SeriesArticle { $this->assertSame(10, Arsse::$db->articleCount("john.doe@example.com", (new Context)->articles(range(1, $setSize * 3)))); } + /** @covers \JKingWeb\Arsse\Database::articleStarred */ public function testFetchStarredCounts(): void { $exp1 = ['total' => 2, 'unread' => 1, 'read' => 1]; $exp2 = ['total' => 0, 'unread' => 0, 'read' => 0]; @@ -1005,17 +1341,20 @@ trait SeriesArticle { $this->assertEquals($exp2, Arsse::$db->articleStarred("jane.doe@example.com")); } + /** @covers \JKingWeb\Arsse\Database::editionLatest */ public function testFetchLatestEdition(): void { $this->assertSame(1001, Arsse::$db->editionLatest($this->user)); $this->assertSame(4, Arsse::$db->editionLatest($this->user, (new Context)->subscription(12))); $this->assertSame(5, Arsse::$db->editionLatest("john.doe@example.com", (new Context)->subscription(3)->hidden(false))); } + /** @covers \JKingWeb\Arsse\Database::editionLatest */ public function testFetchLatestEditionOfMissingSubscription(): void { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->editionLatest($this->user, (new Context)->subscription(1)); } + /** @covers \JKingWeb\Arsse\Database::articleLabelsGet */ public function testListTheLabelsOfAnArticle(): void { $this->assertEquals([1,2], Arsse::$db->articleLabelsGet("john.doe@example.com", 1)); $this->assertEquals([2], Arsse::$db->articleLabelsGet("john.doe@example.com", 5)); @@ -1025,11 +1364,13 @@ trait SeriesArticle { $this->assertEquals([], Arsse::$db->articleLabelsGet("john.doe@example.com", 2, true)); } + /** @covers \JKingWeb\Arsse\Database::articleLabelsGet */ public function testListTheLabelsOfAMissingArticle(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->articleLabelsGet($this->user, 101); } + /** @covers \JKingWeb\Arsse\Database::articleCategoriesGet */ public function testListTheCategoriesOfAnArticle(): void { $exp = ["Fascinating", "Logical"]; $this->assertSame($exp, Arsse::$db->articleCategoriesGet($this->user, 19)); @@ -1039,12 +1380,21 @@ trait SeriesArticle { $this->assertSame($exp, Arsse::$db->articleCategoriesGet($this->user, 4)); } + /** @covers \JKingWeb\Arsse\Database::articleCategoriesGet */ public function testListTheCategoriesOfAMissingArticle(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->articleCategoriesGet($this->user, 101); } - /** @dataProvider provideArrayContextOptions */ + /** + * @dataProvider provideArrayContextOptions + * @covers \JKingWeb\Arsse\Database::articleList + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testUseTooFewValuesInArrayContext(string $option): void { $this->assertException("tooShort", "Db", "ExceptionInput"); Arsse::$db->articleList($this->user, (new Context)->$option([])); @@ -1062,6 +1412,14 @@ trait SeriesArticle { } } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAllArticlesNotHidden(): void { Arsse::$db->articleMark("jane.doe@example.com", ['hidden' => false]); $now = Date::transform(time(), "sql"); @@ -1073,6 +1431,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAllArticlesHidden(): void { Arsse::$db->articleMark("jane.doe@example.com", ['hidden' => true]); $now = Date::transform(time(), "sql"); @@ -1083,6 +1449,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAllArticlesUnreadAndNotHidden(): void { Arsse::$db->articleMark("jane.doe@example.com", ['read' => false, 'hidden' => false]); $now = Date::transform(time(), "sql"); @@ -1097,6 +1471,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAllArticlesReadAndHidden(): void { Arsse::$db->articleMark("jane.doe@example.com", ['read' => true, 'hidden' => true]); $now = Date::transform(time(), "sql"); @@ -1109,6 +1491,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAllArticlesUnreadAndHidden(): void { Arsse::$db->articleMark("jane.doe@example.com", ['read' => false,'hidden' => true]); $now = Date::transform(time(), "sql"); @@ -1122,6 +1512,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAllArticlesReadAndNotHidden(): void { Arsse::$db->articleMark("jane.doe@example.com", ['read' => true,'hidden' => false]); $now = Date::transform(time(), "sql"); @@ -1135,6 +1533,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkMultipleEditionsUnreadAndHiddenWithStale(): void { Arsse::$db->articleMark("jane.doe@example.com", ['read' => false,'hidden' => true], (new Context)->editions([1,2,19,20])); $now = Date::transform(time(), "sql"); @@ -1148,6 +1554,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAStaleEditionHidden(): void { Arsse::$db->articleMark("jane.doe@example.com", ['hidden' => true], (new Context)->edition(20)); $now = Date::transform(time(), "sql"); @@ -1157,6 +1571,14 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAStaleEditionUnreadAndHidden(): void { Arsse::$db->articleMark("jane.doe@example.com", ['read' => false,'hidden' => true], (new Context)->edition(20)); // only starred is changed $now = Date::transform(time(), "sql"); @@ -1166,12 +1588,28 @@ trait SeriesArticle { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleMark + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testMarkAStaleEditionUnreadAndNotHidden(): void { Arsse::$db->articleMark("jane.doe@example.com", ['read' => false,'hidden' => false], (new Context)->edition(20)); // no changes occur $state = $this->primeExpectations($this->data, $this->checkTables); $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::articleList + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testSelectScrapedContent(): void { $exp = [ ['id' => 101, 'content' => "

Article content 1

"], @@ -1185,6 +1623,14 @@ trait SeriesArticle { $this->assertResult($exp, Arsse::$db->articleList("jill.doe@example.com", (new Context)->subscription(15), ["id", "content"])); } + /** + * @covers \JKingWeb\Arsse\Database::articleList + * @covers \JKingWeb\Arsse\Database::articleQuery + * @covers \JKingWeb\Arsse\Database::articleValidateId + * @covers \JKingWeb\Arsse\Database::articleValidateEdition + * @covers \JKingWeb\Arsse\Database::articleColumns + * @covers \JKingWeb\Arsse\Database::articleFilter + */ public function testSearchScrapedContent(): void { $exp = [ ['id' => 101, 'content' => "

Scraped content 1

"], diff --git a/tests/cases/Database/SeriesCleanup.php b/tests/cases/Database/SeriesCleanup.php index 3ec32ace..7d745a06 100644 --- a/tests/cases/Database/SeriesCleanup.php +++ b/tests/cases/Database/SeriesCleanup.php @@ -170,6 +170,7 @@ trait SeriesCleanup { unset($this->data); } + /** @covers \JKingWeb\Arsse\Database::feedCleanup */ public function testCleanUpOrphanedFeeds(): void { Arsse::$db->feedCleanup(); $now = gmdate("Y-m-d H:i:s"); @@ -182,6 +183,7 @@ trait SeriesCleanup { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::feedCleanup */ public function testCleanUpOrphanedFeedsWithUnlimitedRetention(): void { Arsse::$conf->import([ 'purgeFeeds' => null, @@ -196,6 +198,7 @@ trait SeriesCleanup { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::iconCleanup */ public function testCleanUpOrphanedIcons(): void { Arsse::$db->iconCleanup(); $now = gmdate("Y-m-d H:i:s"); @@ -208,6 +211,7 @@ trait SeriesCleanup { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::iconCleanup */ public function testCleanUpOrphanedIconsWithUnlimitedRetention(): void { Arsse::$conf->import([ 'purgeFeeds' => null, @@ -222,6 +226,7 @@ trait SeriesCleanup { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::articleCleanup */ public function testCleanUpOldArticlesWithStandardRetention(): void { Arsse::$db->articleCleanup(); $state = $this->primeExpectations($this->data, [ @@ -233,6 +238,7 @@ trait SeriesCleanup { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::articleCleanup */ public function testCleanUpOldArticlesWithUnlimitedReadRetention(): void { Arsse::$conf->import([ 'purgeArticlesRead' => null, @@ -247,6 +253,7 @@ trait SeriesCleanup { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::articleCleanup */ public function testCleanUpOldArticlesWithUnlimitedUnreadRetention(): void { Arsse::$conf->import([ 'purgeArticlesUnread' => null, @@ -261,6 +268,7 @@ trait SeriesCleanup { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::articleCleanup */ public function testCleanUpOldArticlesWithUnlimitedRetention(): void { Arsse::$conf->import([ 'purgeArticlesRead' => null, @@ -273,6 +281,7 @@ trait SeriesCleanup { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::sessionCleanup */ public function testCleanUpExpiredSessions(): void { Arsse::$db->sessionCleanup(); $state = $this->primeExpectations($this->data, [ @@ -284,6 +293,7 @@ trait SeriesCleanup { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::tokenCleanup */ public function testCleanUpExpiredTokens(): void { Arsse::$db->tokenCleanup(); $state = $this->primeExpectations($this->data, [ diff --git a/tests/cases/Database/SeriesFeed.php b/tests/cases/Database/SeriesFeed.php index f80e4b04..4e18c774 100644 --- a/tests/cases/Database/SeriesFeed.php +++ b/tests/cases/Database/SeriesFeed.php @@ -192,10 +192,12 @@ trait SeriesFeed { unset($this->data, $this->matches); } + /** @covers \JKingWeb\Arsse\Database::feedMatchLatest */ public function testListLatestItems(): void { $this->assertResult($this->matches, Arsse::$db->feedMatchLatest(1, 2)); } + /** @covers \JKingWeb\Arsse\Database::feedMatchIds */ public function testMatchItemsById(): void { $this->assertResult($this->matches, Arsse::$db->feedMatchIds(1, ['804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180','db3e736c2c492f5def5c5da33ddcbea1824040e9ced2142069276b0a6e291a41'])); foreach ($this->matches as $m) { @@ -207,7 +209,10 @@ trait SeriesFeed { $this->assertResult([['id' => 1]], Arsse::$db->feedMatchIds(1, ['e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda'])); // this ID appears in both feed 1 and feed 2; only one result should be returned } - /** @dataProvider provideFilterRules */ + /** + * @dataProvider provideFilterRules + * @covers \JKingWeb\Arsse\Database::feedRulesGet + */ public function testGetRules(int $in, array $exp): void { $this->assertSame($exp, Arsse::$db->feedRulesGet($in)); } @@ -222,6 +227,7 @@ trait SeriesFeed { ]; } + /** @covers \JKingWeb\Arsse\Database::feedUpdate */ public function testUpdateAFeed(): void { // update a valid feed with both new and changed items Arsse::$db->feedUpdate(1); @@ -263,21 +269,25 @@ trait SeriesFeed { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::feedUpdate */ public function testUpdateAMissingFeed(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->feedUpdate(2112); } + /** @covers \JKingWeb\Arsse\Database::feedUpdate */ public function testUpdateAnInvalidFeed(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); Arsse::$db->feedUpdate(-1); } + /** @covers \JKingWeb\Arsse\Database::feedUpdate */ public function testUpdateAFeedThrowingExceptions(): void { $this->assertException("invalidUrl", "Feed"); Arsse::$db->feedUpdate(3, true); } + /** @covers \JKingWeb\Arsse\Database::feedUpdate */ public function testUpdateAFeedWithEnclosuresAndCategories(): void { Arsse::$db->feedUpdate(5); $state = $this->primeExpectations($this->data, [ @@ -298,6 +308,7 @@ trait SeriesFeed { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::feedListStale */ public function testListStaleFeeds(): void { $this->assertEquals([1,3,4], Arsse::$db->feedListStale()); Arsse::$db->feedUpdate(3); @@ -305,6 +316,7 @@ trait SeriesFeed { $this->assertEquals([1], Arsse::$db->feedListStale()); } + /** @covers \JKingWeb\Arsse\Database::feedUpdate */ public function testCheckIconDuringFeedUpdate(): void { Arsse::$db->feedUpdate(6); $state = $this->primeExpectations($this->data, [ @@ -314,6 +326,7 @@ trait SeriesFeed { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::feedUpdate */ public function testAssignIconDuringFeedUpdate(): void { Arsse::$db->feedUpdate(7); $state = $this->primeExpectations($this->data, [ @@ -324,6 +337,7 @@ trait SeriesFeed { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::feedUpdate */ public function testChangeIconDuringFeedUpdate(): void { Arsse::$db->feedUpdate(8); $state = $this->primeExpectations($this->data, [ @@ -334,6 +348,7 @@ trait SeriesFeed { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::feedUpdate */ public function testAddIconDuringFeedUpdate(): void { Arsse::$db->feedUpdate(9); $state = $this->primeExpectations($this->data, [ @@ -344,4 +359,21 @@ trait SeriesFeed { $state['arsse_icons']['rows'][] = [4,'http://localhost:8000/Icon/SVG2','image/svg+xml','']; $this->compareExpectations(static::$drv, $state); } + + /** @covers \JKingWeb\Arsse\Database::feedUpdate */ + public function testUpdateUnmodifiedFeed(): void { + $this->markTestIncomplete("FIXME: there is a bug here around calculation of nextFetch date"); + $state = $this->primeExpectations($this->data, [ + 'arsse_icons' => ["id", "url", "type", "data"], + 'arsse_feeds' => ["id", "url", "title", "err_count", "err_msg", "modified", "next_fetch", "size", "icon"], + 'arsse_subscriptions' => ["id", "owner", "feed", "keep_rule", "block_rule"], + 'arsse_articles' => ["id", "feed", "url", "title", "author", "published", "edited", "content", "guid", "url_title_hash", "url_content_hash", "title_content_hash", "modified"], + 'arsse_editions' => ["id", "article", "modified"], + 'arsse_marks' => ["article", "subscription", "read", "starred", "hidden", "modified"], + 'arsse_enclosures' => ["article", "url", "type"], + 'arsse_categories' => ["article", "name"], + ]); + Arsse::$db->feedUpdate(4); + $this->compareExpectations(static::$drv, $state); + } } diff --git a/tests/cases/Database/SeriesFolder.php b/tests/cases/Database/SeriesFolder.php index 6b0a0f56..ea0946e1 100644 --- a/tests/cases/Database/SeriesFolder.php +++ b/tests/cases/Database/SeriesFolder.php @@ -99,6 +99,11 @@ trait SeriesFolder { unset($this->data); } + /** + * @covers \JKingWeb\Arsse\Database::folderAdd + * @covers \JKingWeb\Arsse\Database::folderValidateId + * @covers \JKingWeb\Arsse\Database::folderValidateName + */ public function testAddARootFolder(): void { $user = "john.doe@example.com"; $folderID = $this->nextID("arsse_folders"); @@ -108,11 +113,21 @@ trait SeriesFolder { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::folderAdd + * @covers \JKingWeb\Arsse\Database::folderValidateId + * @covers \JKingWeb\Arsse\Database::folderValidateName + */ public function testAddADuplicateRootFolder(): void { $this->assertException("constraintViolation", "Db", "ExceptionInput"); Arsse::$db->folderAdd("john.doe@example.com", ['name' => "Politics"]); } + /** + * @covers \JKingWeb\Arsse\Database::folderAdd + * @covers \JKingWeb\Arsse\Database::folderValidateId + * @covers \JKingWeb\Arsse\Database::folderValidateName + */ public function testAddANestedFolder(): void { $user = "john.doe@example.com"; $folderID = $this->nextID("arsse_folders"); @@ -122,36 +137,70 @@ trait SeriesFolder { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::folderAdd + * @covers \JKingWeb\Arsse\Database::folderValidateId + * @covers \JKingWeb\Arsse\Database::folderValidateName + */ public function testAddANestedFolderToAMissingParent(): void { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->folderAdd("john.doe@example.com", ['name' => "Sociology", 'parent' => 2112]); } + /** + * @covers \JKingWeb\Arsse\Database::folderAdd + * @covers \JKingWeb\Arsse\Database::folderValidateId + * @covers \JKingWeb\Arsse\Database::folderValidateName + */ public function testAddANestedFolderToAnInvalidParent(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); Arsse::$db->folderAdd("john.doe@example.com", ['name' => "Sociology", 'parent' => "stringFolderId"]); } + /** + * @covers \JKingWeb\Arsse\Database::folderAdd + * @covers \JKingWeb\Arsse\Database::folderValidateId + * @covers \JKingWeb\Arsse\Database::folderValidateName + */ public function testAddANestedFolderForTheWrongOwner(): void { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->folderAdd("john.doe@example.com", ['name' => "Sociology", 'parent' => 4]); // folder ID 4 belongs to Jane } + /** + * @covers \JKingWeb\Arsse\Database::folderAdd + * @covers \JKingWeb\Arsse\Database::folderValidateId + * @covers \JKingWeb\Arsse\Database::folderValidateName + */ public function testAddAFolderWithAMissingName(): void { $this->assertException("missing", "Db", "ExceptionInput"); Arsse::$db->folderAdd("john.doe@example.com", []); } + /** + * @covers \JKingWeb\Arsse\Database::folderAdd + * @covers \JKingWeb\Arsse\Database::folderValidateId + * @covers \JKingWeb\Arsse\Database::folderValidateName + */ public function testAddAFolderWithABlankName(): void { $this->assertException("missing", "Db", "ExceptionInput"); Arsse::$db->folderAdd("john.doe@example.com", ['name' => ""]); } + /** + * @covers \JKingWeb\Arsse\Database::folderAdd + * @covers \JKingWeb\Arsse\Database::folderValidateId + * @covers \JKingWeb\Arsse\Database::folderValidateName + */ public function testAddAFolderWithAWhitespaceName(): void { $this->assertException("whitespace", "Db", "ExceptionInput"); Arsse::$db->folderAdd("john.doe@example.com", ['name' => " "]); } + /** + * @covers \JKingWeb\Arsse\Database::folderList + * @covers \JKingWeb\Arsse\Database::folderValidateId + */ public function testListRootFolders(): void { $exp = [ ['id' => 5, 'name' => "Politics", 'parent' => null, 'children' => 0, 'feeds' => 2], @@ -166,6 +215,10 @@ trait SeriesFolder { $this->assertResult($exp, Arsse::$db->folderList("admin@example.net", null, false)); } + /** + * @covers \JKingWeb\Arsse\Database::folderList + * @covers \JKingWeb\Arsse\Database::folderValidateId + */ public function testListFoldersRecursively(): void { $exp = [ ['id' => 5, 'name' => "Politics", 'parent' => null, 'children' => 0, 'feeds' => 2], @@ -185,16 +238,25 @@ trait SeriesFolder { $this->assertResult($exp, Arsse::$db->folderList("jane.doe@example.com", 4, true)); } + /** + * @covers \JKingWeb\Arsse\Database::folderList + * @covers \JKingWeb\Arsse\Database::folderValidateId + */ public function testListFoldersOfAMissingParent(): void { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->folderList("john.doe@example.com", 2112); } + /** + * @covers \JKingWeb\Arsse\Database::folderList + * @covers \JKingWeb\Arsse\Database::folderValidateId + */ public function testListFoldersOfTheWrongOwner(): void { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->folderList("john.doe@example.com", 4); // folder ID 4 belongs to Jane } + /** @covers \JKingWeb\Arsse\Database::folderRemove */ public function testRemoveAFolder(): void { $this->assertTrue(Arsse::$db->folderRemove("john.doe@example.com", 6)); $state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]); @@ -202,6 +264,7 @@ trait SeriesFolder { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::folderRemove */ public function testRemoveAFolderTree(): void { $this->assertTrue(Arsse::$db->folderRemove("john.doe@example.com", 1)); $state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]); @@ -211,21 +274,25 @@ trait SeriesFolder { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::folderRemove */ public function testRemoveAMissingFolder(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->folderRemove("john.doe@example.com", 2112); } + /** @covers \JKingWeb\Arsse\Database::folderRemove */ public function testRemoveAnInvalidFolder(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); Arsse::$db->folderRemove("john.doe@example.com", -1); } + /** @covers \JKingWeb\Arsse\Database::folderRemove */ public function testRemoveAFolderOfTheWrongOwner(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->folderRemove("john.doe@example.com", 4); // folder ID 4 belongs to Jane } + /** @covers \JKingWeb\Arsse\Database::folderPropertiesGet */ public function testGetThePropertiesOfAFolder(): void { $exp = [ 'id' => 6, @@ -235,25 +302,33 @@ trait SeriesFolder { $this->assertArraySubset($exp, Arsse::$db->folderPropertiesGet("john.doe@example.com", 6)); } + /** @covers \JKingWeb\Arsse\Database::folderPropertiesGet */ public function testGetThePropertiesOfAMissingFolder(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->folderPropertiesGet("john.doe@example.com", 2112); } + /** @covers \JKingWeb\Arsse\Database::folderPropertiesGet */ public function testGetThePropertiesOfAnInvalidFolder(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); Arsse::$db->folderPropertiesGet("john.doe@example.com", -1); } + /** @covers \JKingWeb\Arsse\Database::folderPropertiesGet */ public function testGetThePropertiesOfAFolderOfTheWrongOwner(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->folderPropertiesGet("john.doe@example.com", 4); // folder ID 4 belongs to Jane } + /** @covers \JKingWeb\Arsse\Database::folderPropertiesSet */ public function testMakeNoChangesToAFolder(): void { $this->assertFalse(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, [])); } + /** + * @covers \JKingWeb\Arsse\Database::folderPropertiesSet + * @covers \JKingWeb\Arsse\Database::folderValidateName + */ public function testRenameAFolder(): void { $this->assertTrue(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['name' => "Opinion"])); $state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]); @@ -261,25 +336,45 @@ trait SeriesFolder { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::folderPropertiesSet + * @covers \JKingWeb\Arsse\Database::folderValidateName + */ public function testRenameTheRootFolder(): void { $this->assertFalse(Arsse::$db->folderPropertiesSet("john.doe@example.com", null, ['name' => "Opinion"])); } + /** + * @covers \JKingWeb\Arsse\Database::folderPropertiesSet + * @covers \JKingWeb\Arsse\Database::folderValidateName + */ public function testRenameAFolderToTheEmptyString(): void { $this->assertException("missing", "Db", "ExceptionInput"); $this->assertTrue(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['name' => ""])); } + /** + * @covers \JKingWeb\Arsse\Database::folderPropertiesSet + * @covers \JKingWeb\Arsse\Database::folderValidateName + */ public function testRenameAFolderToWhitespaceOnly(): void { $this->assertException("whitespace", "Db", "ExceptionInput"); $this->assertTrue(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['name' => " "])); } + /** + * @covers \JKingWeb\Arsse\Database::folderPropertiesSet + * @covers \JKingWeb\Arsse\Database::folderValidateName + */ public function testRenameAFolderToAnInvalidValue(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); $this->assertTrue(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['name' => []])); } + /** + * @covers \JKingWeb\Arsse\Database::folderPropertiesSet + * @covers \JKingWeb\Arsse\Database::folderValidateMove + */ public function testMoveAFolder(): void { $this->assertTrue(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['parent' => 5])); $state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]); @@ -287,51 +382,83 @@ trait SeriesFolder { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::folderPropertiesSet + * @covers \JKingWeb\Arsse\Database::folderValidateMove + */ public function testMoveTheRootFolder(): void { $this->assertException("circularDependence", "Db", "ExceptionInput"); Arsse::$db->folderPropertiesSet("john.doe@example.com", 0, ['parent' => 1]); } + /** + * @covers \JKingWeb\Arsse\Database::folderPropertiesSet + * @covers \JKingWeb\Arsse\Database::folderValidateMove + */ public function testMoveAFolderToItsDescendant(): void { $this->assertException("circularDependence", "Db", "ExceptionInput"); Arsse::$db->folderPropertiesSet("john.doe@example.com", 1, ['parent' => 3]); } + /** + * @covers \JKingWeb\Arsse\Database::folderPropertiesSet + * @covers \JKingWeb\Arsse\Database::folderValidateMove + */ public function testMoveAFolderToItself(): void { $this->assertException("circularDependence", "Db", "ExceptionInput"); Arsse::$db->folderPropertiesSet("john.doe@example.com", 1, ['parent' => 1]); } + /** + * @covers \JKingWeb\Arsse\Database::folderPropertiesSet + * @covers \JKingWeb\Arsse\Database::folderValidateMove + */ public function testMoveAFolderToAMissingParent(): void { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->folderPropertiesSet("john.doe@example.com", 1, ['parent' => 2112]); } + /** + * @covers \JKingWeb\Arsse\Database::folderPropertiesSet + * @covers \JKingWeb\Arsse\Database::folderValidateMove + */ public function testMoveAFolderToAnInvalidParent(): void { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->folderPropertiesSet("john.doe@example.com", 1, ['parent' => "ThisFolderDoesNotExist"]); } + /** + * @covers \JKingWeb\Arsse\Database::folderPropertiesSet + * @covers \JKingWeb\Arsse\Database::folderValidateMove + */ public function testCauseAFolderCollision(): void { $this->assertException("constraintViolation", "Db", "ExceptionInput"); Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['parent' => null]); } + /** + * @covers \JKingWeb\Arsse\Database::folderPropertiesSet + * @covers \JKingWeb\Arsse\Database::folderValidateName + * @covers \JKingWeb\Arsse\Database::folderValidateMove + */ public function testCauseACompoundFolderCollision(): void { $this->assertException("constraintViolation", "Db", "ExceptionInput"); Arsse::$db->folderPropertiesSet("john.doe@example.com", 3, ['parent' => null, 'name' => "Technology"]); } + /** @covers \JKingWeb\Arsse\Database::folderPropertiesSet */ public function testSetThePropertiesOfAMissingFolder(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->folderPropertiesSet("john.doe@example.com", 2112, ['parent' => null]); } + /** @covers \JKingWeb\Arsse\Database::folderPropertiesSet */ public function testSetThePropertiesOfAnInvalidFolder(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); Arsse::$db->folderPropertiesSet("john.doe@example.com", -1, ['parent' => null]); } + /** @covers \JKingWeb\Arsse\Database::folderPropertiesSet */ public function testSetThePropertiesOfAFolderForTheWrongOwner(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->folderPropertiesSet("john.doe@example.com", 4, ['parent' => null]); // folder ID 4 belongs to Jane diff --git a/tests/cases/Database/SeriesIcon.php b/tests/cases/Database/SeriesIcon.php index 31faf17d..361a0280 100644 --- a/tests/cases/Database/SeriesIcon.php +++ b/tests/cases/Database/SeriesIcon.php @@ -83,6 +83,7 @@ trait SeriesIcon { unset($this->data); } + /** @covers \JKingWeb\Arsse\Database::iconList */ public function testListTheIconsOfAUser() { $exp = [ ['id' => 1,'url' => 'http://localhost:8000/Icon/PNG', 'type' => 'image/png', 'data' => base64_decode("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMjHxIGmVAAAADUlEQVQYV2NgYGBgAAAABQABijPjAAAAAABJRU5ErkJggg==")], diff --git a/tests/cases/Database/SeriesLabel.php b/tests/cases/Database/SeriesLabel.php index 2c6f9156..4170376c 100644 --- a/tests/cases/Database/SeriesLabel.php +++ b/tests/cases/Database/SeriesLabel.php @@ -255,6 +255,10 @@ trait SeriesLabel { unset($this->data, $this->checkLabels, $this->checkMembers, $this->user); } + /** + * @covers \JKingWeb\Arsse\Database::labelAdd + * @covers \JKingWeb\Arsse\Database::labelValidateName + */ public function testAddALabel(): void { $user = "john.doe@example.com"; $labelID = $this->nextID("arsse_labels"); @@ -264,26 +268,43 @@ trait SeriesLabel { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::labelAdd + * @covers \JKingWeb\Arsse\Database::labelValidateName + */ public function testAddADuplicateLabel(): void { $this->assertException("constraintViolation", "Db", "ExceptionInput"); Arsse::$db->labelAdd("john.doe@example.com", ['name' => "Interesting"]); } + /** + * @covers \JKingWeb\Arsse\Database::labelAdd + * @covers \JKingWeb\Arsse\Database::labelValidateName + */ public function testAddALabelWithAMissingName(): void { $this->assertException("missing", "Db", "ExceptionInput"); Arsse::$db->labelAdd("john.doe@example.com", []); } + /** + * @covers \JKingWeb\Arsse\Database::labelAdd + * @covers \JKingWeb\Arsse\Database::labelValidateName + */ public function testAddALabelWithABlankName(): void { $this->assertException("missing", "Db", "ExceptionInput"); Arsse::$db->labelAdd("john.doe@example.com", ['name' => ""]); } + /** + * @covers \JKingWeb\Arsse\Database::labelAdd + * @covers \JKingWeb\Arsse\Database::labelValidateName + */ public function testAddALabelWithAWhitespaceName(): void { $this->assertException("whitespace", "Db", "ExceptionInput"); Arsse::$db->labelAdd("john.doe@example.com", ['name' => " "]); } + /** @covers \JKingWeb\Arsse\Database::labelList */ public function testListLabels(): void { $exp = [ ['id' => 2, 'name' => "Fascinating", 'articles' => 3, 'read' => 1], @@ -299,6 +320,10 @@ trait SeriesLabel { $this->assertResult($exp, Arsse::$db->labelList("jane.doe@example.com", false)); } + /** + * @covers \JKingWeb\Arsse\Database::labelRemove + * @covers \JKingWeb\Arsse\Database::labelValidateId + */ public function testRemoveALabel(): void { $this->assertTrue(Arsse::$db->labelRemove("john.doe@example.com", 1)); $state = $this->primeExpectations($this->data, $this->checkLabels); @@ -306,6 +331,10 @@ trait SeriesLabel { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::labelRemove + * @covers \JKingWeb\Arsse\Database::labelValidateId + */ public function testRemoveALabelByName(): void { $this->assertTrue(Arsse::$db->labelRemove("john.doe@example.com", "Interesting", true)); $state = $this->primeExpectations($this->data, $this->checkLabels); @@ -313,26 +342,46 @@ trait SeriesLabel { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::labelRemove + * @covers \JKingWeb\Arsse\Database::labelValidateId + */ public function testRemoveAMissingLabel(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->labelRemove("john.doe@example.com", 2112); } + /** + * @covers \JKingWeb\Arsse\Database::labelRemove + * @covers \JKingWeb\Arsse\Database::labelValidateId + */ public function testRemoveAnInvalidLabel(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); Arsse::$db->labelRemove("john.doe@example.com", -1); } + /** + * @covers \JKingWeb\Arsse\Database::labelRemove + * @covers \JKingWeb\Arsse\Database::labelValidateId + */ public function testRemoveAnInvalidLabelByName(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); Arsse::$db->labelRemove("john.doe@example.com", [], true); } + /** + * @covers \JKingWeb\Arsse\Database::labelRemove + * @covers \JKingWeb\Arsse\Database::labelValidateId + */ public function testRemoveALabelOfTheWrongOwner(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->labelRemove("john.doe@example.com", 3); // label ID 3 belongs to Jane } + /** + * @covers \JKingWeb\Arsse\Database::labelPropertiesGet + * @covers \JKingWeb\Arsse\Database::labelValidateId + */ public function testGetThePropertiesOfALabel(): void { $exp = [ 'id' => 2, @@ -344,30 +393,56 @@ trait SeriesLabel { $this->assertArraySubset($exp, Arsse::$db->labelPropertiesGet("john.doe@example.com", "Fascinating", true)); } + /** + * @covers \JKingWeb\Arsse\Database::labelPropertiesGet + * @covers \JKingWeb\Arsse\Database::labelValidateId + */ public function testGetThePropertiesOfAMissingLabel(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->labelPropertiesGet("john.doe@example.com", 2112); } + /** + * @covers \JKingWeb\Arsse\Database::labelPropertiesGet + * @covers \JKingWeb\Arsse\Database::labelValidateId + */ public function testGetThePropertiesOfAnInvalidLabel(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); Arsse::$db->labelPropertiesGet("john.doe@example.com", -1); } + /** + * @covers \JKingWeb\Arsse\Database::labelPropertiesGet + * @covers \JKingWeb\Arsse\Database::labelValidateId + */ public function testGetThePropertiesOfAnInvalidLabelByName(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); Arsse::$db->labelPropertiesGet("john.doe@example.com", [], true); } + /** + * @covers \JKingWeb\Arsse\Database::labelPropertiesGet + * @covers \JKingWeb\Arsse\Database::labelValidateId + */ public function testGetThePropertiesOfALabelOfTheWrongOwner(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->labelPropertiesGet("john.doe@example.com", 3); // label ID 3 belongs to Jane } + /** + * @covers \JKingWeb\Arsse\Database::labelPropertiesSet + * @covers \JKingWeb\Arsse\Database::labelValidateId + * @covers \JKingWeb\Arsse\Database::labelValidateName + */ public function testMakeNoChangesToALabel(): void { $this->assertFalse(Arsse::$db->labelPropertiesSet("john.doe@example.com", 1, [])); } + /** + * @covers \JKingWeb\Arsse\Database::labelPropertiesSet + * @covers \JKingWeb\Arsse\Database::labelValidateId + * @covers \JKingWeb\Arsse\Database::labelValidateName + */ public function testRenameALabel(): void { $this->assertTrue(Arsse::$db->labelPropertiesSet("john.doe@example.com", 1, ['name' => "Curious"])); $state = $this->primeExpectations($this->data, $this->checkLabels); @@ -375,6 +450,11 @@ trait SeriesLabel { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::labelPropertiesSet + * @covers \JKingWeb\Arsse\Database::labelValidateId + * @covers \JKingWeb\Arsse\Database::labelValidateName + */ public function testRenameALabelByName(): void { $this->assertTrue(Arsse::$db->labelPropertiesSet("john.doe@example.com", "Interesting", ['name' => "Curious"], true)); $state = $this->primeExpectations($this->data, $this->checkLabels); @@ -382,46 +462,90 @@ trait SeriesLabel { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::labelPropertiesSet + * @covers \JKingWeb\Arsse\Database::labelValidateId + * @covers \JKingWeb\Arsse\Database::labelValidateName + */ public function testRenameALabelToTheEmptyString(): void { $this->assertException("missing", "Db", "ExceptionInput"); $this->assertTrue(Arsse::$db->labelPropertiesSet("john.doe@example.com", 1, ['name' => ""])); } + /** + * @covers \JKingWeb\Arsse\Database::labelPropertiesSet + * @covers \JKingWeb\Arsse\Database::labelValidateId + * @covers \JKingWeb\Arsse\Database::labelValidateName + */ public function testRenameALabelToWhitespaceOnly(): void { $this->assertException("whitespace", "Db", "ExceptionInput"); $this->assertTrue(Arsse::$db->labelPropertiesSet("john.doe@example.com", 1, ['name' => " "])); } + /** + * @covers \JKingWeb\Arsse\Database::labelPropertiesSet + * @covers \JKingWeb\Arsse\Database::labelValidateId + * @covers \JKingWeb\Arsse\Database::labelValidateName + */ public function testRenameALabelToAnInvalidValue(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); $this->assertTrue(Arsse::$db->labelPropertiesSet("john.doe@example.com", 1, ['name' => []])); } + /** + * @covers \JKingWeb\Arsse\Database::labelPropertiesSet + * @covers \JKingWeb\Arsse\Database::labelValidateId + * @covers \JKingWeb\Arsse\Database::labelValidateName + */ public function testCauseALabelCollision(): void { $this->assertException("constraintViolation", "Db", "ExceptionInput"); Arsse::$db->labelPropertiesSet("john.doe@example.com", 1, ['name' => "Fascinating"]); } + /** + * @covers \JKingWeb\Arsse\Database::labelPropertiesSet + * @covers \JKingWeb\Arsse\Database::labelValidateId + * @covers \JKingWeb\Arsse\Database::labelValidateName + */ public function testSetThePropertiesOfAMissingLabel(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->labelPropertiesSet("john.doe@example.com", 2112, ['name' => "Exciting"]); } + /** + * @covers \JKingWeb\Arsse\Database::labelPropertiesSet + * @covers \JKingWeb\Arsse\Database::labelValidateId + * @covers \JKingWeb\Arsse\Database::labelValidateName + */ public function testSetThePropertiesOfAnInvalidLabel(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); Arsse::$db->labelPropertiesSet("john.doe@example.com", -1, ['name' => "Exciting"]); } + /** + * @covers \JKingWeb\Arsse\Database::labelPropertiesSet + * @covers \JKingWeb\Arsse\Database::labelValidateId + * @covers \JKingWeb\Arsse\Database::labelValidateName + */ public function testSetThePropertiesOfAnInvalidLabelByName(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); Arsse::$db->labelPropertiesSet("john.doe@example.com", [], ['name' => "Exciting"], true); } + /** + * @covers \JKingWeb\Arsse\Database::labelPropertiesSet + * @covers \JKingWeb\Arsse\Database::labelValidateId + * @covers \JKingWeb\Arsse\Database::labelValidateName + */ public function testSetThePropertiesOfALabelForTheWrongOwner(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->labelPropertiesSet("john.doe@example.com", 3, ['name' => "Exciting"]); // label ID 3 belongs to Jane } + /** + * @covers \JKingWeb\Arsse\Database::labelArticlesGet + * @covers \JKingWeb\Arsse\Database::labelValidateId + */ public function testListLabelledArticles(): void { $exp = [1,19]; $this->assertEquals($exp, Arsse::$db->labelArticlesGet("john.doe@example.com", 1)); @@ -434,16 +558,28 @@ trait SeriesLabel { $this->assertEquals($exp, Arsse::$db->labelArticlesGet("john.doe@example.com", "Lonely", true)); } + /** + * @covers \JKingWeb\Arsse\Database::labelArticlesGet + * @covers \JKingWeb\Arsse\Database::labelValidateId + */ public function testListLabelledArticlesForAMissingLabel(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->labelArticlesGet("john.doe@example.com", 3); } + /** + * @covers \JKingWeb\Arsse\Database::labelArticlesGet + * @covers \JKingWeb\Arsse\Database::labelValidateId + */ public function testListLabelledArticlesForAnInvalidLabel(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); Arsse::$db->labelArticlesGet("john.doe@example.com", -1); } + /** + * @covers \JKingWeb\Arsse\Database::labelArticlesSet + * @covers \JKingWeb\Arsse\Database::labelValidateId + */ public function testApplyALabelToArticles(): void { Arsse::$db->labelArticlesSet("john.doe@example.com", 1, (new Context)->articles([2,5])); $state = $this->primeExpectations($this->data, $this->checkMembers); @@ -452,6 +588,10 @@ trait SeriesLabel { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::labelArticlesSet + * @covers \JKingWeb\Arsse\Database::labelValidateId + */ public function testClearALabelFromArticles(): void { Arsse::$db->labelArticlesSet("john.doe@example.com", 1, (new Context)->articles([1,5]), Database::ASSOC_REMOVE); $state = $this->primeExpectations($this->data, $this->checkMembers); @@ -459,6 +599,10 @@ trait SeriesLabel { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::labelArticlesSet + * @covers \JKingWeb\Arsse\Database::labelValidateId + */ public function testApplyALabelToArticlesByName(): void { Arsse::$db->labelArticlesSet("john.doe@example.com", "Interesting", (new Context)->articles([2,5]), Database::ASSOC_ADD, true); $state = $this->primeExpectations($this->data, $this->checkMembers); @@ -467,6 +611,10 @@ trait SeriesLabel { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::labelArticlesSet + * @covers \JKingWeb\Arsse\Database::labelValidateId + */ public function testClearALabelFromArticlesByName(): void { Arsse::$db->labelArticlesSet("john.doe@example.com", "Interesting", (new Context)->articles([1,5]), Database::ASSOC_REMOVE, true); $state = $this->primeExpectations($this->data, $this->checkMembers); @@ -474,18 +622,30 @@ trait SeriesLabel { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::labelArticlesSet + * @covers \JKingWeb\Arsse\Database::labelValidateId + */ public function testApplyALabelToNoArticles(): void { Arsse::$db->labelArticlesSet("john.doe@example.com", 1, (new Context)->articles([10000])); $state = $this->primeExpectations($this->data, $this->checkMembers); $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::labelArticlesSet + * @covers \JKingWeb\Arsse\Database::labelValidateId + */ public function testClearALabelFromNoArticles(): void { Arsse::$db->labelArticlesSet("john.doe@example.com", 1, (new Context)->articles([10000]), Database::ASSOC_REMOVE); $state = $this->primeExpectations($this->data, $this->checkMembers); $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::labelArticlesSet + * @covers \JKingWeb\Arsse\Database::labelValidateId + */ public function testReplaceArticlesOfALabel(): void { Arsse::$db->labelArticlesSet("john.doe@example.com", 1, (new Context)->articles([2,5]), Database::ASSOC_REPLACE); $state = $this->primeExpectations($this->data, $this->checkMembers); @@ -496,6 +656,10 @@ trait SeriesLabel { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::labelArticlesSet + * @covers \JKingWeb\Arsse\Database::labelValidateId + */ public function testPurgeArticlesOfALabel(): void { Arsse::$db->labelArticlesSet("john.doe@example.com", 1, (new Context)->articles([10000]), Database::ASSOC_REPLACE); $state = $this->primeExpectations($this->data, $this->checkMembers); diff --git a/tests/cases/Database/SeriesMeta.php b/tests/cases/Database/SeriesMeta.php index 8037dcbb..5507e060 100644 --- a/tests/cases/Database/SeriesMeta.php +++ b/tests/cases/Database/SeriesMeta.php @@ -36,6 +36,7 @@ trait SeriesMeta { unset($this->data); } + /** @covers \JKingWeb\Arsse\Database::metaSet */ public function testAddANewValue(): void { $this->assertTrue(Arsse::$db->metaSet("favourite", "Cygnus X-1")); $state = $this->primeExpectations($this->data, ['arsse_meta' => ['key','value']]); @@ -43,6 +44,7 @@ trait SeriesMeta { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::metaSet */ public function testAddANewTypedValue(): void { $this->assertTrue(Arsse::$db->metaSet("answer", 42, "int")); $this->assertTrue(Arsse::$db->metaSet("true", true, "bool")); @@ -56,6 +58,7 @@ trait SeriesMeta { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::metaSet */ public function testChangeAnExistingValue(): void { $this->assertTrue(Arsse::$db->metaSet("album", "Hemispheres")); $state = $this->primeExpectations($this->data, ['arsse_meta' => ['key','value']]); @@ -63,6 +66,7 @@ trait SeriesMeta { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::metaRemove */ public function testRemoveAValue(): void { $this->assertTrue(Arsse::$db->metaRemove("album")); $this->assertFalse(Arsse::$db->metaRemove("album")); @@ -71,6 +75,7 @@ trait SeriesMeta { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::metaGet */ public function testRetrieveAValue(): void { $this->assertSame("".Database::SCHEMA_VERSION, Arsse::$db->metaGet("schema_version")); $this->assertSame("A Farewell to Kings", Arsse::$db->metaGet("album")); diff --git a/tests/cases/Database/SeriesMiscellany.php b/tests/cases/Database/SeriesMiscellany.php index 102f56a7..0decc917 100644 --- a/tests/cases/Database/SeriesMiscellany.php +++ b/tests/cases/Database/SeriesMiscellany.php @@ -20,12 +20,22 @@ trait SeriesMiscellany { protected function tearDownSeriesMiscellany(): void { } + /** + * @covers \JKingWeb\Arsse\Database::__construct + * @covers \JKingWeb\Arsse\Database::driverSchemaVersion + * @covers \JKingWeb\Arsse\Database::driverSchemaUpdate + */ public function testInitializeDatabase(): void { static::dbRaze(static::$drv); $d = new Database(true); $this->assertSame(Database::SCHEMA_VERSION, $d->driverSchemaVersion()); } + /** + * @covers \JKingWeb\Arsse\Database::__construct + * @covers \JKingWeb\Arsse\Database::driverSchemaVersion + * @covers \JKingWeb\Arsse\Database::driverSchemaUpdate + */ public function testManuallyInitializeDatabase(): void { static::dbRaze(static::$drv); $d = new Database(false); @@ -35,10 +45,12 @@ trait SeriesMiscellany { $this->assertFalse($d->driverSchemaUpdate()); } + /** @covers \JKingWeb\Arsse\Database::driverCharsetAcceptable */ public function testCheckCharacterSetAcceptability(): void { $this->assertIsBool(Arsse::$db->driverCharsetAcceptable()); } + /** @covers \JKingWeb\Arsse\Database::driverMaintenance */ public function testPerformMaintenance(): void { $this->assertTrue(Arsse::$db->driverMaintenance()); } diff --git a/tests/cases/Database/SeriesSession.php b/tests/cases/Database/SeriesSession.php index a22c1d3a..4f24b3a2 100644 --- a/tests/cases/Database/SeriesSession.php +++ b/tests/cases/Database/SeriesSession.php @@ -55,6 +55,10 @@ trait SeriesSession { unset($this->data); } + /** + * @covers \JKingWeb\Arsse\Database::sessionResume + * @covers \JKingWeb\Arsse\Database::sessionExpiringSoon + */ public function testResumeAValidSession(): void { $exp1 = [ 'id' => "80fa94c1a11f11e78667001e673b2560", @@ -73,21 +77,34 @@ trait SeriesSession { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::sessionResume + * @covers \JKingWeb\Arsse\Database::sessionExpiringSoon + */ public function testResumeAMissingSession(): void { $this->assertException("invalid", "User", "ExceptionSession"); Arsse::$db->sessionResume("thisSessionDoesNotExist"); } + /** + * @covers \JKingWeb\Arsse\Database::sessionResume + * @covers \JKingWeb\Arsse\Database::sessionExpiringSoon + */ public function testResumeAnExpiredSession(): void { $this->assertException("invalid", "User", "ExceptionSession"); Arsse::$db->sessionResume("27c6de8da13311e78667001e673b2560"); } + /** + * @covers \JKingWeb\Arsse\Database::sessionResume + * @covers \JKingWeb\Arsse\Database::sessionExpiringSoon + */ public function testResumeAStaleSession(): void { $this->assertException("invalid", "User", "ExceptionSession"); Arsse::$db->sessionResume("ab3b3eb8a13311e78667001e673b2560"); } + /** @covers \JKingWeb\Arsse\Database::sessionCreate */ public function testCreateASession(): void { $user = "jane.doe@example.com"; $id = Arsse::$db->sessionCreate($user); @@ -97,6 +114,7 @@ trait SeriesSession { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::sessionDestroy */ public function testDestroyASession(): void { $user = "jane.doe@example.com"; $id = "80fa94c1a11f11e78667001e673b2560"; @@ -108,6 +126,7 @@ trait SeriesSession { $this->assertFalse(Arsse::$db->sessionDestroy($user, $id)); } + /** @covers \JKingWeb\Arsse\Database::sessionDestroy */ public function testDestroyAllSessions(): void { $user = "jane.doe@example.com"; $this->assertTrue(Arsse::$db->sessionDestroy($user)); @@ -118,6 +137,7 @@ trait SeriesSession { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::sessionDestroy */ public function testDestroyASessionForTheWrongUser(): void { $user = "john.doe@example.com"; $id = "80fa94c1a11f11e78667001e673b2560"; diff --git a/tests/cases/Database/SeriesSubscription.php b/tests/cases/Database/SeriesSubscription.php index f32102d3..1990a00a 100644 --- a/tests/cases/Database/SeriesSubscription.php +++ b/tests/cases/Database/SeriesSubscription.php @@ -204,6 +204,10 @@ trait SeriesSubscription { unset($this->data, $this->user); } + /** + * @covers \JKingWeb\Arsse\Database::subscriptionAdd + * @covers \JKingWeb\Arsse\Database::feedAdd + */ public function testAddASubscriptionToAnExistingFeed(): void { $url = "http://example.com/feed1"; $subID = $this->nextID("arsse_subscriptions"); @@ -220,6 +224,10 @@ trait SeriesSubscription { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::subscriptionAdd + * @covers \JKingWeb\Arsse\Database::feedAdd + */ public function testAddASubscriptionToANewFeed(): void { $url = "http://example.org/feed1"; $feedID = $this->nextID("arsse_feeds"); @@ -238,6 +246,10 @@ trait SeriesSubscription { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::subscriptionAdd + * @covers \JKingWeb\Arsse\Database::feedAdd + */ public function testAddASubscriptionToANewFeedViaDiscovery(): void { $url = "http://localhost:8000/Feed/Discovery/Valid"; $discovered = "http://localhost:8000/Feed/Discovery/Feed"; @@ -257,6 +269,10 @@ trait SeriesSubscription { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::subscriptionAdd + * @covers \JKingWeb\Arsse\Database::feedAdd + */ public function testAddASubscriptionToAnInvalidFeed(): void { $url = "http://example.org/feed1"; $feedID = $this->nextID("arsse_feeds"); @@ -276,18 +292,30 @@ trait SeriesSubscription { } } + /** + * @covers \JKingWeb\Arsse\Database::subscriptionAdd + * @covers \JKingWeb\Arsse\Database::feedAdd + */ public function testAddADuplicateSubscription(): void { $url = "http://example.com/feed2"; $this->assertException("constraintViolation", "Db", "ExceptionInput"); Arsse::$db->subscriptionAdd($this->user, $url); } + /** + * @covers \JKingWeb\Arsse\Database::subscriptionAdd + * @covers \JKingWeb\Arsse\Database::feedAdd + */ public function testAddADuplicateSubscriptionWithEquivalentUrl(): void { $url = "http://EXAMPLE.COM/feed2"; $this->assertException("constraintViolation", "Db", "ExceptionInput"); Arsse::$db->subscriptionAdd($this->user, $url); } + /** + * @covers \JKingWeb\Arsse\Database::subscriptionAdd + * @covers \JKingWeb\Arsse\Database::feedAdd + */ public function testAddADuplicateSubscriptionViaRedirection(): void { $url = "http://localhost:8000/Feed/Parsing/Valid"; Arsse::$db->subscriptionAdd($this->user, $url); @@ -296,6 +324,7 @@ trait SeriesSubscription { $this->assertSame($subID, Arsse::$db->subscriptionAdd($this->user, $url)); } + /** @covers \JKingWeb\Arsse\Database::subscriptionRemove */ public function testRemoveASubscription(): void { $this->assertTrue(Arsse::$db->subscriptionRemove($this->user, 1)); $state = $this->primeExpectations($this->data, [ @@ -306,22 +335,29 @@ trait SeriesSubscription { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::subscriptionRemove */ public function testRemoveAMissingSubscription(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->subscriptionRemove($this->user, 2112); } + /** @covers \JKingWeb\Arsse\Database::subscriptionRemove */ public function testRemoveAnInvalidSubscription(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); Arsse::$db->subscriptionRemove($this->user, -1); } + /** @covers \JKingWeb\Arsse\Database::subscriptionRemove */ public function testRemoveASubscriptionForTheWrongOwner(): void { $this->user = "jane.doe@example.com"; $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->subscriptionRemove($this->user, 1); } + /** + * @covers \JKingWeb\Arsse\Database::subscriptionList + * @covers \JKingWeb\Arsse\Database::subscriptionPropertiesGet + */ public function testListSubscriptions(): void { $exp = [ [ @@ -382,6 +418,7 @@ trait SeriesSubscription { $this->assertResult($exp, Arsse::$db->subscriptionList("jill.doe@example.com")); } + /** @covers \JKingWeb\Arsse\Database::subscriptionList */ public function testListSubscriptionsInAFolder(): void { $exp = [ [ @@ -397,6 +434,7 @@ trait SeriesSubscription { $this->assertResult($exp, Arsse::$db->subscriptionList($this->user, null, false)); } + /** @covers \JKingWeb\Arsse\Database::subscriptionList */ public function testListSubscriptionsWithRecursion(): void { $exp = [ [ @@ -412,31 +450,41 @@ trait SeriesSubscription { $this->assertResult($exp, Arsse::$db->subscriptionList($this->user, 2)); } + /** @covers \JKingWeb\Arsse\Database::subscriptionList */ public function testListSubscriptionsInAMissingFolder(): void { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->subscriptionList($this->user, 4); } + /** @covers \JKingWeb\Arsse\Database::subscriptionCount */ public function testCountSubscriptions(): void { $this->assertSame(3, Arsse::$db->subscriptionCount($this->user)); $this->assertSame(1, Arsse::$db->subscriptionCount($this->user, 2)); } + /** @covers \JKingWeb\Arsse\Database::subscriptionCount */ public function testCountSubscriptionsInAMissingFolder(): void { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->subscriptionCount($this->user, 4); } + /** @covers \JKingWeb\Arsse\Database::subscriptionPropertiesGet */ public function testGetThePropertiesOfAMissingSubscription(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->subscriptionPropertiesGet($this->user, 2112); } + /** @covers \JKingWeb\Arsse\Database::subscriptionPropertiesGet */ public function testGetThePropertiesOfAnInvalidSubscription(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); Arsse::$db->subscriptionPropertiesGet($this->user, -1); } + /** + * @covers \JKingWeb\Arsse\Database::subscriptionPropertiesSet + * @covers \JKingWeb\Arsse\Database::subscriptionValidateId + * @covers \JKingWeb\Arsse\Database::subscriptionRulesApply + */ public function testSetThePropertiesOfASubscription(): void { Arsse::$db->subscriptionPropertiesSet($this->user, 1, [ 'title' => "Ook Ook", @@ -465,16 +513,31 @@ trait SeriesSubscription { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::subscriptionPropertiesSet + * @covers \JKingWeb\Arsse\Database::subscriptionValidateId + * @covers \JKingWeb\Arsse\Database::subscriptionRulesApply + */ public function testMoveASubscriptionToAMissingFolder(): void { $this->assertException("idMissing", "Db", "ExceptionInput"); Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['folder' => 4]); } + /** + * @covers \JKingWeb\Arsse\Database::subscriptionPropertiesSet + * @covers \JKingWeb\Arsse\Database::subscriptionValidateId + * @covers \JKingWeb\Arsse\Database::subscriptionRulesApply + */ public function testMoveASubscriptionToTheRootFolder(): void { $this->assertTrue(Arsse::$db->subscriptionPropertiesSet($this->user, 3, ['folder' => null])); } - /** @dataProvider provideInvalidSubscriptionProperties */ + /** + * @dataProvider provideInvalidSubscriptionProperties + * @covers \JKingWeb\Arsse\Database::subscriptionPropertiesSet + * @covers \JKingWeb\Arsse\Database::subscriptionValidateId + * @covers \JKingWeb\Arsse\Database::subscriptionRulesApply + */ public function testSetThePropertiesOfASubscriptionToInvalidValues(array $data, string $exp): void { $this->assertException($exp, "Db", "ExceptionInput"); Arsse::$db->subscriptionPropertiesSet($this->user, 1, $data); @@ -492,20 +555,36 @@ trait SeriesSubscription { ]; } + /** + * @covers \JKingWeb\Arsse\Database::subscriptionPropertiesSet + * @covers \JKingWeb\Arsse\Database::subscriptionValidateId + * @covers \JKingWeb\Arsse\Database::subscriptionRulesApply + */ public function testRenameASubscriptionToZero(): void { $this->assertTrue(Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['title' => 0])); } + /** + * @covers \JKingWeb\Arsse\Database::subscriptionPropertiesSet + * @covers \JKingWeb\Arsse\Database::subscriptionValidateId + * @covers \JKingWeb\Arsse\Database::subscriptionRulesApply + */ public function testSetThePropertiesOfAMissingSubscription(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->subscriptionPropertiesSet($this->user, 2112, ['folder' => null]); } + /** + * @covers \JKingWeb\Arsse\Database::subscriptionPropertiesSet + * @covers \JKingWeb\Arsse\Database::subscriptionValidateId + * @covers \JKingWeb\Arsse\Database::subscriptionRulesApply + */ public function testSetThePropertiesOfAnInvalidSubscription(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); Arsse::$db->subscriptionPropertiesSet($this->user, -1, ['folder' => null]); } + /** @covers \JKingWeb\Arsse\Database::subscriptionIcon */ public function testRetrieveTheFaviconOfASubscription(): void { $exp = "http://example.com/favicon.ico"; $this->assertSame($exp, Arsse::$db->subscriptionIcon(null, 1)['url']); @@ -513,11 +592,13 @@ trait SeriesSubscription { $this->assertSame(null, Arsse::$db->subscriptionIcon(null, 6)); } + /** @covers \JKingWeb\Arsse\Database::subscriptionIcon */ public function testRetrieveTheFaviconOfAMissingSubscription(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->subscriptionIcon(null, -2112); } + /** @covers \JKingWeb\Arsse\Database::subscriptionIcon */ public function testRetrieveTheFaviconOfASubscriptionWithUser(): void { $exp = "http://example.com/favicon.ico"; $user = "john.doe@example.com"; @@ -527,12 +608,14 @@ trait SeriesSubscription { $this->assertSame($exp, Arsse::$db->subscriptionIcon($user, 2)['url']); } + /** @covers \JKingWeb\Arsse\Database::subscriptionIcon */ public function testRetrieveTheFaviconOfASubscriptionOfTheWrongUser(): void { $user = "john.doe@example.com"; $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->subscriptionIcon($user, 2); } + /** @covers \JKingWeb\Arsse\Database::subscriptionTagsGet */ public function testListTheTagsOfASubscription(): void { $this->assertEquals([1,2], Arsse::$db->subscriptionTagsGet("john.doe@example.com", 1)); $this->assertEquals([2], Arsse::$db->subscriptionTagsGet("john.doe@example.com", 3)); @@ -540,22 +623,30 @@ trait SeriesSubscription { $this->assertEquals(["Fascinating"], Arsse::$db->subscriptionTagsGet("john.doe@example.com", 3, true)); } + /** @covers \JKingWeb\Arsse\Database::subscriptionTagsGet */ public function testListTheTagsOfAMissingSubscription(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->subscriptionTagsGet($this->user, 101); } + /** @covers \JKingWeb\Arsse\Database::subscriptionRefreshed */ public function testGetRefreshTimeOfASubscription(): void { $user = "john.doe@example.com"; $this->assertTime(strtotime("now + 1 hour"), Arsse::$db->subscriptionRefreshed($user)); $this->assertTime(strtotime("now - 1 hour"), Arsse::$db->subscriptionRefreshed($user, 1)); } + /** @covers \JKingWeb\Arsse\Database::subscriptionRefreshed */ public function testGetRefreshTimeOfAMissingSubscription(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); $this->assertTime(strtotime("now - 1 hour"), Arsse::$db->subscriptionRefreshed("john.doe@example.com", 2)); } + /** + * @covers \JKingWeb\Arsse\Database::subscriptionPropertiesSet + * @covers \JKingWeb\Arsse\Database::subscriptionValidateId + * @covers \JKingWeb\Arsse\Database::subscriptionRulesApply + */ public function testSetTheFilterRulesOfASubscriptionCheckingMarks(): void { Arsse::$db->subscriptionPropertiesSet("jack.doe@example.com", 5, ['keep_rule' => "1|B|3|D", 'block_rule' => "4"]); $state = $this->primeExpectations($this->data, ['arsse_marks' => ['article', 'subscription', 'hidden']]); diff --git a/tests/cases/Database/SeriesTag.php b/tests/cases/Database/SeriesTag.php index 0cbde3bb..5c653cdc 100644 --- a/tests/cases/Database/SeriesTag.php +++ b/tests/cases/Database/SeriesTag.php @@ -113,6 +113,10 @@ trait SeriesTag { unset($this->data, $this->checkTags, $this->checkMembers, $this->user); } + /** + * @covers \JKingWeb\Arsse\Database::tagAdd + * @covers \JKingWeb\Arsse\Database::tagValidateName + */ public function testAddATag(): void { $user = "john.doe@example.com"; $tagID = $this->nextID("arsse_tags"); @@ -122,26 +126,43 @@ trait SeriesTag { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::tagAdd + * @covers \JKingWeb\Arsse\Database::tagValidateName + */ public function testAddADuplicateTag(): void { $this->assertException("constraintViolation", "Db", "ExceptionInput"); Arsse::$db->tagAdd("john.doe@example.com", ['name' => "Interesting"]); } + /** + * @covers \JKingWeb\Arsse\Database::tagAdd + * @covers \JKingWeb\Arsse\Database::tagValidateName + */ public function testAddATagWithAMissingName(): void { $this->assertException("missing", "Db", "ExceptionInput"); Arsse::$db->tagAdd("john.doe@example.com", []); } + /** + * @covers \JKingWeb\Arsse\Database::tagAdd + * @covers \JKingWeb\Arsse\Database::tagValidateName + */ public function testAddATagWithABlankName(): void { $this->assertException("missing", "Db", "ExceptionInput"); Arsse::$db->tagAdd("john.doe@example.com", ['name' => ""]); } + /** + * @covers \JKingWeb\Arsse\Database::tagAdd + * @covers \JKingWeb\Arsse\Database::tagValidateName + */ public function testAddATagWithAWhitespaceName(): void { $this->assertException("whitespace", "Db", "ExceptionInput"); Arsse::$db->tagAdd("john.doe@example.com", ['name' => " "]); } + /** @covers \JKingWeb\Arsse\Database::tagList */ public function testListTags(): void { $exp = [ ['id' => 2, 'name' => "Fascinating"], @@ -157,6 +178,10 @@ trait SeriesTag { $this->assertResult($exp, Arsse::$db->tagList("jane.doe@example.com", false)); } + /** + * @covers \JKingWeb\Arsse\Database::tagRemove + * @covers \JKingWeb\Arsse\Database::tagValidateId + */ public function testRemoveATag(): void { $this->assertTrue(Arsse::$db->tagRemove("john.doe@example.com", 1)); $state = $this->primeExpectations($this->data, $this->checkTags); @@ -164,6 +189,10 @@ trait SeriesTag { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::tagRemove + * @covers \JKingWeb\Arsse\Database::tagValidateId + */ public function testRemoveATagByName(): void { $this->assertTrue(Arsse::$db->tagRemove("john.doe@example.com", "Interesting", true)); $state = $this->primeExpectations($this->data, $this->checkTags); @@ -171,26 +200,46 @@ trait SeriesTag { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::tagRemove + * @covers \JKingWeb\Arsse\Database::tagValidateId + */ public function testRemoveAMissingTag(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->tagRemove("john.doe@example.com", 2112); } + /** + * @covers \JKingWeb\Arsse\Database::tagRemove + * @covers \JKingWeb\Arsse\Database::tagValidateId + */ public function testRemoveAnInvalidTag(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); Arsse::$db->tagRemove("john.doe@example.com", -1); } + /** + * @covers \JKingWeb\Arsse\Database::tagRemove + * @covers \JKingWeb\Arsse\Database::tagValidateId + */ public function testRemoveAnInvalidTagByName(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); Arsse::$db->tagRemove("john.doe@example.com", [], true); } + /** + * @covers \JKingWeb\Arsse\Database::tagRemove + * @covers \JKingWeb\Arsse\Database::tagValidateId + */ public function testRemoveATagOfTheWrongOwner(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->tagRemove("john.doe@example.com", 3); // tag ID 3 belongs to Jane } + /** + * @covers \JKingWeb\Arsse\Database::tagPropertiesGet + * @covers \JKingWeb\Arsse\Database::tagValidateId + */ public function testGetThePropertiesOfATag(): void { $exp = [ 'id' => 2, @@ -200,30 +249,56 @@ trait SeriesTag { $this->assertArraySubset($exp, Arsse::$db->tagPropertiesGet("john.doe@example.com", "Fascinating", true)); } + /** + * @covers \JKingWeb\Arsse\Database::tagPropertiesGet + * @covers \JKingWeb\Arsse\Database::tagValidateId + */ public function testGetThePropertiesOfAMissingTag(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->tagPropertiesGet("john.doe@example.com", 2112); } + /** + * @covers \JKingWeb\Arsse\Database::tagPropertiesGet + * @covers \JKingWeb\Arsse\Database::tagValidateId + */ public function testGetThePropertiesOfAnInvalidTag(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); Arsse::$db->tagPropertiesGet("john.doe@example.com", -1); } + /** + * @covers \JKingWeb\Arsse\Database::tagPropertiesGet + * @covers \JKingWeb\Arsse\Database::tagValidateId + */ public function testGetThePropertiesOfAnInvalidTagByName(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); Arsse::$db->tagPropertiesGet("john.doe@example.com", [], true); } + /** + * @covers \JKingWeb\Arsse\Database::tagPropertiesGet + * @covers \JKingWeb\Arsse\Database::tagValidateId + */ public function testGetThePropertiesOfATagOfTheWrongOwner(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->tagPropertiesGet("john.doe@example.com", 3); // tag ID 3 belongs to Jane } + /** + * @covers \JKingWeb\Arsse\Database::tagPropertiesSet + * @covers \JKingWeb\Arsse\Database::tagValidateId + * @covers \JKingWeb\Arsse\Database::tagValidateName + */ public function testMakeNoChangesToATag(): void { $this->assertFalse(Arsse::$db->tagPropertiesSet("john.doe@example.com", 1, [])); } + /** + * @covers \JKingWeb\Arsse\Database::tagPropertiesSet + * @covers \JKingWeb\Arsse\Database::tagValidateId + * @covers \JKingWeb\Arsse\Database::tagValidateName + */ public function testRenameATag(): void { $this->assertTrue(Arsse::$db->tagPropertiesSet("john.doe@example.com", 1, ['name' => "Curious"])); $state = $this->primeExpectations($this->data, $this->checkTags); @@ -231,6 +306,11 @@ trait SeriesTag { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::tagPropertiesSet + * @covers \JKingWeb\Arsse\Database::tagValidateId + * @covers \JKingWeb\Arsse\Database::tagValidateName + */ public function testRenameATagByName(): void { $this->assertTrue(Arsse::$db->tagPropertiesSet("john.doe@example.com", "Interesting", ['name' => "Curious"], true)); $state = $this->primeExpectations($this->data, $this->checkTags); @@ -238,46 +318,90 @@ trait SeriesTag { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::tagPropertiesSet + * @covers \JKingWeb\Arsse\Database::tagValidateId + * @covers \JKingWeb\Arsse\Database::tagValidateName + */ public function testRenameATagToTheEmptyString(): void { $this->assertException("missing", "Db", "ExceptionInput"); $this->assertTrue(Arsse::$db->tagPropertiesSet("john.doe@example.com", 1, ['name' => ""])); } + /** + * @covers \JKingWeb\Arsse\Database::tagPropertiesSet + * @covers \JKingWeb\Arsse\Database::tagValidateId + * @covers \JKingWeb\Arsse\Database::tagValidateName + */ public function testRenameATagToWhitespaceOnly(): void { $this->assertException("whitespace", "Db", "ExceptionInput"); $this->assertTrue(Arsse::$db->tagPropertiesSet("john.doe@example.com", 1, ['name' => " "])); } + /** + * @covers \JKingWeb\Arsse\Database::tagPropertiesSet + * @covers \JKingWeb\Arsse\Database::tagValidateId + * @covers \JKingWeb\Arsse\Database::tagValidateName + */ public function testRenameATagToAnInvalidValue(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); $this->assertTrue(Arsse::$db->tagPropertiesSet("john.doe@example.com", 1, ['name' => []])); } + /** + * @covers \JKingWeb\Arsse\Database::tagPropertiesSet + * @covers \JKingWeb\Arsse\Database::tagValidateId + * @covers \JKingWeb\Arsse\Database::tagValidateName + */ public function testCauseATagCollision(): void { $this->assertException("constraintViolation", "Db", "ExceptionInput"); Arsse::$db->tagPropertiesSet("john.doe@example.com", 1, ['name' => "Fascinating"]); } + /** + * @covers \JKingWeb\Arsse\Database::tagPropertiesSet + * @covers \JKingWeb\Arsse\Database::tagValidateId + * @covers \JKingWeb\Arsse\Database::tagValidateName + */ public function testSetThePropertiesOfAMissingTag(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->tagPropertiesSet("john.doe@example.com", 2112, ['name' => "Exciting"]); } + /** + * @covers \JKingWeb\Arsse\Database::tagPropertiesSet + * @covers \JKingWeb\Arsse\Database::tagValidateId + * @covers \JKingWeb\Arsse\Database::tagValidateName + */ public function testSetThePropertiesOfAnInvalidTag(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); Arsse::$db->tagPropertiesSet("john.doe@example.com", -1, ['name' => "Exciting"]); } + /** + * @covers \JKingWeb\Arsse\Database::tagPropertiesSet + * @covers \JKingWeb\Arsse\Database::tagValidateId + * @covers \JKingWeb\Arsse\Database::tagValidateName + */ public function testSetThePropertiesOfAnInvalidTagByName(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); Arsse::$db->tagPropertiesSet("john.doe@example.com", [], ['name' => "Exciting"], true); } + /** + * @covers \JKingWeb\Arsse\Database::tagPropertiesSet + * @covers \JKingWeb\Arsse\Database::tagValidateId + * @covers \JKingWeb\Arsse\Database::tagValidateName + */ public function testSetThePropertiesOfATagForTheWrongOwner(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->tagPropertiesSet("john.doe@example.com", 3, ['name' => "Exciting"]); // tag ID 3 belongs to Jane } + /** + * @covers \JKingWeb\Arsse\Database::tagSubscriptionsGet + * @covers \JKingWeb\Arsse\Database::tagValidateId + */ public function testListTaggedSubscriptions(): void { $exp = [1,5]; $this->assertEquals($exp, Arsse::$db->tagSubscriptionsGet("john.doe@example.com", 1)); @@ -290,16 +414,28 @@ trait SeriesTag { $this->assertEquals($exp, Arsse::$db->tagSubscriptionsGet("john.doe@example.com", "Lonely", true)); } + /** + * @covers \JKingWeb\Arsse\Database::tagSubscriptionsGet + * @covers \JKingWeb\Arsse\Database::tagValidateId + */ public function testListTaggedSubscriptionsForAMissingTag(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->tagSubscriptionsGet("john.doe@example.com", 3); } + /** + * @covers \JKingWeb\Arsse\Database::tagSubscriptionsGet + * @covers \JKingWeb\Arsse\Database::tagValidateId + */ public function testListTaggedSubscriptionsForAnInvalidTag(): void { $this->assertException("typeViolation", "Db", "ExceptionInput"); Arsse::$db->tagSubscriptionsGet("john.doe@example.com", -1); } + /** + * @covers \JKingWeb\Arsse\Database::tagSubscriptionsSet + * @covers \JKingWeb\Arsse\Database::tagValidateId + */ public function testApplyATagToSubscriptions(): void { Arsse::$db->tagSubscriptionsSet("john.doe@example.com", 1, [3,4]); $state = $this->primeExpectations($this->data, $this->checkMembers); @@ -308,6 +444,10 @@ trait SeriesTag { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::tagSubscriptionsSet + * @covers \JKingWeb\Arsse\Database::tagValidateId + */ public function testClearATagFromSubscriptions(): void { Arsse::$db->tagSubscriptionsSet("john.doe@example.com", 1, [1,3], Database::ASSOC_REMOVE); $state = $this->primeExpectations($this->data, $this->checkMembers); @@ -315,6 +455,10 @@ trait SeriesTag { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::tagSubscriptionsSet + * @covers \JKingWeb\Arsse\Database::tagValidateId + */ public function testApplyATagToSubscriptionsByName(): void { Arsse::$db->tagSubscriptionsSet("john.doe@example.com", "Interesting", [3,4], Database::ASSOC_ADD, true); $state = $this->primeExpectations($this->data, $this->checkMembers); @@ -323,6 +467,10 @@ trait SeriesTag { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::tagSubscriptionsSet + * @covers \JKingWeb\Arsse\Database::tagValidateId + */ public function testClearATagFromSubscriptionsByName(): void { Arsse::$db->tagSubscriptionsSet("john.doe@example.com", "Interesting", [1,3], Database::ASSOC_REMOVE, true); $state = $this->primeExpectations($this->data, $this->checkMembers); @@ -330,18 +478,30 @@ trait SeriesTag { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::tagSubscriptionsSet + * @covers \JKingWeb\Arsse\Database::tagValidateId + */ public function testApplyATagToNoSubscriptionsByName(): void { Arsse::$db->tagSubscriptionsSet("john.doe@example.com", "Interesting", [], Database::ASSOC_ADD, true); $state = $this->primeExpectations($this->data, $this->checkMembers); $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::tagSubscriptionsSet + * @covers \JKingWeb\Arsse\Database::tagValidateId + */ public function testClearATagFromNoSubscriptionsByName(): void { Arsse::$db->tagSubscriptionsSet("john.doe@example.com", "Interesting", [], Database::ASSOC_REMOVE, true); $state = $this->primeExpectations($this->data, $this->checkMembers); $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::tagSubscriptionsSet + * @covers \JKingWeb\Arsse\Database::tagValidateId + */ public function testReplaceSubscriptionsOfATag(): void { Arsse::$db->tagSubscriptionsSet("john.doe@example.com", 1, [3,4], Database::ASSOC_REPLACE); $state = $this->primeExpectations($this->data, $this->checkMembers); @@ -352,6 +512,10 @@ trait SeriesTag { $this->compareExpectations(static::$drv, $state); } + /** + * @covers \JKingWeb\Arsse\Database::tagSubscriptionsSet + * @covers \JKingWeb\Arsse\Database::tagValidateId + */ public function testPurgeSubscriptionsOfATag(): void { Arsse::$db->tagSubscriptionsSet("john.doe@example.com", 1, [], Database::ASSOC_REPLACE); $state = $this->primeExpectations($this->data, $this->checkMembers); @@ -360,6 +524,7 @@ trait SeriesTag { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::tagSummarize */ public function testSummarizeTags(): void { $exp = [ ['id' => 1, 'name' => "Interesting", 'subscription' => 1], diff --git a/tests/cases/Database/SeriesToken.php b/tests/cases/Database/SeriesToken.php index 249d2459..7a8073e4 100644 --- a/tests/cases/Database/SeriesToken.php +++ b/tests/cases/Database/SeriesToken.php @@ -53,6 +53,7 @@ trait SeriesToken { unset($this->data); } + /** @covers \JKingWeb\Arsse\Database::tokenLookup */ public function testLookUpAValidToken(): void { $exp1 = [ 'id' => "80fa94c1a11f11e78667001e673b2560", @@ -74,21 +75,25 @@ trait SeriesToken { $this->assertArraySubset($exp3, Arsse::$db->tokenLookup("class.class", "ab3b3eb8a13311e78667001e673b2560")); } + /** @covers \JKingWeb\Arsse\Database::tokenLookup */ public function testLookUpAMissingToken(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->tokenLookup("class", "thisTokenDoesNotExist"); } + /** @covers \JKingWeb\Arsse\Database::tokenLookup */ public function testLookUpAnExpiredToken(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->tokenLookup("fever.login", "27c6de8da13311e78667001e673b2560"); } + /** @covers \JKingWeb\Arsse\Database::tokenLookup */ public function testLookUpATokenOfTheWrongClass(): void { $this->assertException("subjectMissing", "Db", "ExceptionInput"); Arsse::$db->tokenLookup("some.class", "80fa94c1a11f11e78667001e673b2560"); } + /** @covers \JKingWeb\Arsse\Database::tokenCreate */ public function testCreateAToken(): void { $user = "jane.doe@example.com"; $state = $this->primeExpectations($this->data, ['arsse_tokens' => ["id", "class", "expires", "user"]]); @@ -103,11 +108,13 @@ trait SeriesToken { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::tokenCreate */ public function testCreateATokenForAMissingUser(): void { $this->assertException("doesNotExist", "User", "ExceptionConflict"); Arsse::$db->tokenCreate("fever.login", "jane.doe@example.biz"); } + /** @covers \JKingWeb\Arsse\Database::tokenRevoke */ public function testRevokeAToken(): void { $user = "jane.doe@example.com"; $id = "80fa94c1a11f11e78667001e673b2560"; @@ -119,6 +126,7 @@ trait SeriesToken { $this->assertFalse(Arsse::$db->tokenRevoke($user, "fever.login", $id)); } + /** @covers \JKingWeb\Arsse\Database::tokenRevoke */ public function testRevokeAllTokens(): void { $user = "jane.doe@example.com"; $state = $this->primeExpectations($this->data, ['arsse_tokens' => ["id", "expires", "user"]]); @@ -133,6 +141,7 @@ trait SeriesToken { $this->assertFalse(Arsse::$db->tokenRevoke($user, "unknown.class")); } + /** @covers \JKingWeb\Arsse\Database::tokenList */ public function testListTokens(): void { $user = "jane.doe@example.com"; $exp = [ diff --git a/tests/cases/Database/SeriesUser.php b/tests/cases/Database/SeriesUser.php index 7c6d14ac..47b4acb7 100644 --- a/tests/cases/Database/SeriesUser.php +++ b/tests/cases/Database/SeriesUser.php @@ -48,23 +48,27 @@ trait SeriesUser { unset($this->data); } + /** @covers \JKingWeb\Arsse\Database::userExists */ public function testCheckThatAUserExists(): void { $this->assertTrue(Arsse::$db->userExists("jane.doe@example.com")); $this->assertFalse(Arsse::$db->userExists("jane.doe@example.org")); $this->compareExpectations(static::$drv, $this->data); } + /** @covers \JKingWeb\Arsse\Database::userPasswordGet */ public function testGetAPassword(): void { $hash = Arsse::$db->userPasswordGet("admin@example.net"); $this->assertSame('$2y$10$PbcG2ZR3Z8TuPzM7aHTF8.v61dtCjzjK78gdZJcp4UePE8T9jEgBW', $hash); $this->assertTrue(password_verify("secret", $hash)); } + /** @covers \JKingWeb\Arsse\Database::userPasswordGet */ public function testGetThePasswordOfAMissingUser(): void { $this->assertException("doesNotExist", "User", "ExceptionConflict"); Arsse::$db->userPasswordGet("john.doe@example.org"); } + /** @covers \JKingWeb\Arsse\Database::userAdd */ public function testAddANewUser(): void { $this->assertTrue(Arsse::$db->userAdd("john.doe@example.org", "")); $state = $this->primeExpectations($this->data, ['arsse_users' => ['id']]); @@ -72,11 +76,13 @@ trait SeriesUser { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::userAdd */ public function testAddAnExistingUser(): void { $this->assertException("alreadyExists", "User", "ExceptionConflict"); Arsse::$db->userAdd("john.doe@example.com", ""); } + /** @covers \JKingWeb\Arsse\Database::userRemove */ public function testRemoveAUser(): void { $this->assertTrue(Arsse::$db->userRemove("admin@example.net")); $state = $this->primeExpectations($this->data, ['arsse_users' => ['id']]); @@ -84,19 +90,19 @@ trait SeriesUser { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::userRemove */ public function testRemoveAMissingUser(): void { $this->assertException("doesNotExist", "User", "ExceptionConflict"); Arsse::$db->userRemove("john.doe@example.org"); } + /** @covers \JKingWeb\Arsse\Database::userList */ public function testListAllUsers(): void { $users = ["admin@example.net", "jane.doe@example.com", "john.doe@example.com"]; $this->assertSame($users, Arsse::$db->userList()); } - /** - * @depends testGetAPassword - */ + /** @covers \JKingWeb\Arsse\Database::userPasswordSet */ public function testSetAPassword(): void { $user = "john.doe@example.com"; $pass = "secret"; @@ -107,6 +113,7 @@ trait SeriesUser { $this->assertTrue(password_verify($pass, $hash), "Failed verifying password of $user '$pass' against hash '$hash'."); } + /** @covers \JKingWeb\Arsse\Database::userPasswordSet */ public function testUnsetAPassword(): void { $user = "john.doe@example.com"; $this->assertEquals("", Arsse::$db->userPasswordGet($user)); @@ -114,12 +121,16 @@ trait SeriesUser { $this->assertNull(Arsse::$db->userPasswordGet($user)); } + /** @covers \JKingWeb\Arsse\Database::userPasswordSet */ public function testSetThePasswordOfAMissingUser(): void { $this->assertException("doesNotExist", "User", "ExceptionConflict"); Arsse::$db->userPasswordSet("john.doe@example.org", "secret"); } - /** @dataProvider provideMetaData */ + /** + * @dataProvider provideMetaData + * @covers \JKingWeb\Arsse\Database::userPropertiesGet + */ public function testGetMetadata(string $user, bool $includeLarge, array $exp): void { $this->assertSame($exp, Arsse::$db->userPropertiesGet($user, $includeLarge)); } @@ -135,11 +146,13 @@ trait SeriesUser { ]; } + /** @covers \JKingWeb\Arsse\Database::userPropertiesGet */ public function testGetTheMetadataOfAMissingUser(): void { $this->assertException("doesNotExist", "User", "ExceptionConflict"); Arsse::$db->userPropertiesGet("john.doe@example.org"); } + /** @covers \JKingWeb\Arsse\Database::userPropertiesSet */ public function testSetMetadata(): void { $in = [ 'admin' => true, @@ -156,6 +169,7 @@ trait SeriesUser { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::userPropertiesSet */ public function testSetNoMetadata(): void { $in = [ 'num' => 2112, @@ -166,22 +180,26 @@ trait SeriesUser { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::userPropertiesSet */ public function testSetTheMetadataOfAMissingUser(): void { $this->assertException("doesNotExist", "User", "ExceptionConflict"); Arsse::$db->userPropertiesSet("john.doe@example.org", ['admin' => true]); } + /** @covers \JKingWeb\Arsse\Database::userLookup */ public function testLookUpAUserByNumber(): void { $this->assertSame("admin@example.net", Arsse::$db->userLookup(1)); $this->assertSame("jane.doe@example.com", Arsse::$db->userLookup(2)); $this->assertSame("john.doe@example.com", Arsse::$db->userLookup(3)); } + /** @covers \JKingWeb\Arsse\Database::userLookup */ public function testLookUpAMissingUserByNumber(): void { $this->assertException("doesNotExist", "User", "ExceptionConflict"); Arsse::$db->userLookup(2112); } + /** @covers \JKingWeb\Arsse\Database::userRename */ public function testRenameAUser(): void { $this->assertTrue(Arsse::$db->userRename("john.doe@example.com", "juan.doe@example.com")); $state = $this->primeExpectations($this->data, [ @@ -193,20 +211,24 @@ trait SeriesUser { $this->compareExpectations(static::$drv, $state); } + /** @covers \JKingWeb\Arsse\Database::userRename */ public function testRenameAUserToTheSameName(): void { $this->assertFalse(Arsse::$db->userRename("john.doe@example.com", "john.doe@example.com")); } + /** @covers \JKingWeb\Arsse\Database::userRename */ public function testRenameAMissingUser(): void { $this->assertException("doesNotExist", "User", "ExceptionConflict"); Arsse::$db->userRename("juan.doe@example.com", "john.doe@example.com"); } + /** @covers \JKingWeb\Arsse\Database::userRename */ public function testRenameAUserToADuplicateName(): void { $this->assertException("alreadyExists", "User", "ExceptionConflict"); Arsse::$db->userRename("john.doe@example.com", "jane.doe@example.com"); } + /** @covers \JKingWeb\Arsse\Database::userAdd */ public function testAddFirstUser(): void { // first truncate the users table static::$drv->exec("DELETE FROM arsse_users"); diff --git a/tests/cases/Database/TestDatabase.php b/tests/cases/Database/TestDatabase.php index 5c915eff..e013d081 100644 --- a/tests/cases/Database/TestDatabase.php +++ b/tests/cases/Database/TestDatabase.php @@ -8,8 +8,9 @@ declare(strict_types=1); namespace JKingWeb\Arsse\TestCase\Database; use JKingWeb\Arsse\Database; +use JKingWeb\Arsse\Db\Transaction; -/** @covers \JKingWeb\Arsse\Database */ +/** @coversNothing */ class TestDatabase extends \JKingWeb\Arsse\Test\AbstractTest { protected $db = null; @@ -34,7 +35,10 @@ class TestDatabase extends \JKingWeb\Arsse\Test\AbstractTest { return $m->invoke($this->db, ...$arg); } - /** @dataProvider provideInClauses */ + /** + * @dataProvider provideInClauses + * @covers \JKingWeb\Arsse\Database::generateIn + */ public function testGenerateInClause(string $clause, array $values, array $inV, string $inT): void { $types = array_fill(0, sizeof($values), $inT); $exp = [$clause, $types, $values]; @@ -68,7 +72,10 @@ class TestDatabase extends \JKingWeb\Arsse\Test\AbstractTest { ]; } - /** @dataProvider provideSearchClauses */ + /** + * @dataProvider provideSearchClauses + * @covers \JKingWeb\Arsse\Database::generateSearch + */ public function testGenerateSearchClause(string $clause, array $values, array $inV, array $inC, bool $inAny): void { // this is not an exhaustive test; integration tests already cover the ins and outs of the functionality $types = array_fill(0, sizeof($values), "str"); @@ -91,4 +98,36 @@ class TestDatabase extends \JKingWeb\Arsse\Test\AbstractTest { ["(".implode(" or ", $clause)." or test like ? escape '^')", ["%?%"], array_merge($terms, ["?"]), ["test"], true], ]; } + + /** @covers \JKingWeb\Arsse\Database::generateSet */ + public function testGenerateSetClause(): void { + $in = [ + 'ook' => true, + 'ack' => false, + 'bar' => "Nimoy", + 'foo' => "Shatner", + ]; + $valid = [ + 'ook' => "bool", + 'eek' => "int", + 'foo' => "str", + 'bar' => "str", + ]; + $exp = [ + '"ook" = ?, "foo" = ?, "bar" = ?', + ["bool", "str", "str"], + [true, "Shatner", "Nimoy"], + ]; + $this->assertSame($exp, $this->invoke("generateSet", $in, $valid)); + } + + /** @covers \JKingWeb\Arsse\Database::begin */ + public function testBeginATransaction(): void { + $this->assertInstanceOf(Transaction::class, $this->invoke("begin")); + } + + /** @covers \JKingWeb\Arsse\Database::caller */ + public function testReportCallingMethod(): void { + $this->assertSame("caller", $this->invoke("caller")); + } } diff --git a/tests/cases/Db/MySQL/TestDatabase.php b/tests/cases/Db/MySQL/TestDatabase.php index b7e8d8be..b2a45697 100644 --- a/tests/cases/Db/MySQL/TestDatabase.php +++ b/tests/cases/Db/MySQL/TestDatabase.php @@ -10,7 +10,7 @@ namespace JKingWeb\Arsse\TestCase\Db\MySQL; /** * @group slow * @group coverageOptional - * @covers \JKingWeb\Arsse\Database + * @coversNothing */ class TestDatabase extends \JKingWeb\Arsse\TestCase\Database\AbstractTest { use \JKingWeb\Arsse\Test\DatabaseDrivers\MySQL; diff --git a/tests/cases/Db/MySQLPDO/TestDatabase.php b/tests/cases/Db/MySQLPDO/TestDatabase.php index 41cd3ff6..2b9fd8ce 100644 --- a/tests/cases/Db/MySQLPDO/TestDatabase.php +++ b/tests/cases/Db/MySQLPDO/TestDatabase.php @@ -11,7 +11,7 @@ namespace JKingWeb\Arsse\TestCase\Db\MySQLPDO; * @group slow * @group optional * @group coverageOptional - * @covers \JKingWeb\Arsse\Database + * @coversNothing */ class TestDatabase extends \JKingWeb\Arsse\TestCase\Database\AbstractTest { use \JKingWeb\Arsse\Test\DatabaseDrivers\MySQLPDO; diff --git a/tests/cases/Db/PostgreSQL/TestDatabase.php b/tests/cases/Db/PostgreSQL/TestDatabase.php index 8342c087..18883ae0 100644 --- a/tests/cases/Db/PostgreSQL/TestDatabase.php +++ b/tests/cases/Db/PostgreSQL/TestDatabase.php @@ -10,7 +10,7 @@ namespace JKingWeb\Arsse\TestCase\Db\PostgreSQL; /** * @group slow * @group coverageOptional - * @covers \JKingWeb\Arsse\Database + * @coversNothing */ class TestDatabase extends \JKingWeb\Arsse\TestCase\Database\AbstractTest { use \JKingWeb\Arsse\Test\DatabaseDrivers\PostgreSQL; diff --git a/tests/cases/Db/PostgreSQLPDO/TestDatabase.php b/tests/cases/Db/PostgreSQLPDO/TestDatabase.php index 7b7a723e..18e042e4 100644 --- a/tests/cases/Db/PostgreSQLPDO/TestDatabase.php +++ b/tests/cases/Db/PostgreSQLPDO/TestDatabase.php @@ -11,7 +11,7 @@ namespace JKingWeb\Arsse\TestCase\Db\PostgreSQLPDO; * @group slow * @group optional * @group coverageOptional - * @covers \JKingWeb\Arsse\Database + * @coversNothing */ class TestDatabase extends \JKingWeb\Arsse\TestCase\Database\AbstractTest { use \JKingWeb\Arsse\Test\DatabaseDrivers\PostgreSQLPDO; diff --git a/tests/cases/Db/SQLite3/TestDatabase.php b/tests/cases/Db/SQLite3/TestDatabase.php index ee3070ba..6d4ffcf4 100644 --- a/tests/cases/Db/SQLite3/TestDatabase.php +++ b/tests/cases/Db/SQLite3/TestDatabase.php @@ -9,7 +9,7 @@ namespace JKingWeb\Arsse\TestCase\Db\SQLite3; /** * @group optional - * @covers \JKingWeb\Arsse\Database + * @coversNothing */ class TestDatabase extends \JKingWeb\Arsse\TestCase\Database\AbstractTest { use \JKingWeb\Arsse\Test\DatabaseDrivers\SQLite3; diff --git a/tests/cases/Db/SQLite3PDO/TestDatabase.php b/tests/cases/Db/SQLite3PDO/TestDatabase.php index e5341f3c..b22fb005 100644 --- a/tests/cases/Db/SQLite3PDO/TestDatabase.php +++ b/tests/cases/Db/SQLite3PDO/TestDatabase.php @@ -8,7 +8,7 @@ declare(strict_types=1); namespace JKingWeb\Arsse\TestCase\Db\SQLite3PDO; /** - * @covers \JKingWeb\Arsse\Database + * @coversNothing */ class TestDatabase extends \JKingWeb\Arsse\TestCase\Database\AbstractTest { use \JKingWeb\Arsse\Test\DatabaseDrivers\SQLite3PDO; diff --git a/tests/cases/Misc/TestURL.php b/tests/cases/Misc/TestURL.php index f207b712..087e8105 100644 --- a/tests/cases/Misc/TestURL.php +++ b/tests/cases/Misc/TestURL.php @@ -12,7 +12,7 @@ use JKingWeb\Arsse\Misc\URL; /** @covers \JKingWeb\Arsse\Misc\URL */ class TestURL extends \JKingWeb\Arsse\Test\AbstractTest { /** @dataProvider provideNormalizations */ - public function testNormalizeAUrl(string $url, string $exp, string $user = null, string $pass = null): void { + public function testNormalizeAUrl(string $url, string $exp, ?string $user = null, ?string $pass = null): void { $this->assertSame($exp, URL::normalize($url, $user, $pass)); } diff --git a/tests/cases/Misc/TestValueInfo.php b/tests/cases/Misc/TestValueInfo.php index 9f0e8223..ed03d34c 100644 --- a/tests/cases/Misc/TestValueInfo.php +++ b/tests/cases/Misc/TestValueInfo.php @@ -315,6 +315,9 @@ class TestValueInfo extends \JKingWeb\Arsse\Test\AbstractTest { $this->assertNan($act, $msg); } elseif (is_scalar($exp)) { $this->assertSame($exp, $act, $msg); + } elseif ($exp instanceof \DateInterval && $act instanceof \DateInterval) { + $format = "\Py\Ym\Md\D\Th\HiMs\S"; + $this->assertSame($exp->format($format), $act->format($format), $msg); } else { $this->assertEquals($exp, $act, $msg); } @@ -532,6 +535,7 @@ class TestValueInfo extends \JKingWeb\Arsse\Test\AbstractTest { [$this->i("P2DT1H"), [null,true], [true, false], [(48 + 1) * 60 * 60, false], [1.0 * (48 + 1) * 60 * 60, false], ["P2DT1H", true], [[$this->i("P2DT1H")], false], [$this->i("P2DT1H"), true]], [$this->i("PT0H"), [null,true], [true, false], [0, false], [0.0, false], ["PT0S", true], [[$this->i("PT0H")], false], [$this->i("PT0H"), true]], [$dateDiff, [null,true], [true, false], [366 * 24 * 60 * 60, false], [1.0 * 366 * 24 * 60 * 60, false], ["P366D", true], [[$dateDiff], false], [$dateNorm, true]], + ["1 year, 2 days", [null,true], [true, false], [0, false], [0.0, false], ["1 year, 2 days", true], [["1 year, 2 days"], false], [$this->i("P1Y2D"), false]], ["P1Y2D", [null,true], [true, false], [0, false], [0.0, false], ["P1Y2D", true], [["P1Y2D"], false], [$this->i("P1Y2D"), true]], ] as $set) { // shift the input value off the set diff --git a/tests/cases/REST/Fever/TestAPI.php b/tests/cases/REST/Fever/TestAPI.php index f631c7c1..d23b972b 100644 --- a/tests/cases/REST/Fever/TestAPI.php +++ b/tests/cases/REST/Fever/TestAPI.php @@ -172,7 +172,7 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { } /** @dataProvider provideTokenAuthenticationRequests */ - public function testAuthenticateAUserToken(bool $httpRequired, bool $tokenEnforced, string $httpUser = null, array $dataPost, array $dataGet, ResponseInterface $exp): void { + public function testAuthenticateAUserToken(bool $httpRequired, bool $tokenEnforced, ?string $httpUser, array $dataPost, array $dataGet, ResponseInterface $exp): void { self::setConf([ 'userHTTPAuthRequired' => $httpRequired, 'userSessionEnforced' => $tokenEnforced, diff --git a/tests/cases/REST/Fever/TestUser.php b/tests/cases/REST/Fever/TestUser.php index 4b976ef2..4fb42393 100644 --- a/tests/cases/REST/Fever/TestUser.php +++ b/tests/cases/REST/Fever/TestUser.php @@ -38,7 +38,7 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest { } /** @dataProvider providePasswordCreations */ - public function testRegisterAUserPassword(string $user, string $password = null, $exp): void { + public function testRegisterAUserPassword(string $user, ?string $password, $exp): void { $this->userMock->generatePassword->returns("RANDOM_PASSWORD"); $this->dbMock->tokenCreate->does(function($user, $class, $id = null) { return $id ?? "RANDOM_TOKEN"; diff --git a/tests/cases/REST/Miniflux/TestV1.php b/tests/cases/REST/Miniflux/TestV1.php index 615a418a..00076313 100644 --- a/tests/cases/REST/Miniflux/TestV1.php +++ b/tests/cases/REST/Miniflux/TestV1.php @@ -169,6 +169,11 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest { ]; } + public function testRejectMalformedData(): void { + $exp = V1::respError(["InvalidBodyJSON", "Syntax error"], 400); + $this->assertMessage($exp, $this->req("POST", "/discover", "{")); + } + public function testRejectBadlyTypedData(): void { $exp = V1::respError(["InvalidInputType", 'field' => "url", 'expected' => "string", 'actual' => "integer"], 422); $this->assertMessage($exp, $this->req("POST", "/discover", ['url' => 2112])); diff --git a/tests/cases/REST/TestREST.php b/tests/cases/REST/TestREST.php index f0fd0008..380d4993 100644 --- a/tests/cases/REST/TestREST.php +++ b/tests/cases/REST/TestREST.php @@ -105,7 +105,7 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest { } /** @dataProvider provideUnnormalizedOrigins */ - public function testNormalizeOrigins(string $origin, string $exp, array $ports = null): void { + public function testNormalizeOrigins(string $origin, string $exp, ?array $ports = null): void { $r = new REST(); $act = $r->corsNormalizeOrigin($origin, $ports); $this->assertSame($exp, $act); @@ -148,7 +148,7 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest { } /** @dataProvider provideCorsNegotiations */ - public function testNegotiateCors($origin, bool $exp, string $allowed = null, string $denied = null): void { + public function testNegotiateCors($origin, bool $exp, ?string $allowed = null, ?string $denied = null): void { self::setConf(); $rMock = $this->partialMock(REST::class); $rMock->corsNormalizeOrigin->does(function($origin) { @@ -250,7 +250,7 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest { } /** @dataProvider provideUnnormalizedResponses */ - public function testNormalizeHttpResponses(ResponseInterface $res, ResponseInterface $exp, RequestInterface $req = null): void { + public function testNormalizeHttpResponses(ResponseInterface $res, ResponseInterface $exp, ?RequestInterface $req = null): void { $rMock = $this->partialMock(REST::class); $rMock->corsNegotiate->returns(true); $rMock->challenge->does(function($res) { diff --git a/tests/cases/REST/TinyTinyRSS/TestAPI.php b/tests/cases/REST/TinyTinyRSS/TestAPI.php index 3a0eac48..768a4b93 100644 --- a/tests/cases/REST/TinyTinyRSS/TestAPI.php +++ b/tests/cases/REST/TinyTinyRSS/TestAPI.php @@ -150,7 +150,7 @@ LONG_STRING; $this->h = new API(); } - protected function req($data, string $method = "POST", string $target = "", string $strData = null, string $user = null): ResponseInterface { + protected function req($data, string $method = "POST", string $target = "", ?string $strData = null, ?string $user = null): ResponseInterface { Arsse::$obj = $this->objMock->get(); Arsse::$db = $this->dbMock->get(); Arsse::$user = $this->userMock->get(); @@ -1223,19 +1223,19 @@ LONG_STRING; $this->assertMessage($exp, $this->req($in)); } - protected function filterFolders(int $id = null): array { + protected function filterFolders(?int $id = null): array { return array_filter($this->folders, function($value) use ($id) { return $value['parent'] == $id; }); } - protected function filterSubs(int $folder = null): array { + protected function filterSubs(?int $folder = null): array { return array_filter($this->subscriptions, function($value) use ($folder) { return $value['folder'] == $folder; }); } - protected function reduceFolders(int $id = null): int { + protected function reduceFolders(?int $id = null): int { $out = 0; foreach ($this->filterFolders($id) as $f) { $out += $this->reduceFolders($f['id']); diff --git a/tests/cases/REST/TinyTinyRSS/TestIcon.php b/tests/cases/REST/TinyTinyRSS/TestIcon.php index e8c52187..dc8a73bd 100644 --- a/tests/cases/REST/TinyTinyRSS/TestIcon.php +++ b/tests/cases/REST/TinyTinyRSS/TestIcon.php @@ -29,7 +29,7 @@ class TestIcon extends \JKingWeb\Arsse\Test\AbstractTest { $this->h = new Icon(); } - protected function req(string $target, string $method = "GET", string $user = null): ResponseInterface { + protected function req(string $target, string $method = "GET", ?string $user = null): ResponseInterface { Arsse::$db = $this->dbMock->get(); $prefix = "/tt-rss/feed-icons/"; $url = $prefix.$target; diff --git a/tests/lib/AbstractTest.php b/tests/lib/AbstractTest.php index 9fad7637..89085f15 100644 --- a/tests/lib/AbstractTest.php +++ b/tests/lib/AbstractTest.php @@ -62,7 +62,7 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase { Arsse::$conf = (($force ? null : Arsse::$conf) ?? (new Conf))->import($defaults)->import($conf); } - protected function serverRequest(string $method, string $url, string $urlPrefix, array $headers = [], array $vars = [], $body = null, string $type = "", $params = [], string $user = null): ServerRequestInterface { + protected function serverRequest(string $method, string $url, string $urlPrefix, array $headers = [], array $vars = [], $body = null, string $type = "", $params = [], ?string $user = null): ServerRequestInterface { $server = [ 'REQUEST_METHOD' => $method, 'REQUEST_URI' => $url, diff --git a/tests/lib/Lang/Setup.php b/tests/lib/Lang/Setup.php index 0969bf6b..71140957 100644 --- a/tests/lib/Lang/Setup.php +++ b/tests/lib/Lang/Setup.php @@ -43,11 +43,8 @@ trait Setup { return Glob::glob($this->path."*.php"); }); $this->l = $this->l->get(); - // create a mock Lang object so as not to create a dependency loop self::clearData(false); - Arsse::$lang = $this->mock(Lang::class); - Arsse::$lang->msg->returns(""); - Arsse::$lang = Arsse::$lang->get(); + Arsse::$lang = $this->l; // call the additional setup method if it exists if (method_exists($this, "setUpSeries")) { $this->setUpSeries(); diff --git a/vendor-bin/csfixer/composer.lock b/vendor-bin/csfixer/composer.lock index 9f34d1b4..2ac01aba 100644 --- a/vendor-bin/csfixer/composer.lock +++ b/vendor-bin/csfixer/composer.lock @@ -8,31 +8,103 @@ "packages": [], "packages-dev": [ { - "name": "composer/pcre", - "version": "3.1.1", + "name": "clue/ndjson-react", + "version": "v1.3.0", "source": { "type": "git", - "url": "https://github.com/composer/pcre.git", - "reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9" + "url": "https://github.com/clue/reactphp-ndjson.git", + "reference": "392dc165fce93b5bb5c637b67e59619223c931b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/00104306927c7a0919b4ced2aaa6782c1e61a3c9", - "reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9", + "url": "https://api.github.com/repos/clue/reactphp-ndjson/zipball/392dc165fce93b5bb5c637b67e59619223c931b0", + "reference": "392dc165fce93b5bb5c637b67e59619223c931b0", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "react/stream": "^1.2" + }, + "require-dev": { + "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35", + "react/event-loop": "^1.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Clue\\React\\NDJson\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + } + ], + "description": "Streaming newline-delimited JSON (NDJSON) parser and encoder for ReactPHP.", + "homepage": "https://github.com/clue/reactphp-ndjson", + "keywords": [ + "NDJSON", + "json", + "jsonlines", + "newline", + "reactphp", + "streaming" + ], + "support": { + "issues": "https://github.com/clue/reactphp-ndjson/issues", + "source": "https://github.com/clue/reactphp-ndjson/tree/v1.3.0" + }, + "funding": [ + { + "url": "https://clue.engineering/support", + "type": "custom" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-12-23T10:58:28+00:00" + }, + { + "name": "composer/pcre", + "version": "3.3.2", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", "shasum": "" }, "require": { "php": "^7.4 || ^8.0" }, + "conflict": { + "phpstan/phpstan": "<1.11.10" + }, "require-dev": { - "phpstan/phpstan": "^1.3", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^5" + "phpstan/phpstan": "^1.12 || ^2", + "phpstan/phpstan-strict-rules": "^1 || ^2", + "phpunit/phpunit": "^8 || ^9" }, "type": "library", "extra": { "branch-alias": { "dev-main": "3.x-dev" + }, + "phpstan": { + "includes": [ + "extension.neon" + ] } }, "autoload": { @@ -60,7 +132,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.1.1" + "source": "https://github.com/composer/pcre/tree/3.3.2" }, "funding": [ { @@ -76,28 +148,28 @@ "type": "tidelift" } ], - "time": "2023-10-11T07:11:09+00:00" + "time": "2024-11-12T16:29:46+00:00" }, { "name": "composer/semver", - "version": "3.4.0", + "version": "3.4.3", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32" + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32", - "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32", + "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", "shasum": "" }, "require": { "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { - "phpstan/phpstan": "^1.4", - "symfony/phpunit-bridge": "^4.2 || ^5" + "phpstan/phpstan": "^1.11", + "symfony/phpunit-bridge": "^3 || ^7" }, "type": "library", "extra": { @@ -141,7 +213,7 @@ "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" + "source": "https://github.com/composer/semver/tree/3.4.3" }, "funding": [ { @@ -157,20 +229,20 @@ "type": "tidelift" } ], - "time": "2023-08-31T09:50:34+00:00" + "time": "2024-09-19T14:15:21+00:00" }, { "name": "composer/xdebug-handler", - "version": "3.0.3", + "version": "3.0.5", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", - "reference": "ced299686f41dce890debac69273b47ffe98a40c" + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c", - "reference": "ced299686f41dce890debac69273b47ffe98a40c", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", "shasum": "" }, "require": { @@ -181,7 +253,7 @@ "require-dev": { "phpstan/phpstan": "^1.0", "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^6.0" + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" }, "type": "library", "autoload": { @@ -205,9 +277,9 @@ "performance" ], "support": { - "irc": "irc://irc.freenode.org/composer", + "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/3.0.3" + "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" }, "funding": [ { @@ -223,54 +295,169 @@ "type": "tidelift" } ], - "time": "2022-02-25T21:32:43+00:00" + "time": "2024-05-06T16:37:16+00:00" }, { - "name": "friendsofphp/php-cs-fixer", - "version": "v3.38.0", + "name": "evenement/evenement", + "version": "v3.0.2", "source": { "type": "git", - "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "7e6070026e76aa09d77a47519625c86593fb8e31" + "url": "https://github.com/igorw/evenement.git", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/7e6070026e76aa09d77a47519625c86593fb8e31", - "reference": "7e6070026e76aa09d77a47519625c86593fb8e31", + "url": "https://api.github.com/repos/igorw/evenement/zipball/0a16b0d71ab13284339abb99d9d2bd813640efbc", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc", "shasum": "" }, "require": { - "composer/semver": "^3.3", - "composer/xdebug-handler": "^3.0.3", - "ext-json": "*", - "ext-tokenizer": "*", - "php": "^7.4 || ^8.0", - "sebastian/diff": "^4.0 || ^5.0", - "symfony/console": "^5.4 || ^6.0", - "symfony/event-dispatcher": "^5.4 || ^6.0", - "symfony/filesystem": "^5.4 || ^6.0", - "symfony/finder": "^5.4 || ^6.0", - "symfony/options-resolver": "^5.4 || ^6.0", - "symfony/polyfill-mbstring": "^1.27", - "symfony/polyfill-php80": "^1.27", - "symfony/polyfill-php81": "^1.27", - "symfony/process": "^5.4 || ^6.0", - "symfony/stopwatch": "^5.4 || ^6.0" + "php": ">=7.0" }, "require-dev": { - "facile-it/paraunit": "^1.3 || ^2.0", - "justinrainbow/json-schema": "^5.2", - "keradus/cli-executor": "^2.0", - "mikey179/vfsstream": "^1.6.11", - "php-coveralls/php-coveralls": "^2.5.3", + "phpunit/phpunit": "^9 || ^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Evenement\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + } + ], + "description": "Événement is a very simple event dispatching library for PHP", + "keywords": [ + "event-dispatcher", + "event-emitter" + ], + "support": { + "issues": "https://github.com/igorw/evenement/issues", + "source": "https://github.com/igorw/evenement/tree/v3.0.2" + }, + "time": "2023-08-08T05:53:35+00:00" + }, + { + "name": "fidry/cpu-core-counter", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/theofidry/cpu-core-counter.git", + "reference": "8520451a140d3f46ac33042715115e290cf5785f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/8520451a140d3f46ac33042715115e290cf5785f", + "reference": "8520451a140d3f46ac33042715115e290cf5785f", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "fidry/makefile": "^0.2.0", + "fidry/php-cs-fixer-config": "^1.1.2", + "phpstan/extension-installer": "^1.2.0", + "phpstan/phpstan": "^1.9.2", + "phpstan/phpstan-deprecation-rules": "^1.0.0", + "phpstan/phpstan-phpunit": "^1.2.2", + "phpstan/phpstan-strict-rules": "^1.4.4", + "phpunit/phpunit": "^8.5.31 || ^9.5.26", + "webmozarts/strict-phpunit": "^7.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Fidry\\CpuCoreCounter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Théo FIDRY", + "email": "theo.fidry@gmail.com" + } + ], + "description": "Tiny utility to get the number of CPU cores.", + "keywords": [ + "CPU", + "core" + ], + "support": { + "issues": "https://github.com/theofidry/cpu-core-counter/issues", + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.2.0" + }, + "funding": [ + { + "url": "https://github.com/theofidry", + "type": "github" + } + ], + "time": "2024-08-06T10:04:20+00:00" + }, + { + "name": "friendsofphp/php-cs-fixer", + "version": "v3.65.0", + "source": { + "type": "git", + "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", + "reference": "79d4f3e77b250a7d8043d76c6af8f0695e8a469f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/79d4f3e77b250a7d8043d76c6af8f0695e8a469f", + "reference": "79d4f3e77b250a7d8043d76c6af8f0695e8a469f", + "shasum": "" + }, + "require": { + "clue/ndjson-react": "^1.0", + "composer/semver": "^3.4", + "composer/xdebug-handler": "^3.0.3", + "ext-filter": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "fidry/cpu-core-counter": "^1.2", + "php": "^7.4 || ^8.0", + "react/child-process": "^0.6.5", + "react/event-loop": "^1.0", + "react/promise": "^2.0 || ^3.0", + "react/socket": "^1.0", + "react/stream": "^1.0", + "sebastian/diff": "^4.0 || ^5.0 || ^6.0", + "symfony/console": "^5.4 || ^6.0 || ^7.0", + "symfony/event-dispatcher": "^5.4 || ^6.0 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.0 || ^7.0", + "symfony/finder": "^5.4 || ^6.0 || ^7.0", + "symfony/options-resolver": "^5.4 || ^6.0 || ^7.0", + "symfony/polyfill-mbstring": "^1.28", + "symfony/polyfill-php80": "^1.28", + "symfony/polyfill-php81": "^1.28", + "symfony/process": "^5.4 || ^6.0 || ^7.0", + "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0" + }, + "require-dev": { + "facile-it/paraunit": "^1.3.1 || ^2.4", + "infection/infection": "^0.29.8", + "justinrainbow/json-schema": "^5.3 || ^6.0", + "keradus/cli-executor": "^2.1", + "mikey179/vfsstream": "^1.6.12", + "php-coveralls/php-coveralls": "^2.7", "php-cs-fixer/accessible-object": "^1.1", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", - "phpspec/prophecy": "^1.16", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.5", - "symfony/phpunit-bridge": "^6.2.3", - "symfony/yaml": "^5.4 || ^6.0" + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.5", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.5", + "phpunit/phpunit": "^9.6.21 || ^10.5.38 || ^11.4.3", + "symfony/var-dumper": "^5.4.47 || ^6.4.15 || ^7.1.8", + "symfony/yaml": "^5.4.45 || ^6.4.13 || ^7.1.6" }, "suggest": { "ext-dom": "For handling output formats in XML", @@ -283,7 +470,10 @@ "autoload": { "psr-4": { "PhpCsFixer\\": "src/" - } + }, + "exclude-from-classmap": [ + "src/Fixer/Internal/*" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -308,7 +498,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.38.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.65.0" }, "funding": [ { @@ -316,7 +506,7 @@ "type": "github" } ], - "time": "2023-11-07T08:44:54+00:00" + "time": "2024-11-25T00:39:24+00:00" }, { "name": "psr/container", @@ -423,16 +613,16 @@ }, { "name": "psr/log", - "version": "3.0.0", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", "shasum": "" }, "require": { @@ -467,35 +657,565 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/3.0.0" + "source": "https://github.com/php-fig/log/tree/3.0.2" }, - "time": "2021-07-14T16:46:02+00:00" + "time": "2024-09-11T13:17:53+00:00" }, { - "name": "sebastian/diff", - "version": "5.0.3", + "name": "react/cache", + "version": "v1.2.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b" + "url": "https://github.com/reactphp/cache.git", + "reference": "d47c472b64aa5608225f47965a484b75c7817d5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/912dc2fbe3e3c1e7873313cc801b100b6c68c87b", - "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b", + "url": "https://api.github.com/repos/reactphp/cache/zipball/d47c472b64aa5608225f47965a484b75c7817d5b", + "reference": "d47c472b64aa5608225f47965a484b75c7817d5b", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=5.3.0", + "react/promise": "^3.0 || ^2.0 || ^1.1" }, "require-dev": { - "phpunit/phpunit": "^10.0", + "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async, Promise-based cache interface for ReactPHP", + "keywords": [ + "cache", + "caching", + "promise", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/cache/issues", + "source": "https://github.com/reactphp/cache/tree/v1.2.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2022-11-30T15:59:55+00:00" + }, + { + "name": "react/child-process", + "version": "v0.6.5", + "source": { + "type": "git", + "url": "https://github.com/reactphp/child-process.git", + "reference": "e71eb1aa55f057c7a4a0d08d06b0b0a484bead43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/child-process/zipball/e71eb1aa55f057c7a4a0d08d06b0b0a484bead43", + "reference": "e71eb1aa55f057c7a4a0d08d06b0b0a484bead43", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.0", + "react/event-loop": "^1.2", + "react/stream": "^1.2" + }, + "require-dev": { + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35", + "react/socket": "^1.8", + "sebastian/environment": "^5.0 || ^3.0 || ^2.0 || ^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\ChildProcess\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven library for executing child processes with ReactPHP.", + "keywords": [ + "event-driven", + "process", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/child-process/issues", + "source": "https://github.com/reactphp/child-process/tree/v0.6.5" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-09-16T13:41:56+00:00" + }, + { + "name": "react/dns", + "version": "v1.13.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/dns.git", + "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/dns/zipball/eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", + "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "react/cache": "^1.0 || ^0.6 || ^0.5", + "react/event-loop": "^1.2", + "react/promise": "^3.2 || ^2.7 || ^1.2.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/async": "^4.3 || ^3 || ^2", + "react/promise-timer": "^1.11" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Dns\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async DNS resolver for ReactPHP", + "keywords": [ + "async", + "dns", + "dns-resolver", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/dns/issues", + "source": "https://github.com/reactphp/dns/tree/v1.13.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-06-13T14:18:03+00:00" + }, + { + "name": "react/event-loop", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/event-loop.git", + "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "suggest": { + "ext-pcntl": "For signal handling support when using the StreamSelectLoop" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\EventLoop\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.", + "keywords": [ + "asynchronous", + "event-loop" + ], + "support": { + "issues": "https://github.com/reactphp/event-loop/issues", + "source": "https://github.com/reactphp/event-loop/tree/v1.5.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2023-11-13T13:48:05+00:00" + }, + { + "name": "react/promise", + "version": "v3.2.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise.git", + "reference": "8a164643313c71354582dc850b42b33fa12a4b63" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise/zipball/8a164643313c71354582dc850b42b33fa12a4b63", + "reference": "8a164643313c71354582dc850b42b33fa12a4b63", + "shasum": "" + }, + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "phpstan/phpstan": "1.10.39 || 1.4.10", + "phpunit/phpunit": "^9.6 || ^7.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "React\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "A lightweight implementation of CommonJS Promises/A for PHP", + "keywords": [ + "promise", + "promises" + ], + "support": { + "issues": "https://github.com/reactphp/promise/issues", + "source": "https://github.com/reactphp/promise/tree/v3.2.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-05-24T10:39:05+00:00" + }, + { + "name": "react/socket", + "version": "v1.16.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/socket.git", + "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/socket/zipball/23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", + "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.0", + "react/dns": "^1.13", + "react/event-loop": "^1.2", + "react/promise": "^3.2 || ^2.6 || ^1.2.1", + "react/stream": "^1.4" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/async": "^4.3 || ^3.3 || ^2", + "react/promise-stream": "^1.4", + "react/promise-timer": "^1.11" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Socket\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP", + "keywords": [ + "Connection", + "Socket", + "async", + "reactphp", + "stream" + ], + "support": { + "issues": "https://github.com/reactphp/socket/issues", + "source": "https://github.com/reactphp/socket/tree/v1.16.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-07-26T10:38:09+00:00" + }, + { + "name": "react/stream", + "version": "v1.4.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/stream.git", + "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/stream/zipball/1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.8", + "react/event-loop": "^1.2" + }, + "require-dev": { + "clue/stream-filter": "~1.2", + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Stream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP", + "keywords": [ + "event-driven", + "io", + "non-blocking", + "pipe", + "reactphp", + "readable", + "stream", + "writable" + ], + "support": { + "issues": "https://github.com/reactphp/stream/issues", + "source": "https://github.com/reactphp/stream/tree/v1.4.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-06-11T12:45:25+00:00" + }, + { + "name": "sebastian/diff", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0", "symfony/process": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -528,7 +1248,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/5.0.3" + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" }, "funding": [ { @@ -536,47 +1256,50 @@ "type": "github" } ], - "time": "2023-05-01T07:48:21+00:00" + "time": "2024-07-03T04:53:05+00:00" }, { "name": "symfony/console", - "version": "v6.3.4", + "version": "v7.2.1", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6" + "reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/eca495f2ee845130855ddf1cf18460c38966c8b6", - "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6", + "url": "https://api.github.com/repos/symfony/console/zipball/fefcc18c0f5d0efe3ab3152f15857298868dc2c3", + "reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=8.2", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^5.4|^6.0" + "symfony/string": "^6.4|^7.0" }, "conflict": { - "symfony/dependency-injection": "<5.4", - "symfony/dotenv": "<5.4", - "symfony/event-dispatcher": "<5.4", - "symfony/lock": "<5.4", - "symfony/process": "<5.4" + "symfony/dependency-injection": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/lock": "<6.4", + "symfony/process": "<6.4" }, "provide": { "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/lock": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -610,7 +1333,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.3.4" + "source": "https://github.com/symfony/console/tree/v7.2.1" }, "funding": [ { @@ -626,20 +1349,20 @@ "type": "tidelift" } ], - "time": "2023-08-16T10:10:12+00:00" + "time": "2024-12-11T03:49:26+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.3.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", "shasum": "" }, "require": { @@ -648,7 +1371,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -677,7 +1400,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" }, "funding": [ { @@ -693,28 +1416,28 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.3.2", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e" + "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/adb01fe097a4ee930db9258a3cc906b5beb5cf2e", - "reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/910c5db85a5356d0fea57680defec4e99eb9c8c1", + "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<5.4", + "symfony/dependency-injection": "<6.4", "symfony/service-contracts": "<2.5" }, "provide": { @@ -723,13 +1446,13 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/error-handler": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^5.4|^6.0" + "symfony/stopwatch": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -757,7 +1480,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.3.2" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.2.0" }, "funding": [ { @@ -773,20 +1496,20 @@ "type": "tidelift" } ], - "time": "2023-07-06T06:56:43+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.3.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "a76aed96a42d2b521153fb382d418e30d18b59df" + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df", - "reference": "a76aed96a42d2b521153fb382d418e30d18b59df", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", "shasum": "" }, "require": { @@ -796,7 +1519,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -833,7 +1556,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1" }, "funding": [ { @@ -849,27 +1572,30 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/filesystem", - "version": "v6.3.1", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae" + "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", - "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/b8dce482de9d7c9fe2891155035a7248ab5c7fdb", + "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8" }, + "require-dev": { + "symfony/process": "^6.4|^7.0" + }, "type": "library", "autoload": { "psr-4": { @@ -896,7 +1622,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.3.1" + "source": "https://github.com/symfony/filesystem/tree/v7.2.0" }, "funding": [ { @@ -912,27 +1638,27 @@ "type": "tidelift" } ], - "time": "2023-06-01T08:30:39+00:00" + "time": "2024-10-25T15:15:23+00:00" }, { "name": "symfony/finder", - "version": "v6.3.5", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "a1b31d88c0e998168ca7792f222cbecee47428c4" + "reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/a1b31d88c0e998168ca7792f222cbecee47428c4", - "reference": "a1b31d88c0e998168ca7792f222cbecee47428c4", + "url": "https://api.github.com/repos/symfony/finder/zipball/6de263e5868b9a137602dd1e33e4d48bfae99c49", + "reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "symfony/filesystem": "^6.0" + "symfony/filesystem": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -960,7 +1686,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.3.5" + "source": "https://github.com/symfony/finder/tree/v7.2.0" }, "funding": [ { @@ -976,24 +1702,24 @@ "type": "tidelift" } ], - "time": "2023-09-26T12:56:25+00:00" + "time": "2024-10-23T06:56:12+00:00" }, { "name": "symfony/options-resolver", - "version": "v6.3.0", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "a10f19f5198d589d5c33333cffe98dc9820332dd" + "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/a10f19f5198d589d5c33333cffe98dc9820332dd", - "reference": "a10f19f5198d589d5c33333cffe98dc9820332dd", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/7da8fbac9dcfef75ffc212235d76b2754ce0cf50", + "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3" }, "type": "library", @@ -1027,7 +1753,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v6.3.0" + "source": "https://github.com/symfony/options-resolver/tree/v7.2.0" }, "funding": [ { @@ -1043,24 +1769,24 @@ "type": "tidelift" } ], - "time": "2023-05-12T14:21:09+00:00" + "time": "2024-11-20T11:17:29+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.28.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-ctype": "*" @@ -1070,12 +1796,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -1109,7 +1832,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" }, "funding": [ { @@ -1125,36 +1848,33 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.28.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "875e90aeea2777b6f135677f618529449334a612" + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", - "reference": "875e90aeea2777b6f135677f618529449334a612", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -1190,7 +1910,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" }, "funding": [ { @@ -1206,36 +1926,33 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.28.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -1274,7 +1991,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" }, "funding": [ { @@ -1290,24 +2007,24 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.28.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "42292d99c55abe617799667f454222c54c60e229" + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", - "reference": "42292d99c55abe617799667f454222c54c60e229", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-mbstring": "*" @@ -1317,12 +2034,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -1357,7 +2071,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" }, "funding": [ { @@ -1373,33 +2087,30 @@ "type": "tidelift" } ], - "time": "2023-07-28T09:04:16+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.28.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -1440,7 +2151,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" }, "funding": [ { @@ -1456,33 +2167,30 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-php81", - "version": "v1.28.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b" + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/7581cd600fa9fd681b797d00b02f068e2f13263b", - "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -1519,7 +2227,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0" }, "funding": [ { @@ -1535,24 +2243,24 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/process", - "version": "v6.3.4", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "0b5c29118f2e980d455d2e34a5659f4579847c54" + "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/0b5c29118f2e980d455d2e34a5659f4579847c54", - "reference": "0b5c29118f2e980d455d2e34a5659f4579847c54", + "url": "https://api.github.com/repos/symfony/process/zipball/d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", + "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "type": "library", "autoload": { @@ -1580,7 +2288,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.3.4" + "source": "https://github.com/symfony/process/tree/v7.2.0" }, "funding": [ { @@ -1596,25 +2304,26 @@ "type": "tidelift" } ], - "time": "2023-08-07T10:39:22+00:00" + "time": "2024-11-06T14:24:19+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.3.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4" + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", - "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^2.0" + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { "ext-psr": "<1.1|>=2" @@ -1622,7 +2331,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -1662,7 +2371,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" }, "funding": [ { @@ -1678,24 +2387,24 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/stopwatch", - "version": "v6.3.0", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2" + "reference": "696f418b0d722a4225e1c3d95489d262971ca924" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2", - "reference": "fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/696f418b0d722a4225e1c3d95489d262971ca924", + "reference": "696f418b0d722a4225e1c3d95489d262971ca924", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/service-contracts": "^2.5|^3" }, "type": "library", @@ -1724,7 +2433,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v6.3.0" + "source": "https://github.com/symfony/stopwatch/tree/v7.2.0" }, "funding": [ { @@ -1740,24 +2449,24 @@ "type": "tidelift" } ], - "time": "2023-02-16T10:14:28+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/string", - "version": "v6.3.5", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "13d76d0fb049051ed12a04bef4f9de8715bea339" + "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/13d76d0fb049051ed12a04bef4f9de8715bea339", - "reference": "13d76d0fb049051ed12a04bef4f9de8715bea339", + "url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82", + "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", @@ -1767,11 +2476,12 @@ "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/intl": "^6.2", + "symfony/emoji": "^7.1", + "symfony/error-handler": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^5.4|^6.0" + "symfony/var-exporter": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -1810,7 +2520,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.3.5" + "source": "https://github.com/symfony/string/tree/v7.2.0" }, "funding": [ { @@ -1826,15 +2536,15 @@ "type": "tidelift" } ], - "time": "2023-09-18T10:38:32+00:00" + "time": "2024-11-13T13:31:26+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, - "platform": [], - "platform-dev": [], + "platform": {}, + "platform-dev": {}, "plugin-api-version": "2.6.0" } diff --git a/vendor-bin/daux/composer.lock b/vendor-bin/daux/composer.lock index 53ba0679..053515f9 100644 --- a/vendor-bin/daux/composer.lock +++ b/vendor-bin/daux/composer.lock @@ -83,22 +83,22 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.8.0", + "version": "7.9.2", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9" + "reference": "d281ed313b989f213357e3be1a179f02196ac99b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/1110f66a6530a40fe7aea0378fe608ee2b2248f9", - "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b", + "reference": "d281ed313b989f213357e3be1a179f02196ac99b", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0.1", - "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", + "guzzlehttp/promises": "^1.5.3 || ^2.0.3", + "guzzlehttp/psr7": "^2.7.0", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -107,11 +107,11 @@ "psr/http-client-implementation": "1.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", + "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", - "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "guzzle/client-integration-tests": "3.0.2", "php-http/message-factory": "^1.1", - "phpunit/phpunit": "^8.5.29 || ^9.5.23", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { @@ -189,7 +189,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.8.0" + "source": "https://github.com/guzzle/guzzle/tree/7.9.2" }, "funding": [ { @@ -205,28 +205,28 @@ "type": "tidelift" } ], - "time": "2023-08-27T10:20:53+00:00" + "time": "2024-07-24T11:22:20+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.0.1", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "111166291a0f8130081195ac4556a5587d7f1b5d" + "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/111166291a0f8130081195ac4556a5587d7f1b5d", - "reference": "111166291a0f8130081195ac4556a5587d7f1b5d", + "url": "https://api.github.com/repos/guzzle/promises/zipball/f9c436286ab2892c7db7be8c8da4ef61ccf7b455", + "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", - "phpunit/phpunit": "^8.5.29 || ^9.5.23" + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" }, "type": "library", "extra": { @@ -272,7 +272,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.0.1" + "source": "https://github.com/guzzle/promises/tree/2.0.4" }, "funding": [ { @@ -288,20 +288,20 @@ "type": "tidelift" } ], - "time": "2023-08-03T15:11:55+00:00" + "time": "2024-10-17T10:06:22+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.6.1", + "version": "2.7.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727" + "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/be45764272e8873c72dbe3d2edcfdfcc3bc9f727", - "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201", + "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201", "shasum": "" }, "require": { @@ -315,9 +315,9 @@ "psr/http-message-implementation": "1.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", - "http-interop/http-factory-tests": "^0.9", - "phpunit/phpunit": "^8.5.29 || ^9.5.23" + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -388,7 +388,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.6.1" + "source": "https://github.com/guzzle/psr7/tree/2.7.0" }, "funding": [ { @@ -404,7 +404,7 @@ "type": "tidelift" } ], - "time": "2023-08-27T10:13:57+00:00" + "time": "2024-07-18T11:15:46+00:00" }, { "name": "league/commonmark", @@ -501,24 +501,24 @@ }, { "name": "league/plates", - "version": "v3.5.0", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/thephpleague/plates.git", - "reference": "a6a3238e46c6e19af7318fdc36bfbe49b0620231" + "reference": "12ee65166adbc6fb5916fb80b0c0758e49a2d996" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/plates/zipball/a6a3238e46c6e19af7318fdc36bfbe49b0620231", - "reference": "a6a3238e46c6e19af7318fdc36bfbe49b0620231", + "url": "https://api.github.com/repos/thephpleague/plates/zipball/12ee65166adbc6fb5916fb80b0c0758e49a2d996", + "reference": "12ee65166adbc6fb5916fb80b0c0758e49a2d996", "shasum": "" }, "require": { - "php": "^7.0|^8.0" + "php": "^8.0" }, "require-dev": { "mikey179/vfsstream": "^1.6", - "phpunit/phpunit": "^9.5", + "phpunit/phpunit": "^11.4", "squizlabs/php_codesniffer": "^3.5" }, "type": "library", @@ -559,9 +559,9 @@ ], "support": { "issues": "https://github.com/thephpleague/plates/issues", - "source": "https://github.com/thephpleague/plates/tree/v3.5.0" + "source": "https://github.com/thephpleague/plates/tree/v3.6.0" }, - "time": "2023-01-16T20:25:45+00:00" + "time": "2024-11-02T15:03:35+00:00" }, { "name": "psr/container", @@ -670,20 +670,20 @@ }, { "name": "psr/http-factory", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-factory.git", - "reference": "e616d01114759c4c489f93b099585439f795fe35" + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", - "reference": "e616d01114759c4c489f93b099585439f795fe35", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", "shasum": "" }, "require": { - "php": ">=7.0.0", + "php": ">=7.1", "psr/http-message": "^1.0 || ^2.0" }, "type": "library", @@ -707,7 +707,7 @@ "homepage": "https://www.php-fig.org/" } ], - "description": "Common interfaces for PSR-7 HTTP message factories", + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", "keywords": [ "factory", "http", @@ -719,9 +719,9 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-factory/tree/1.0.2" + "source": "https://github.com/php-fig/http-factory" }, - "time": "2023-04-10T20:10:41+00:00" + "time": "2024-04-15T12:06:14+00:00" }, { "name": "psr/http-message", @@ -900,16 +900,16 @@ }, { "name": "symfony/console", - "version": "v5.4.28", + "version": "v5.4.47", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "f4f71842f24c2023b91237c72a365306f3c58827" + "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/f4f71842f24c2023b91237c72a365306f3c58827", - "reference": "f4f71842f24c2023b91237c72a365306f3c58827", + "url": "https://api.github.com/repos/symfony/console/zipball/c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed", + "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed", "shasum": "" }, "require": { @@ -979,7 +979,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.28" + "source": "https://github.com/symfony/console/tree/v5.4.47" }, "funding": [ { @@ -995,20 +995,20 @@ "type": "tidelift" } ], - "time": "2023-08-07T06:12:30+00:00" + "time": "2024-11-06T11:30:55+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.3.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", "shasum": "" }, "require": { @@ -1017,7 +1017,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -1046,7 +1046,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" }, "funding": [ { @@ -1062,20 +1062,20 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/http-foundation", - "version": "v5.4.30", + "version": "v5.4.48", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "671769f79de0532da1478c60968b42506e185d2e" + "reference": "3f38b8af283b830e1363acd79e5bc3412d055341" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/671769f79de0532da1478c60968b42506e185d2e", - "reference": "671769f79de0532da1478c60968b42506e185d2e", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/3f38b8af283b830e1363acd79e5bc3412d055341", + "reference": "3f38b8af283b830e1363acd79e5bc3412d055341", "shasum": "" }, "require": { @@ -1085,7 +1085,7 @@ "symfony/polyfill-php80": "^1.16" }, "require-dev": { - "predis/predis": "~1.0", + "predis/predis": "^1.0|^2.0", "symfony/cache": "^4.4|^5.0|^6.0", "symfony/dependency-injection": "^5.4|^6.0", "symfony/expression-language": "^4.4|^5.0|^6.0", @@ -1122,7 +1122,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v5.4.30" + "source": "https://github.com/symfony/http-foundation/tree/v5.4.48" }, "funding": [ { @@ -1138,20 +1138,20 @@ "type": "tidelift" } ], - "time": "2023-10-28T23:35:12+00:00" + "time": "2024-11-13T18:58:02+00:00" }, { "name": "symfony/mime", - "version": "v5.4.26", + "version": "v5.4.45", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "2ea06dfeee20000a319d8407cea1d47533d5a9d2" + "reference": "8c1b9b3e5b52981551fc6044539af1d974e39064" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/2ea06dfeee20000a319d8407cea1d47533d5a9d2", - "reference": "2ea06dfeee20000a319d8407cea1d47533d5a9d2", + "url": "https://api.github.com/repos/symfony/mime/zipball/8c1b9b3e5b52981551fc6044539af1d974e39064", + "reference": "8c1b9b3e5b52981551fc6044539af1d974e39064", "shasum": "" }, "require": { @@ -1166,15 +1166,16 @@ "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", "symfony/mailer": "<4.4", - "symfony/serializer": "<5.4.26|>=6,<6.2.13|>=6.3,<6.3.2" + "symfony/serializer": "<5.4.35|>=6,<6.3.12|>=6.4,<6.4.3" }, "require-dev": { "egulias/email-validator": "^2.1.10|^3.1|^4", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/process": "^5.4|^6.4", "symfony/property-access": "^4.4|^5.1|^6.0", "symfony/property-info": "^4.4|^5.1|^6.0", - "symfony/serializer": "^5.4.26|~6.2.13|^6.3.2" + "symfony/serializer": "^5.4.35|~6.3.12|^6.4.3" }, "type": "library", "autoload": { @@ -1206,7 +1207,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v5.4.26" + "source": "https://github.com/symfony/mime/tree/v5.4.45" }, "funding": [ { @@ -1222,24 +1223,24 @@ "type": "tidelift" } ], - "time": "2023-07-27T06:29:31+00:00" + "time": "2024-10-23T20:18:32+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.28.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-ctype": "*" @@ -1249,12 +1250,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -1288,7 +1286,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" }, "funding": [ { @@ -1304,36 +1302,33 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.28.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "875e90aeea2777b6f135677f618529449334a612" + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", - "reference": "875e90aeea2777b6f135677f618529449334a612", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -1369,7 +1364,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" }, "funding": [ { @@ -1385,33 +1380,30 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-icu", - "version": "v1.28.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-icu.git", - "reference": "e46b4da57951a16053cd751f63f4a24292788157" + "reference": "d80a05e9904d2c2b9b95929f3e4b5d3a8f418d78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/e46b4da57951a16053cd751f63f4a24292788157", - "reference": "e46b4da57951a16053cd751f63f4a24292788157", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/d80a05e9904d2c2b9b95929f3e4b5d3a8f418d78", + "reference": "d80a05e9904d2c2b9b95929f3e4b5d3a8f418d78", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance and support of other locales than \"en\"" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -1456,7 +1448,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.31.0" }, "funding": [ { @@ -1472,38 +1464,34 @@ "type": "tidelift" } ], - "time": "2023-03-21T17:27:24+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.28.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "ecaafce9f77234a6a449d29e49267ba10499116d" + "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/ecaafce9f77234a6a449d29e49267ba10499116d", - "reference": "ecaafce9f77234a6a449d29e49267ba10499116d", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c36586dcf89a12315939e00ec9b4474adcb1d773", + "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773", "shasum": "" }, "require": { - "php": ">=7.1", - "symfony/polyfill-intl-normalizer": "^1.10", - "symfony/polyfill-php72": "^1.10" + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -1543,7 +1531,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.31.0" }, "funding": [ { @@ -1559,36 +1547,33 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:30:37+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.28.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -1627,7 +1612,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" }, "funding": [ { @@ -1643,24 +1628,24 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.28.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "42292d99c55abe617799667f454222c54c60e229" + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", - "reference": "42292d99c55abe617799667f454222c54c60e229", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-mbstring": "*" @@ -1670,12 +1655,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -1710,7 +1692,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" }, "funding": [ { @@ -1726,109 +1708,30 @@ "type": "tidelift" } ], - "time": "2023-07-28T09:04:16+00:00" - }, - { - "name": "symfony/polyfill-php72", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/70f4aebd92afca2f865444d30a4d2151c13c3179", - "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" - } - }, - "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": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.28.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-01-26T09:26:14+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.28.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "fe2f306d1d9d346a7fee353d0d5012e401e984b5" + "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fe2f306d1d9d346a7fee353d0d5012e401e984b5", - "reference": "fe2f306d1d9d346a7fee353d0d5012e401e984b5", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb", + "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -1865,7 +1768,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.31.0" }, "funding": [ { @@ -1881,33 +1784,30 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.28.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -1948,7 +1848,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" }, "funding": [ { @@ -1964,20 +1864,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/process", - "version": "v5.4.28", + "version": "v5.4.47", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "45261e1fccad1b5447a8d7a8e67aa7b4a9798b7b" + "reference": "5d1662fb32ebc94f17ddb8d635454a776066733d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/45261e1fccad1b5447a8d7a8e67aa7b4a9798b7b", - "reference": "45261e1fccad1b5447a8d7a8e67aa7b4a9798b7b", + "url": "https://api.github.com/repos/symfony/process/zipball/5d1662fb32ebc94f17ddb8d635454a776066733d", + "reference": "5d1662fb32ebc94f17ddb8d635454a776066733d", "shasum": "" }, "require": { @@ -2010,7 +1910,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v5.4.28" + "source": "https://github.com/symfony/process/tree/v5.4.47" }, "funding": [ { @@ -2026,25 +1926,26 @@ "type": "tidelift" } ], - "time": "2023-08-07T10:36:04+00:00" + "time": "2024-11-06T11:36:42+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.3.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4" + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", - "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^2.0" + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { "ext-psr": "<1.1|>=2" @@ -2052,7 +1953,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -2092,7 +1993,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" }, "funding": [ { @@ -2108,20 +2009,20 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/string", - "version": "v6.3.5", + "version": "v6.4.15", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "13d76d0fb049051ed12a04bef4f9de8715bea339" + "reference": "73a5e66ea2e1677c98d4449177c5a9cf9d8b4c6f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/13d76d0fb049051ed12a04bef4f9de8715bea339", - "reference": "13d76d0fb049051ed12a04bef4f9de8715bea339", + "url": "https://api.github.com/repos/symfony/string/zipball/73a5e66ea2e1677c98d4449177c5a9cf9d8b4c6f", + "reference": "73a5e66ea2e1677c98d4449177c5a9cf9d8b4c6f", "shasum": "" }, "require": { @@ -2135,11 +2036,11 @@ "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/intl": "^6.2", + "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" + "symfony/var-exporter": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -2178,7 +2079,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.3.5" + "source": "https://github.com/symfony/string/tree/v6.4.15" }, "funding": [ { @@ -2194,20 +2095,20 @@ "type": "tidelift" } ], - "time": "2023-09-18T10:38:32+00:00" + "time": "2024-11-13T13:31:12+00:00" }, { "name": "symfony/yaml", - "version": "v6.3.7", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "9758b6c69d179936435d0ffb577c3708d57e38a8" + "reference": "e99b4e94d124b29ee4cf3140e1b537d2dad8cec9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/9758b6c69d179936435d0ffb577c3708d57e38a8", - "reference": "9758b6c69d179936435d0ffb577c3708d57e38a8", + "url": "https://api.github.com/repos/symfony/yaml/zipball/e99b4e94d124b29ee4cf3140e1b537d2dad8cec9", + "reference": "e99b4e94d124b29ee4cf3140e1b537d2dad8cec9", "shasum": "" }, "require": { @@ -2219,7 +2120,7 @@ "symfony/console": "<5.4" }, "require-dev": { - "symfony/console": "^5.4|^6.0" + "symfony/console": "^5.4|^6.0|^7.0" }, "bin": [ "Resources/bin/yaml-lint" @@ -2250,7 +2151,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v6.3.7" + "source": "https://github.com/symfony/yaml/tree/v6.4.13" }, "funding": [ { @@ -2266,7 +2167,7 @@ "type": "tidelift" } ], - "time": "2023-10-28T23:31:00+00:00" + "time": "2024-09-25T14:18:03+00:00" }, { "name": "webuni/front-matter", @@ -2343,10 +2244,10 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, - "platform": [], - "platform-dev": [], + "platform": {}, + "platform-dev": {}, "plugin-api-version": "2.6.0" } diff --git a/vendor-bin/phpstan/composer.lock b/vendor-bin/phpstan/composer.lock index ba6fe47d..b383d88a 100644 --- a/vendor-bin/phpstan/composer.lock +++ b/vendor-bin/phpstan/composer.lock @@ -9,10 +9,10 @@ "packages-dev": [], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, - "platform": [], - "platform-dev": [], + "platform": {}, + "platform-dev": {}, "plugin-api-version": "2.6.0" } diff --git a/vendor-bin/phpunit/composer.lock b/vendor-bin/phpunit/composer.lock index 4abc68f3..b518848d 100644 --- a/vendor-bin/phpunit/composer.lock +++ b/vendor-bin/phpunit/composer.lock @@ -340,23 +340,24 @@ }, { "name": "mikey179/vfsstream", - "version": "v1.6.11", + "version": "v1.6.12", "source": { "type": "git", "url": "https://github.com/bovigo/vfsStream.git", - "reference": "17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f" + "reference": "fe695ec993e0a55c3abdda10a9364eb31c6f1bf0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f", - "reference": "17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f", + "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/fe695ec993e0a55c3abdda10a9364eb31c6f1bf0", + "reference": "fe695ec993e0a55c3abdda10a9364eb31c6f1bf0", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=7.1.0" }, "require-dev": { - "phpunit/phpunit": "^4.5|^5.0" + "phpunit/phpunit": "^7.5||^8.5||^9.6", + "yoast/phpunit-polyfills": "^2.0" }, "type": "library", "extra": { @@ -387,20 +388,20 @@ "source": "https://github.com/bovigo/vfsStream/tree/master", "wiki": "https://github.com/bovigo/vfsStream/wiki" }, - "time": "2022-02-23T02:02:42+00:00" + "time": "2024-08-29T18:43:31+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.11.1", + "version": "1.12.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", "shasum": "" }, "require": { @@ -408,11 +409,12 @@ }, "conflict": { "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { "doctrine/collections": "^1.6.8", "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", @@ -438,7 +440,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" }, "funding": [ { @@ -446,29 +448,31 @@ "type": "tidelift" } ], - "time": "2023-03-08T13:26:56+00:00" + "time": "2024-11-08T17:47:46+00:00" }, { "name": "nikic/php-parser", - "version": "v4.17.1", + "version": "v5.3.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", - "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b", + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b", "shasum": "" }, "require": { + "ext-ctype": "*", + "ext-json": "*", "ext-tokenizer": "*", - "php": ">=7.0" + "php": ">=7.4" }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^9.0" }, "bin": [ "bin/php-parse" @@ -476,7 +480,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.9-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -500,33 +504,33 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1" }, - "time": "2023-08-13T19:53:39+00:00" + "time": "2024-10-08T18:51:32+00:00" }, { "name": "phake/phake", - "version": "v4.4.0", + "version": "v4.5.3", "source": { "type": "git", "url": "https://github.com/phake/phake.git", - "reference": "5c8954791645d9b7fc027bf76822a221a5a4de8a" + "reference": "695a4feda9ff25608e5065bfd48a7d3c6add57ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phake/phake/zipball/5c8954791645d9b7fc027bf76822a221a5a4de8a", - "reference": "5c8954791645d9b7fc027bf76822a221a5a4de8a", + "url": "https://api.github.com/repos/phake/phake/zipball/695a4feda9ff25608e5065bfd48a7d3c6add57ce", + "reference": "695a4feda9ff25608e5065bfd48a7d3c6add57ce", "shasum": "" }, "require": { "doctrine/instantiator": "^1.4", "php": "^7.1|^8.0", - "sebastian/comparator": "^1.1|^2.0|^3.0|^4.0|^5.0" + "sebastian/comparator": "^1.1|^2.0|^3.0|^4.0|^5.0|^6.0" }, "require-dev": { "doctrine/annotations": "^1.13", - "hamcrest/hamcrest-php": "1.1.*", - "phpunit/phpunit": "^6.5|^7.0|^8.0|^9.0|^10.0", + "hamcrest/hamcrest-php": "^1.1|^2.0", + "phpunit/phpunit": "^6.5|^7.0|^8.0|^9.0|^10.0|^11.0", "psalm/phar": "^4.18" }, "suggest": { @@ -536,7 +540,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.4-dev" + "dev-4.4": "4.4.x-dev", + "dev-master": "5.0.x-dev" } }, "autoload": { @@ -570,26 +575,27 @@ "support": { "docs": "https://phake.github.io/doc/", "issues": "https://github.com/phake/phake/issues", - "source": "https://github.com/phake/phake/tree/v4.4.0" + "source": "https://github.com/phake/phake/tree/v4.5.3" }, - "time": "2023-02-10T20:32:41+00:00" + "time": "2024-12-09T14:46:24+00:00" }, { "name": "phar-io/manifest", - "version": "2.0.3", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + "reference": "54750ef60c58e43759730615a392c31c80e23176" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "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", @@ -630,9 +636,15 @@ "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.3" + "source": "https://github.com/phar-io/manifest/tree/2.0.4" }, - "time": "2021-07-20T11:28:43+00:00" + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" }, { "name": "phar-io/version", @@ -687,35 +699,35 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.29", + "version": "9.2.32", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76" + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6a3a87ac2bbe33b25042753df8195ba4aa534c76", - "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5", + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.15", + "nikic/php-parser": "^4.19.1 || ^5.1.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" + "phpunit/php-file-iterator": "^3.0.6", + "phpunit/php-text-template": "^2.0.4", + "sebastian/code-unit-reverse-lookup": "^2.0.3", + "sebastian/complexity": "^2.0.3", + "sebastian/environment": "^5.1.5", + "sebastian/lines-of-code": "^1.0.4", + "sebastian/version": "^3.0.2", + "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^9.6" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -724,7 +736,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.2-dev" + "dev-main": "9.2.x-dev" } }, "autoload": { @@ -753,7 +765,7 @@ "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.29" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.32" }, "funding": [ { @@ -761,7 +773,7 @@ "type": "github" } ], - "time": "2023-09-19T04:57:46+00:00" + "time": "2024-08-22T04:23:01+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1006,45 +1018,45 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.13", + "version": "9.6.22", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "f3d767f7f9e191eab4189abe41ab37797e30b1be" + "reference": "f80235cb4d3caa59ae09be3adf1ded27521d1a9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f3d767f7f9e191eab4189abe41ab37797e30b1be", - "reference": "f3d767f7f9e191eab4189abe41ab37797e30b1be", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f80235cb4d3caa59ae09be3adf1ded27521d1a9c", + "reference": "f80235cb4d3caa59ae09be3adf1ded27521d1a9c", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1 || ^2", + "doctrine/instantiator": "^1.5.0 || ^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", + "myclabs/deep-copy": "^1.12.1", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.28", - "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-code-coverage": "^9.2.32", + "phpunit/php-file-iterator": "^3.0.6", "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", + "phpunit/php-text-template": "^2.0.4", + "phpunit/php-timer": "^5.0.3", + "sebastian/cli-parser": "^1.0.2", + "sebastian/code-unit": "^1.0.8", "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/diff": "^4.0.6", + "sebastian/environment": "^5.1.5", + "sebastian/exporter": "^4.0.6", + "sebastian/global-state": "^5.0.7", + "sebastian/object-enumerator": "^4.0.4", + "sebastian/resource-operations": "^3.0.4", + "sebastian/type": "^3.2.1", "sebastian/version": "^3.0.2" }, "suggest": { @@ -1089,7 +1101,7 @@ "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.13" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.22" }, "funding": [ { @@ -1105,20 +1117,20 @@ "type": "tidelift" } ], - "time": "2023-09-19T05:39:22+00:00" + "time": "2024-12-05T13:48:26+00:00" }, { "name": "sebastian/cli-parser", - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", "shasum": "" }, "require": { @@ -1153,7 +1165,7 @@ "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.1" + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" }, "funding": [ { @@ -1161,7 +1173,7 @@ "type": "github" } ], - "time": "2020-09-28T06:08:49+00:00" + "time": "2024-03-02T06:27:43+00:00" }, { "name": "sebastian/code-unit", @@ -1350,20 +1362,20 @@ }, { "name": "sebastian/complexity", - "version": "2.0.2", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", "shasum": "" }, "require": { - "nikic/php-parser": "^4.7", + "nikic/php-parser": "^4.18 || ^5.0", "php": ">=7.3" }, "require-dev": { @@ -1395,7 +1407,7 @@ "homepage": "https://github.com/sebastianbergmann/complexity", "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" }, "funding": [ { @@ -1403,20 +1415,20 @@ "type": "github" } ], - "time": "2020-10-26T15:52:27+00:00" + "time": "2023-12-22T06:19:30+00:00" }, { "name": "sebastian/diff", - "version": "4.0.5", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", "shasum": "" }, "require": { @@ -1461,7 +1473,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" }, "funding": [ { @@ -1469,7 +1481,7 @@ "type": "github" } ], - "time": "2023-05-07T05:35:17+00:00" + "time": "2024-03-02T06:30:58+00:00" }, { "name": "sebastian/environment", @@ -1536,16 +1548,16 @@ }, { "name": "sebastian/exporter", - "version": "4.0.5", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", "shasum": "" }, "require": { @@ -1601,7 +1613,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" }, "funding": [ { @@ -1609,20 +1621,20 @@ "type": "github" } ], - "time": "2022-09-14T06:03:37+00:00" + "time": "2024-03-02T06:33:00+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.6", + "version": "5.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bde739e7565280bda77be70044ac1047bc007e34" + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", - "reference": "bde739e7565280bda77be70044ac1047bc007e34", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", "shasum": "" }, "require": { @@ -1665,7 +1677,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" }, "funding": [ { @@ -1673,24 +1685,24 @@ "type": "github" } ], - "time": "2023-08-02T09:26:13+00:00" + "time": "2024-03-02T06:35:11+00:00" }, { "name": "sebastian/lines-of-code", - "version": "1.0.3", + "version": "1.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", "shasum": "" }, "require": { - "nikic/php-parser": "^4.6", + "nikic/php-parser": "^4.18 || ^5.0", "php": ">=7.3" }, "require-dev": { @@ -1722,7 +1734,7 @@ "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.3" + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" }, "funding": [ { @@ -1730,7 +1742,7 @@ "type": "github" } ], - "time": "2020-11-28T06:42:11+00:00" + "time": "2023-12-22T06:20:34+00:00" }, { "name": "sebastian/object-enumerator", @@ -1909,16 +1921,16 @@ }, { "name": "sebastian/resource-operations", - "version": "3.0.3", + "version": "3.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", "shasum": "" }, "require": { @@ -1930,7 +1942,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -1951,8 +1963,7 @@ "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" + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" }, "funding": [ { @@ -1960,7 +1971,7 @@ "type": "github" } ], - "time": "2020-09-28T06:45:17+00:00" + "time": "2024-03-14T16:00:52+00:00" }, { "name": "sebastian/type", @@ -2073,16 +2084,16 @@ }, { "name": "theseer/tokenizer", - "version": "1.2.1", + "version": "1.2.3", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", "shasum": "" }, "require": { @@ -2111,7 +2122,7 @@ "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.1" + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" }, "funding": [ { @@ -2119,20 +2130,20 @@ "type": "github" } ], - "time": "2021-07-28T10:34:58+00:00" + "time": "2024-03-03T12:36:25+00:00" }, { "name": "webmozart/glob", - "version": "4.6.0", + "version": "4.7.0", "source": { "type": "git", "url": "https://github.com/webmozarts/glob.git", - "reference": "3c17f7dec3d9d0e87b575026011f2e75a56ed655" + "reference": "8a2842112d6916e61e0e15e316465b611f3abc17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/glob/zipball/3c17f7dec3d9d0e87b575026011f2e75a56ed655", - "reference": "3c17f7dec3d9d0e87b575026011f2e75a56ed655", + "url": "https://api.github.com/repos/webmozarts/glob/zipball/8a2842112d6916e61e0e15e316465b611f3abc17", + "reference": "8a2842112d6916e61e0e15e316465b611f3abc17", "shasum": "" }, "require": { @@ -2166,17 +2177,17 @@ "description": "A PHP implementation of Ant's glob.", "support": { "issues": "https://github.com/webmozarts/glob/issues", - "source": "https://github.com/webmozarts/glob/tree/4.6.0" + "source": "https://github.com/webmozarts/glob/tree/4.7.0" }, - "time": "2022-05-24T19:45:58+00:00" + "time": "2024-03-07T20:33:40+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, - "platform": [], - "platform-dev": [], + "platform": {}, + "platform-dev": {}, "plugin-api-version": "2.6.0" } diff --git a/vendor-bin/robo/composer.json b/vendor-bin/robo/composer.json index b3180b72..4c09d599 100644 --- a/vendor-bin/robo/composer.json +++ b/vendor-bin/robo/composer.json @@ -1,6 +1,6 @@ { "require-dev": { - "consolidation/robo": "^3.0", + "consolidation/robo": "^5.0", "pear/archive_tar": "^1.4" } } diff --git a/vendor-bin/robo/composer.lock b/vendor-bin/robo/composer.lock index ccbed20d..6e0c02ec 100644 --- a/vendor-bin/robo/composer.lock +++ b/vendor-bin/robo/composer.lock @@ -4,111 +4,30 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ee0b828426eaa5ff905ef60d9a4b9aca", + "content-hash": "35272676865627e62150c1d3056e0268", "packages": [], "packages-dev": [ - { - "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" - } - ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", - "keywords": [ - "semantic", - "semver", - "validation", - "versioning" - ], - "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": "consolidation/annotated-command", - "version": "4.9.1", + "version": "4.10.1", "source": { "type": "git", "url": "https://github.com/consolidation/annotated-command.git", - "reference": "e01152f698eff4cb5df3ebfe5e097ef335dbd3c9" + "reference": "362310b13ececa9f6f0a4a880811fa08fecc348b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/annotated-command/zipball/e01152f698eff4cb5df3ebfe5e097ef335dbd3c9", - "reference": "e01152f698eff4cb5df3ebfe5e097ef335dbd3c9", + "url": "https://api.github.com/repos/consolidation/annotated-command/zipball/362310b13ececa9f6f0a4a880811fa08fecc348b", + "reference": "362310b13ececa9f6f0a4a880811fa08fecc348b", "shasum": "" }, "require": { "consolidation/output-formatters": "^4.3.1", "php": ">=7.1.3", "psr/log": "^1 || ^2 || ^3", - "symfony/console": "^4.4.8 || ^5 || ^6", - "symfony/event-dispatcher": "^4.4.8 || ^5 || ^6", - "symfony/finder": "^4.4.8 || ^5 || ^6" + "symfony/console": "^4.4.8 || ^5 || ^6 || ^7", + "symfony/event-dispatcher": "^4.4.8 || ^5 || ^6 || ^7", + "symfony/finder": "^4.4.8 || ^5 || ^6 || ^7" }, "require-dev": { "composer-runtime-api": "^2.0", @@ -140,36 +59,36 @@ "description": "Initialize Symfony Console commands from annotated command class methods.", "support": { "issues": "https://github.com/consolidation/annotated-command/issues", - "source": "https://github.com/consolidation/annotated-command/tree/4.9.1" + "source": "https://github.com/consolidation/annotated-command/tree/4.10.1" }, - "time": "2023-05-20T04:19:01+00:00" + "time": "2024-12-13T19:55:40+00:00" }, { "name": "consolidation/config", - "version": "2.1.2", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/consolidation/config.git", - "reference": "597f8d7fbeef801736250ec10c3e190569b1b0ae" + "reference": "0615499781449ab773ffc609b97b934b3357b3f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/config/zipball/597f8d7fbeef801736250ec10c3e190569b1b0ae", - "reference": "597f8d7fbeef801736250ec10c3e190569b1b0ae", + "url": "https://api.github.com/repos/consolidation/config/zipball/0615499781449ab773ffc609b97b934b3357b3f9", + "reference": "0615499781449ab773ffc609b97b934b3357b3f9", "shasum": "" }, "require": { - "dflydev/dot-access-data": "^1.1.0 || ^2 || ^3", - "grasmash/expander": "^2.0.1 || ^3", - "php": ">=7.1.3", - "symfony/event-dispatcher": "^4 || ^5 || ^6" + "dflydev/dot-access-data": "^3", + "grasmash/expander": "^3", + "php": ">=8.2.0", + "symfony/event-dispatcher": "^7" }, "require-dev": { "ext-json": "*", - "phpunit/phpunit": ">=7.5.20", + "phpunit/phpunit": "^9", "squizlabs/php_codesniffer": "^3", - "symfony/console": "^4 || ^5 || ^6", - "symfony/yaml": "^4 || ^5 || ^6", + "symfony/console": "^7", + "symfony/yaml": "^7", "yoast/phpunit-polyfills": "^1" }, "suggest": { @@ -200,38 +119,38 @@ "description": "Provide configuration services for a commandline tool.", "support": { "issues": "https://github.com/consolidation/config/issues", - "source": "https://github.com/consolidation/config/tree/2.1.2" + "source": "https://github.com/consolidation/config/tree/3.1.0" }, - "time": "2022-10-06T17:48:03+00:00" + "time": "2024-11-28T14:37:27+00:00" }, { "name": "consolidation/log", - "version": "2.1.1", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/consolidation/log.git", - "reference": "3ad08dc57e8aff9400111bad36beb0ed387fe6a9" + "reference": "c27a3beb36137c141ccbce0d89f64befb243c015" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/log/zipball/3ad08dc57e8aff9400111bad36beb0ed387fe6a9", - "reference": "3ad08dc57e8aff9400111bad36beb0ed387fe6a9", + "url": "https://api.github.com/repos/consolidation/log/zipball/c27a3beb36137c141ccbce0d89f64befb243c015", + "reference": "c27a3beb36137c141ccbce0d89f64befb243c015", "shasum": "" }, "require": { - "php": ">=7.1.3", - "psr/log": "^1 || ^2", - "symfony/console": "^4 || ^5 || ^6" + "php": ">=8.0.0", + "psr/log": "^3", + "symfony/console": "^5 || ^6 || ^7" }, "require-dev": { - "phpunit/phpunit": ">=7.5.20", + "phpunit/phpunit": "^7.5.20 || ^8 || ^9", "squizlabs/php_codesniffer": "^3", "yoast/phpunit-polyfills": "^0.2.0" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "2.x-dev" + "platform": { + "php": "8.2.17" } }, "autoload": { @@ -252,36 +171,36 @@ "description": "Improved Psr-3 / Psr\\Log logger based on Symfony Console components.", "support": { "issues": "https://github.com/consolidation/log/issues", - "source": "https://github.com/consolidation/log/tree/2.1.1" + "source": "https://github.com/consolidation/log/tree/3.1.0" }, - "time": "2022-02-24T04:27:32+00:00" + "time": "2024-04-04T23:50:25+00:00" }, { "name": "consolidation/output-formatters", - "version": "4.3.2", + "version": "4.6.0", "source": { "type": "git", "url": "https://github.com/consolidation/output-formatters.git", - "reference": "06711568b4cd169700ff7e8075db0a9a341ceb58" + "reference": "5fd5656718d7068a02d046f418a7ba873d5abbfe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/output-formatters/zipball/06711568b4cd169700ff7e8075db0a9a341ceb58", - "reference": "06711568b4cd169700ff7e8075db0a9a341ceb58", + "url": "https://api.github.com/repos/consolidation/output-formatters/zipball/5fd5656718d7068a02d046f418a7ba873d5abbfe", + "reference": "5fd5656718d7068a02d046f418a7ba873d5abbfe", "shasum": "" }, "require": { "dflydev/dot-access-data": "^1.1.0 || ^2 || ^3", "php": ">=7.1.3", - "symfony/console": "^4 || ^5 || ^6", - "symfony/finder": "^4 || ^5 || ^6" + "symfony/console": "^4 || ^5 || ^6 || ^7", + "symfony/finder": "^4 || ^5 || ^6 || ^7" }, "require-dev": { "php-coveralls/php-coveralls": "^2.4.2", "phpunit/phpunit": "^7 || ^8 || ^9", "squizlabs/php_codesniffer": "^3", - "symfony/var-dumper": "^4 || ^5 || ^6", - "symfony/yaml": "^4 || ^5 || ^6", + "symfony/var-dumper": "^4 || ^5 || ^6 || ^7", + "symfony/yaml": "^4 || ^5 || ^6 || ^7", "yoast/phpunit-polyfills": "^1" }, "suggest": { @@ -306,38 +225,38 @@ "description": "Format text by applying transformations provided by plug-in formatters.", "support": { "issues": "https://github.com/consolidation/output-formatters/issues", - "source": "https://github.com/consolidation/output-formatters/tree/4.3.2" + "source": "https://github.com/consolidation/output-formatters/tree/4.6.0" }, - "time": "2023-07-06T04:45:41+00:00" + "time": "2024-10-18T14:02:48+00:00" }, { "name": "consolidation/robo", - "version": "3.0.12", + "version": "5.1.0", "source": { "type": "git", "url": "https://github.com/consolidation/robo.git", - "reference": "0c3a5085357f46c90a0b756e3d326f44847158b8" + "reference": "dde6bd88de5e1e8a7f6ed8906f80353817647ad9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/robo/zipball/0c3a5085357f46c90a0b756e3d326f44847158b8", - "reference": "0c3a5085357f46c90a0b756e3d326f44847158b8", + "url": "https://api.github.com/repos/consolidation/robo/zipball/dde6bd88de5e1e8a7f6ed8906f80353817647ad9", + "reference": "dde6bd88de5e1e8a7f6ed8906f80353817647ad9", "shasum": "" }, "require": { - "consolidation/annotated-command": "^4.3", - "consolidation/config": "^1.2.1 || ^2.0.1", - "consolidation/log": "^1.1.1 || ^2.0.2", + "consolidation/annotated-command": "^4.8.1", + "consolidation/config": "^3", + "consolidation/log": "^3", "consolidation/output-formatters": "^4.1.2", - "consolidation/self-update": "^2.0", "league/container": "^3.3.1 || ^4.0", - "php": ">=7.1.3", - "symfony/console": "^4.4.19 || ^5 || ^6", - "symfony/event-dispatcher": "^4.4.19 || ^5 || ^6", - "symfony/filesystem": "^4.4.9 || ^5 || ^6", - "symfony/finder": "^4.4.9 || ^5 || ^6", - "symfony/process": "^4.4.9 || ^5 || ^6", - "symfony/yaml": "^4.4 || ^5 || ^6" + "php": ">=8.2", + "phpowermove/docblock": "^4.0", + "symfony/console": "^6 || ^7", + "symfony/event-dispatcher": "^6 || ^7", + "symfony/filesystem": "^6 || ^7", + "symfony/finder": "^6 || ^7", + "symfony/process": "^6 || ^7", + "symfony/yaml": "^6 || ^7" }, "conflict": { "codegyre/robo": "*" @@ -346,11 +265,12 @@ "natxet/cssmin": "3.0.4", "patchwork/jsqueeze": "^2", "pear/archive_tar": "^1.4.4", - "phpunit/phpunit": "^7.5.20 || ^8", + "phpunit/phpunit": "^7.5.20 || ^8 || ^9", "squizlabs/php_codesniffer": "^3.6", "yoast/phpunit-polyfills": "^0.2.0" }, "suggest": { + "consolidation/self-update": "For self-updating a phar-based app built with Robo", "natxet/cssmin": "For minifying CSS files in taskMinify", "patchwork/jsqueeze": "For minifying JS files in taskMinify", "pear/archive_tar": "Allows tar archives to be created and extracted in taskPack and taskExtract, respectively.", @@ -360,33 +280,6 @@ "robo" ], "type": "library", - "extra": { - "scenarios": { - "symfony4": { - "require": { - "symfony/console": "^4.4.11", - "symfony/event-dispatcher": "^4.4.11", - "symfony/filesystem": "^4.4.11", - "symfony/finder": "^4.4.11", - "symfony/process": "^4.4.11", - "phpunit/phpunit": "^6", - "nikic/php-parser": "^2" - }, - "remove": [ - "codeception/phpunit-wrapper" - ], - "config": { - "platform": { - "php": "7.1.3" - } - } - } - }, - "branch-alias": { - "dev-master": "2.x-dev", - "dev-main": "2.x-dev" - } - }, "autoload": { "psr-4": { "Robo\\": "src" @@ -405,77 +298,22 @@ "description": "Modern task runner", "support": { "issues": "https://github.com/consolidation/robo/issues", - "source": "https://github.com/consolidation/robo/tree/3.0.12" + "source": "https://github.com/consolidation/robo/tree/5.1.0" }, - "time": "2023-04-30T21:18:09+00:00" - }, - { - "name": "consolidation/self-update", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/consolidation/self-update.git", - "reference": "972a1016761c9b63314e040836a12795dff6953a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/consolidation/self-update/zipball/972a1016761c9b63314e040836a12795dff6953a", - "reference": "972a1016761c9b63314e040836a12795dff6953a", - "shasum": "" - }, - "require": { - "composer/semver": "^3.2", - "php": ">=5.5.0", - "symfony/console": "^2.8 || ^3 || ^4 || ^5 || ^6", - "symfony/filesystem": "^2.5 || ^3 || ^4 || ^5 || ^6" - }, - "bin": [ - "scripts/release" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "SelfUpdate\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Alexander Menk", - "email": "menk@mestrona.net" - }, - { - "name": "Greg Anderson", - "email": "greg.1.anderson@greenknowe.org" - } - ], - "description": "Provides a self:update command for Symfony Console applications.", - "support": { - "issues": "https://github.com/consolidation/self-update/issues", - "source": "https://github.com/consolidation/self-update/tree/2.2.0" - }, - "time": "2023-03-18T01:37:41+00:00" + "time": "2024-10-22T13:18:54+00:00" }, { "name": "dflydev/dot-access-data", - "version": "v3.0.2", + "version": "v3.0.3", "source": { "type": "git", "url": "https://github.com/dflydev/dflydev-dot-access-data.git", - "reference": "f41715465d65213d644d3141a6a93081be5d3549" + "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/f41715465d65213d644d3141a6a93081be5d3549", - "reference": "f41715465d65213d644d3141a6a93081be5d3549", + "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/a23a2bf4f31d3518f3ecb38660c95715dfead60f", + "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f", "shasum": "" }, "require": { @@ -535,22 +373,22 @@ ], "support": { "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues", - "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.2" + "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.3" }, - "time": "2022-10-27T11:44:00+00:00" + "time": "2024-07-08T12:26:09+00:00" }, { "name": "grasmash/expander", - "version": "3.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/grasmash/expander.git", - "reference": "bb1c1a2430957945cf08c5a62f5d72a6aa6a2c82" + "reference": "eea11b9afb0c32483b18b9009f4ca07b770e39f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/grasmash/expander/zipball/bb1c1a2430957945cf08c5a62f5d72a6aa6a2c82", - "reference": "bb1c1a2430957945cf08c5a62f5d72a6aa6a2c82", + "url": "https://api.github.com/repos/grasmash/expander/zipball/eea11b9afb0c32483b18b9009f4ca07b770e39f4", + "reference": "eea11b9afb0c32483b18b9009f4ca07b770e39f4", "shasum": "" }, "require": { @@ -587,22 +425,22 @@ "description": "Expands internal property references in PHP arrays file.", "support": { "issues": "https://github.com/grasmash/expander/issues", - "source": "https://github.com/grasmash/expander/tree/3.0.0" + "source": "https://github.com/grasmash/expander/tree/3.0.1" }, - "time": "2022-05-10T13:14:49+00:00" + "time": "2024-11-25T23:28:05+00:00" }, { "name": "league/container", - "version": "4.2.0", + "version": "4.2.4", "source": { "type": "git", "url": "https://github.com/thephpleague/container.git", - "reference": "375d13cb828649599ef5d48a339c4af7a26cd0ab" + "reference": "7ea728b013b9a156c409c6f0fc3624071b742dec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/container/zipball/375d13cb828649599ef5d48a339c4af7a26cd0ab", - "reference": "375d13cb828649599ef5d48a339c4af7a26cd0ab", + "url": "https://api.github.com/repos/thephpleague/container/zipball/7ea728b013b9a156c409c6f0fc3624071b742dec", + "reference": "7ea728b013b9a156c409c6f0fc3624071b742dec", "shasum": "" }, "require": { @@ -627,11 +465,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.x-dev", - "dev-4.x": "4.x-dev", - "dev-3.x": "3.x-dev", + "dev-1.x": "1.x-dev", "dev-2.x": "2.x-dev", - "dev-1.x": "1.x-dev" + "dev-3.x": "3.x-dev", + "dev-4.x": "4.x-dev", + "dev-master": "4.x-dev" } }, "autoload": { @@ -663,7 +501,7 @@ ], "support": { "issues": "https://github.com/thephpleague/container/issues", - "source": "https://github.com/thephpleague/container/tree/4.2.0" + "source": "https://github.com/thephpleague/container/tree/4.2.4" }, "funding": [ { @@ -671,20 +509,20 @@ "type": "github" } ], - "time": "2021-11-16T10:29:06+00:00" + "time": "2024-11-10T12:42:13+00:00" }, { "name": "pear/archive_tar", - "version": "1.4.14", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/pear/Archive_Tar.git", - "reference": "4d761c5334c790e45ef3245f0864b8955c562caa" + "reference": "b439c859564f5cbb0f64ad6002d0afe84a889602" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pear/Archive_Tar/zipball/4d761c5334c790e45ef3245f0864b8955c562caa", - "reference": "4d761c5334c790e45ef3245f0864b8955c562caa", + "url": "https://api.github.com/repos/pear/Archive_Tar/zipball/b439c859564f5cbb0f64ad6002d0afe84a889602", + "reference": "b439c859564f5cbb0f64ad6002d0afe84a889602", "shasum": "" }, "require": { @@ -715,7 +553,7 @@ "./" ], "license": [ - "BSD-3-Clause" + "BSD-2-Clause" ], "authors": [ { @@ -741,17 +579,7 @@ "issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=Archive_Tar", "source": "https://github.com/pear/Archive_Tar" }, - "funding": [ - { - "url": "https://github.com/mrook", - "type": "github" - }, - { - "url": "https://www.patreon.com/michielrook", - "type": "patreon" - } - ], - "time": "2021-07-20T13:53:39+00:00" + "time": "2024-03-16T16:21:40+00:00" }, { "name": "pear/console_getopt", @@ -806,30 +634,31 @@ }, { "name": "pear/pear-core-minimal", - "version": "v1.10.13", + "version": "v1.10.16", "source": { "type": "git", "url": "https://github.com/pear/pear-core-minimal.git", - "reference": "aed862e95fd286c53cc546734868dc38ff4b5b1d" + "reference": "c0f51b45f50683bf5bbf558036854ebc9b54d033" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pear/pear-core-minimal/zipball/aed862e95fd286c53cc546734868dc38ff4b5b1d", - "reference": "aed862e95fd286c53cc546734868dc38ff4b5b1d", + "url": "https://api.github.com/repos/pear/pear-core-minimal/zipball/c0f51b45f50683bf5bbf558036854ebc9b54d033", + "reference": "c0f51b45f50683bf5bbf558036854ebc9b54d033", "shasum": "" }, "require": { "pear/console_getopt": "~1.4", - "pear/pear_exception": "~1.0" + "pear/pear_exception": "~1.0", + "php": ">=5.4" }, "replace": { "rsky/pear-core-min": "self.version" }, "type": "library", "autoload": { - "psr-0": { - "": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "include-path": [ @@ -850,7 +679,7 @@ "issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=PEAR", "source": "https://github.com/pear/pear-core-minimal" }, - "time": "2023-04-19T19:15:47+00:00" + "time": "2024-11-24T22:27:58+00:00" }, { "name": "pear/pear_exception", @@ -911,6 +740,162 @@ }, "time": "2021-03-21T15:43:46+00:00" }, + { + "name": "phootwork/collection", + "version": "v3.2.3", + "source": { + "type": "git", + "url": "https://github.com/phootwork/collection.git", + "reference": "46dde20420fba17766c89200bc3ff91d3e58eafa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phootwork/collection/zipball/46dde20420fba17766c89200bc3ff91d3e58eafa", + "reference": "46dde20420fba17766c89200bc3ff91d3e58eafa", + "shasum": "" + }, + "require": { + "phootwork/lang": "^3.0", + "php": ">=8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "phootwork\\collection\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Thomas Gossmann", + "homepage": "http://gos.si" + } + ], + "description": "The phootwork library fills gaps in the php language and provides better solutions than the existing ones php offers.", + "homepage": "https://phootwork.github.io/collection/", + "keywords": [ + "Array object", + "Text object", + "collection", + "collections", + "json", + "list", + "map", + "queue", + "set", + "stack", + "xml" + ], + "support": { + "issues": "https://github.com/phootwork/phootwork/issues", + "source": "https://github.com/phootwork/collection/tree/v3.2.3" + }, + "time": "2022-08-27T12:51:24+00:00" + }, + { + "name": "phootwork/lang", + "version": "v3.2.3", + "source": { + "type": "git", + "url": "https://github.com/phootwork/lang.git", + "reference": "52ec8cce740ce1c424eef02f43b43d5ddfec7b5e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phootwork/lang/zipball/52ec8cce740ce1c424eef02f43b43d5ddfec7b5e", + "reference": "52ec8cce740ce1c424eef02f43b43d5ddfec7b5e", + "shasum": "" + }, + "require": { + "php": ">=8.0", + "symfony/polyfill-mbstring": "^1.12", + "symfony/polyfill-php81": "^1.22" + }, + "type": "library", + "autoload": { + "psr-4": { + "phootwork\\lang\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Thomas Gossmann", + "homepage": "http://gos.si" + } + ], + "description": "Missing PHP language constructs", + "homepage": "https://phootwork.github.io/lang/", + "keywords": [ + "array", + "comparator", + "comparison", + "string" + ], + "support": { + "issues": "https://github.com/phootwork/phootwork/issues", + "source": "https://github.com/phootwork/lang/tree/v3.2.3" + }, + "time": "2024-10-03T13:43:19+00:00" + }, + { + "name": "phpowermove/docblock", + "version": "v4.0", + "source": { + "type": "git", + "url": "https://github.com/phpowermove/docblock.git", + "reference": "a73f6e17b7d4e1b92ca5378c248c952c9fae7826" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpowermove/docblock/zipball/a73f6e17b7d4e1b92ca5378c248c952c9fae7826", + "reference": "a73f6e17b7d4e1b92ca5378c248c952c9fae7826", + "shasum": "" + }, + "require": { + "phootwork/collection": "^3.0", + "phootwork/lang": "^3.0", + "php": ">=8.0" + }, + "require-dev": { + "phootwork/php-cs-fixer-config": "^0.4", + "phpunit/phpunit": "^9.0", + "psalm/phar": "^4.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "phpowermove\\docblock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Thomas Gossmann", + "homepage": "http://gos.si" + } + ], + "description": "PHP Docblock parser and generator. An API to read and write Docblocks.", + "keywords": [ + "docblock", + "generator", + "parser" + ], + "support": { + "issues": "https://github.com/phpowermove/docblock/issues", + "source": "https://github.com/phpowermove/docblock/tree/v4.0" + }, + "time": "2021-09-22T16:57:06+00:00" + }, { "name": "psr/container", "version": "2.0.2", @@ -1016,16 +1001,16 @@ }, { "name": "psr/log", - "version": "2.0.0", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376" + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/ef29f6d262798707a9edd554e2b82517ef3a9376", - "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", "shasum": "" }, "require": { @@ -1034,7 +1019,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.x-dev" } }, "autoload": { @@ -1060,49 +1045,52 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/2.0.0" + "source": "https://github.com/php-fig/log/tree/3.0.2" }, - "time": "2021-07-14T16:41:46+00:00" + "time": "2024-09-11T13:17:53+00:00" }, { "name": "symfony/console", - "version": "v6.3.4", + "version": "v7.2.1", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6" + "reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/eca495f2ee845130855ddf1cf18460c38966c8b6", - "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6", + "url": "https://api.github.com/repos/symfony/console/zipball/fefcc18c0f5d0efe3ab3152f15857298868dc2c3", + "reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=8.2", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^5.4|^6.0" + "symfony/string": "^6.4|^7.0" }, "conflict": { - "symfony/dependency-injection": "<5.4", - "symfony/dotenv": "<5.4", - "symfony/event-dispatcher": "<5.4", - "symfony/lock": "<5.4", - "symfony/process": "<5.4" + "symfony/dependency-injection": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/lock": "<6.4", + "symfony/process": "<6.4" }, "provide": { "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/lock": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -1136,7 +1124,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.3.4" + "source": "https://github.com/symfony/console/tree/v7.2.1" }, "funding": [ { @@ -1152,20 +1140,20 @@ "type": "tidelift" } ], - "time": "2023-08-16T10:10:12+00:00" + "time": "2024-12-11T03:49:26+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.3.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", "shasum": "" }, "require": { @@ -1174,7 +1162,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -1203,7 +1191,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" }, "funding": [ { @@ -1219,28 +1207,28 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.3.2", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e" + "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/adb01fe097a4ee930db9258a3cc906b5beb5cf2e", - "reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/910c5db85a5356d0fea57680defec4e99eb9c8c1", + "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<5.4", + "symfony/dependency-injection": "<6.4", "symfony/service-contracts": "<2.5" }, "provide": { @@ -1249,13 +1237,13 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/error-handler": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^5.4|^6.0" + "symfony/stopwatch": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -1283,7 +1271,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.3.2" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.2.0" }, "funding": [ { @@ -1299,20 +1287,20 @@ "type": "tidelift" } ], - "time": "2023-07-06T06:56:43+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.3.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "a76aed96a42d2b521153fb382d418e30d18b59df" + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df", - "reference": "a76aed96a42d2b521153fb382d418e30d18b59df", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", "shasum": "" }, "require": { @@ -1322,7 +1310,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -1359,7 +1347,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1" }, "funding": [ { @@ -1375,27 +1363,30 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/filesystem", - "version": "v6.3.1", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae" + "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", - "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/b8dce482de9d7c9fe2891155035a7248ab5c7fdb", + "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8" }, + "require-dev": { + "symfony/process": "^6.4|^7.0" + }, "type": "library", "autoload": { "psr-4": { @@ -1422,7 +1413,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.3.1" + "source": "https://github.com/symfony/filesystem/tree/v7.2.0" }, "funding": [ { @@ -1438,27 +1429,27 @@ "type": "tidelift" } ], - "time": "2023-06-01T08:30:39+00:00" + "time": "2024-10-25T15:15:23+00:00" }, { "name": "symfony/finder", - "version": "v6.3.5", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "a1b31d88c0e998168ca7792f222cbecee47428c4" + "reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/a1b31d88c0e998168ca7792f222cbecee47428c4", - "reference": "a1b31d88c0e998168ca7792f222cbecee47428c4", + "url": "https://api.github.com/repos/symfony/finder/zipball/6de263e5868b9a137602dd1e33e4d48bfae99c49", + "reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "symfony/filesystem": "^6.0" + "symfony/filesystem": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -1486,7 +1477,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.3.5" + "source": "https://github.com/symfony/finder/tree/v7.2.0" }, "funding": [ { @@ -1502,24 +1493,24 @@ "type": "tidelift" } ], - "time": "2023-09-26T12:56:25+00:00" + "time": "2024-10-23T06:56:12+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.28.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-ctype": "*" @@ -1529,12 +1520,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -1568,7 +1556,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" }, "funding": [ { @@ -1584,36 +1572,33 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.28.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "875e90aeea2777b6f135677f618529449334a612" + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", - "reference": "875e90aeea2777b6f135677f618529449334a612", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -1649,7 +1634,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" }, "funding": [ { @@ -1665,36 +1650,33 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.28.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -1733,7 +1715,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" }, "funding": [ { @@ -1749,24 +1731,24 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.28.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "42292d99c55abe617799667f454222c54c60e229" + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", - "reference": "42292d99c55abe617799667f454222c54c60e229", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-mbstring": "*" @@ -1776,12 +1758,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -1816,7 +1795,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" }, "funding": [ { @@ -1832,24 +1811,100 @@ "type": "tidelift" } ], - "time": "2023-07-28T09:04:16+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { - "name": "symfony/process", - "version": "v6.3.4", + "name": "symfony/polyfill-php81", + "version": "v1.31.0", "source": { "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "0b5c29118f2e980d455d2e34a5659f4579847c54" + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/0b5c29118f2e980d455d2e34a5659f4579847c54", - "reference": "0b5c29118f2e980d455d2e34a5659f4579847c54", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "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": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.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-09-09T11:45:10+00:00" + }, + { + "name": "symfony/process", + "version": "v7.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", + "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", + "shasum": "" + }, + "require": { + "php": ">=8.2" }, "type": "library", "autoload": { @@ -1877,7 +1932,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.3.4" + "source": "https://github.com/symfony/process/tree/v7.2.0" }, "funding": [ { @@ -1893,25 +1948,26 @@ "type": "tidelift" } ], - "time": "2023-08-07T10:39:22+00:00" + "time": "2024-11-06T14:24:19+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.3.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4" + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", - "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^2.0" + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { "ext-psr": "<1.1|>=2" @@ -1919,7 +1975,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -1959,7 +2015,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" }, "funding": [ { @@ -1975,24 +2031,24 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/string", - "version": "v6.3.5", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "13d76d0fb049051ed12a04bef4f9de8715bea339" + "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/13d76d0fb049051ed12a04bef4f9de8715bea339", - "reference": "13d76d0fb049051ed12a04bef4f9de8715bea339", + "url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82", + "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", @@ -2002,11 +2058,12 @@ "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/intl": "^6.2", + "symfony/emoji": "^7.1", + "symfony/error-handler": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^5.4|^6.0" + "symfony/var-exporter": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -2045,7 +2102,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.3.5" + "source": "https://github.com/symfony/string/tree/v7.2.0" }, "funding": [ { @@ -2061,32 +2118,32 @@ "type": "tidelift" } ], - "time": "2023-09-18T10:38:32+00:00" + "time": "2024-11-13T13:31:26+00:00" }, { "name": "symfony/yaml", - "version": "v6.3.7", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "9758b6c69d179936435d0ffb577c3708d57e38a8" + "reference": "099581e99f557e9f16b43c5916c26380b54abb22" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/9758b6c69d179936435d0ffb577c3708d57e38a8", - "reference": "9758b6c69d179936435d0ffb577c3708d57e38a8", + "url": "https://api.github.com/repos/symfony/yaml/zipball/099581e99f557e9f16b43c5916c26380b54abb22", + "reference": "099581e99f557e9f16b43c5916c26380b54abb22", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "symfony/console": "<5.4" + "symfony/console": "<6.4" }, "require-dev": { - "symfony/console": "^5.4|^6.0" + "symfony/console": "^6.4|^7.0" }, "bin": [ "Resources/bin/yaml-lint" @@ -2117,7 +2174,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v6.3.7" + "source": "https://github.com/symfony/yaml/tree/v7.2.0" }, "funding": [ { @@ -2133,15 +2190,15 @@ "type": "tidelift" } ], - "time": "2023-10-28T23:31:00+00:00" + "time": "2024-10-23T06:56:12+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, - "platform": [], - "platform-dev": [], + "platform": {}, + "platform-dev": {}, "plugin-api-version": "2.6.0" }