mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-22 05:02:40 +00:00
Merge branch 'master' into dbtest
This commit is contained in:
commit
a77b47cd59
47 changed files with 1288 additions and 1770 deletions
|
@ -1,4 +1,4 @@
|
|||
Version 0.1?.? (2022-??-??)
|
||||
Version 0.10.3 (2022-09-14)
|
||||
===========================
|
||||
|
||||
Bug fixes:
|
||||
|
@ -6,6 +6,7 @@ Bug fixes:
|
|||
- Allow multiple date ranges in search strings in Tiny Tiny RSS
|
||||
- Honour user time zone when interpreting search strings in Tiny Tiny RSS
|
||||
- Perform MySQL table maintenance more reliably
|
||||
- Address CVE-2022-31090, CVE-2022-31091, CVE-2022-29248, and CVE-2022-31109
|
||||
|
||||
Version 0.10.2 (2022-04-04)
|
||||
===========================
|
||||
|
|
|
@ -164,7 +164,7 @@ class RoboFile extends \Robo\Tasks {
|
|||
if (
|
||||
(IS_WIN && (!exec(escapeshellarg($bin)." --help $blackhole", $junk, $status) || $status))
|
||||
|| (!IS_WIN && (!exec("which ".escapeshellarg($bin)." $blackhole", $junk, $status) || $status))
|
||||
) {
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,13 @@ usually prudent:
|
|||
`composer install -o --no-dev`
|
||||
|
||||
|
||||
Upgrading from 0.10.2 to 0.10.3
|
||||
=============================
|
||||
|
||||
- The following Composer dependencies have been removed:
|
||||
- laminas/laminas-diactoros
|
||||
|
||||
|
||||
Upgrading from 0.8.5 to 0.9.0
|
||||
=============================
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
"hosteurope/password-generator": "1.*",
|
||||
"docopt/docopt": "1.*",
|
||||
"jkingweb/druuid": "3.*",
|
||||
"laminas/laminas-diactoros": "2.*",
|
||||
"guzzlehttp/psr7": "1.*",
|
||||
"laminas/laminas-httphandlerrunner": "1.*"
|
||||
},
|
||||
"require-dev": {
|
||||
|
|
240
composer.lock
generated
240
composer.lock
generated
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "c658930fbc56b2b2cf646e34c6a8d8d3",
|
||||
"content-hash": "2671d9010a4ac73e877838baf3586df2",
|
||||
"packages": [
|
||||
{
|
||||
"name": "docopt/docopt",
|
||||
|
@ -58,24 +58,24 @@
|
|||
},
|
||||
{
|
||||
"name": "guzzlehttp/guzzle",
|
||||
"version": "6.5.6",
|
||||
"version": "6.5.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/guzzle.git",
|
||||
"reference": "f092dd734083473658de3ee4bef093ed77d2689c"
|
||||
"reference": "a52f0440530b54fa079ce76e8c5d196a42cad981"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/f092dd734083473658de3ee4bef093ed77d2689c",
|
||||
"reference": "f092dd734083473658de3ee4bef093ed77d2689c",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/a52f0440530b54fa079ce76e8c5d196a42cad981",
|
||||
"reference": "a52f0440530b54fa079ce76e8c5d196a42cad981",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"guzzlehttp/promises": "^1.0",
|
||||
"guzzlehttp/psr7": "^1.6.1",
|
||||
"guzzlehttp/psr7": "^1.9",
|
||||
"php": ">=5.5",
|
||||
"symfony/polyfill-intl-idn": "^1.17.0"
|
||||
"symfony/polyfill-intl-idn": "^1.17"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-curl": "*",
|
||||
|
@ -153,7 +153,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/guzzle/guzzle/issues",
|
||||
"source": "https://github.com/guzzle/guzzle/tree/6.5.6"
|
||||
"source": "https://github.com/guzzle/guzzle/tree/6.5.8"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -169,20 +169,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-25T13:19:12+00:00"
|
||||
"time": "2022-06-20T22:16:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/promises",
|
||||
"version": "1.5.1",
|
||||
"version": "1.5.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/promises.git",
|
||||
"reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da"
|
||||
"reference": "b94b2807d85443f9719887892882d0329d1e2598"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/promises/zipball/fe752aedc9fd8fcca3fe7ad05d419d32998a06da",
|
||||
"reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da",
|
||||
"url": "https://api.github.com/repos/guzzle/promises/zipball/b94b2807d85443f9719887892882d0329d1e2598",
|
||||
"reference": "b94b2807d85443f9719887892882d0329d1e2598",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -237,7 +237,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/guzzle/promises/issues",
|
||||
"source": "https://github.com/guzzle/promises/tree/1.5.1"
|
||||
"source": "https://github.com/guzzle/promises/tree/1.5.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -253,20 +253,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-10-22T20:56:57+00:00"
|
||||
"time": "2022-08-28T14:55:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/psr7",
|
||||
"version": "1.8.5",
|
||||
"version": "1.9.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/psr7.git",
|
||||
"reference": "337e3ad8e5716c15f9657bd214d16cc5e69df268"
|
||||
"reference": "e98e3e6d4f86621a9b75f623996e6bbdeb4b9318"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/337e3ad8e5716c15f9657bd214d16cc5e69df268",
|
||||
"reference": "337e3ad8e5716c15f9657bd214d16cc5e69df268",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/e98e3e6d4f86621a9b75f623996e6bbdeb4b9318",
|
||||
"reference": "e98e3e6d4f86621a9b75f623996e6bbdeb4b9318",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -287,7 +287,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.7-dev"
|
||||
"dev-master": "1.9-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -347,7 +347,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/guzzle/psr7/issues",
|
||||
"source": "https://github.com/guzzle/psr7/tree/1.8.5"
|
||||
"source": "https://github.com/guzzle/psr7/tree/1.9.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -363,7 +363,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-20T21:51:18+00:00"
|
||||
"time": "2022-06-20T21:43:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "hosteurope/password-generator",
|
||||
|
@ -537,105 +537,6 @@
|
|||
},
|
||||
"time": "2017-08-17T12:23:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laminas/laminas-diactoros",
|
||||
"version": "2.4.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laminas/laminas-diactoros.git",
|
||||
"reference": "36ef09b73e884135d2059cc498c938e90821bb57"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/36ef09b73e884135d2059cc498c938e90821bb57",
|
||||
"reference": "36ef09b73e884135d2059cc498c938e90821bb57",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"laminas/laminas-zendframework-bridge": "^1.0",
|
||||
"php": "^7.1",
|
||||
"psr/http-factory": "^1.0",
|
||||
"psr/http-message": "^1.0"
|
||||
},
|
||||
"conflict": {
|
||||
"phpspec/prophecy": "<1.9.0"
|
||||
},
|
||||
"provide": {
|
||||
"psr/http-factory-implementation": "1.0",
|
||||
"psr/http-message-implementation": "1.0"
|
||||
},
|
||||
"replace": {
|
||||
"zendframework/zend-diactoros": "^2.2.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-curl": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-gd": "*",
|
||||
"ext-libxml": "*",
|
||||
"http-interop/http-factory-tests": "^0.5.0",
|
||||
"laminas/laminas-coding-standard": "~1.0.0",
|
||||
"php-http/psr7-integration-tests": "^1.0",
|
||||
"phpunit/phpunit": "^7.5.18"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laminas": {
|
||||
"config-provider": "Laminas\\Diactoros\\ConfigProvider",
|
||||
"module": "Laminas\\Diactoros"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/functions/create_uploaded_file.php",
|
||||
"src/functions/marshal_headers_from_sapi.php",
|
||||
"src/functions/marshal_method_from_sapi.php",
|
||||
"src/functions/marshal_protocol_version_from_sapi.php",
|
||||
"src/functions/marshal_uri_from_sapi.php",
|
||||
"src/functions/normalize_server.php",
|
||||
"src/functions/normalize_uploaded_files.php",
|
||||
"src/functions/parse_cookie_header.php",
|
||||
"src/functions/create_uploaded_file.legacy.php",
|
||||
"src/functions/marshal_headers_from_sapi.legacy.php",
|
||||
"src/functions/marshal_method_from_sapi.legacy.php",
|
||||
"src/functions/marshal_protocol_version_from_sapi.legacy.php",
|
||||
"src/functions/marshal_uri_from_sapi.legacy.php",
|
||||
"src/functions/normalize_server.legacy.php",
|
||||
"src/functions/normalize_uploaded_files.legacy.php",
|
||||
"src/functions/parse_cookie_header.legacy.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Laminas\\Diactoros\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"description": "PSR HTTP Message implementations",
|
||||
"homepage": "https://laminas.dev",
|
||||
"keywords": [
|
||||
"http",
|
||||
"laminas",
|
||||
"psr",
|
||||
"psr-17",
|
||||
"psr-7"
|
||||
],
|
||||
"support": {
|
||||
"chat": "https://laminas.dev/chat",
|
||||
"docs": "https://docs.laminas.dev/laminas-diactoros/",
|
||||
"forum": "https://discourse.laminas.dev",
|
||||
"issues": "https://github.com/laminas/laminas-diactoros/issues",
|
||||
"rss": "https://github.com/laminas/laminas-diactoros/releases.atom",
|
||||
"source": "https://github.com/laminas/laminas-diactoros"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://funding.communitybridge.org/projects/laminas-project",
|
||||
"type": "community_bridge"
|
||||
}
|
||||
],
|
||||
"time": "2020-09-03T14:29:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laminas/laminas-httphandlerrunner",
|
||||
"version": "1.2.0",
|
||||
|
@ -892,61 +793,6 @@
|
|||
},
|
||||
"time": "2020-09-15T07:28:23+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-factory",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/http-factory.git",
|
||||
"reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
|
||||
"reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.0.0",
|
||||
"psr/http-message": "^1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Http\\Message\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interfaces for PSR-7 HTTP message factories",
|
||||
"keywords": [
|
||||
"factory",
|
||||
"http",
|
||||
"message",
|
||||
"psr",
|
||||
"psr-17",
|
||||
"psr-7",
|
||||
"request",
|
||||
"response"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/http-factory/tree/master"
|
||||
},
|
||||
"time": "2019-04-30T12:38:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-message",
|
||||
"version": "1.0.1",
|
||||
|
@ -1153,16 +999,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-idn",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-idn.git",
|
||||
"reference": "749045c69efb97c70d25d7463abba812e91f3a44"
|
||||
"reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/749045c69efb97c70d25d7463abba812e91f3a44",
|
||||
"reference": "749045c69efb97c70d25d7463abba812e91f3a44",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/59a8d271f00dd0e4c2e518104cc7963f655a1aa8",
|
||||
"reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1176,7 +1022,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1220,7 +1066,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1236,20 +1082,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-09-14T14:02:44+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-normalizer",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
||||
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8"
|
||||
"reference": "219aa369ceff116e673852dce47c3a41794c14bd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8",
|
||||
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
|
||||
"reference": "219aa369ceff116e673852dce47c3a41794c14bd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1261,7 +1107,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1304,7 +1150,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1320,20 +1166,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-02-19T12:13:01+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php72",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php72.git",
|
||||
"reference": "9a142215a36a3888e30d0a9eeea9766764e96976"
|
||||
"reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9a142215a36a3888e30d0a9eeea9766764e96976",
|
||||
"reference": "9a142215a36a3888e30d0a9eeea9766764e96976",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/bf44a9fd41feaac72b074de600314a93e2ae78e2",
|
||||
"reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1342,7 +1188,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1380,7 +1226,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php72/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-php72/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1396,7 +1242,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-05-27T09:17:38+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
|
|
|
@ -7,7 +7,7 @@ declare(strict_types=1);
|
|||
namespace JKingWeb\Arsse;
|
||||
|
||||
class Arsse {
|
||||
public const VERSION = "0.10.2";
|
||||
public const VERSION = "0.10.3";
|
||||
public const REQUIRED_EXTENSIONS = [
|
||||
"intl", // as this extension is required to prepare formatted messages, its absence will throw a distinct English-only exception
|
||||
"dom",
|
||||
|
|
|
@ -27,7 +27,7 @@ trait ExceptionBuilder {
|
|||
public static function buildConnectionException($code, string $msg): array {
|
||||
switch ($code) {
|
||||
case 1045:
|
||||
// @codeCoverageIgnoreStart
|
||||
// @codeCoverageIgnoreStart
|
||||
case 1043:
|
||||
case 1044:
|
||||
case 1046:
|
||||
|
@ -48,7 +48,7 @@ trait ExceptionBuilder {
|
|||
case 2018:
|
||||
case 2026:
|
||||
case 2028:
|
||||
// @codeCoverageIgnoreEnd
|
||||
// @codeCoverageIgnoreEnd
|
||||
return [Exception::class, 'connectionFailure', ['engine' => "MySQL", 'message' => $msg]];
|
||||
default:
|
||||
return [Exception::class, 'engineErrorGeneral', $msg]; // @codeCoverageIgnore
|
||||
|
|
|
@ -7,16 +7,41 @@ declare(strict_types=1);
|
|||
namespace JKingWeb\Arsse\Misc;
|
||||
|
||||
use Psr\Http\Message\MessageInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
|
||||
class HTTP {
|
||||
public static function matchType(MessageInterface $msg, string ...$type): bool {
|
||||
$header = $msg->getHeaderLine("Content-Type") ?? "";
|
||||
foreach ($type as $t) {
|
||||
$pattern = "/^".preg_quote(trim($t), "/")."\s*($|;|,)/Di";
|
||||
if (($t[0] ?? "") === "+") {
|
||||
$pattern = "/^[^+;,\s]*".preg_quote(trim($t), "/")."\s*($|;|,)/Di";
|
||||
} else {
|
||||
$pattern = "/^".preg_quote(trim($t), "/")."\s*($|;|,)/Di";
|
||||
}
|
||||
if (preg_match($pattern, $header)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function respEmpty(int $status, ?array $headers = []): ResponseInterface {
|
||||
return new Response($status, $headers ?? []);
|
||||
}
|
||||
|
||||
public static function respJson($body, int $status = 200, ?array $headers = []): ResponseInterface {
|
||||
$headers = ($headers ?? []) + ['Content-Type' => "application/json"];
|
||||
return new Response($status, $headers, json_encode($body, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
|
||||
public static function respText(string $body, int $status = 200, ?array $headers = []): ResponseInterface {
|
||||
$headers = ($headers ?? []) + ['Content-Type' => "text/plain; charset=UTF-8"];
|
||||
return new Response($status, $headers, $body);
|
||||
}
|
||||
|
||||
public static function respXml(string $body, int $status = 200, ?array $headers = []): ResponseInterface {
|
||||
$headers = ($headers ?? []) + ['Content-Type' => "application/xml; charset=UTF-8"];
|
||||
return new Response($status, $headers, $body);
|
||||
}
|
||||
}
|
||||
|
|
10
lib/REST.php
10
lib/REST.php
|
@ -7,11 +7,11 @@ declare(strict_types=1);
|
|||
namespace JKingWeb\Arsse;
|
||||
|
||||
use JKingWeb\Arsse\Misc\URL;
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\ServerRequestFactory;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
use GuzzleHttp\Psr7\ServerRequest;
|
||||
|
||||
class REST {
|
||||
public const API_LIST = [
|
||||
|
@ -84,7 +84,7 @@ class REST {
|
|||
// ensure the require extensions are loaded
|
||||
Arsse::checkExtensions(...Arsse::REQUIRED_EXTENSIONS);
|
||||
// create a request object if not provided
|
||||
$req = $req ?? ServerRequestFactory::fromGlobals();
|
||||
$req = $req ?? ServerRequest::fromGlobals();
|
||||
// find the API to handle
|
||||
[, $target, $class] = $this->apiMatch($req->getRequestTarget(), $this->apis);
|
||||
// authenticate the request pre-emptively
|
||||
|
@ -101,7 +101,7 @@ class REST {
|
|||
$res = $drv->dispatch($req);
|
||||
}
|
||||
} catch (REST\Exception501 $e) {
|
||||
$res = new EmptyResponse(501);
|
||||
$res = HTTP::respEmpty(501);
|
||||
}
|
||||
// modify the response so that it has all the required metadata
|
||||
return $this->normalizeResponse($res, $req);
|
||||
|
@ -180,7 +180,7 @@ class REST {
|
|||
}
|
||||
// if the response is to a HEAD request, the body should be omitted
|
||||
if ($req && $req->getMethod() === "HEAD") {
|
||||
$res = new EmptyResponse($res->getStatusCode(), $res->getHeaders());
|
||||
$res = HTTP::respEmpty($res->getStatusCode(), $res->getHeaders());
|
||||
}
|
||||
// if an Allow header field is present, normalize it
|
||||
if ($res->hasHeader("Allow")) {
|
||||
|
|
|
@ -10,13 +10,10 @@ use JKingWeb\Arsse\Arsse;
|
|||
use JKingWeb\Arsse\Context\Context;
|
||||
use JKingWeb\Arsse\Misc\ValueInfo as V;
|
||||
use JKingWeb\Arsse\Misc\Date;
|
||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Laminas\Diactoros\Response\XmlResponse;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
|
||||
class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||
public const LEVEL = 3;
|
||||
|
@ -62,11 +59,11 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
$P = $this->normalizeInputPost($req->getParsedBody() ?? []);
|
||||
if (!isset($G['api'])) {
|
||||
// the original would have shown the Fever UI in the absence of the "api" parameter, but we'll return 404
|
||||
return new EmptyResponse(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
switch ($req->getMethod()) {
|
||||
case "OPTIONS":
|
||||
return new EmptyResponse(204, [
|
||||
return HTTP::respEmpty(204, [
|
||||
'Allow' => "POST",
|
||||
'Accept' => implode(", ", self::ACCEPTED_TYPES),
|
||||
]);
|
||||
|
@ -82,7 +79,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
$out['auth'] = 1;
|
||||
} elseif (Arsse::$conf->userHTTPAuthRequired || Arsse::$conf->userPreAuth || $req->getAttribute("authenticationFailed", false)) {
|
||||
// otherwise if HTTP authentication failed or is required, deny access at the HTTP level
|
||||
return new EmptyResponse(401);
|
||||
return HTTP::respEmpty(401);
|
||||
}
|
||||
// produce a full response if authenticated or a basic response otherwise
|
||||
if ($this->logIn(strtolower($P['api_key'] ?? ""))) {
|
||||
|
@ -93,7 +90,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
// return the result, possibly formatted as XML
|
||||
return $this->formatResponse($out, ($G['api'] === "xml"));
|
||||
default:
|
||||
return new EmptyResponse(405, ['Allow' => "OPTIONS,POST"]);
|
||||
return HTTP::respEmpty(405, ['Allow' => "OPTIONS,POST"]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,9 +179,9 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
if ($xml) {
|
||||
$d = new \DOMDocument("1.0", "utf-8");
|
||||
$d->appendChild($this->makeXMLAssoc($data, $d->createElement("response")));
|
||||
return new XmlResponse($d->saveXML());
|
||||
return HTTP::respXml($d->saveXML());
|
||||
} else {
|
||||
return new JsonResponse($data, 200, [], \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE);
|
||||
return HTTP::respJson($data, 200, [], \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
/** @license MIT
|
||||
* Copyright 2017 J. King, Dustin Wilson et al.
|
||||
* See LICENSE and AUTHORS files for details */
|
||||
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\Arsse\REST\Miniflux;
|
||||
|
||||
use JKingWeb\Arsse\Arsse;
|
||||
|
||||
class ErrorResponse extends \Laminas\Diactoros\Response\JsonResponse {
|
||||
public function __construct($data, int $status = 400, array $headers = [], int $encodingOptions = self::DEFAULT_JSON_FLAGS) {
|
||||
assert(isset(Arsse::$lang) && Arsse::$lang instanceof \JKingWeb\Arsse\Lang, new \Exception("Language database must be initialized before use"));
|
||||
$data = (array) $data;
|
||||
$msg = array_shift($data);
|
||||
$data = ["error_message" => Arsse::$lang->msg("API.Miniflux.Error.".$msg, $data)];
|
||||
parent::__construct($data, $status, $headers, $encodingOptions);
|
||||
}
|
||||
}
|
|
@ -6,10 +6,9 @@
|
|||
declare(strict_types=1);
|
||||
namespace JKingWeb\Arsse\REST\Miniflux;
|
||||
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
use Laminas\Diactoros\Response\TextResponse;
|
||||
|
||||
class Status extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||
public function __construct() {
|
||||
|
@ -18,13 +17,13 @@ class Status extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
public function dispatch(ServerRequestInterface $req): ResponseInterface {
|
||||
$target = parse_url($req->getRequestTarget())['path'] ?? "";
|
||||
if (!in_array($target, ["/version", "/healthcheck"])) {
|
||||
return new EmptyResponse(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
$method = $req->getMethod();
|
||||
if ($method === "OPTIONS") {
|
||||
return new EmptyResponse(204, ['Allow' => "HEAD, GET"]);
|
||||
return HTTP::respEmpty(204, ['Allow' => "HEAD, GET"]);
|
||||
} elseif ($method !== "GET") {
|
||||
return new EmptyResponse(405, ['Allow' => "HEAD, GET"]);
|
||||
return HTTP::respEmpty(405, ['Allow' => "HEAD, GET"]);
|
||||
}
|
||||
$out = "";
|
||||
if ($target === "/version") {
|
||||
|
@ -32,6 +31,6 @@ class Status extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
} elseif ($target === "/healthcheck") {
|
||||
$out = "OK";
|
||||
}
|
||||
return new TextResponse($out);
|
||||
return HTTP::respText($out);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ use JKingWeb\Arsse\ImportExport\OPML;
|
|||
use JKingWeb\Arsse\ImportExport\Exception as ImportException;
|
||||
use JKingWeb\Arsse\Misc\Date;
|
||||
use JKingWeb\Arsse\Misc\URL;
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use JKingWeb\Arsse\Misc\ValueInfo as V;
|
||||
use JKingWeb\Arsse\REST\Exception;
|
||||
use JKingWeb\Arsse\Rule\Rule;
|
||||
|
@ -26,10 +27,7 @@ use JKingWeb\Arsse\User\ExceptionConflict;
|
|||
use JKingWeb\Arsse\User\Exception as UserException;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
use Laminas\Diactoros\Response\JsonResponse as Response;
|
||||
use Laminas\Diactoros\Response\TextResponse as GenericResponse;
|
||||
use Laminas\Diactoros\Uri;
|
||||
use GuzzleHttp\Psr7\Uri;
|
||||
|
||||
class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||
public const VERSION = "2.0.28";
|
||||
|
@ -215,6 +213,14 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
public function __construct() {
|
||||
}
|
||||
|
||||
public static function respError($data, int $status = 400, array $headers = []): ResponseInterface {
|
||||
assert(isset(Arsse::$lang) && Arsse::$lang instanceof \JKingWeb\Arsse\Lang, new \Exception("Language database must be initialized before use"));
|
||||
$data = (array) $data;
|
||||
$msg = array_shift($data);
|
||||
$data = ["error_message" => Arsse::$lang->msg("API.Miniflux.Error.".$msg, $data)];
|
||||
return HTTP::respJson($data, $status, $headers);
|
||||
}
|
||||
|
||||
protected function authenticate(ServerRequestInterface $req): bool {
|
||||
// first check any tokens; this is what Miniflux does
|
||||
if ($req->hasHeader("X-Auth-Token")) {
|
||||
|
@ -247,7 +253,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
}
|
||||
// try to authenticate
|
||||
if (!$this->authenticate($req)) {
|
||||
return new ErrorResponse("401", 401);
|
||||
return self::respError("401", 401);
|
||||
}
|
||||
$func = $this->chooseCall($target, $method);
|
||||
if ($func instanceof ResponseInterface) {
|
||||
|
@ -256,7 +262,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
[$func, $reqAdmin, $reqPath, $reqBody, $reqQuery, $reqFields] = $func;
|
||||
}
|
||||
if ($reqAdmin && !$this->isAdmin()) {
|
||||
return new ErrorResponse("403", 403);
|
||||
return self::respError("403", 403);
|
||||
}
|
||||
$args = [];
|
||||
if ($reqPath) {
|
||||
|
@ -271,7 +277,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
$data = @json_decode($data, true);
|
||||
if (json_last_error() !== \JSON_ERROR_NONE) {
|
||||
// if the body could not be parsed as JSON, return "400 Bad Request"
|
||||
return new ErrorResponse(["InvalidBodyJSON", json_last_error_msg()], 400);
|
||||
return self::respError(["InvalidBodyJSON", json_last_error_msg()], 400);
|
||||
}
|
||||
} else {
|
||||
$data = [];
|
||||
|
@ -295,10 +301,10 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
// @codeCoverageIgnoreStart
|
||||
} catch (Exception $e) {
|
||||
// if there was a REST exception return 400
|
||||
return new EmptyResponse(400);
|
||||
return HTTP::respEmpty(400);
|
||||
} catch (AbstractException $e) {
|
||||
// if there was any other Arsse exception return 500
|
||||
return new EmptyResponse(500);
|
||||
return HTTP::respEmpty(500);
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
@ -317,11 +323,11 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
return self::CALLS[$url][$method];
|
||||
} else {
|
||||
// otherwise return 405
|
||||
return new EmptyResponse(405, ['Allow' => implode(", ", array_keys(self::CALLS[$url]))]);
|
||||
return HTTP::respEmpty(405, ['Allow' => implode(", ", array_keys(self::CALLS[$url]))]);
|
||||
}
|
||||
} else {
|
||||
// if the path is not supported, return 404
|
||||
return new EmptyResponse(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -346,20 +352,20 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
if (!isset($body[$k])) {
|
||||
$body[$k] = null;
|
||||
} elseif (gettype($body[$k]) !== $t) {
|
||||
return new ErrorResponse(["InvalidInputType", 'field' => $k, 'expected' => $t, 'actual' => gettype($body[$k])], 422);
|
||||
return self::respError(["InvalidInputType", 'field' => $k, 'expected' => $t, 'actual' => gettype($body[$k])], 422);
|
||||
} elseif (
|
||||
(in_array($k, ["keeplist_rules", "blocklist_rules"]) && !Rule::validate($body[$k]))
|
||||
|| (in_array($k, ["url", "feed_url"]) && !URL::absolute($body[$k]))
|
||||
|| ($k === "category_id" && $body[$k] < 1)
|
||||
|| ($k === "status" && !in_array($body[$k], ["read", "unread", "removed"]))
|
||||
) {
|
||||
return new ErrorResponse(["InvalidInputValue", 'field' => $k], 422);
|
||||
return self::respError(["InvalidInputValue", 'field' => $k], 422);
|
||||
} elseif ($k === "entry_ids") {
|
||||
foreach ($body[$k] as $v) {
|
||||
if (gettype($v) !== "integer") {
|
||||
return new ErrorResponse(["InvalidInputType", 'field' => $k, 'expected' => "integer", 'actual' => gettype($v)], 422);
|
||||
return self::respError(["InvalidInputType", 'field' => $k, 'expected' => "integer", 'actual' => gettype($v)], 422);
|
||||
} elseif ($v < 1) {
|
||||
return new ErrorResponse(["InvalidInputValue", 'field' => $k], 422);
|
||||
return self::respError(["InvalidInputValue", 'field' => $k], 422);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -371,16 +377,16 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
$body[$k] = null;
|
||||
} elseif ($k === "entry_sorting_direction") {
|
||||
if (!in_array($body[$k], ["asc", "desc"])) {
|
||||
return new ErrorResponse(["InvalidInputValue", 'field' => $k], 422);
|
||||
return self::respError(["InvalidInputValue", 'field' => $k], 422);
|
||||
}
|
||||
} elseif (gettype($body[$k]) !== $t) {
|
||||
return new ErrorResponse(["InvalidInputType", 'field' => $k, 'expected' => $t, 'actual' => gettype($body[$k])], 422);
|
||||
return self::respError(["InvalidInputType", 'field' => $k, 'expected' => $t, 'actual' => gettype($body[$k])], 422);
|
||||
}
|
||||
}
|
||||
// check for any missing required values
|
||||
foreach ($req as $k) {
|
||||
if (!isset($body[$k]) || (is_array($body[$k]) && !$body[$k])) {
|
||||
return new ErrorResponse(["MissingInputValue", 'field' => $k], 422);
|
||||
return self::respError(["MissingInputValue", 'field' => $k], 422);
|
||||
}
|
||||
}
|
||||
return $body;
|
||||
|
@ -409,7 +415,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
if ($seen[$k] && !$a) {
|
||||
// if the key has already been seen and it's not an array field, bail
|
||||
// NOTE: Miniflux itself simply ignores duplicates entirely
|
||||
return new ErrorResponse(["DuplicateInputValue", 'field' => $k], 400);
|
||||
return self::respError(["DuplicateInputValue", 'field' => $k], 400);
|
||||
}
|
||||
$seen[$k] = true;
|
||||
if ($k === "starred") {
|
||||
|
@ -425,7 +431,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
$out[$k] = V::normalize($v, $t + V::M_STRICT, "unix");
|
||||
}
|
||||
} catch (ExceptionType $e) {
|
||||
return new ErrorResponse(["InvalidInputValue", 'field' => $k], 400);
|
||||
return self::respError(["InvalidInputValue", 'field' => $k], 400);
|
||||
}
|
||||
// perform additional validation
|
||||
if (
|
||||
|
@ -435,7 +441,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
|| ($k === "order" && !in_array($v, ["id", "status", "published_at", "category_title", "category_id"]))
|
||||
|| ($k === "status" && !in_array($v, ["read", "unread", "removed"]))
|
||||
) {
|
||||
return new ErrorResponse(["InvalidInputValue", 'field' => $k], 400);
|
||||
return self::respError(["InvalidInputValue", 'field' => $k], 400);
|
||||
}
|
||||
}
|
||||
return $out;
|
||||
|
@ -451,13 +457,13 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
if (in_array("GET", $allowed)) {
|
||||
array_unshift($allowed, "HEAD");
|
||||
}
|
||||
return new EmptyResponse(204, [
|
||||
return HTTP::respEmpty(204, [
|
||||
'Allow' => implode(", ", $allowed),
|
||||
'Accept' => implode(", ", $url === "/import" ? self::ACCEPTED_TYPES_OPML : self::ACCEPTED_TYPES_JSON),
|
||||
]);
|
||||
} else {
|
||||
// if the path is not supported, return 404
|
||||
return new EmptyResponse(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -527,40 +533,40 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
10507 => "Fetch401",
|
||||
10521 => "Fetch404",
|
||||
][$e->getCode()] ?? "FetchOther";
|
||||
return new ErrorResponse($msg, 502);
|
||||
return self::respError($msg, 502);
|
||||
}
|
||||
$out = [];
|
||||
foreach ($list as $url) {
|
||||
// TODO: This needs to be refined once PicoFeed is replaced
|
||||
$out[] = ['title' => "Feed", 'type' => "rss", 'url' => $url];
|
||||
}
|
||||
return new Response($out);
|
||||
return HTTP::respJson($out);
|
||||
}
|
||||
|
||||
protected function getUsers(): ResponseInterface {
|
||||
$tr = Arsse::$user->begin();
|
||||
return new Response($this->listUsers(Arsse::$user->list(), false));
|
||||
return HTTP::respJson($this->listUsers(Arsse::$user->list(), false));
|
||||
}
|
||||
|
||||
protected function getUserById(array $path): ResponseInterface {
|
||||
try {
|
||||
return new Response($this->listUsers([$path[1]], true)[0] ?? new \stdClass);
|
||||
return HTTP::respJson($this->listUsers([$path[1]], true)[0] ?? new \stdClass);
|
||||
} catch (UserException $e) {
|
||||
return new ErrorResponse("404", 404);
|
||||
return self::respError("404", 404);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getUserByNum(array $path): ResponseInterface {
|
||||
try {
|
||||
$user = Arsse::$user->lookup((int) $path[1]);
|
||||
return new Response($this->listUsers([$user], true)[0] ?? new \stdClass);
|
||||
return HTTP::respJson($this->listUsers([$user], true)[0] ?? new \stdClass);
|
||||
} catch (UserException $e) {
|
||||
return new ErrorResponse("404", 404);
|
||||
return self::respError("404", 404);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getCurrentUser(): ResponseInterface {
|
||||
return new Response($this->listUsers([Arsse::$user->id], false)[0] ?? new \stdClass);
|
||||
return HTTP::respJson($this->listUsers([Arsse::$user->id], false)[0] ?? new \stdClass);
|
||||
}
|
||||
|
||||
protected function createUser(array $data): ResponseInterface {
|
||||
|
@ -572,17 +578,17 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
} catch (UserException $e) {
|
||||
switch ($e->getCode()) {
|
||||
case 10403:
|
||||
return new ErrorResponse(["DuplicateUser", 'user' => $data['username']], 409);
|
||||
return self::respError(["DuplicateUser", 'user' => $data['username']], 409);
|
||||
case 10441:
|
||||
return new ErrorResponse(["InvalidInputValue", 'field' => "timezone"], 422);
|
||||
return self::respError(["InvalidInputValue", 'field' => "timezone"], 422);
|
||||
case 10443:
|
||||
return new ErrorResponse(["InvalidInputValue", 'field' => "entries_per_page"], 422);
|
||||
return self::respError(["InvalidInputValue", 'field' => "entries_per_page"], 422);
|
||||
case 10444:
|
||||
return new ErrorResponse(["InvalidInputValue", 'field' => "username"], 422);
|
||||
return self::respError(["InvalidInputValue", 'field' => "username"], 422);
|
||||
}
|
||||
throw $e; // @codeCoverageIgnore
|
||||
}
|
||||
return new Response($out, 201);
|
||||
return HTTP::respJson($out, 201);
|
||||
}
|
||||
|
||||
protected function updateUserByNum(array $path, array $data): ResponseInterface {
|
||||
|
@ -591,16 +597,16 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
if (((int) $path[1]) === $user['num']) {
|
||||
if ($data['is_admin'] && !$user['admin']) {
|
||||
// non-admins should not be able to set themselves as admin
|
||||
return new ErrorResponse("InvalidElevation", 403);
|
||||
return self::respError("InvalidElevation", 403);
|
||||
}
|
||||
$user = Arsse::$user->id;
|
||||
} elseif (!$user['admin']) {
|
||||
return new ErrorResponse("403", 403);
|
||||
return self::respError("403", 403);
|
||||
} else {
|
||||
try {
|
||||
$user = Arsse::$user->lookup((int) $path[1]);
|
||||
} catch (ExceptionConflict $e) {
|
||||
return new ErrorResponse("404", 404);
|
||||
return self::respError("404", 404);
|
||||
}
|
||||
}
|
||||
// make any requested changes
|
||||
|
@ -618,26 +624,26 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
} catch (UserException $e) {
|
||||
switch ($e->getCode()) {
|
||||
case 10403:
|
||||
return new ErrorResponse(["DuplicateUser", 'user' => $data['username']], 409);
|
||||
return self::respError(["DuplicateUser", 'user' => $data['username']], 409);
|
||||
case 10441:
|
||||
return new ErrorResponse(["InvalidInputValue", 'field' => "timezone"], 422);
|
||||
return self::respError(["InvalidInputValue", 'field' => "timezone"], 422);
|
||||
case 10443:
|
||||
return new ErrorResponse(["InvalidInputValue", 'field' => "entries_per_page"], 422);
|
||||
return self::respError(["InvalidInputValue", 'field' => "entries_per_page"], 422);
|
||||
case 10444:
|
||||
return new ErrorResponse(["InvalidInputValue", 'field' => "username"], 422);
|
||||
return self::respError(["InvalidInputValue", 'field' => "username"], 422);
|
||||
}
|
||||
throw $e; // @codeCoverageIgnore
|
||||
}
|
||||
return new Response($out, 201);
|
||||
return HTTP::respJson($out, 201);
|
||||
}
|
||||
|
||||
protected function deleteUserByNum(array $path): ResponseInterface {
|
||||
try {
|
||||
Arsse::$user->remove(Arsse::$user->lookup((int) $path[1]));
|
||||
} catch (ExceptionConflict $e) {
|
||||
return new ErrorResponse("404", 404);
|
||||
return self::respError("404", 404);
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
/** Returns a useful subset of user metadata
|
||||
|
@ -667,7 +673,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
// always add 1 to the ID since the root folder will always be 1 instead of 0.
|
||||
$out[] = ['id' => $f['id'] + 1, 'title' => $f['name'], 'user_id' => $meta['num']];
|
||||
}
|
||||
return new Response($out);
|
||||
return HTTP::respJson($out);
|
||||
}
|
||||
|
||||
protected function createCategory(array $data): ResponseInterface {
|
||||
|
@ -675,13 +681,13 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
$id = Arsse::$db->folderAdd(Arsse::$user->id, ['name' => (string) $data['title']]);
|
||||
} catch (ExceptionInput $e) {
|
||||
if ($e->getCode() === 10236) {
|
||||
return new ErrorResponse(["DuplicateCategory", 'title' => $data['title']], 409);
|
||||
return self::respError(["DuplicateCategory", 'title' => $data['title']], 409);
|
||||
} else {
|
||||
return new ErrorResponse(["InvalidCategory", 'title' => $data['title']], 422);
|
||||
return self::respError(["InvalidCategory", 'title' => $data['title']], 422);
|
||||
}
|
||||
}
|
||||
$meta = Arsse::$user->propertiesGet(Arsse::$user->id, false);
|
||||
return new Response(['id' => $id + 1, 'title' => $data['title'], 'user_id' => $meta['num']], 201);
|
||||
return HTTP::respJson(['id' => $id + 1, 'title' => $data['title'], 'user_id' => $meta['num']], 201);
|
||||
}
|
||||
|
||||
protected function updateCategory(array $path, array $data): ResponseInterface {
|
||||
|
@ -700,15 +706,15 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
}
|
||||
} catch (ExceptionInput $e) {
|
||||
if ($e->getCode() === 10236) {
|
||||
return new ErrorResponse(["DuplicateCategory", 'title' => $title], 409);
|
||||
return self::respError(["DuplicateCategory", 'title' => $title], 409);
|
||||
} elseif (in_array($e->getCode(), [10237, 10239])) {
|
||||
return new ErrorResponse("404", 404);
|
||||
return self::respError("404", 404);
|
||||
} else {
|
||||
return new ErrorResponse(["InvalidCategory", 'title' => $title], 422);
|
||||
return self::respError(["InvalidCategory", 'title' => $title], 422);
|
||||
}
|
||||
}
|
||||
$meta = Arsse::$user->propertiesGet(Arsse::$user->id, false);
|
||||
return new Response(['id' => (int) $path[1], 'title' => $title, 'user_id' => $meta['num']], 201);
|
||||
return HTTP::respJson(['id' => (int) $path[1], 'title' => $title, 'user_id' => $meta['num']], 201);
|
||||
}
|
||||
|
||||
protected function deleteCategory(array $path): ResponseInterface {
|
||||
|
@ -726,9 +732,9 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
$tr->commit();
|
||||
}
|
||||
} catch (ExceptionInput $e) {
|
||||
return new ErrorResponse("404", 404);
|
||||
return self::respError("404", 404);
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
protected function transformFeed(array $sub, int $uid, string $rootName, \DateTimeZone $tz): array {
|
||||
|
@ -772,7 +778,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
foreach (Arsse::$db->subscriptionList(Arsse::$user->id) as $r) {
|
||||
$out[] = $this->transformFeed($r, $meta['num'], $meta['root'], $meta['tz']);
|
||||
}
|
||||
return new Response($out);
|
||||
return HTTP::respJson($out);
|
||||
}
|
||||
|
||||
protected function getCategoryFeeds(array $path): ResponseInterface {
|
||||
|
@ -790,9 +796,9 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
}
|
||||
} catch (ExceptionInput $e) {
|
||||
// the folder does not exist
|
||||
return new ErrorResponse("404", 404);
|
||||
return self::respError("404", 404);
|
||||
}
|
||||
return new Response($out);
|
||||
return HTTP::respJson($out);
|
||||
}
|
||||
|
||||
protected function getFeed(array $path): ResponseInterface {
|
||||
|
@ -800,9 +806,9 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
$meta = $this->userMeta(Arsse::$user->id);
|
||||
try {
|
||||
$sub = Arsse::$db->subscriptionPropertiesGet(Arsse::$user->id, (int) $path[1]);
|
||||
return new Response($this->transformFeed($sub, $meta['num'], $meta['root'], $meta['tz']));
|
||||
return HTTP::respJson($this->transformFeed($sub, $meta['num'], $meta['root'], $meta['tz']));
|
||||
} catch (ExceptionInput $e) {
|
||||
return new ErrorResponse("404", 404);
|
||||
return self::respError("404", 404);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -825,16 +831,16 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
10521 => "Fetch404",
|
||||
10522 => "FetchFormat",
|
||||
][$e->getCode()] ?? "FetchOther";
|
||||
return new ErrorResponse($msg, 502);
|
||||
return self::respError($msg, 502);
|
||||
} catch (ExceptionInput $e) {
|
||||
switch ($e->getCode()) {
|
||||
case 10235:
|
||||
return new ErrorResponse("MissingCategory", 422);
|
||||
return self::respError("MissingCategory", 422);
|
||||
case 10236:
|
||||
return new ErrorResponse("DuplicateFeed", 409);
|
||||
return self::respError("DuplicateFeed", 409);
|
||||
}
|
||||
}
|
||||
return new Response(['feed_id' => $id], 201);
|
||||
return HTTP::respJson(['feed_id' => $id], 201);
|
||||
}
|
||||
|
||||
protected function updateFeed(array $path, array $data): ResponseInterface {
|
||||
|
@ -853,11 +859,11 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
switch ($e->getCode()) {
|
||||
case 10231:
|
||||
case 10232:
|
||||
return new ErrorResponse("InvalidTitle", 422);
|
||||
return self::respError("InvalidTitle", 422);
|
||||
case 10235:
|
||||
return new ErrorResponse("MissingCategory", 422);
|
||||
return self::respError("MissingCategory", 422);
|
||||
case 10239:
|
||||
return new ErrorResponse("404", 404);
|
||||
return self::respError("404", 404);
|
||||
}
|
||||
}
|
||||
return $this->getFeed($path)->withStatus(201);
|
||||
|
@ -866,9 +872,9 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
protected function deleteFeed(array $path): ResponseInterface {
|
||||
try {
|
||||
Arsse::$db->subscriptionRemove(Arsse::$user->id, (int) $path[1]);
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
} catch (ExceptionInput $e) {
|
||||
return new ErrorResponse("404", 404);
|
||||
return self::respError("404", 404);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -876,12 +882,12 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
try {
|
||||
$icon = Arsse::$db->subscriptionIcon(Arsse::$user->id, (int) $path[1]);
|
||||
} catch (ExceptionInput $e) {
|
||||
return new ErrorResponse("404", 404);
|
||||
return self::respError("404", 404);
|
||||
}
|
||||
if (!$icon || !$icon['type'] || !$icon['data']) {
|
||||
return new ErrorResponse("404", 404);
|
||||
return self::respError("404", 404);
|
||||
}
|
||||
return new Response([
|
||||
return HTTP::respJson([
|
||||
'id' => (int) $icon['id'],
|
||||
'data' => $icon['type'].";base64,".base64_encode($icon['data']),
|
||||
'mime_type' => $icon['type'],
|
||||
|
@ -1038,45 +1044,45 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
|
||||
protected function getEntries(array $query): ResponseInterface {
|
||||
try {
|
||||
return new Response($this->listEntries($query, new Context));
|
||||
return HTTP::respJson($this->listEntries($query, new Context));
|
||||
} catch (ExceptionInput $e) {
|
||||
return new ErrorResponse("MissingCategory", 400);
|
||||
return self::respError("MissingCategory", 400);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getFeedEntries(array $path, array $query): ResponseInterface {
|
||||
$c = (new Context)->subscription((int) $path[1]);
|
||||
try {
|
||||
return new Response($this->listEntries($query, $c));
|
||||
return HTTP::respJson($this->listEntries($query, $c));
|
||||
} catch (ExceptionInput $e) {
|
||||
// FIXME: this should differentiate between a missing feed and a missing category, but doesn't
|
||||
return new ErrorResponse("404", 404);
|
||||
return self::respError("404", 404);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getCategoryEntries(array $path, array $query): ResponseInterface {
|
||||
$query['category_id'] = (int) $path[1];
|
||||
try {
|
||||
return new Response($this->listEntries($query, new Context));
|
||||
return HTTP::respJson($this->listEntries($query, new Context));
|
||||
} catch (ExceptionInput $e) {
|
||||
return new ErrorResponse("404", 404);
|
||||
return self::respError("404", 404);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getEntry(array $path): ResponseInterface {
|
||||
try {
|
||||
return new Response($this->findEntry((int) $path[1]));
|
||||
return HTTP::respJson($this->findEntry((int) $path[1]));
|
||||
} catch (ExceptionInput $e) {
|
||||
return new ErrorResponse("404", 404);
|
||||
return self::respError("404", 404);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getFeedEntry(array $path): ResponseInterface {
|
||||
$c = (new Context)->subscription((int) $path[1]);
|
||||
try {
|
||||
return new Response($this->findEntry((int) $path[3], $c));
|
||||
return HTTP::respJson($this->findEntry((int) $path[3], $c));
|
||||
} catch (ExceptionInput $e) {
|
||||
return new ErrorResponse("404", 404);
|
||||
return self::respError("404", 404);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1088,9 +1094,9 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
$c->folder((int) $path[1] - 1);
|
||||
}
|
||||
try {
|
||||
return new Response($this->findEntry((int) $path[3], $c));
|
||||
return HTTP::respJson($this->findEntry((int) $path[3], $c));
|
||||
} catch (ExceptionInput $e) {
|
||||
return new ErrorResponse("404", 404);
|
||||
return self::respError("404", 404);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1104,7 +1110,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
}
|
||||
assert(isset($in), new \Exception("Unknown status specified"));
|
||||
Arsse::$db->articleMark(Arsse::$user->id, $in, (new Context)->articles($data['entry_ids']));
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
protected function massRead(Context $c): void {
|
||||
|
@ -1115,19 +1121,19 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
// this function is restricted to the logged-in user
|
||||
$user = Arsse::$user->propertiesGet(Arsse::$user->id, false);
|
||||
if (((int) $path[1]) !== $user['num']) {
|
||||
return new ErrorResponse("403", 403);
|
||||
return self::respError("403", 403);
|
||||
}
|
||||
$this->massRead(new Context);
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
protected function markFeed(array $path): ResponseInterface {
|
||||
try {
|
||||
$this->massRead((new Context)->subscription((int) $path[1]));
|
||||
} catch (ExceptionInput $e) {
|
||||
return new ErrorResponse("404", 404);
|
||||
return self::respError("404", 404);
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
protected function markCategory(array $path): ResponseInterface {
|
||||
|
@ -1142,9 +1148,9 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
try {
|
||||
$this->massRead($c);
|
||||
} catch (ExceptionInput $e) {
|
||||
return new ErrorResponse("404", 404);
|
||||
return self::respError("404", 404);
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
protected function toggleEntryBookmark(array $path): ResponseInterface {
|
||||
|
@ -1160,9 +1166,9 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
}
|
||||
$tr->commit();
|
||||
} catch (ExceptionInput $e) {
|
||||
return new ErrorResponse("404", 404);
|
||||
return self::respError("404", 404);
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
protected function refreshFeed(array $path): ResponseInterface {
|
||||
|
@ -1170,15 +1176,15 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
try {
|
||||
Arsse::$db->subscriptionPropertiesGet(Arsse::$user->id, (int) $path[1]);
|
||||
} catch (ExceptionInput $e) {
|
||||
return new ErrorResponse("404", 404);
|
||||
return self::respError("404", 404);
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
protected function refreshAllFeeds(): ResponseInterface {
|
||||
// NOTE: This is a no-op
|
||||
// It could be implemented, but the need is considered low since we use a dynamic schedule always
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
protected function opmlImport(string $data): ResponseInterface {
|
||||
|
@ -1187,23 +1193,23 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
} catch (ImportException $e) {
|
||||
switch ($e->getCode()) {
|
||||
case 10611:
|
||||
return new ErrorResponse("InvalidBodyXML", 400);
|
||||
return self::respError("InvalidBodyXML", 400);
|
||||
case 10612:
|
||||
return new ErrorResponse("InvalidBodyOPML", 422);
|
||||
return self::respError("InvalidBodyOPML", 422);
|
||||
case 10613:
|
||||
return new ErrorResponse("InvalidImportCategory", 422);
|
||||
return self::respError("InvalidImportCategory", 422);
|
||||
case 10614:
|
||||
return new ErrorResponse("DuplicateImportCategory", 422);
|
||||
return self::respError("DuplicateImportCategory", 422);
|
||||
case 10615:
|
||||
return new ErrorResponse("InvalidImportLabel", 422);
|
||||
return self::respError("InvalidImportLabel", 422);
|
||||
}
|
||||
} catch (FeedException $e) {
|
||||
return new ErrorResponse(["FailedImportFeed", 'url' => $e->getParams()['url'], 'code' => $e->getCode()], 502);
|
||||
return self::respError(["FailedImportFeed", 'url' => $e->getParams()['url'], 'code' => $e->getCode()], 502);
|
||||
}
|
||||
return new Response(['message' => Arsse::$lang->msg("API.Miniflux.ImportSuccess")]);
|
||||
return HTTP::respJson(['message' => Arsse::$lang->msg("API.Miniflux.ImportSuccess")]);
|
||||
}
|
||||
|
||||
protected function opmlExport(): ResponseInterface {
|
||||
return new GenericResponse(Arsse::$obj->get(OPML::class)->export(Arsse::$user->id), 200, ['Content-Type' => "application/xml"]);
|
||||
return HTTP::respText(Arsse::$obj->get(OPML::class)->export(Arsse::$user->id), 200, ['Content-Type' => "application/xml"]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,6 @@ use JKingWeb\Arsse\Misc\HTTP;
|
|||
use JKingWeb\Arsse\REST\Exception;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\JsonResponse as Response;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
|
||||
class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||
public const VERSION = "11.0.5";
|
||||
|
@ -86,19 +84,19 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
if ($req->getAttribute("authenticated", false)) {
|
||||
Arsse::$user->id = $req->getAttribute("authenticatedUser");
|
||||
} else {
|
||||
return new EmptyResponse(401);
|
||||
return HTTP::respEmpty(401);
|
||||
}
|
||||
// normalize the input
|
||||
$data = (string) $req->getBody();
|
||||
if ($data) {
|
||||
// if the entity body is not JSON according to content type, return "415 Unsupported Media Type"
|
||||
if (!HTTP::matchType($req, "", self::ACCEPTED_TYPE)) {
|
||||
return new EmptyResponse(415, ['Accept' => self::ACCEPTED_TYPE]);
|
||||
return HTTP::respEmpty(415, ['Accept' => self::ACCEPTED_TYPE]);
|
||||
}
|
||||
$data = @json_decode($data, true);
|
||||
if (json_last_error() !== \JSON_ERROR_NONE) {
|
||||
// if the body could not be parsed as JSON, return "400 Bad Request"
|
||||
return new EmptyResponse(400);
|
||||
return HTTP::respEmpty(400);
|
||||
}
|
||||
} else {
|
||||
$data = [];
|
||||
|
@ -117,10 +115,10 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
// @codeCoverageIgnoreStart
|
||||
} catch (Exception $e) {
|
||||
// if there was a REST exception return 400
|
||||
return new EmptyResponse(400);
|
||||
return HTTP::respEmpty(400);
|
||||
} catch (AbstractException $e) {
|
||||
// if there was any other Arsse exception return 500
|
||||
return new EmptyResponse(500);
|
||||
return HTTP::respEmpty(500);
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
@ -162,11 +160,11 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
return $this->paths[$url][$method];
|
||||
} else {
|
||||
// otherwise return 405
|
||||
return new EmptyResponse(405, ['Allow' => implode(", ", array_keys($this->paths[$url]))]);
|
||||
return HTTP::respEmpty(405, ['Allow' => implode(", ", array_keys($this->paths[$url]))]);
|
||||
}
|
||||
} else {
|
||||
// if the path is not supported, return 404
|
||||
return new EmptyResponse(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -268,13 +266,13 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
if (in_array("GET", $allowed)) {
|
||||
array_unshift($allowed, "HEAD");
|
||||
}
|
||||
return new EmptyResponse(204, [
|
||||
return HTTP::respEmpty(204, [
|
||||
'Allow' => implode(",", $allowed),
|
||||
'Accept' => self::ACCEPTED_TYPE,
|
||||
]);
|
||||
} else {
|
||||
// if the path is not supported, return 404
|
||||
return new EmptyResponse(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,7 +282,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
foreach (Arsse::$db->folderList(Arsse::$user->id, null, false) as $folder) {
|
||||
$folders[] = $this->folderTranslate($folder);
|
||||
}
|
||||
return new Response(['folders' => $folders]);
|
||||
return HTTP::respJson(['folders' => $folders]);
|
||||
}
|
||||
|
||||
// create a folder
|
||||
|
@ -294,16 +292,16 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
} catch (ExceptionInput $e) {
|
||||
switch ($e->getCode()) {
|
||||
// folder already exists
|
||||
case 10236: return new EmptyResponse(409);
|
||||
// folder name not acceptable
|
||||
case 10236: return HTTP::respEmpty(409);
|
||||
// folder name not acceptable
|
||||
case 10231:
|
||||
case 10232: return new EmptyResponse(422);
|
||||
case 10232: return HTTP::respEmpty(422);
|
||||
// other errors related to input
|
||||
default: return new EmptyResponse(400); // @codeCoverageIgnore
|
||||
default: return HTTP::respEmpty(400); // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
$folder = $this->folderTranslate(Arsse::$db->folderPropertiesGet(Arsse::$user->id, $folder));
|
||||
return new Response(['folders' => [$folder]]);
|
||||
return HTTP::respJson(['folders' => [$folder]]);
|
||||
}
|
||||
|
||||
// delete a folder
|
||||
|
@ -313,9 +311,9 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
Arsse::$db->folderRemove(Arsse::$user->id, (int) $url[1]);
|
||||
} catch (ExceptionInput $e) {
|
||||
// folder does not exist
|
||||
return new EmptyResponse(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
// rename a folder (also supports moving nesting folders, but this is not a feature of the API)
|
||||
|
@ -325,24 +323,24 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
} catch (ExceptionInput $e) {
|
||||
switch ($e->getCode()) {
|
||||
// folder does not exist
|
||||
case 10239: return new EmptyResponse(404);
|
||||
// folder already exists
|
||||
case 10236: return new EmptyResponse(409);
|
||||
// folder name not acceptable
|
||||
case 10239: return HTTP::respEmpty(404);
|
||||
// folder already exists
|
||||
case 10236: return HTTP::respEmpty(409);
|
||||
// folder name not acceptable
|
||||
case 10231:
|
||||
case 10232: return new EmptyResponse(422);
|
||||
case 10232: return HTTP::respEmpty(422);
|
||||
// other errors related to input
|
||||
default: return new EmptyResponse(400); // @codeCoverageIgnore
|
||||
default: return HTTP::respEmpty(400); // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
// mark all articles associated with a folder as read
|
||||
protected function folderMarkRead(array $url, array $data): ResponseInterface {
|
||||
if (!ValueInfo::id($data['newestItemId'])) {
|
||||
// if the item ID is invalid (i.e. not a positive integer), this is an error
|
||||
return new EmptyResponse(422);
|
||||
return HTTP::respEmpty(422);
|
||||
}
|
||||
// build the context
|
||||
$c = (new Context)->hidden(false);
|
||||
|
@ -353,15 +351,15 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
Arsse::$db->articleMark(Arsse::$user->id, ['read' => true], $c);
|
||||
} catch (ExceptionInput $e) {
|
||||
// folder does not exist
|
||||
return new EmptyResponse(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
// return list of feeds which should be refreshed
|
||||
protected function feedListStale(array $url, array $data): ResponseInterface {
|
||||
if (!$this->isAdmin()) {
|
||||
return new EmptyResponse(403);
|
||||
return HTTP::respEmpty(403);
|
||||
}
|
||||
// list stale feeds which should be checked for updates
|
||||
$feeds = Arsse::$db->feedListStale();
|
||||
|
@ -370,27 +368,27 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
// since in our implementation feeds don't belong the users, the 'userId' field will always be an empty string
|
||||
$out[] = ['id' => (int) $feed, 'userId' => ""];
|
||||
}
|
||||
return new Response(['feeds' => $out]);
|
||||
return HTTP::respJson(['feeds' => $out]);
|
||||
}
|
||||
|
||||
// refresh a feed
|
||||
protected function feedUpdate(array $url, array $data): ResponseInterface {
|
||||
if (!$this->isAdmin()) {
|
||||
return new EmptyResponse(403);
|
||||
return HTTP::respEmpty(403);
|
||||
}
|
||||
try {
|
||||
Arsse::$db->feedUpdate($data['feedId']);
|
||||
} catch (ExceptionInput $e) {
|
||||
switch ($e->getCode()) {
|
||||
case 10239: // feed does not exist
|
||||
return new EmptyResponse(404);
|
||||
return HTTP::respEmpty(404);
|
||||
case 10237: // feed ID invalid
|
||||
return new EmptyResponse(422);
|
||||
return HTTP::respEmpty(422);
|
||||
default: // other errors related to input
|
||||
return new EmptyResponse(400); // @codeCoverageIgnore
|
||||
return HTTP::respEmpty(400); // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
// add a new feed
|
||||
|
@ -401,10 +399,10 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
$id = Arsse::$db->subscriptionAdd(Arsse::$user->id, (string) $data['url']);
|
||||
} catch (ExceptionInput $e) {
|
||||
// feed already exists
|
||||
return new EmptyResponse(409);
|
||||
return HTTP::respEmpty(409);
|
||||
} catch (FeedException $e) {
|
||||
// feed could not be retrieved
|
||||
return new EmptyResponse(422);
|
||||
return HTTP::respEmpty(422);
|
||||
}
|
||||
// if a folder was specified, move the feed to the correct folder; silently ignore errors
|
||||
if ($data['folderId']) {
|
||||
|
@ -422,7 +420,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
if ($newest) {
|
||||
$out['newestItemId'] = $newest;
|
||||
}
|
||||
return new Response($out);
|
||||
return HTTP::respJson($out);
|
||||
}
|
||||
|
||||
// return list of feeds for the logged-in user
|
||||
|
@ -438,7 +436,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
if ($newest) {
|
||||
$out['newestItemId'] = $newest;
|
||||
}
|
||||
return new Response($out);
|
||||
return HTTP::respJson($out);
|
||||
}
|
||||
|
||||
// delete a feed
|
||||
|
@ -447,9 +445,9 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
Arsse::$db->subscriptionRemove(Arsse::$user->id, (int) $url[1]);
|
||||
} catch (ExceptionInput $e) {
|
||||
// feed does not exist
|
||||
return new EmptyResponse(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
// rename a feed
|
||||
|
@ -459,22 +457,22 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
} catch (ExceptionInput $e) {
|
||||
switch ($e->getCode()) {
|
||||
// subscription does not exist
|
||||
case 10239: return new EmptyResponse(404);
|
||||
// name is invalid
|
||||
case 10239: return HTTP::respEmpty(404);
|
||||
// name is invalid
|
||||
case 10231:
|
||||
case 10232: return new EmptyResponse(422);
|
||||
case 10232: return HTTP::respEmpty(422);
|
||||
// other errors related to input
|
||||
default: return new EmptyResponse(400); // @codeCoverageIgnore
|
||||
default: return HTTP::respEmpty(400); // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
// move a feed to a folder
|
||||
protected function subscriptionMove(array $url, array $data): ResponseInterface {
|
||||
// if no folder is specified this is an error
|
||||
if (!isset($data['folderId'])) {
|
||||
return new EmptyResponse(422);
|
||||
return HTTP::respEmpty(422);
|
||||
}
|
||||
// perform the move
|
||||
try {
|
||||
|
@ -482,22 +480,22 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
} catch (ExceptionInput $e) {
|
||||
switch ($e->getCode()) {
|
||||
case 10239: // subscription does not exist
|
||||
return new EmptyResponse(404);
|
||||
return HTTP::respEmpty(404);
|
||||
case 10235: // folder does not exist
|
||||
case 10237: // folder ID is invalid
|
||||
return new EmptyResponse(422);
|
||||
return HTTP::respEmpty(422);
|
||||
default: // other errors related to input
|
||||
return new EmptyResponse(400); // @codeCoverageIgnore
|
||||
return HTTP::respEmpty(400); // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
// mark all articles associated with a subscription as read
|
||||
protected function subscriptionMarkRead(array $url, array $data): ResponseInterface {
|
||||
if (!ValueInfo::id($data['newestItemId'])) {
|
||||
// if the item ID is invalid (i.e. not a positive integer), this is an error
|
||||
return new EmptyResponse(422);
|
||||
return HTTP::respEmpty(422);
|
||||
}
|
||||
// build the context
|
||||
$c = (new Context)->hidden(false);
|
||||
|
@ -508,9 +506,9 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
Arsse::$db->articleMark(Arsse::$user->id, ['read' => true], $c);
|
||||
} catch (ExceptionInput $e) {
|
||||
// subscription does not exist
|
||||
return new EmptyResponse(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
// list articles and their properties
|
||||
|
@ -579,28 +577,28 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
], [$reverse ? "edition desc" : "edition"]);
|
||||
} catch (ExceptionInput $e) {
|
||||
// ID of subscription or folder is not valid
|
||||
return new EmptyResponse(422);
|
||||
return HTTP::respEmpty(422);
|
||||
}
|
||||
$out = [];
|
||||
foreach ($items as $item) {
|
||||
$out[] = $this->articleTranslate($item);
|
||||
}
|
||||
$out = ['items' => $out];
|
||||
return new Response($out);
|
||||
return HTTP::respJson($out);
|
||||
}
|
||||
|
||||
// mark all articles as read
|
||||
protected function articleMarkReadAll(array $url, array $data): ResponseInterface {
|
||||
if (!ValueInfo::id($data['newestItemId'])) {
|
||||
// if the item ID is invalid (i.e. not a positive integer), this is an error
|
||||
return new EmptyResponse(422);
|
||||
return HTTP::respEmpty(422);
|
||||
}
|
||||
// build the context
|
||||
$c = (new Context)->hidden(false);
|
||||
$c->editionRange(null, (int) $data['newestItemId']);
|
||||
// perform the operation
|
||||
Arsse::$db->articleMark(Arsse::$user->id, ['read' => true], $c);
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
// mark a single article as read
|
||||
|
@ -614,9 +612,9 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
Arsse::$db->articleMark(Arsse::$user->id, ['read' => $set], $c);
|
||||
} catch (ExceptionInput $e) {
|
||||
// ID is not valid
|
||||
return new EmptyResponse(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
// mark a single article as read
|
||||
|
@ -630,9 +628,9 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
Arsse::$db->articleMark(Arsse::$user->id, ['starred' => $set], $c);
|
||||
} catch (ExceptionInput $e) {
|
||||
// ID is not valid
|
||||
return new EmptyResponse(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
// mark an array of articles as read
|
||||
|
@ -646,7 +644,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
Arsse::$db->articleMark(Arsse::$user->id, ['read' => $set], $c);
|
||||
} catch (ExceptionInput $e) {
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
// mark an array of articles as starred
|
||||
|
@ -660,11 +658,11 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
Arsse::$db->articleMark(Arsse::$user->id, ['starred' => $set], $c);
|
||||
} catch (ExceptionInput $e) {
|
||||
}
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
protected function userStatus(array $url, array $data): ResponseInterface {
|
||||
return new Response([
|
||||
return HTTP::respJson([
|
||||
'userId' => (string) Arsse::$user->id,
|
||||
'displayName' => (string) Arsse::$user->id,
|
||||
'lastLoginTimestamp' => time(),
|
||||
|
@ -674,30 +672,30 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
|
||||
protected function cleanupBefore(array $url, array $data): ResponseInterface {
|
||||
if (!$this->isAdmin()) {
|
||||
return new EmptyResponse(403);
|
||||
return HTTP::respEmpty(403);
|
||||
}
|
||||
Service::cleanupPre();
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
protected function cleanupAfter(array $url, array $data): ResponseInterface {
|
||||
if (!$this->isAdmin()) {
|
||||
return new EmptyResponse(403);
|
||||
return HTTP::respEmpty(403);
|
||||
}
|
||||
Service::cleanupPost();
|
||||
return new EmptyResponse(204);
|
||||
return HTTP::respEmpty(204);
|
||||
}
|
||||
|
||||
// return the server version
|
||||
protected function serverVersion(array $url, array $data): ResponseInterface {
|
||||
return new Response([
|
||||
return HTTP::respJson([
|
||||
'version' => self::VERSION,
|
||||
'arsse_version' => Arsse::VERSION,
|
||||
]);
|
||||
}
|
||||
|
||||
protected function serverStatus(array $url, array $data): ResponseInterface {
|
||||
return new Response([
|
||||
return HTTP::respJson([
|
||||
'version' => self::VERSION,
|
||||
'arsse_version' => Arsse::VERSION,
|
||||
'warnings' => [
|
||||
|
|
|
@ -6,10 +6,9 @@
|
|||
declare(strict_types=1);
|
||||
namespace JKingWeb\Arsse\REST\NextcloudNews;
|
||||
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\JsonResponse as Response;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
|
||||
class Versions implements \JKingWeb\Arsse\REST\Handler {
|
||||
public function __construct() {
|
||||
|
@ -18,12 +17,12 @@ class Versions implements \JKingWeb\Arsse\REST\Handler {
|
|||
public function dispatch(ServerRequestInterface $req): ResponseInterface {
|
||||
if (!preg_match("<^/?$>D", $req->getRequestTarget())) {
|
||||
// if the request path is more than an empty string or a slash, the client is probably trying a version we don't support
|
||||
return new EmptyResponse(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
switch ($req->getMethod()) {
|
||||
case "OPTIONS":
|
||||
// if the request method is OPTIONS, respond accordingly
|
||||
return new EmptyResponse(204, ['Allow' => "HEAD,GET"]);
|
||||
return HTTP::respEmpty(204, ['Allow' => "HEAD,GET"]);
|
||||
case "GET":
|
||||
// otherwise return the supported versions
|
||||
$out = [
|
||||
|
@ -31,10 +30,10 @@ class Versions implements \JKingWeb\Arsse\REST\Handler {
|
|||
'v1-2',
|
||||
],
|
||||
];
|
||||
return new Response($out);
|
||||
return HTTP::respJson($out);
|
||||
default:
|
||||
// if any other method was used, this is an error
|
||||
return new EmptyResponse(405, ['Allow' => "HEAD,GET"]);
|
||||
return HTTP::respEmpty(405, ['Allow' => "HEAD,GET"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ use JKingWeb\Arsse\Service;
|
|||
use JKingWeb\Arsse\Database;
|
||||
use JKingWeb\Arsse\Context\Context;
|
||||
use JKingWeb\Arsse\Misc\Date;
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use JKingWeb\Arsse\Misc\ValueInfo as V;
|
||||
use JKingWeb\Arsse\AbstractException;
|
||||
use JKingWeb\Arsse\ExceptionType;
|
||||
|
@ -20,8 +21,6 @@ use JKingWeb\Arsse\Db\ResultEmpty;
|
|||
use JKingWeb\Arsse\Feed\Exception as FeedException;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\JsonResponse as Response;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
|
||||
class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||
public const LEVEL = 15; // emulated API level
|
||||
|
@ -96,11 +95,11 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
public function dispatch(ServerRequestInterface $req): ResponseInterface {
|
||||
if (!preg_match("<^(?:/(?:index\.php)?)?$>D", $req->getRequestTarget())) {
|
||||
// reject paths other than the index
|
||||
return new EmptyResponse(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
if ($req->getMethod() === "OPTIONS") {
|
||||
// respond to OPTIONS rquests; the response is a fib, as we technically accept any type or method
|
||||
return new EmptyResponse(204, [
|
||||
return HTTP::respEmpty(204, [
|
||||
'Allow' => "POST",
|
||||
'Accept' => implode(", ", self::ACCEPTED_TYPES),
|
||||
]);
|
||||
|
@ -110,7 +109,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
// only JSON entities are allowed, but Content-Type is ignored, as is request method
|
||||
$data = @json_decode($data, true);
|
||||
if (json_last_error() !== \JSON_ERROR_NONE || !is_array($data)) {
|
||||
return new Response(self::FATAL_ERR);
|
||||
return HTTP::respJson(self::FATAL_ERR);
|
||||
}
|
||||
try {
|
||||
// normalize input
|
||||
|
@ -125,7 +124,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
Arsse::$user->id = $req->getAttribute("authenticatedUser");
|
||||
} elseif (Arsse::$conf->userHTTPAuthRequired || Arsse::$conf->userPreAuth || $req->getAttribute("authenticationFailed", false)) {
|
||||
// otherwise if HTTP authentication failed or is required, deny access at the HTTP level
|
||||
return new EmptyResponse(401);
|
||||
return HTTP::respEmpty(401);
|
||||
}
|
||||
if (strtolower((string) $data['op']) !== "login") {
|
||||
// unless logging in, a session identifier is required
|
||||
|
@ -136,23 +135,23 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
// TT-RSS operations are case-insensitive by dint of PHP method names being case-insensitive; this will only trigger if the method really doesn't exist
|
||||
throw new Exception("UNKNOWN_METHOD", ['method' => $data['op']]);
|
||||
}
|
||||
return new Response([
|
||||
return HTTP::respJson([
|
||||
'seq' => $data['seq'],
|
||||
'status' => 0,
|
||||
'content' => $this->$method($data),
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
return new Response([
|
||||
return HTTP::respJson([
|
||||
'seq' => $data['seq'],
|
||||
'status' => 1,
|
||||
'content' => $e->getData(),
|
||||
]);
|
||||
} catch (AbstractException $e) {
|
||||
return new EmptyResponse(500);
|
||||
return HTTP::respEmpty(500);
|
||||
}
|
||||
} else {
|
||||
// absence of a request body indicates an error
|
||||
return new Response(self::FATAL_ERR);
|
||||
return HTTP::respJson(self::FATAL_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1000,7 +999,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
switch ($e->getCode()) {
|
||||
case 10236: // label already exists
|
||||
// retrieve the ID of the existing label; duplicating a label silently returns the existing one
|
||||
return $this->labelOut(Arsse::$db->labelPropertiesGet(Arsse::$user->id, $in['name'], true)['id']);
|
||||
return $this->labelOut(Arsse::$db->labelPropertiesGet(Arsse::$user->id, $in['name'], true)['id']);
|
||||
default: // other errors related to input
|
||||
throw new Exception("INCORRECT_USAGE");
|
||||
}
|
||||
|
|
|
@ -7,10 +7,10 @@ declare(strict_types=1);
|
|||
namespace JKingWeb\Arsse\REST\TinyTinyRSS;
|
||||
|
||||
use JKingWeb\Arsse\Arsse;
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\EmptyResponse as Response;
|
||||
|
||||
class Icon extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||
public function __construct() {
|
||||
|
@ -22,25 +22,25 @@ class Icon extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|||
Arsse::$user->id = $req->getAttribute("authenticatedUser");
|
||||
} elseif ($req->getAttribute("authenticationFailed", false) || Arsse::$conf->userHTTPAuthRequired) {
|
||||
// otherwise if HTTP authentication failed or did not occur when it is required, deny access at the HTTP level
|
||||
return new Response(401);
|
||||
return HTTP::respEmpty(401);
|
||||
}
|
||||
if ($req->getMethod() !== "GET") {
|
||||
// only GET requests are allowed
|
||||
return new Response(405, ['Allow' => "GET"]);
|
||||
return HTTP::respEmpty(405, ['Allow' => "GET"]);
|
||||
} elseif (!preg_match("<^(\d+)\.ico$>D", $req->getRequestTarget(), $match) || !((int) $match[1])) {
|
||||
return new Response(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
try {
|
||||
$url = Arsse::$db->subscriptionIcon(Arsse::$user->id ?? null, (int) $match[1], false)['url'] ?? null;
|
||||
if (!$url) {
|
||||
return new Response(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
if (($pos = strpos($url, "\r")) !== false || ($pos = strpos($url, "\n")) !== false) {
|
||||
$url = substr($url, 0, $pos);
|
||||
}
|
||||
return new Response(301, ['Location' => $url]);
|
||||
return HTTP::respEmpty(301, ['Location' => $url]);
|
||||
} catch (ExceptionInput $e) {
|
||||
return new Response(404);
|
||||
return HTTP::respEmpty(404);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ return [
|
|||
'API.Miniflux.Error.InvalidTitle' => 'Invalid feed title',
|
||||
'API.Miniflux.Error.InvalidImportCategory' => 'Payload contains an invalid category name',
|
||||
'API.Miniflux.Error.DuplicateImportCategory' => 'Payload contains the same category name twice',
|
||||
'API.Miniflux.Error.FailedImportFeed' => 'Unable to import feed at URL "{url}" (code {code}',
|
||||
'API.Miniflux.Error.FailedImportFeed' => 'Unable to import feed at URL "{url}" (code {code})',
|
||||
'API.Miniflux.Error.InvalidImportLabel' => 'Payload contains an invalid label name',
|
||||
|
||||
'API.TTRSS.Category.Uncategorized' => 'Uncategorized',
|
||||
|
|
|
@ -19,7 +19,7 @@ trait SeriesArticle {
|
|||
$this->data = [
|
||||
'arsse_users' => [
|
||||
'columns' => ["id", "password", "num"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
["jane.doe@example.com", "", 1],
|
||||
["john.doe@example.com", "", 2],
|
||||
["john.doe@example.org", "", 3],
|
||||
|
@ -29,7 +29,7 @@ trait SeriesArticle {
|
|||
],
|
||||
'arsse_feeds' => [
|
||||
'columns' => ["id", "url", "title"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,"http://example.com/1", "Feed 1"],
|
||||
[2,"http://example.com/2", "Feed 2"],
|
||||
[3,"http://example.com/3", "Feed 3"],
|
||||
|
@ -47,7 +47,7 @@ trait SeriesArticle {
|
|||
],
|
||||
'arsse_folders' => [
|
||||
'columns' => ["id", "owner", "parent", "name"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1, "john.doe@example.com", null, "Technology"],
|
||||
[2, "john.doe@example.com", 1, "Software"],
|
||||
[3, "john.doe@example.com", 1, "Rocketry"],
|
||||
|
@ -61,7 +61,7 @@ trait SeriesArticle {
|
|||
],
|
||||
'arsse_tags' => [
|
||||
'columns' => ["id", "owner", "name"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1, "john.doe@example.com", "Technology"],
|
||||
[2, "john.doe@example.com", "Software"],
|
||||
[3, "john.doe@example.com", "Rocketry"],
|
||||
|
@ -74,7 +74,7 @@ trait SeriesArticle {
|
|||
],
|
||||
'arsse_subscriptions' => [
|
||||
'columns' => ["id", "owner", "feed", "folder", "title", "scrape"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1, "john.doe@example.com",1, null,"Subscription 1", 0],
|
||||
[2, "john.doe@example.com",2, null,null, 0],
|
||||
[3, "john.doe@example.com",3, 1,"Subscription 3", 0],
|
||||
|
@ -94,7 +94,7 @@ trait SeriesArticle {
|
|||
],
|
||||
'arsse_tag_members' => [
|
||||
'columns' => ["tag", "subscription", "assigned"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,3,1],
|
||||
[1,4,1],
|
||||
[2,4,1],
|
||||
|
@ -109,8 +109,8 @@ trait SeriesArticle {
|
|||
],
|
||||
'arsse_articles' => [
|
||||
'columns' => [
|
||||
"id", "feed", "url", "title", "author", "published", "edited", "content", "guid",
|
||||
"url_title_hash", "url_content_hash", "title_content_hash", "modified", "content_scraped"
|
||||
"id", "feed", "url", "title", "author", "published", "edited", "content", "guid",
|
||||
"url_title_hash", "url_content_hash", "title_content_hash", "modified", "content_scraped",
|
||||
],
|
||||
'rows' => [
|
||||
[1,1,null,"Title one", null,null,null,"First article", null,"","","","2000-01-01T00:00:00Z",null],
|
||||
|
@ -142,7 +142,7 @@ trait SeriesArticle {
|
|||
],
|
||||
'arsse_enclosures' => [
|
||||
'columns' => ["article", "url", "type"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[102,"http://example.com/text","text/plain"],
|
||||
[103,"http://example.com/video","video/webm"],
|
||||
[104,"http://example.com/image","image/svg+xml"],
|
||||
|
@ -152,7 +152,7 @@ trait SeriesArticle {
|
|||
],
|
||||
'arsse_editions' => [
|
||||
'columns' => ["id", "article"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,1],
|
||||
[2,2],
|
||||
[3,3],
|
||||
|
@ -188,7 +188,7 @@ trait SeriesArticle {
|
|||
],
|
||||
'arsse_marks' => [
|
||||
'columns' => ["subscription", "article", "read", "starred", "modified", "note", "hidden"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1, 1,1,1,'2000-01-01 00:00:00','',0],
|
||||
[5, 19,1,0,'2016-01-01 00:00:00','',0],
|
||||
[5, 20,0,1,'2005-01-01 00:00:00','',0],
|
||||
|
@ -209,7 +209,7 @@ trait SeriesArticle {
|
|||
],
|
||||
'arsse_categories' => [ // author-supplied categories
|
||||
'columns' => ["article", "name"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[19,"Fascinating"],
|
||||
[19,"Logical"],
|
||||
[20,"Interesting"],
|
||||
|
@ -218,7 +218,7 @@ trait SeriesArticle {
|
|||
],
|
||||
'arsse_labels' => [ // labels applied to articles
|
||||
'columns' => ["id", "owner", "name"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,"john.doe@example.com","Interesting"],
|
||||
[2,"john.doe@example.com","Fascinating"],
|
||||
[3,"jane.doe@example.com","Boring"],
|
||||
|
@ -227,7 +227,7 @@ trait SeriesArticle {
|
|||
],
|
||||
'arsse_label_members' => [
|
||||
'columns' => ["label", "article", "subscription", "assigned", "modified"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1, 1,1,1,'2000-01-01 00:00:00'],
|
||||
[2, 1,1,1,'2000-01-01 00:00:00'],
|
||||
[1,19,5,1,'2000-01-01 00:00:00'],
|
||||
|
|
|
@ -28,14 +28,14 @@ trait SeriesCleanup {
|
|||
$this->data = [
|
||||
'arsse_users' => [
|
||||
'columns' => ["id", "password", "num"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
["jane.doe@example.com", "",1],
|
||||
["john.doe@example.com", "",2],
|
||||
],
|
||||
],
|
||||
'arsse_sessions' => [
|
||||
'columns' => ["id", "created", "expires", "user"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
["a", $nowish, $faroff, "jane.doe@example.com"], // not expired and recently created, thus kept
|
||||
["b", $nowish, $soon, "jane.doe@example.com"], // not expired and recently created, thus kept
|
||||
["c", $daysago, $soon, "jane.doe@example.com"], // created more than a day ago, thus deleted
|
||||
|
@ -45,7 +45,7 @@ trait SeriesCleanup {
|
|||
],
|
||||
'arsse_tokens' => [
|
||||
'columns' => ["id", "class", "user", "expires"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
["80fa94c1a11f11e78667001e673b2560", "fever.login", "jane.doe@example.com", $faroff],
|
||||
["27c6de8da13311e78667001e673b2560", "fever.login", "jane.doe@example.com", $weeksago], // expired
|
||||
["ab3b3eb8a13311e78667001e673b2560", "class.class", "jane.doe@example.com", null],
|
||||
|
@ -54,7 +54,7 @@ trait SeriesCleanup {
|
|||
],
|
||||
'arsse_icons' => [
|
||||
'columns' => ["id", "url", "orphaned"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,'http://localhost:8000/Icon/PNG',$daybefore],
|
||||
[2,'http://localhost:8000/Icon/GIF',$daybefore],
|
||||
[3,'http://localhost:8000/Icon/SVG1',null],
|
||||
|
@ -62,7 +62,7 @@ trait SeriesCleanup {
|
|||
],
|
||||
'arsse_feeds' => [
|
||||
'columns' => ["id", "url", "title", "orphaned", "size", "icon"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,"http://example.com/1","",$daybefore,2,null], //latest two articles should be kept
|
||||
[2,"http://example.com/2","",$yesterday,0,2],
|
||||
[3,"http://example.com/3","",null,0,1],
|
||||
|
@ -71,7 +71,7 @@ trait SeriesCleanup {
|
|||
],
|
||||
'arsse_subscriptions' => [
|
||||
'columns' => ["id", "owner", "feed"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
// one feed previously marked for deletion has a subscription again, and so should not be deleted
|
||||
[1,'jane.doe@example.com',1],
|
||||
// other subscriptions exist for article cleanup tests
|
||||
|
@ -80,7 +80,7 @@ trait SeriesCleanup {
|
|||
],
|
||||
'arsse_articles' => [
|
||||
'columns' => ["id", "feed", "url_title_hash", "url_content_hash", "title_content_hash", "modified"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,1,"","","",$weeksago], // is the latest article, thus is kept
|
||||
[2,1,"","","",$weeksago], // is the second latest article, thus is kept
|
||||
[3,1,"","","",$weeksago], // is starred by one user, thus is kept
|
||||
|
@ -94,7 +94,7 @@ trait SeriesCleanup {
|
|||
],
|
||||
'arsse_editions' => [
|
||||
'columns' => ["id", "article"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,1],
|
||||
[2,2],
|
||||
[3,3],
|
||||
|
@ -105,7 +105,7 @@ trait SeriesCleanup {
|
|||
],
|
||||
'arsse_marks' => [
|
||||
'columns' => ["article", "subscription", "read", "starred", "hidden", "modified"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[3,1,0,1,0,$weeksago],
|
||||
[4,1,1,0,0,$daysago],
|
||||
[6,1,1,0,0,$nowish],
|
||||
|
|
|
@ -18,14 +18,14 @@ trait SeriesFeed {
|
|||
$this->data = [
|
||||
'arsse_users' => [
|
||||
'columns' => ["id", "password", "num"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
["jane.doe@example.com", "",1],
|
||||
["john.doe@example.com", "",2],
|
||||
],
|
||||
],
|
||||
'arsse_icons' => [
|
||||
'columns' => ["id", "url", "type", "data"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,'http://localhost:8000/Icon/PNG','image/png',base64_decode("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMjHxIGmVAAAADUlEQVQYV2NgYGBgAAAABQABijPjAAAAAABJRU5ErkJggg==")],
|
||||
[2,'http://localhost:8000/Icon/GIF','image/gif',base64_decode("R0lGODlhAQABAIABAAAAAP///yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==")],
|
||||
// this actually contains the data of SVG2, which will lead to a row update when retieved
|
||||
|
@ -34,7 +34,7 @@ trait SeriesFeed {
|
|||
],
|
||||
'arsse_feeds' => [
|
||||
'columns' => ["id", "url", "title", "err_count", "err_msg", "modified", "next_fetch", "size", "icon"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,"http://localhost:8000/Feed/Matching/3","Ook",0,"",$past,$past,0,null],
|
||||
[2,"http://localhost:8000/Feed/Matching/1","Eek",5,"There was an error last time",$past,$future,0,null],
|
||||
[3,"http://localhost:8000/Feed/Fetching/Error?code=404","Ack",0,"",$past,$now,0,null],
|
||||
|
@ -49,7 +49,7 @@ trait SeriesFeed {
|
|||
],
|
||||
'arsse_subscriptions' => [
|
||||
'columns' => ["id", "owner", "feed", "keep_rule", "block_rule"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,'john.doe@example.com',1,null,'^Sport$'],
|
||||
[2,'john.doe@example.com',2,"",null],
|
||||
[3,'john.doe@example.com',3,'\w+',null],
|
||||
|
@ -60,7 +60,7 @@ trait SeriesFeed {
|
|||
],
|
||||
'arsse_articles' => [
|
||||
'columns' => ["id", "feed", "url", "title", "author", "published", "edited", "content", "guid", "url_title_hash", "url_content_hash", "title_content_hash", "modified"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,1,'http://example.com/1','Article title 1','','2000-01-01 00:00:00','2000-01-01 00:00:00','<p>Article content 1</p>','e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda','f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6','fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4','18fdd4fa93d693128c43b004399e5c9cea6c261ddfa002518d3669f55d8c2207',$past],
|
||||
[2,1,'http://example.com/2','Article title 2','','2000-01-02 00:00:00','2000-01-02 00:00:00','<p>Article content 2</p>','5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7','0e86d2de822a174fe3c44a466953e63ca1f1a58a19cbf475fce0855d4e3d5153','13075894189c47ffcfafd1dfe7fbb539f7c74a69d35a399b3abf8518952714f9','2abd0a8cba83b8214a66c8f0293ba63e467d720540e29ff8ddcdab069d4f1c9e',$past],
|
||||
[3,1,'http://example.com/3','Article title 3','','2000-01-03 00:00:00','2000-01-03 00:00:00','<p>Article content 3</p>','31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92','f74b06b240bd08abf4d3fdfc20dba6a6f6eb8b4f1a00e9a617efd63a87180a4b','b278380e984cefe63f0e412b88ffc9cb0befdfa06fdc00bace1da99a8daff406','ad622b31e739cd3a3f3c788991082cf4d2f7a8773773008e75f0572e58cd373b',$past],
|
||||
|
@ -72,7 +72,7 @@ trait SeriesFeed {
|
|||
],
|
||||
'arsse_editions' => [
|
||||
'columns' => ["id", "article", "modified"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,1,$past],
|
||||
[2,2,$past],
|
||||
[3,3,$past],
|
||||
|
@ -82,7 +82,7 @@ trait SeriesFeed {
|
|||
],
|
||||
'arsse_marks' => [
|
||||
'columns' => ["article", "subscription", "read", "starred", "hidden", "modified"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
// Jane's marks
|
||||
[1,6,1,0,0,$past],
|
||||
[2,6,1,0,0,$past],
|
||||
|
@ -97,13 +97,13 @@ trait SeriesFeed {
|
|||
],
|
||||
'arsse_enclosures' => [
|
||||
'columns' => ["article", "url", "type"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[7,'http://example.com/png','image/png'],
|
||||
],
|
||||
],
|
||||
'arsse_categories' => [
|
||||
'columns' => ["article", "name"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[7,'Syrinx'],
|
||||
],
|
||||
],
|
||||
|
|
|
@ -13,7 +13,7 @@ trait SeriesFolder {
|
|||
$this->data = [
|
||||
'arsse_users' => [
|
||||
'columns' => ["id", "password", "num"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
["jane.doe@example.com", "",1],
|
||||
["john.doe@example.com", "",2],
|
||||
],
|
||||
|
@ -41,7 +41,7 @@ trait SeriesFolder {
|
|||
],
|
||||
'arsse_feeds' => [
|
||||
'columns' => ["id", "url", "title"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,"http://example.com/1", "Feed 1"],
|
||||
[2,"http://example.com/2", "Feed 2"],
|
||||
[3,"http://example.com/3", "Feed 3"],
|
||||
|
@ -59,7 +59,7 @@ trait SeriesFolder {
|
|||
],
|
||||
'arsse_subscriptions' => [
|
||||
'columns' => ["id", "owner", "feed", "folder"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1, "john.doe@example.com",1, null],
|
||||
[2, "john.doe@example.com",2, null],
|
||||
[3, "john.doe@example.com",3, 1],
|
||||
|
|
|
@ -17,14 +17,14 @@ trait SeriesIcon {
|
|||
$this->data = [
|
||||
'arsse_users' => [
|
||||
'columns' => ["id", "password", "num"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
["jane.doe@example.com", "",1],
|
||||
["john.doe@example.com", "",2],
|
||||
],
|
||||
],
|
||||
'arsse_icons' => [
|
||||
'columns' => ["id", "url", "type", "data"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,'http://localhost:8000/Icon/PNG','image/png',base64_decode("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMjHxIGmVAAAADUlEQVQYV2NgYGBgAAAABQABijPjAAAAAABJRU5ErkJggg==")],
|
||||
[2,'http://localhost:8000/Icon/GIF','image/gif',base64_decode("R0lGODlhAQABAIABAAAAAP///yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==")],
|
||||
[3,'http://localhost:8000/Icon/SVG1','image/svg+xml','<svg xmlns="http://www.w3.org/2000/svg" width="900" height="600"><rect fill="#fff" height="600" width="900"/><circle fill="#bc002d" cx="450" cy="300" r="180"/></svg>'],
|
||||
|
@ -33,7 +33,7 @@ trait SeriesIcon {
|
|||
],
|
||||
'arsse_feeds' => [
|
||||
'columns' => ["id", "url", "title", "err_count", "err_msg", "modified", "next_fetch", "size", "icon"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,"http://localhost:8000/Feed/Matching/3","Ook",0,"",$past,$past,0,1],
|
||||
[2,"http://localhost:8000/Feed/Matching/1","Eek",5,"There was an error last time",$past,$future,0,2],
|
||||
[3,"http://localhost:8000/Feed/Fetching/Error?code=404","Ack",0,"",$past,$now,0,3],
|
||||
|
@ -43,7 +43,7 @@ trait SeriesIcon {
|
|||
],
|
||||
'arsse_subscriptions' => [
|
||||
'columns' => ["id", "owner", "feed"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,'john.doe@example.com',1],
|
||||
[2,'john.doe@example.com',2],
|
||||
[3,'john.doe@example.com',3],
|
||||
|
|
|
@ -15,7 +15,7 @@ trait SeriesLabel {
|
|||
$this->data = [
|
||||
'arsse_users' => [
|
||||
'columns' => ["id", "password", "num"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
["jane.doe@example.com", "",1],
|
||||
["john.doe@example.com", "",2],
|
||||
["john.doe@example.org", "",3],
|
||||
|
@ -24,7 +24,7 @@ trait SeriesLabel {
|
|||
],
|
||||
'arsse_folders' => [
|
||||
'columns' => ["id", "owner", "parent", "name"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1, "john.doe@example.com", null, "Technology"],
|
||||
[2, "john.doe@example.com", 1, "Software"],
|
||||
[3, "john.doe@example.com", 1, "Rocketry"],
|
||||
|
@ -38,7 +38,7 @@ trait SeriesLabel {
|
|||
],
|
||||
'arsse_feeds' => [
|
||||
'columns' => ["id", "url"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,"http://example.com/1"],
|
||||
[2,"http://example.com/2"],
|
||||
[3,"http://example.com/3"],
|
||||
|
@ -56,7 +56,7 @@ trait SeriesLabel {
|
|||
],
|
||||
'arsse_subscriptions' => [
|
||||
'columns' => ["id", "owner", "feed", "folder"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,"john.doe@example.com",1,null],
|
||||
[2,"john.doe@example.com",2,null],
|
||||
[3,"john.doe@example.com",3,1],
|
||||
|
@ -75,7 +75,7 @@ trait SeriesLabel {
|
|||
],
|
||||
'arsse_articles' => [
|
||||
'columns' => ["id", "feed", "url", "title", "author", "published", "edited", "content", "guid", "url_title_hash", "url_content_hash", "title_content_hash", "modified"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,1,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
|
||||
[2,1,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
|
||||
[3,2,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
|
||||
|
@ -105,7 +105,7 @@ trait SeriesLabel {
|
|||
],
|
||||
'arsse_enclosures' => [
|
||||
'columns' => ["article", "url", "type"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[102,"http://example.com/text","text/plain"],
|
||||
[103,"http://example.com/video","video/webm"],
|
||||
[104,"http://example.com/image","image/svg+xml"],
|
||||
|
@ -115,7 +115,7 @@ trait SeriesLabel {
|
|||
],
|
||||
'arsse_editions' => [
|
||||
'columns' => ["id", "article"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,1],
|
||||
[2,2],
|
||||
[3,3],
|
||||
|
@ -151,7 +151,7 @@ trait SeriesLabel {
|
|||
],
|
||||
'arsse_marks' => [
|
||||
'columns' => ["subscription", "article", "read", "starred", "modified", "hidden"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1, 1,1,1,'2000-01-01 00:00:00',0],
|
||||
[5, 19,1,0,'2000-01-01 00:00:00',0],
|
||||
[5, 20,0,1,'2010-01-01 00:00:00',0],
|
||||
|
@ -169,7 +169,7 @@ trait SeriesLabel {
|
|||
],
|
||||
'arsse_labels' => [
|
||||
'columns' => ["id", "owner", "name"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,"john.doe@example.com","Interesting"],
|
||||
[2,"john.doe@example.com","Fascinating"],
|
||||
[3,"jane.doe@example.com","Boring"],
|
||||
|
@ -178,7 +178,7 @@ trait SeriesLabel {
|
|||
],
|
||||
'arsse_label_members' => [
|
||||
'columns' => ["label", "article", "subscription", "assigned"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1, 1,1,1],
|
||||
[2, 1,1,1],
|
||||
[1,19,5,1],
|
||||
|
|
|
@ -14,7 +14,7 @@ trait SeriesMeta {
|
|||
$dataBare = [
|
||||
'arsse_meta' => [
|
||||
'columns' => ["key", "value"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
//['schema_version', "".\JKingWeb\Arsse\Database::SCHEMA_VERSION],
|
||||
['album',"A Farewell to Kings"],
|
||||
],
|
||||
|
|
|
@ -24,14 +24,14 @@ trait SeriesSession {
|
|||
$this->data = [
|
||||
'arsse_users' => [
|
||||
'columns' => ["id", "password", "num"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
["jane.doe@example.com", "",1],
|
||||
["john.doe@example.com", "",2],
|
||||
],
|
||||
],
|
||||
'arsse_sessions' => [
|
||||
'columns' => ["id", "user", "created", "expires"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
["80fa94c1a11f11e78667001e673b2560", "jane.doe@example.com", $past, $faroff],
|
||||
["27c6de8da13311e78667001e673b2560", "jane.doe@example.com", $past, $past], // expired
|
||||
["ab3b3eb8a13311e78667001e673b2560", "jane.doe@example.com", $old, $future], // too old
|
||||
|
|
|
@ -16,7 +16,7 @@ trait SeriesSubscription {
|
|||
$this->data = [
|
||||
'arsse_users' => [
|
||||
'columns' => ["id", "password", "num"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
["jane.doe@example.com", "", 1],
|
||||
["john.doe@example.com", "", 2],
|
||||
["jill.doe@example.com", "", 3],
|
||||
|
@ -25,7 +25,7 @@ trait SeriesSubscription {
|
|||
],
|
||||
'arsse_folders' => [
|
||||
'columns' => ["id", "owner", "parent", "name"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1, "john.doe@example.com", null, "Technology"],
|
||||
[2, "john.doe@example.com", 1, "Software"],
|
||||
[3, "john.doe@example.com", 1, "Rocketry"],
|
||||
|
@ -36,14 +36,14 @@ trait SeriesSubscription {
|
|||
],
|
||||
'arsse_icons' => [
|
||||
'columns' => ["id", "url", "data"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,"http://example.com/favicon.ico", "ICON DATA"],
|
||||
[2,"http://example.net/favicon.ico", null],
|
||||
],
|
||||
],
|
||||
'arsse_feeds' => [
|
||||
'columns' => ["id", "url", "title", "username", "password", "updated", "next_fetch", "icon"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,"http://example.com/feed1", "Ook", "", "",strtotime("now"),strtotime("now"),null],
|
||||
[2,"http://example.com/feed2", "eek", "", "",strtotime("now - 1 hour"),strtotime("now - 1 hour"),1],
|
||||
[3,"http://example.com/feed3", "Ack", "", "",strtotime("now + 1 hour"),strtotime("now + 1 hour"),2],
|
||||
|
@ -52,7 +52,7 @@ trait SeriesSubscription {
|
|||
],
|
||||
'arsse_subscriptions' => [
|
||||
'columns' => ["id", "owner", "feed", "title", "folder", "pinned", "order_type", "keep_rule", "block_rule", "scrape"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,"john.doe@example.com",2,null,null,1,2,null,null,0],
|
||||
[2,"jane.doe@example.com",2,null,null,0,0,null,null,0],
|
||||
[3,"john.doe@example.com",3,"Ook",2,0,1,null,null,0],
|
||||
|
@ -63,7 +63,7 @@ trait SeriesSubscription {
|
|||
],
|
||||
'arsse_tags' => [
|
||||
'columns' => ["id", "owner", "name"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,"john.doe@example.com","Interesting"],
|
||||
[2,"john.doe@example.com","Fascinating"],
|
||||
[3,"jane.doe@example.com","Boring"],
|
||||
|
@ -72,7 +72,7 @@ trait SeriesSubscription {
|
|||
],
|
||||
'arsse_tag_members' => [
|
||||
'columns' => ["tag", "subscription", "assigned"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,1,1],
|
||||
[1,3,0],
|
||||
[2,1,1],
|
||||
|
@ -82,7 +82,7 @@ trait SeriesSubscription {
|
|||
],
|
||||
'arsse_articles' => [
|
||||
'columns' => ["id", "feed", "url_title_hash", "url_content_hash", "title_content_hash", "title"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,2,"","","","Title 1"],
|
||||
[2,2,"","","","Title 2"],
|
||||
[3,2,"","","","Title 3"],
|
||||
|
@ -95,7 +95,7 @@ trait SeriesSubscription {
|
|||
],
|
||||
'arsse_editions' => [
|
||||
'columns' => ["id", "article"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,1],
|
||||
[2,2],
|
||||
[3,3],
|
||||
|
@ -108,7 +108,7 @@ trait SeriesSubscription {
|
|||
],
|
||||
'arsse_categories' => [
|
||||
'columns' => ["article", "name"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,"A"],
|
||||
[2,"B"],
|
||||
[4,"D"],
|
||||
|
@ -120,7 +120,7 @@ trait SeriesSubscription {
|
|||
],
|
||||
'arsse_marks' => [
|
||||
'columns' => ["article", "subscription", "read", "starred", "hidden"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,2,1,0,0],
|
||||
[2,2,1,0,0],
|
||||
[3,2,1,0,0],
|
||||
|
|
|
@ -14,7 +14,7 @@ trait SeriesTag {
|
|||
$this->data = [
|
||||
'arsse_users' => [
|
||||
'columns' => ["id", "password", "num"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
["jane.doe@example.com", "",1],
|
||||
["john.doe@example.com", "",2],
|
||||
["john.doe@example.org", "",3],
|
||||
|
@ -23,7 +23,7 @@ trait SeriesTag {
|
|||
],
|
||||
'arsse_feeds' => [
|
||||
'columns' => ["id", "url", "title"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,"http://example.com/1",""],
|
||||
[2,"http://example.com/2",""],
|
||||
[3,"http://example.com/3","Feed Title"],
|
||||
|
@ -41,7 +41,7 @@ trait SeriesTag {
|
|||
],
|
||||
'arsse_subscriptions' => [
|
||||
'columns' => ["id", "owner", "feed", "title"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1, "john.doe@example.com", 1,"Lord of Carrots"],
|
||||
[2, "john.doe@example.com", 2,null],
|
||||
[3, "john.doe@example.com", 3,"Subscription Title"],
|
||||
|
@ -60,7 +60,7 @@ trait SeriesTag {
|
|||
],
|
||||
'arsse_tags' => [
|
||||
'columns' => ["id", "owner", "name"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,"john.doe@example.com","Interesting"],
|
||||
[2,"john.doe@example.com","Fascinating"],
|
||||
[3,"jane.doe@example.com","Boring"],
|
||||
|
@ -69,7 +69,7 @@ trait SeriesTag {
|
|||
],
|
||||
'arsse_tag_members' => [
|
||||
'columns' => ["tag", "subscription", "assigned"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1,1,1],
|
||||
[1,3,0],
|
||||
[1,5,1],
|
||||
|
|
|
@ -18,14 +18,14 @@ trait SeriesToken {
|
|||
$this->data = [
|
||||
'arsse_users' => [
|
||||
'columns' => ["id", "password", "num"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
["jane.doe@example.com", "",1],
|
||||
["john.doe@example.com", "",2],
|
||||
],
|
||||
],
|
||||
'arsse_tokens' => [
|
||||
'columns' => ["id", "class", "user", "expires", "data"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
["80fa94c1a11f11e78667001e673b2560", "fever.login", "jane.doe@example.com", $faroff, null],
|
||||
["27c6de8da13311e78667001e673b2560", "fever.login", "jane.doe@example.com", $past, null], // expired
|
||||
["ab3b3eb8a13311e78667001e673b2560", "class.class", "jane.doe@example.com", null, null],
|
||||
|
|
|
@ -13,7 +13,7 @@ trait SeriesUser {
|
|||
$this->data = [
|
||||
'arsse_users' => [
|
||||
'columns' => ["id", "password", "num", "admin"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
["admin@example.net", '$2y$10$PbcG2ZR3Z8TuPzM7aHTF8.v61dtCjzjK78gdZJcp4UePE8T9jEgBW', 1, 1], // password is hash of "secret"
|
||||
["jane.doe@example.com", "", 2, 0],
|
||||
["john.doe@example.com", "", 3, 0],
|
||||
|
@ -21,7 +21,7 @@ trait SeriesUser {
|
|||
],
|
||||
'arsse_user_meta' => [
|
||||
'columns' => ["owner", "key", "value"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
["admin@example.net", "lang", "en"],
|
||||
["admin@example.net", "tz", "America/Toronto"],
|
||||
["admin@example.net", "sort_asc", "0"],
|
||||
|
|
|
@ -42,14 +42,14 @@ class TestImportExport extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$this->data = [
|
||||
'arsse_users' => [
|
||||
'columns' => ["id", "password", "num"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
["john.doe@example.com", "", 1],
|
||||
["jane.doe@example.com", "", 2],
|
||||
],
|
||||
],
|
||||
'arsse_folders' => [
|
||||
'columns' => ["id", "owner", "parent", "name"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1, "john.doe@example.com", null, "Science"],
|
||||
[2, "john.doe@example.com", 1, "Rocketry"],
|
||||
[3, "john.doe@example.com", null, "Politics"],
|
||||
|
@ -60,7 +60,7 @@ class TestImportExport extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
],
|
||||
'arsse_feeds' => [
|
||||
'columns' => ["id", "url", "title"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1, "http://localhost:8000/Import/nasa-jpl", "NASA JPL"],
|
||||
[2, "http://localhost:8000/Import/torstar", "Toronto Star"],
|
||||
[3, "http://localhost:8000/Import/ars", "Ars Technica"],
|
||||
|
@ -71,7 +71,7 @@ class TestImportExport extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
],
|
||||
'arsse_subscriptions' => [
|
||||
'columns' => ["id", "owner", "folder", "feed", "title"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1, "john.doe@example.com", 2, 1, "NASA JPL"],
|
||||
[2, "john.doe@example.com", 5, 2, "Toronto Star"],
|
||||
[3, "john.doe@example.com", 1, 3, "Ars Technica"],
|
||||
|
@ -82,7 +82,7 @@ class TestImportExport extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
],
|
||||
'arsse_tags' => [
|
||||
'columns' => ["id", "owner", "name"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1, "john.doe@example.com", "canada"],
|
||||
[2, "john.doe@example.com", "frequent"],
|
||||
[3, "john.doe@example.com", "gaming"],
|
||||
|
@ -93,7 +93,7 @@ class TestImportExport extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
],
|
||||
'arsse_tag_members' => [
|
||||
'columns' => ["tag", "subscription", "assigned"],
|
||||
'rows' => [
|
||||
'rows' => [
|
||||
[1, 2, 1],
|
||||
[1, 4, 1],
|
||||
[1, 5, 1],
|
||||
|
|
|
@ -7,14 +7,17 @@ declare(strict_types=1);
|
|||
namespace JKingWeb\Arsse\TestCase\Misc;
|
||||
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use GuzzleHttp\Psr7\Request;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/** @covers \JKingWeb\Arsse\Misc\HTTP */
|
||||
class TestHTTP extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||
/** @dataProvider provideMediaTypes */
|
||||
public function testMatchMediaType(string $header, array $types, bool $exp): void {
|
||||
$msg = (new \Laminas\Diactoros\Request)->withHeader("Content-Type", $header);
|
||||
$msg = (new Request("POST", "/"))->withHeader("Content-Type", $header);
|
||||
$this->assertSame($exp, HTTP::matchType($msg, ...$types));
|
||||
$msg = (new \Laminas\Diactoros\Response)->withHeader("Content-Type", $header);
|
||||
$msg = (new Response)->withHeader("Content-Type", $header);
|
||||
$this->assertSame($exp, HTTP::matchType($msg, ...$types));
|
||||
}
|
||||
|
||||
|
@ -27,6 +30,26 @@ class TestHTTP extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
["", ["application/json"], false],
|
||||
["", ["application/json", ""], true],
|
||||
["application/json ;", ["application/json"], true],
|
||||
["application/feed+json", ["application/json", "+json"], true],
|
||||
["application/xhtml+xml", ["application/json", "+json"], false],
|
||||
];
|
||||
}
|
||||
|
||||
/** @dataProvider provideTypedMessages */
|
||||
public function testCreateResponses(string $type, array $params, ResponseInterface $exp): void {
|
||||
$act = call_user_func(["JKingWeb\\Arsse\\Misc\\HTTP", $type], ...$params);
|
||||
$this->assertMessage($exp, $act);
|
||||
}
|
||||
|
||||
public function provideTypedMessages(): iterable {
|
||||
return [
|
||||
["respEmpty", [422, ['Content-Length' => "0"]], new Response(422, ['Content-Length' => "0"])],
|
||||
["respText", ["OOK"], new Response(200, ['Content-Type' => "text/plain; charset=UTF-8"], "OOK")],
|
||||
["respText", ["OOK", 201, ['Content-Type' => "application/octet-stream"]], new Response(201, ['Content-Type' => "application/octet-stream"], "OOK")],
|
||||
["respJson", [['ook' => "eek"]], new Response(200, ['Content-Type' => "application/json"], '{"ook":"eek"}')],
|
||||
["respJson", [['ook' => "eek"], 400, ['Content-Type' => "application/feed+json"]], new Response(400, ['Content-Type' => "application/feed+json"], '{"ook":"eek"}')],
|
||||
["respXml", ["<html/>"], new Response(200, ['Content-Type' => "application/xml; charset=UTF-8"], "<html/>")],
|
||||
["respXml", ["<html/>", 451, ['Content-Type' => "text/plain", 'Vary' => "ETag"]], new Response(451, ['Content-Type' => "text/plain", 'Vary' => "ETag"], "<html/>")],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,15 +9,13 @@ namespace JKingWeb\Arsse\TestCase\REST\Fever;
|
|||
use JKingWeb\Arsse\Arsse;
|
||||
use JKingWeb\Arsse\User;
|
||||
use JKingWeb\Arsse\Database;
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use JKingWeb\Arsse\Test\Result;
|
||||
use JKingWeb\Arsse\Context\Context;
|
||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||
use JKingWeb\Arsse\Db\Transaction;
|
||||
use JKingWeb\Arsse\REST\Fever\API;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Laminas\Diactoros\Response\XmlResponse;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
|
||||
/** @covers \JKingWeb\Arsse\REST\Fever\API<extended> */
|
||||
class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||
|
@ -192,9 +190,9 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
}
|
||||
|
||||
public function provideTokenAuthenticationRequests(): iterable {
|
||||
$success = new JsonResponse(['auth' => 1]);
|
||||
$failure = new JsonResponse(['auth' => 0]);
|
||||
$denied = new EmptyResponse(401);
|
||||
$success = HTTP::respJson(['auth' => 1]);
|
||||
$failure = HTTP::respJson(['auth' => 0]);
|
||||
$denied = HTTP::respEmpty(401);
|
||||
return [
|
||||
[false, true, null, [], ['api' => null], $failure],
|
||||
[false, false, null, [], ['api' => null], $failure],
|
||||
|
@ -255,7 +253,7 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
['id' => 2, 'name' => "Interesting", 'subscription' => 1],
|
||||
['id' => 2, 'name' => "Interesting", 'subscription' => 3],
|
||||
]));
|
||||
$exp = new JsonResponse([
|
||||
$exp = HTTP::respJson([
|
||||
'groups' => [
|
||||
['id' => 1, 'title' => "Fascinating"],
|
||||
['id' => 2, 'title' => "Interesting"],
|
||||
|
@ -281,7 +279,7 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
['id' => 2, 'name' => "Interesting", 'subscription' => 1],
|
||||
['id' => 2, 'name' => "Interesting", 'subscription' => 3],
|
||||
]));
|
||||
$exp = new JsonResponse([
|
||||
$exp = HTTP::respJson([
|
||||
'feeds' => [
|
||||
['id' => 1, 'favicon_id' => 42, 'title' => "Ankh-Morpork News", 'url' => "http://example.com/feed", 'site_url' => "http://example.com/", 'is_spark' => 0, 'last_updated_on_time' => strtotime("2019-01-01T21:12:00Z")],
|
||||
['id' => 2, 'favicon_id' => 0, 'title' => "Ook, Ook Eek Ook!", 'url' => "http://example.net/feed", 'site_url' => "http://example.net/", 'is_spark' => 0, 'last_updated_on_time' => strtotime("1988-06-24T12:21:00Z")],
|
||||
|
@ -301,7 +299,7 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$order = [$desc ? "id desc" : "id"];
|
||||
$this->dbMock->articleList->returns(new Result($this->articles['db']));
|
||||
$this->dbMock->articleCount->with($this->userId, (new Context)->hidden(false))->returns(1024);
|
||||
$exp = new JsonResponse([
|
||||
$exp = HTTP::respJson([
|
||||
'items' => $this->articles['rest'],
|
||||
'total_items' => 1024,
|
||||
]);
|
||||
|
@ -330,15 +328,15 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$unread = [['id' => 4],['id' => 5],['id' => 6]];
|
||||
$this->dbMock->articleList->with($this->userId, (new Context)->starred(true)->hidden(false))->returns(new Result($saved));
|
||||
$this->dbMock->articleList->with($this->userId, (new Context)->unread(true)->hidden(false))->returns(new Result($unread));
|
||||
$exp = new JsonResponse(['saved_item_ids' => "1,2,3"]);
|
||||
$exp = HTTP::respJson(['saved_item_ids' => "1,2,3"]);
|
||||
$this->assertMessage($exp, $this->req("api&saved_item_ids"));
|
||||
$exp = new JsonResponse(['unread_item_ids' => "4,5,6"]);
|
||||
$exp = HTTP::respJson(['unread_item_ids' => "4,5,6"]);
|
||||
$this->assertMessage($exp, $this->req("api&unread_item_ids"));
|
||||
}
|
||||
|
||||
public function testListHotLinks(): void {
|
||||
// hot links are not actually implemented, so an empty array should be all we get
|
||||
$exp = new JsonResponse(['links' => []]);
|
||||
$exp = HTTP::respJson(['links' => []]);
|
||||
$this->assertMessage($exp, $this->req("api&links"));
|
||||
}
|
||||
|
||||
|
@ -350,7 +348,7 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$this->dbMock->articleList->with($this->userId, (new Context)->unread(true)->hidden(false))->returns(new Result($unread));
|
||||
$this->dbMock->articleMark->returns(0);
|
||||
$this->dbMock->articleMark->with($this->userId, $this->anything(), (new Context)->article(2112))->throws(new \JKingWeb\Arsse\Db\ExceptionInput("subjectMissing"));
|
||||
$exp = new JsonResponse($out);
|
||||
$exp = HTTP::respJson($out);
|
||||
$this->assertMessage($exp, $this->req("api", $post));
|
||||
if ($c && $data) {
|
||||
$this->dbMock->articleMark->calledWith($this->userId, $data, $this->equalTo($c));
|
||||
|
@ -367,7 +365,7 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$this->dbMock->articleList->with($this->userId, (new Context)->unread(true)->hidden(false))->returns(new Result($unread));
|
||||
$this->dbMock->articleMark->returns(0);
|
||||
$this->dbMock->articleMark->with($this->userId, $this->anything(), (new Context)->article(2112))->throws(new \JKingWeb\Arsse\Db\ExceptionInput("subjectMissing"));
|
||||
$exp = new JsonResponse($out);
|
||||
$exp = HTTP::respJson($out);
|
||||
$this->assertMessage($exp, $this->req("api&$get"));
|
||||
if ($c && $data) {
|
||||
$this->dbMock->articleMark->calledWith($this->userId, $data, $this->equalTo($c));
|
||||
|
@ -421,11 +419,11 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
public function provideInvalidRequests(): iterable {
|
||||
return [
|
||||
'Not an API request' => ["", "", "POST", null, new EmptyResponse(404)],
|
||||
'Wrong method' => ["api", "", "PUT", null, new EmptyResponse(405, ['Allow' => "OPTIONS,POST"])],
|
||||
'Non-standard method' => ["api", "", "GET", null, new JsonResponse([])],
|
||||
'Wrong content type' => ["api", '{"api_key":"validToken"}', "POST", "application/json", new JsonResponse([])], // some clients send nonsensical content types; Fever seems to have allowed this
|
||||
'Non-standard content type' => ["api", '{"api_key":"validToken"}', "POST", "multipart/form-data; boundary=33b68964f0de4c1f-5144aa6caaa6e4a8-18bfaf416a1786c8-5c5053a45f221bc1", new JsonResponse([])], // some clients send nonsensical content types; Fever seems to have allowed this
|
||||
'Not an API request' => ["", "", "POST", null, HTTP::respEmpty(404)],
|
||||
'Wrong method' => ["api", "", "PUT", null, HTTP::respEmpty(405, ['Allow' => "OPTIONS,POST"])],
|
||||
'Non-standard method' => ["api", "", "GET", null, HTTP::respJson([])],
|
||||
'Wrong content type' => ["api", '{"api_key":"validToken"}', "POST", "application/json", HTTP::respJson([])], // some clients send nonsensical content types; Fever seems to have allowed this
|
||||
'Non-standard content type' => ["api", '{"api_key":"validToken"}', "POST", "multipart/form-data; boundary=33b68964f0de4c1f-5144aa6caaa6e4a8-18bfaf416a1786c8-5c5053a45f221bc1", HTTP::respJson([])], // some clients send nonsensical content types; Fever seems to have allowed this
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -433,21 +431,21 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$this->hMock->baseResponse->forwards();
|
||||
$this->hMock->logIn->returns(true);
|
||||
$this->dbMock->subscriptionRefreshed->with($this->userId)->returns(new \DateTimeImmutable("2000-01-01T00:00:00Z"));
|
||||
$exp = new JsonResponse([
|
||||
$exp = HTTP::respJson([
|
||||
'api_version' => API::LEVEL,
|
||||
'auth' => 1,
|
||||
'last_refreshed_on_time' => 946684800,
|
||||
]);
|
||||
$this->assertMessage($exp, $this->req("api"));
|
||||
$this->dbMock->subscriptionRefreshed->with($this->userId)->returns(null); // no subscriptions
|
||||
$exp = new JsonResponse([
|
||||
$exp = HTTP::respJson([
|
||||
'api_version' => API::LEVEL,
|
||||
'auth' => 1,
|
||||
'last_refreshed_on_time' => null,
|
||||
]);
|
||||
$this->assertMessage($exp, $this->req("api"));
|
||||
$this->hMock->logIn->returns(false);
|
||||
$exp = new JsonResponse([
|
||||
$exp = HTTP::respJson([
|
||||
'api_version' => API::LEVEL,
|
||||
'auth' => 0,
|
||||
]);
|
||||
|
@ -460,7 +458,7 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$this->dbMock->articleList->with($this->userId, $this->equalTo((new Context)->limit(1)->hidden(false)), ["marked_date"], ["marked_date desc"])->returns(new Result([['marked_date' => "2000-01-01 00:00:00"]]));
|
||||
$this->dbMock->articleList->with($this->userId, $this->equalTo((new Context)->unread(true)->hidden(false)))->returns(new Result($unread));
|
||||
$this->dbMock->articleMark->returns(0);
|
||||
$exp = new JsonResponse($out);
|
||||
$exp = HTTP::respJson($out);
|
||||
$this->assertMessage($exp, $this->req("api", ['unread_recently_read' => 1]));
|
||||
$this->dbMock->articleMark->calledWith($this->userId, ['read' => false], $this->equalTo((new Context)->unread(false)->markedRange("1999-12-31T23:59:45Z", null)->hidden(false)));
|
||||
$this->dbMock->articleList->with($this->userId, (new Context)->limit(1)->hidden(false), ["marked_date"], ["marked_date desc"])->returns(new Result([]));
|
||||
|
@ -473,7 +471,7 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
'items' => $this->articles['rest'],
|
||||
'total_items' => 1024,
|
||||
]);
|
||||
$exp = new XmlResponse("<response><items><item><id>101</id><feed_id>8</feed_id><title>Article title 1</title><author></author><html><p>Article content 1</p></html><url>http://example.com/1</url><is_saved>0</is_saved><is_read>0</is_read><created_on_time>946684800</created_on_time></item><item><id>102</id><feed_id>8</feed_id><title>Article title 2</title><author></author><html><p>Article content 2</p></html><url>http://example.com/2</url><is_saved>0</is_saved><is_read>1</is_read><created_on_time>946771200</created_on_time></item><item><id>103</id><feed_id>9</feed_id><title>Article title 3</title><author></author><html><p>Article content 3</p></html><url>http://example.com/3</url><is_saved>1</is_saved><is_read>0</is_read><created_on_time>946857600</created_on_time></item><item><id>104</id><feed_id>9</feed_id><title>Article title 4</title><author></author><html><p>Article content 4</p></html><url>http://example.com/4</url><is_saved>1</is_saved><is_read>1</is_read><created_on_time>946944000</created_on_time></item><item><id>105</id><feed_id>10</feed_id><title>Article title 5</title><author></author><html><p>Article content 5</p></html><url>http://example.com/5</url><is_saved>0</is_saved><is_read>0</is_read><created_on_time>947030400</created_on_time></item></items><total_items>1024</total_items></response>");
|
||||
$exp = HTTP::respXml("<response><items><item><id>101</id><feed_id>8</feed_id><title>Article title 1</title><author></author><html><p>Article content 1</p></html><url>http://example.com/1</url><is_saved>0</is_saved><is_read>0</is_read><created_on_time>946684800</created_on_time></item><item><id>102</id><feed_id>8</feed_id><title>Article title 2</title><author></author><html><p>Article content 2</p></html><url>http://example.com/2</url><is_saved>0</is_saved><is_read>1</is_read><created_on_time>946771200</created_on_time></item><item><id>103</id><feed_id>9</feed_id><title>Article title 3</title><author></author><html><p>Article content 3</p></html><url>http://example.com/3</url><is_saved>1</is_saved><is_read>0</is_read><created_on_time>946857600</created_on_time></item><item><id>104</id><feed_id>9</feed_id><title>Article title 4</title><author></author><html><p>Article content 4</p></html><url>http://example.com/4</url><is_saved>1</is_saved><is_read>1</is_read><created_on_time>946944000</created_on_time></item><item><id>105</id><feed_id>10</feed_id><title>Article title 5</title><author></author><html><p>Article content 5</p></html><url>http://example.com/5</url><is_saved>0</is_saved><is_read>0</is_read><created_on_time>947030400</created_on_time></item></items><total_items>1024</total_items></response>");
|
||||
$this->assertMessage($exp, $this->req("api=xml"));
|
||||
}
|
||||
|
||||
|
@ -485,7 +483,7 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
['id' => 44, 'type' => null, 'data' => "IMAGE DATA"],
|
||||
['id' => 47, 'type' => null, 'data' => null],
|
||||
])));
|
||||
$exp = new JsonResponse(['favicons' => [
|
||||
$exp = HTTP::respJson(['favicons' => [
|
||||
['id' => 0, 'data' => $iconType.",".$iconData],
|
||||
['id' => 42, 'data' => "image/svg+xml;base64,PHN2Zy8+"],
|
||||
['id' => 44, 'data' => "application/octet-stream;base64,SU1BR0UgREFUQQ=="],
|
||||
|
@ -494,7 +492,7 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
}
|
||||
|
||||
public function testAnswerOptionsRequest(): void {
|
||||
$exp = new EmptyResponse(204, [
|
||||
$exp = HTTP::respEmpty(204, [
|
||||
'Allow' => "POST",
|
||||
'Accept' => "application/x-www-form-urlencoded, multipart/form-data",
|
||||
]);
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
<?php
|
||||
/** @license MIT
|
||||
* Copyright 2017 J. King, Dustin Wilson et al.
|
||||
* See LICENSE and AUTHORS files for details */
|
||||
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\Arsse\TestCase\REST\Miniflux;
|
||||
|
||||
use JKingWeb\Arsse\REST\Miniflux\ErrorResponse;
|
||||
|
||||
/** @covers \JKingWeb\Arsse\REST\Miniflux\ErrorResponse */
|
||||
class TestErrorResponse extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||
public function testCreateConstantResponse(): void {
|
||||
$act = new ErrorResponse("401", 401);
|
||||
$this->assertSame('{"error_message":"Access Unauthorized"}', (string) $act->getBody());
|
||||
}
|
||||
|
||||
public function testCreateVariableResponse(): void {
|
||||
$act = new ErrorResponse(["InvalidBodyJSON", "Doh!"], 401);
|
||||
$this->assertSame('{"error_message":"Invalid JSON payload: Doh!"}', (string) $act->getBody());
|
||||
}
|
||||
}
|
|
@ -6,11 +6,10 @@
|
|||
declare(strict_types=1);
|
||||
namespace JKingWeb\Arsse\TestCase\REST\Miniflux;
|
||||
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use JKingWeb\Arsse\REST\Miniflux\Status;
|
||||
use JKingWeb\Arsse\REST\Miniflux\V1;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
use Laminas\Diactoros\Response\TextResponse;
|
||||
|
||||
/** @covers \JKingWeb\Arsse\REST\Miniflux\Status */
|
||||
class TestStatus extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||
|
@ -22,13 +21,13 @@ class TestStatus extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
public function provideRequests(): iterable {
|
||||
return [
|
||||
["/version", "GET", new TextResponse(V1::VERSION)],
|
||||
["/version", "POST", new EmptyResponse(405, ['Allow' => "HEAD, GET"])],
|
||||
["/version", "OPTIONS", new EmptyResponse(204, ['Allow' => "HEAD, GET"])],
|
||||
["/healthcheck", "GET", new TextResponse("OK")],
|
||||
["/healthcheck", "POST", new EmptyResponse(405, ['Allow' => "HEAD, GET"])],
|
||||
["/healthcheck", "OPTIONS", new EmptyResponse(204, ['Allow' => "HEAD, GET"])],
|
||||
["/version/", "GET", new EmptyResponse(404)],
|
||||
["/version", "GET", HTTP::respText(V1::VERSION)],
|
||||
["/version", "POST", HTTP::respEmpty(405, ['Allow' => "HEAD, GET"])],
|
||||
["/version", "OPTIONS", HTTP::respEmpty(204, ['Allow' => "HEAD, GET"])],
|
||||
["/healthcheck", "GET", HTTP::respText("OK")],
|
||||
["/healthcheck", "POST", HTTP::respEmpty(405, ['Allow' => "HEAD, GET"])],
|
||||
["/healthcheck", "OPTIONS", HTTP::respEmpty(204, ['Allow' => "HEAD, GET"])],
|
||||
["/version/", "GET", HTTP::respEmpty(404)],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,10 +14,10 @@ use JKingWeb\Arsse\Context\RootContext;
|
|||
use JKingWeb\Arsse\Context\UnionContext;
|
||||
use JKingWeb\Arsse\User;
|
||||
use JKingWeb\Arsse\Database;
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use JKingWeb\Arsse\Db\Transaction;
|
||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||
use JKingWeb\Arsse\REST\Miniflux\V1;
|
||||
use JKingWeb\Arsse\REST\Miniflux\ErrorResponse;
|
||||
use JKingWeb\Arsse\Feed\Exception as FeedException;
|
||||
use JKingWeb\Arsse\ImportExport\Exception as ImportException;
|
||||
use JKingWeb\Arsse\ImportExport\OPML;
|
||||
|
@ -25,9 +25,6 @@ use JKingWeb\Arsse\User\ExceptionConflict;
|
|||
use JKingWeb\Arsse\User\ExceptionInput as UserExceptionInput;
|
||||
use JKingWeb\Arsse\Test\Result;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\JsonResponse as Response;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
use Laminas\Diactoros\Response\TextResponse;
|
||||
|
||||
/** @covers \JKingWeb\Arsse\REST\Miniflux\V1<extended> */
|
||||
class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||
|
@ -100,9 +97,15 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
return $value;
|
||||
}
|
||||
|
||||
public function testGenerateErrorResponse() {
|
||||
$act = V1::respError(["DuplicateUser", 'user' => "john.doe"], 409, ['Cache-Control' => "no-store"]);
|
||||
$exp = HTTP::respJson(['error_message' => 'The user name "john.doe" already exists'], 409, ['Cache-Control' => "no-store"]);
|
||||
$this->assertMessage($exp, $act);
|
||||
}
|
||||
|
||||
/** @dataProvider provideAuthResponses */
|
||||
public function testAuthenticateAUser($token, bool $auth, bool $success): void {
|
||||
$exp = $success ? new EmptyResponse(404) : new ErrorResponse("401", 401);
|
||||
$exp = $success ? HTTP::respEmpty(404) : V1::respError("401", 401);
|
||||
$user = "john.doe@example.com";
|
||||
if ($token !== null) {
|
||||
$headers = ['X-Auth-Token' => $token];
|
||||
|
@ -133,7 +136,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
/** @dataProvider provideInvalidPaths */
|
||||
public function testRespondToInvalidPaths($path, $method, $code, $allow = null): void {
|
||||
$exp = new EmptyResponse($code, $allow ? ['Allow' => $allow] : []);
|
||||
$exp = HTTP::respEmpty($code, $allow ? ['Allow' => $allow] : []);
|
||||
$this->assertMessage($exp, $this->req($method, $path));
|
||||
}
|
||||
|
||||
|
@ -148,7 +151,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
/** @dataProvider provideOptionsRequests */
|
||||
public function testRespondToOptionsRequests(string $url, string $allow, string $accept): void {
|
||||
$exp = new EmptyResponse(204, [
|
||||
$exp = HTTP::respEmpty(204, [
|
||||
'Allow' => $allow,
|
||||
'Accept' => $accept,
|
||||
]);
|
||||
|
@ -166,7 +169,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
}
|
||||
|
||||
public function testRejectBadlyTypedData(): void {
|
||||
$exp = new ErrorResponse(["InvalidInputType", 'field' => "url", 'expected' => "string", 'actual' => "integer"], 422);
|
||||
$exp = V1::respError(["InvalidInputType", 'field' => "url", 'expected' => "string", 'actual' => "integer"], 422);
|
||||
$this->assertMessage($exp, $this->req("POST", "/discover", ['url' => 2112]));
|
||||
}
|
||||
|
||||
|
@ -182,12 +185,12 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
['title' => "Feed", 'type' => "rss", 'url' => "http://localhost:8000/Feed/Discovery/Missing"],
|
||||
];
|
||||
return [
|
||||
["http://localhost:8000/Feed/Discovery/Valid", new Response($discovered)],
|
||||
["http://localhost:8000/Feed/Discovery/Invalid", new Response([])],
|
||||
["http://localhost:8000/Feed/Discovery/Missing", new ErrorResponse("Fetch404", 502)],
|
||||
[1, new ErrorResponse(["InvalidInputType", 'field' => "url", 'expected' => "string", 'actual' => "integer"], 422)],
|
||||
["Not a URL", new ErrorResponse(["InvalidInputValue", 'field' => "url"], 422)],
|
||||
[null, new ErrorResponse(["MissingInputValue", 'field' => "url"], 422)],
|
||||
["http://localhost:8000/Feed/Discovery/Valid", HTTP::respJson($discovered)],
|
||||
["http://localhost:8000/Feed/Discovery/Invalid", HTTP::respJson([])],
|
||||
["http://localhost:8000/Feed/Discovery/Missing", V1::respError("Fetch404", 502)],
|
||||
[1, V1::respError(["InvalidInputType", 'field' => "url", 'expected' => "string", 'actual' => "integer"], 422)],
|
||||
["Not a URL", V1::respError(["InvalidInputValue", 'field' => "url"], 422)],
|
||||
[null, V1::respError(["MissingInputValue", 'field' => "url"], 422)],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -226,22 +229,22 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
public function provideUserQueries(): iterable {
|
||||
self::clearData();
|
||||
return [
|
||||
[true, "/users", new Response(self::USERS)],
|
||||
[true, "/me", new Response(self::USERS[0])],
|
||||
[true, "/users/john.doe@example.com", new Response(self::USERS[0])],
|
||||
[true, "/users/1", new Response(self::USERS[0])],
|
||||
[true, "/users/jane.doe@example.com", new Response(self::USERS[1])],
|
||||
[true, "/users/2", new Response(self::USERS[1])],
|
||||
[true, "/users/jack.doe@example.com", new ErrorResponse("404", 404)],
|
||||
[true, "/users/47", new ErrorResponse("404", 404)],
|
||||
[false, "/users", new ErrorResponse("403", 403)],
|
||||
[false, "/me", new Response(self::USERS[1])],
|
||||
[false, "/users/john.doe@example.com", new ErrorResponse("403", 403)],
|
||||
[false, "/users/1", new ErrorResponse("403", 403)],
|
||||
[false, "/users/jane.doe@example.com", new ErrorResponse("403", 403)],
|
||||
[false, "/users/2", new ErrorResponse("403", 403)],
|
||||
[false, "/users/jack.doe@example.com", new ErrorResponse("403", 403)],
|
||||
[false, "/users/47", new ErrorResponse("403", 403)],
|
||||
[true, "/users", HTTP::respJson(self::USERS)],
|
||||
[true, "/me", HTTP::respJson(self::USERS[0])],
|
||||
[true, "/users/john.doe@example.com", HTTP::respJson(self::USERS[0])],
|
||||
[true, "/users/1", HTTP::respJson(self::USERS[0])],
|
||||
[true, "/users/jane.doe@example.com", HTTP::respJson(self::USERS[1])],
|
||||
[true, "/users/2", HTTP::respJson(self::USERS[1])],
|
||||
[true, "/users/jack.doe@example.com", V1::respError("404", 404)],
|
||||
[true, "/users/47", V1::respError("404", 404)],
|
||||
[false, "/users", V1::respError("403", 403)],
|
||||
[false, "/me", HTTP::respJson(self::USERS[1])],
|
||||
[false, "/users/john.doe@example.com", V1::respError("403", 403)],
|
||||
[false, "/users/1", V1::respError("403", 403)],
|
||||
[false, "/users/jane.doe@example.com", V1::respError("403", 403)],
|
||||
[false, "/users/2", V1::respError("403", 403)],
|
||||
[false, "/users/jack.doe@example.com", V1::respError("403", 403)],
|
||||
[false, "/users/47", V1::respError("403", 403)],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -306,21 +309,21 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$resp1 = array_merge(self::USERS[1], ['username' => "john.doe@example.com"]);
|
||||
$resp2 = array_merge(self::USERS[1], ['id' => 1, 'is_admin' => true]);
|
||||
return [
|
||||
[false, "/users/1", ['is_admin' => 0], null, null, null, null, null, null, new ErrorResponse(["InvalidInputType", 'field' => "is_admin", 'expected' => "boolean", 'actual' => "integer"], 422)],
|
||||
[false, "/users/1", ['entry_sorting_direction' => "bad"], null, null, null, null, null, null, new ErrorResponse(["InvalidInputValue", 'field' => "entry_sorting_direction"], 422)],
|
||||
[false, "/users/1", ['theme' => "stark"], null, null, null, null, null, null, new ErrorResponse("403", 403)],
|
||||
[false, "/users/2", ['is_admin' => true], null, null, null, null, null, null, new ErrorResponse("InvalidElevation", 403)],
|
||||
[false, "/users/2", ['language' => "fr_CA"], null, null, null, null, ['lang' => "fr_CA"], $out1, new Response($resp1, 201)],
|
||||
[false, "/users/2", ['entry_sorting_direction' => "asc"], null, null, null, null, ['sort_asc' => true], $out1, new Response($resp1, 201)],
|
||||
[false, "/users/2", ['entry_sorting_direction' => "desc"], null, null, null, null, ['sort_asc' => false], $out1, new Response($resp1, 201)],
|
||||
[false, "/users/2", ['entries_per_page' => -1], null, null, null, null, ['page_size' => -1], new UserExceptionInput("invalidNonZeroInteger"), new ErrorResponse(["InvalidInputValue", 'field' => "entries_per_page"], 422)],
|
||||
[false, "/users/2", ['timezone' => "Ook"], null, null, null, null, ['tz' => "Ook"], new UserExceptionInput("invalidTimezone"), new ErrorResponse(["InvalidInputValue", 'field' => "timezone"], 422)],
|
||||
[false, "/users/2", ['username' => "j:k"], "j:k", new UserExceptionInput("invalidUsername"), null, null, null, null, new ErrorResponse(["InvalidInputValue", 'field' => "username"], 422)],
|
||||
[false, "/users/2", ['username' => "ook"], "ook", new ExceptionConflict("alreadyExists"), null, null, null, null, new ErrorResponse(["DuplicateUser", 'user' => "ook"], 409)],
|
||||
[false, "/users/2", ['password' => "ook"], null, null, "ook", "ook", null, null, new Response(array_merge($resp1, ['password' => "ook"]), 201)],
|
||||
[false, "/users/2", ['username' => "ook", 'password' => "ook"], "ook", true, "ook", "ook", null, null, new Response(array_merge($resp1, ['username' => "ook", 'password' => "ook"]), 201)],
|
||||
[true, "/users/1", ['theme' => "stark"], null, null, null, null, ['theme' => "stark"], $out2, new Response($resp2, 201)],
|
||||
[true, "/users/3", ['theme' => "stark"], null, null, null, null, null, null, new ErrorResponse("404", 404)],
|
||||
[false, "/users/1", ['is_admin' => 0], null, null, null, null, null, null, V1::respError(["InvalidInputType", 'field' => "is_admin", 'expected' => "boolean", 'actual' => "integer"], 422)],
|
||||
[false, "/users/1", ['entry_sorting_direction' => "bad"], null, null, null, null, null, null, V1::respError(["InvalidInputValue", 'field' => "entry_sorting_direction"], 422)],
|
||||
[false, "/users/1", ['theme' => "stark"], null, null, null, null, null, null, V1::respError("403", 403)],
|
||||
[false, "/users/2", ['is_admin' => true], null, null, null, null, null, null, V1::respError("InvalidElevation", 403)],
|
||||
[false, "/users/2", ['language' => "fr_CA"], null, null, null, null, ['lang' => "fr_CA"], $out1, HTTP::respJson($resp1, 201)],
|
||||
[false, "/users/2", ['entry_sorting_direction' => "asc"], null, null, null, null, ['sort_asc' => true], $out1, HTTP::respJson($resp1, 201)],
|
||||
[false, "/users/2", ['entry_sorting_direction' => "desc"], null, null, null, null, ['sort_asc' => false], $out1, HTTP::respJson($resp1, 201)],
|
||||
[false, "/users/2", ['entries_per_page' => -1], null, null, null, null, ['page_size' => -1], new UserExceptionInput("invalidNonZeroInteger"), V1::respError(["InvalidInputValue", 'field' => "entries_per_page"], 422)],
|
||||
[false, "/users/2", ['timezone' => "Ook"], null, null, null, null, ['tz' => "Ook"], new UserExceptionInput("invalidTimezone"), V1::respError(["InvalidInputValue", 'field' => "timezone"], 422)],
|
||||
[false, "/users/2", ['username' => "j:k"], "j:k", new UserExceptionInput("invalidUsername"), null, null, null, null, V1::respError(["InvalidInputValue", 'field' => "username"], 422)],
|
||||
[false, "/users/2", ['username' => "ook"], "ook", new ExceptionConflict("alreadyExists"), null, null, null, null, V1::respError(["DuplicateUser", 'user' => "ook"], 409)],
|
||||
[false, "/users/2", ['password' => "ook"], null, null, "ook", "ook", null, null, HTTP::respJson(array_merge($resp1, ['password' => "ook"]), 201)],
|
||||
[false, "/users/2", ['username' => "ook", 'password' => "ook"], "ook", true, "ook", "ook", null, null, HTTP::respJson(array_merge($resp1, ['username' => "ook", 'password' => "ook"]), 201)],
|
||||
[true, "/users/1", ['theme' => "stark"], null, null, null, null, ['theme' => "stark"], $out2, HTTP::respJson($resp2, 201)],
|
||||
[true, "/users/3", ['theme' => "stark"], null, null, null, null, null, null, V1::respError("404", 404)],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -361,18 +364,18 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
public function provideUserAdditions(): iterable {
|
||||
$resp1 = array_merge(self::USERS[1], ['username' => "ook", 'password' => "eek"]);
|
||||
return [
|
||||
[[], null, null, null, null, new ErrorResponse(["MissingInputValue", 'field' => "username"], 422)],
|
||||
[['username' => "ook"], null, null, null, null, new ErrorResponse(["MissingInputValue", 'field' => "password"], 422)],
|
||||
[['username' => "ook", 'password' => "eek"], ["ook", "eek"], new ExceptionConflict("alreadyExists"), null, null, new ErrorResponse(["DuplicateUser", 'user' => "ook"], 409)],
|
||||
[['username' => "j:k", 'password' => "eek"], ["j:k", "eek"], new UserExceptionInput("invalidUsername"), null, null, new ErrorResponse(["InvalidInputValue", 'field' => "username"], 422)],
|
||||
[['username' => "ook", 'password' => "eek", 'timezone' => "ook"], ["ook", "eek"], "eek", ['tz' => "ook"], new UserExceptionInput("invalidTimezone"), new ErrorResponse(["InvalidInputValue", 'field' => "timezone"], 422)],
|
||||
[['username' => "ook", 'password' => "eek", 'entries_per_page' => -1], ["ook", "eek"], "eek", ['page_size' => -1], new UserExceptionInput("invalidNonZeroInteger"), new ErrorResponse(["InvalidInputValue", 'field' => "entries_per_page"], 422)],
|
||||
[['username' => "ook", 'password' => "eek", 'theme' => "default"], ["ook", "eek"], "eek", ['theme' => "default"], ['theme' => "default"], new Response($resp1, 201)],
|
||||
[[], null, null, null, null, V1::respError(["MissingInputValue", 'field' => "username"], 422)],
|
||||
[['username' => "ook"], null, null, null, null, V1::respError(["MissingInputValue", 'field' => "password"], 422)],
|
||||
[['username' => "ook", 'password' => "eek"], ["ook", "eek"], new ExceptionConflict("alreadyExists"), null, null, V1::respError(["DuplicateUser", 'user' => "ook"], 409)],
|
||||
[['username' => "j:k", 'password' => "eek"], ["j:k", "eek"], new UserExceptionInput("invalidUsername"), null, null, V1::respError(["InvalidInputValue", 'field' => "username"], 422)],
|
||||
[['username' => "ook", 'password' => "eek", 'timezone' => "ook"], ["ook", "eek"], "eek", ['tz' => "ook"], new UserExceptionInput("invalidTimezone"), V1::respError(["InvalidInputValue", 'field' => "timezone"], 422)],
|
||||
[['username' => "ook", 'password' => "eek", 'entries_per_page' => -1], ["ook", "eek"], "eek", ['page_size' => -1], new UserExceptionInput("invalidNonZeroInteger"), V1::respError(["InvalidInputValue", 'field' => "entries_per_page"], 422)],
|
||||
[['username' => "ook", 'password' => "eek", 'theme' => "default"], ["ook", "eek"], "eek", ['theme' => "default"], ['theme' => "default"], HTTP::respJson($resp1, 201)],
|
||||
];
|
||||
}
|
||||
|
||||
public function testAddAUserWithoutAuthority(): void {
|
||||
$this->assertMessage(new ErrorResponse("403", 403), $this->req("POST", "/users", []));
|
||||
$this->assertMessage(V1::respError("403", 403), $this->req("POST", "/users", []));
|
||||
}
|
||||
|
||||
public function testDeleteAUser(): void {
|
||||
|
@ -382,7 +385,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
Arsse::$user->method("remove")->willReturn(true);
|
||||
Arsse::$user->expects($this->exactly(1))->method("lookup")->with(2112);
|
||||
Arsse::$user->expects($this->exactly(1))->method("remove")->with("john.doe@example.com");
|
||||
$this->assertMessage(new EmptyResponse(204), $this->req("DELETE", "/users/2112"));
|
||||
$this->assertMessage(HTTP::respEmpty(204), $this->req("DELETE", "/users/2112"));
|
||||
}
|
||||
|
||||
public function testDeleteAMissingUser(): void {
|
||||
|
@ -392,13 +395,13 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
Arsse::$user->method("remove")->willReturn(true);
|
||||
Arsse::$user->expects($this->exactly(1))->method("lookup")->with(2112);
|
||||
Arsse::$user->expects($this->exactly(0))->method("remove");
|
||||
$this->assertMessage(new ErrorResponse("404", 404), $this->req("DELETE", "/users/2112"));
|
||||
$this->assertMessage(V1::respError("404", 404), $this->req("DELETE", "/users/2112"));
|
||||
}
|
||||
|
||||
public function testDeleteAUserWithoutAuthority(): void {
|
||||
Arsse::$user->expects($this->exactly(0))->method("lookup");
|
||||
Arsse::$user->expects($this->exactly(0))->method("remove");
|
||||
$this->assertMessage(new ErrorResponse("403", 403), $this->req("DELETE", "/users/2112"));
|
||||
$this->assertMessage(V1::respError("403", 403), $this->req("DELETE", "/users/2112"));
|
||||
}
|
||||
|
||||
public function testListCategories(): void {
|
||||
|
@ -406,7 +409,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
['id' => 1, 'name' => "Science"],
|
||||
['id' => 20, 'name' => "Technology"],
|
||||
])));
|
||||
$exp = new Response([
|
||||
$exp = HTTP::respJson([
|
||||
['id' => 1, 'title' => "All", 'user_id' => 42],
|
||||
['id' => 2, 'title' => "Science", 'user_id' => 42],
|
||||
['id' => 21, 'title' => "Technology", 'user_id' => 42],
|
||||
|
@ -416,7 +419,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
// run test again with a renamed root folder
|
||||
Arsse::$user = $this->createMock(User::class);
|
||||
Arsse::$user->method("propertiesGet")->willReturn(['num' => 47, 'admin' => false, 'root_folder_name' => "Uncategorized"]);
|
||||
$exp = new Response([
|
||||
$exp = HTTP::respJson([
|
||||
['id' => 1, 'title' => "Uncategorized", 'user_id' => 47],
|
||||
['id' => 2, 'title' => "Science", 'user_id' => 47],
|
||||
['id' => 21, 'title' => "Technology", 'user_id' => 47],
|
||||
|
@ -440,12 +443,12 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
public function provideCategoryAdditions(): iterable {
|
||||
return [
|
||||
["New", new Response(['id' => 2112, 'title' => "New", 'user_id' => 42], 201)],
|
||||
["Duplicate", new ErrorResponse(["DuplicateCategory", 'title' => "Duplicate"], 409)],
|
||||
["", new ErrorResponse(["InvalidCategory", 'title' => ""], 422)],
|
||||
[" ", new ErrorResponse(["InvalidCategory", 'title' => " "], 422)],
|
||||
[null, new ErrorResponse(["MissingInputValue", 'field' => "title"], 422)],
|
||||
[false, new ErrorResponse(["InvalidInputType", 'field' => "title", 'actual' => "boolean", 'expected' => "string"], 422)],
|
||||
["New", HTTP::respJson(['id' => 2112, 'title' => "New", 'user_id' => 42], 201)],
|
||||
["Duplicate", V1::respError(["DuplicateCategory", 'title' => "Duplicate"], 409)],
|
||||
["", V1::respError(["InvalidCategory", 'title' => ""], 422)],
|
||||
[" ", V1::respError(["InvalidCategory", 'title' => " "], 422)],
|
||||
[null, V1::respError(["MissingInputValue", 'field' => "title"], 422)],
|
||||
[false, V1::respError(["InvalidInputType", 'field' => "title", 'actual' => "boolean", 'expected' => "string"], 422)],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -466,27 +469,27 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
public function provideCategoryUpdates(): iterable {
|
||||
return [
|
||||
[3, "New", "subjectMissing", new ErrorResponse("404", 404)],
|
||||
[2, "New", true, new Response(['id' => 2, 'title' => "New", 'user_id' => 42], 201)],
|
||||
[2, "Duplicate", "constraintViolation", new ErrorResponse(["DuplicateCategory", 'title' => "Duplicate"], 409)],
|
||||
[2, "", "missing", new ErrorResponse(["InvalidCategory", 'title' => ""], 422)],
|
||||
[2, " ", "whitespace", new ErrorResponse(["InvalidCategory", 'title' => " "], 422)],
|
||||
[2, null, "missing", new ErrorResponse(["MissingInputValue", 'field' => "title"], 422)],
|
||||
[2, false, "subjectMissing", new ErrorResponse(["InvalidInputType", 'field' => "title", 'actual' => "boolean", 'expected' => "string"], 422)],
|
||||
[1, "New", true, new Response(['id' => 1, 'title' => "New", 'user_id' => 42], 201)],
|
||||
[1, "Duplicate", "constraintViolation", new Response(['id' => 1, 'title' => "Duplicate", 'user_id' => 42], 201)], // This is allowed because the name of the root folder is only a duplicate in circumstances where it is used
|
||||
[1, "", "missing", new ErrorResponse(["InvalidCategory", 'title' => ""], 422)],
|
||||
[1, " ", "whitespace", new ErrorResponse(["InvalidCategory", 'title' => " "], 422)],
|
||||
[1, null, "missing", new ErrorResponse(["MissingInputValue", 'field' => "title"], 422)],
|
||||
[1, false, false, new ErrorResponse(["InvalidInputType", 'field' => "title", 'actual' => "boolean", 'expected' => "string"], 422)],
|
||||
[3, "New", "subjectMissing", V1::respError("404", 404)],
|
||||
[2, "New", true, HTTP::respJson(['id' => 2, 'title' => "New", 'user_id' => 42], 201)],
|
||||
[2, "Duplicate", "constraintViolation", V1::respError(["DuplicateCategory", 'title' => "Duplicate"], 409)],
|
||||
[2, "", "missing", V1::respError(["InvalidCategory", 'title' => ""], 422)],
|
||||
[2, " ", "whitespace", V1::respError(["InvalidCategory", 'title' => " "], 422)],
|
||||
[2, null, "missing", V1::respError(["MissingInputValue", 'field' => "title"], 422)],
|
||||
[2, false, "subjectMissing", V1::respError(["InvalidInputType", 'field' => "title", 'actual' => "boolean", 'expected' => "string"], 422)],
|
||||
[1, "New", true, HTTP::respJson(['id' => 1, 'title' => "New", 'user_id' => 42], 201)],
|
||||
[1, "Duplicate", "constraintViolation", HTTP::respJson(['id' => 1, 'title' => "Duplicate", 'user_id' => 42], 201)], // This is allowed because the name of the root folder is only a duplicate in circumstances where it is used
|
||||
[1, "", "missing", V1::respError(["InvalidCategory", 'title' => ""], 422)],
|
||||
[1, " ", "whitespace", V1::respError(["InvalidCategory", 'title' => " "], 422)],
|
||||
[1, null, "missing", V1::respError(["MissingInputValue", 'field' => "title"], 422)],
|
||||
[1, false, false, V1::respError(["InvalidInputType", 'field' => "title", 'actual' => "boolean", 'expected' => "string"], 422)],
|
||||
];
|
||||
}
|
||||
|
||||
public function testDeleteARealCategory(): void {
|
||||
$this->dbMock->folderRemove->returns(true)->throws(new ExceptionInput("subjectMissing"));
|
||||
$this->assertMessage(new EmptyResponse(204), $this->req("DELETE", "/categories/2112"));
|
||||
$this->assertMessage(HTTP::respEmpty(204), $this->req("DELETE", "/categories/2112"));
|
||||
$this->dbMock->folderRemove->calledWith("john.doe@example.com", 2111);
|
||||
$this->assertMessage(new ErrorResponse("404", 404), $this->req("DELETE", "/categories/47"));
|
||||
$this->assertMessage(V1::respError("404", 404), $this->req("DELETE", "/categories/47"));
|
||||
$this->dbMock->folderRemove->calledWith("john.doe@example.com", 46);
|
||||
}
|
||||
|
||||
|
@ -497,7 +500,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
['id' => 2112],
|
||||
])));
|
||||
$this->dbMock->subscriptionRemove->returns(true);
|
||||
$this->assertMessage(new EmptyResponse(204), $this->req("DELETE", "/categories/1"));
|
||||
$this->assertMessage(HTTP::respEmpty(204), $this->req("DELETE", "/categories/1"));
|
||||
Phony::inOrder(
|
||||
$this->dbMock->begin->calledWith(),
|
||||
$this->dbMock->subscriptionList->calledWith("john.doe@example.com", null, false),
|
||||
|
@ -510,42 +513,42 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
public function testListFeeds(): void {
|
||||
$this->dbMock->subscriptionList->returns(new Result($this->v(self::FEEDS)));
|
||||
$exp = new Response(self::FEEDS_OUT);
|
||||
$exp = HTTP::respJson(self::FEEDS_OUT);
|
||||
$this->assertMessage($exp, $this->req("GET", "/feeds"));
|
||||
}
|
||||
|
||||
public function testListFeedsOfACategory(): void {
|
||||
$this->dbMock->subscriptionList->returns(new Result($this->v(self::FEEDS)));
|
||||
$exp = new Response(self::FEEDS_OUT);
|
||||
$exp = HTTP::respJson(self::FEEDS_OUT);
|
||||
$this->assertMessage($exp, $this->req("GET", "/categories/2112/feeds"));
|
||||
$this->dbMock->subscriptionList->calledWith(Arsse::$user->id, 2111, true);
|
||||
}
|
||||
|
||||
public function testListFeedsOfTheRootCategory(): void {
|
||||
$this->dbMock->subscriptionList->returns(new Result($this->v(self::FEEDS)));
|
||||
$exp = new Response(self::FEEDS_OUT);
|
||||
$exp = HTTP::respJson(self::FEEDS_OUT);
|
||||
$this->assertMessage($exp, $this->req("GET", "/categories/1/feeds"));
|
||||
$this->dbMock->subscriptionList->calledWith(Arsse::$user->id, 0, false);
|
||||
}
|
||||
|
||||
public function testListFeedsOfAMissingCategory(): void {
|
||||
$this->dbMock->subscriptionList->throws(new ExceptionInput("idMissing"));
|
||||
$exp = new ErrorResponse("404", 404);
|
||||
$exp = V1::respError("404", 404);
|
||||
$this->assertMessage($exp, $this->req("GET", "/categories/2112/feeds"));
|
||||
$this->dbMock->subscriptionList->calledWith(Arsse::$user->id, 2111, true);
|
||||
}
|
||||
|
||||
public function testGetAFeed(): void {
|
||||
$this->dbMock->subscriptionPropertiesGet->returns($this->v(self::FEEDS[0]))->returns($this->v(self::FEEDS[1]));
|
||||
$this->assertMessage(new Response(self::FEEDS_OUT[0]), $this->req("GET", "/feeds/1"));
|
||||
$this->assertMessage(HTTP::respJson(self::FEEDS_OUT[0]), $this->req("GET", "/feeds/1"));
|
||||
$this->dbMock->subscriptionPropertiesGet->calledWith(Arsse::$user->id, 1);
|
||||
$this->assertMessage(new Response(self::FEEDS_OUT[1]), $this->req("GET", "/feeds/55"));
|
||||
$this->assertMessage(HTTP::respJson(self::FEEDS_OUT[1]), $this->req("GET", "/feeds/55"));
|
||||
$this->dbMock->subscriptionPropertiesGet->calledWith(Arsse::$user->id, 55);
|
||||
}
|
||||
|
||||
public function testGetAMissingFeed(): void {
|
||||
$this->dbMock->subscriptionPropertiesGet->throws(new ExceptionInput("subjectMissing"));
|
||||
$this->assertMessage(new ErrorResponse("404", 404), $this->req("GET", "/feeds/1"));
|
||||
$this->assertMessage(V1::respError("404", 404), $this->req("GET", "/feeds/1"));
|
||||
$this->dbMock->subscriptionPropertiesGet->calledWith(Arsse::$user->id, 1);
|
||||
}
|
||||
|
||||
|
@ -611,39 +614,39 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
public function provideFeedCreations(): iterable {
|
||||
self::clearData();
|
||||
return [
|
||||
[['category_id' => 1], null, null, null, null, new ErrorResponse(["MissingInputValue", 'field' => "feed_url"], 422)],
|
||||
[['feed_url' => "http://example.com/"], null, null, null, null, new ErrorResponse(["MissingInputValue", 'field' => "category_id"], 422)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => "1"], null, null, null, null, new ErrorResponse(["InvalidInputType", 'field' => "category_id", 'expected' => "integer", 'actual' => "string"], 422)],
|
||||
[['feed_url' => "Not a URL", 'category_id' => 1], null, null, null, null, new ErrorResponse(["InvalidInputValue", 'field' => "feed_url"], 422)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 0], null, null, null, null, new ErrorResponse(["InvalidInputValue", 'field' => "category_id"], 422)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1, 'keeplist_rules' => "["], null, null, null, null, new ErrorResponse(["InvalidInputValue", 'field' => "keeplist_rules"], 422)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1, 'blocklist_rules' => "["], null, null, null, null, new ErrorResponse(["InvalidInputValue", 'field' => "blocklist_rules"], 422)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("internalError"), null, null, null, new ErrorResponse("FetchOther", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("invalidCertificate"), null, null, null, new ErrorResponse("FetchOther", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("invalidUrl"), null, null, null, new ErrorResponse("Fetch404", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("maxRedirect"), null, null, null, new ErrorResponse("FetchOther", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("maxSize"), null, null, null, new ErrorResponse("FetchOther", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("timeout"), null, null, null, new ErrorResponse("FetchOther", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("forbidden"), null, null, null, new ErrorResponse("Fetch403", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("unauthorized"), null, null, null, new ErrorResponse("Fetch401", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("transmissionError"), null, null, null, new ErrorResponse("FetchOther", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("connectionFailed"), null, null, null, new ErrorResponse("FetchOther", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("malformedXml"), null, null, null, new ErrorResponse("FetchOther", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("xmlEntity"), null, null, null, new ErrorResponse("FetchOther", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("subscriptionNotFound"), null, null, null, new ErrorResponse("Fetch404", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("unsupportedFeedFormat"), null, null, null, new ErrorResponse("FetchFormat", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], 2112, new ExceptionInput("constraintViolation"), null, null, new ErrorResponse("DuplicateFeed", 409)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], 2112, 44, new ExceptionInput("idMissing"), null, new ErrorResponse("MissingCategory", 422)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], 2112, 44, true, null, new Response(['feed_id' => 44], 201)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1, 'keeplist_rules' => "^A"], 2112, 44, true, true, new Response(['feed_id' => 44], 201)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1, 'blocklist_rules' => "A"], 2112, 44, true, true, new Response(['feed_id' => 44], 201)],
|
||||
[['category_id' => 1], null, null, null, null, V1::respError(["MissingInputValue", 'field' => "feed_url"], 422)],
|
||||
[['feed_url' => "http://example.com/"], null, null, null, null, V1::respError(["MissingInputValue", 'field' => "category_id"], 422)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => "1"], null, null, null, null, V1::respError(["InvalidInputType", 'field' => "category_id", 'expected' => "integer", 'actual' => "string"], 422)],
|
||||
[['feed_url' => "Not a URL", 'category_id' => 1], null, null, null, null, V1::respError(["InvalidInputValue", 'field' => "feed_url"], 422)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 0], null, null, null, null, V1::respError(["InvalidInputValue", 'field' => "category_id"], 422)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1, 'keeplist_rules' => "["], null, null, null, null, V1::respError(["InvalidInputValue", 'field' => "keeplist_rules"], 422)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1, 'blocklist_rules' => "["], null, null, null, null, V1::respError(["InvalidInputValue", 'field' => "blocklist_rules"], 422)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("internalError"), null, null, null, V1::respError("FetchOther", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("invalidCertificate"), null, null, null, V1::respError("FetchOther", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("invalidUrl"), null, null, null, V1::respError("Fetch404", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("maxRedirect"), null, null, null, V1::respError("FetchOther", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("maxSize"), null, null, null, V1::respError("FetchOther", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("timeout"), null, null, null, V1::respError("FetchOther", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("forbidden"), null, null, null, V1::respError("Fetch403", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("unauthorized"), null, null, null, V1::respError("Fetch401", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("transmissionError"), null, null, null, V1::respError("FetchOther", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("connectionFailed"), null, null, null, V1::respError("FetchOther", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("malformedXml"), null, null, null, V1::respError("FetchOther", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("xmlEntity"), null, null, null, V1::respError("FetchOther", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("subscriptionNotFound"), null, null, null, V1::respError("Fetch404", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], new FeedException("unsupportedFeedFormat"), null, null, null, V1::respError("FetchFormat", 502)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], 2112, new ExceptionInput("constraintViolation"), null, null, V1::respError("DuplicateFeed", 409)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], 2112, 44, new ExceptionInput("idMissing"), null, V1::respError("MissingCategory", 422)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1], 2112, 44, true, null, HTTP::respJson(['feed_id' => 44], 201)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1, 'keeplist_rules' => "^A"], 2112, 44, true, true, HTTP::respJson(['feed_id' => 44], 201)],
|
||||
[['feed_url' => "http://example.com/", 'category_id' => 1, 'blocklist_rules' => "A"], 2112, 44, true, true, HTTP::respJson(['feed_id' => 44], 201)],
|
||||
];
|
||||
}
|
||||
|
||||
/** @dataProvider provideFeedModifications */
|
||||
public function testModifyAFeed(array $in, array $data, $out, ResponseInterface $exp): void {
|
||||
$this->h = $this->partialMock(V1::class);
|
||||
$this->h->getFeed->returns(new Response(self::FEEDS_OUT[0]));
|
||||
$this->h->getFeed->returns(HTTP::respJson(self::FEEDS_OUT[0]));
|
||||
if ($out instanceof \Exception) {
|
||||
$this->dbMock->subscriptionPropertiesSet->throws($out);
|
||||
} else {
|
||||
|
@ -655,14 +658,14 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
public function provideFeedModifications(): iterable {
|
||||
self::clearData();
|
||||
$success = new Response(self::FEEDS_OUT[0], 201);
|
||||
$success = HTTP::respJson(self::FEEDS_OUT[0], 201);
|
||||
return [
|
||||
[[], [], true, $success],
|
||||
[[], [], new ExceptionInput("subjectMissing"), new ErrorResponse("404", 404)],
|
||||
[['title' => ""], ['title' => ""], new ExceptionInput("missing"), new ErrorResponse("InvalidTitle", 422)],
|
||||
[['title' => " "], ['title' => " "], new ExceptionInput("whitespace"), new ErrorResponse("InvalidTitle", 422)],
|
||||
[['title' => " "], ['title' => " "], new ExceptionInput("whitespace"), new ErrorResponse("InvalidTitle", 422)],
|
||||
[['category_id' => 47], ['folder' => 46], new ExceptionInput("idMissing"), new ErrorResponse("MissingCategory", 422)],
|
||||
[[], [], new ExceptionInput("subjectMissing"), V1::respError("404", 404)],
|
||||
[['title' => ""], ['title' => ""], new ExceptionInput("missing"), V1::respError("InvalidTitle", 422)],
|
||||
[['title' => " "], ['title' => " "], new ExceptionInput("whitespace"), V1::respError("InvalidTitle", 422)],
|
||||
[['title' => " "], ['title' => " "], new ExceptionInput("whitespace"), V1::respError("InvalidTitle", 422)],
|
||||
[['category_id' => 47], ['folder' => 46], new ExceptionInput("idMissing"), V1::respError("MissingCategory", 422)],
|
||||
[['crawler' => false], ['scrape' => false], true, $success],
|
||||
[['keeplist_rules' => ""], ['keep_rule' => ""], true, $success],
|
||||
[['blocklist_rules' => "ook"], ['block_rule' => "ook"], true, $success],
|
||||
|
@ -672,21 +675,21 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
public function testModifyAFeedWithNoBody(): void {
|
||||
$this->h = $this->partialMock(V1::class);
|
||||
$this->h->getFeed->returns(new Response(self::FEEDS_OUT[0]));
|
||||
$this->h->getFeed->returns(HTTP::respJson(self::FEEDS_OUT[0]));
|
||||
$this->dbMock->subscriptionPropertiesSet->returns(true);
|
||||
$this->assertMessage(new Response(self::FEEDS_OUT[0], 201), $this->req("PUT", "/feeds/2112", ""));
|
||||
$this->assertMessage(HTTP::respJson(self::FEEDS_OUT[0], 201), $this->req("PUT", "/feeds/2112", ""));
|
||||
$this->dbMock->subscriptionPropertiesSet->calledWith(Arsse::$user->id, 2112, []);
|
||||
}
|
||||
|
||||
public function testDeleteAFeed(): void {
|
||||
$this->dbMock->subscriptionRemove->returns(true);
|
||||
$this->assertMessage(new EmptyResponse(204), $this->req("DELETE", "/feeds/2112"));
|
||||
$this->assertMessage(HTTP::respEmpty(204), $this->req("DELETE", "/feeds/2112"));
|
||||
$this->dbMock->subscriptionRemove->calledWith(Arsse::$user->id, 2112);
|
||||
}
|
||||
|
||||
public function testDeleteAMissingFeed(): void {
|
||||
$this->dbMock->subscriptionRemove->throws(new ExceptionInput("subjectMissing"));
|
||||
$this->assertMessage(new ErrorResponse("404", 404), $this->req("DELETE", "/feeds/2112"));
|
||||
$this->assertMessage(V1::respError("404", 404), $this->req("DELETE", "/feeds/2112"));
|
||||
$this->dbMock->subscriptionRemove->calledWith(Arsse::$user->id, 2112);
|
||||
}
|
||||
|
||||
|
@ -703,12 +706,12 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
public function provideIcons(): iterable {
|
||||
return [
|
||||
[['id' => 44, 'type' => "image/svg+xml", 'data' => "<svg/>"], new Response(['id' => 44, 'data' => "image/svg+xml;base64,PHN2Zy8+", 'mime_type' => "image/svg+xml"])],
|
||||
[['id' => 47, 'type' => "", 'data' => "<svg/>"], new ErrorResponse("404", 404)],
|
||||
[['id' => 47, 'type' => null, 'data' => "<svg/>"], new ErrorResponse("404", 404)],
|
||||
[['id' => 47, 'type' => null, 'data' => null], new ErrorResponse("404", 404)],
|
||||
[null, new ErrorResponse("404", 404)],
|
||||
[new ExceptionInput("subjectMissing"), new ErrorResponse("404", 404)],
|
||||
[['id' => 44, 'type' => "image/svg+xml", 'data' => "<svg/>"], HTTP::respJson(['id' => 44, 'data' => "image/svg+xml;base64,PHN2Zy8+", 'mime_type' => "image/svg+xml"])],
|
||||
[['id' => 47, 'type' => "", 'data' => "<svg/>"], V1::respError("404", 404)],
|
||||
[['id' => 47, 'type' => null, 'data' => "<svg/>"], V1::respError("404", 404)],
|
||||
[['id' => 47, 'type' => null, 'data' => null], V1::respError("404", 404)],
|
||||
[null, V1::respError("404", 404)],
|
||||
[new ExceptionInput("subjectMissing"), V1::respError("404", 404)],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -744,62 +747,62 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$c = (new Context)->limit(100);
|
||||
$o = ["modified_date"]; // the default sort order
|
||||
return [
|
||||
["/entries?after=A", null, null, [], false, new ErrorResponse(["InvalidInputValue", 'field' => "after"], 400)],
|
||||
["/entries?before=B", null, null, [], false, new ErrorResponse(["InvalidInputValue", 'field' => "before"], 400)],
|
||||
["/entries?category_id=0", null, null, [], false, new ErrorResponse(["InvalidInputValue", 'field' => "category_id"], 400)],
|
||||
["/entries?after_entry_id=0", null, null, [], false, new ErrorResponse(["InvalidInputValue", 'field' => "after_entry_id"], 400)],
|
||||
["/entries?before_entry_id=0", null, null, [], false, new ErrorResponse(["InvalidInputValue", 'field' => "before_entry_id"], 400)],
|
||||
["/entries?limit=-1", null, null, [], false, new ErrorResponse(["InvalidInputValue", 'field' => "limit"], 400)],
|
||||
["/entries?offset=-1", null, null, [], false, new ErrorResponse(["InvalidInputValue", 'field' => "offset"], 400)],
|
||||
["/entries?direction=sideways", null, null, [], false, new ErrorResponse(["InvalidInputValue", 'field' => "direction"], 400)],
|
||||
["/entries?order=false", null, null, [], false, new ErrorResponse(["InvalidInputValue", 'field' => "order"], 400)],
|
||||
["/entries?starred&starred", null, null, [], false, new ErrorResponse(["DuplicateInputValue", 'field' => "starred"], 400)],
|
||||
["/entries?after&after=0", null, null, [], false, new ErrorResponse(["DuplicateInputValue", 'field' => "after"], 400)],
|
||||
["/entries", $c, $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?category_id=47", (clone $c)->folder(46), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?category_id=1", (clone $c)->folderShallow(0), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?status=unread", (clone $c)->unread(true)->hidden(false), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?status=read", (clone $c)->unread(false)->hidden(false), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?status=removed", (clone $c)->hidden(true), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?status=unread&status=read", (clone $c)->hidden(false), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?status=unread&status=removed", new UnionContext((clone $c)->unread(true), (clone $c)->hidden(true)), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?status=removed&status=read", new UnionContext((clone $c)->unread(false), (clone $c)->hidden(true)), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?status=removed&status=read&status=removed", new UnionContext((clone $c)->unread(false), (clone $c)->hidden(true)), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?status=removed&status=read&status=unread", $c, $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?starred", (clone $c)->starred(true), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?starred=", (clone $c)->starred(true), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?starred=true", (clone $c)->starred(true), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?starred=false", (clone $c)->starred(true), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?after=0", (clone $c)->modifiedRange(0, null), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?before=0", $c, $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?before=1", (clone $c)->modifiedRange(null, 1), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?before=1&after=0", (clone $c)->modifiedRange(0, 1), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?after_entry_id=42", (clone $c)->articleRange(43, null), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?before_entry_id=47", (clone $c)->articleRange(null, 46), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?search=alpha%20beta", (clone $c)->searchTerms(["alpha", "beta"]), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?limit=4", (clone $c)->limit(4), $o, self::ENTRIES, true, new Response(['total' => 2112, 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?offset=20", (clone $c)->offset(20), $o, [], true, new Response(['total' => 2112, 'entries' => []])],
|
||||
["/entries?direction=asc", $c, $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?order=id", $c, ["id"], self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?order=published_at", $c, ["modified_date"], self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?order=category_id", $c, ["top_folder"], self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?order=category_title", $c, ["top_folder_name"], self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?order=status", $c, ["hidden", "unread desc"], self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?direction=desc", $c, ["modified_date desc"], self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?order=id&direction=desc", $c, ["id desc"], self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?order=published_at&direction=desc", $c, ["modified_date desc"], self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?order=category_id&direction=desc", $c, ["top_folder desc"], self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?order=category_title&direction=desc", $c, ["top_folder_name desc"], self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?order=status&direction=desc", $c, ["hidden desc", "unread"], self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?category_id=2112", (clone $c)->folder(2111), $o, new ExceptionInput("idMissing"), false, new ErrorResponse("MissingCategory")],
|
||||
["/feeds/42/entries", (clone $c)->subscription(42), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/feeds/42/entries?category_id=47", (clone $c)->subscription(42)->folder(46), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/feeds/2112/entries", (clone $c)->subscription(2112), $o, new ExceptionInput("idMissing"), false, new ErrorResponse("404", 404)],
|
||||
["/categories/42/entries", (clone $c)->folder(41), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/categories/42/entries?category_id=47", (clone $c)->folder(41), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/categories/42/entries?starred", (clone $c)->folder(41)->starred(true), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/categories/1/entries", (clone $c)->folderShallow(0), $o, self::ENTRIES, false, new Response(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/categories/2112/entries", (clone $c)->folder(2111), $o, new ExceptionInput("idMissing"), false, new ErrorResponse("404", 404)],
|
||||
["/entries?after=A", null, null, [], false, V1::respError(["InvalidInputValue", 'field' => "after"], 400)],
|
||||
["/entries?before=B", null, null, [], false, V1::respError(["InvalidInputValue", 'field' => "before"], 400)],
|
||||
["/entries?category_id=0", null, null, [], false, V1::respError(["InvalidInputValue", 'field' => "category_id"], 400)],
|
||||
["/entries?after_entry_id=0", null, null, [], false, V1::respError(["InvalidInputValue", 'field' => "after_entry_id"], 400)],
|
||||
["/entries?before_entry_id=0", null, null, [], false, V1::respError(["InvalidInputValue", 'field' => "before_entry_id"], 400)],
|
||||
["/entries?limit=-1", null, null, [], false, V1::respError(["InvalidInputValue", 'field' => "limit"], 400)],
|
||||
["/entries?offset=-1", null, null, [], false, V1::respError(["InvalidInputValue", 'field' => "offset"], 400)],
|
||||
["/entries?direction=sideways", null, null, [], false, V1::respError(["InvalidInputValue", 'field' => "direction"], 400)],
|
||||
["/entries?order=false", null, null, [], false, V1::respError(["InvalidInputValue", 'field' => "order"], 400)],
|
||||
["/entries?starred&starred", null, null, [], false, V1::respError(["DuplicateInputValue", 'field' => "starred"], 400)],
|
||||
["/entries?after&after=0", null, null, [], false, V1::respError(["DuplicateInputValue", 'field' => "after"], 400)],
|
||||
["/entries", $c, $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?category_id=47", (clone $c)->folder(46), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?category_id=1", (clone $c)->folderShallow(0), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?status=unread", (clone $c)->unread(true)->hidden(false), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?status=read", (clone $c)->unread(false)->hidden(false), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?status=removed", (clone $c)->hidden(true), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?status=unread&status=read", (clone $c)->hidden(false), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?status=unread&status=removed", new UnionContext((clone $c)->unread(true), (clone $c)->hidden(true)), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?status=removed&status=read", new UnionContext((clone $c)->unread(false), (clone $c)->hidden(true)), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?status=removed&status=read&status=removed", new UnionContext((clone $c)->unread(false), (clone $c)->hidden(true)), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?status=removed&status=read&status=unread", $c, $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?starred", (clone $c)->starred(true), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?starred=", (clone $c)->starred(true), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?starred=true", (clone $c)->starred(true), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?starred=false", (clone $c)->starred(true), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?after=0", (clone $c)->modifiedRange(0, null), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?before=0", $c, $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?before=1", (clone $c)->modifiedRange(null, 1), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?before=1&after=0", (clone $c)->modifiedRange(0, 1), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?after_entry_id=42", (clone $c)->articleRange(43, null), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?before_entry_id=47", (clone $c)->articleRange(null, 46), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?search=alpha%20beta", (clone $c)->searchTerms(["alpha", "beta"]), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?limit=4", (clone $c)->limit(4), $o, self::ENTRIES, true, HTTP::respJson(['total' => 2112, 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?offset=20", (clone $c)->offset(20), $o, [], true, HTTP::respJson(['total' => 2112, 'entries' => []])],
|
||||
["/entries?direction=asc", $c, $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?order=id", $c, ["id"], self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?order=published_at", $c, ["modified_date"], self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?order=category_id", $c, ["top_folder"], self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?order=category_title", $c, ["top_folder_name"], self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?order=status", $c, ["hidden", "unread desc"], self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?direction=desc", $c, ["modified_date desc"], self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?order=id&direction=desc", $c, ["id desc"], self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?order=published_at&direction=desc", $c, ["modified_date desc"], self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?order=category_id&direction=desc", $c, ["top_folder desc"], self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?order=category_title&direction=desc", $c, ["top_folder_name desc"], self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?order=status&direction=desc", $c, ["hidden desc", "unread"], self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/entries?category_id=2112", (clone $c)->folder(2111), $o, new ExceptionInput("idMissing"), false, V1::respError("MissingCategory")],
|
||||
["/feeds/42/entries", (clone $c)->subscription(42), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/feeds/42/entries?category_id=47", (clone $c)->subscription(42)->folder(46), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/feeds/2112/entries", (clone $c)->subscription(2112), $o, new ExceptionInput("idMissing"), false, V1::respError("404", 404)],
|
||||
["/categories/42/entries", (clone $c)->folder(41), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/categories/42/entries?category_id=47", (clone $c)->folder(41), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/categories/42/entries?starred", (clone $c)->folder(41)->starred(true), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/categories/1/entries", (clone $c)->folderShallow(0), $o, self::ENTRIES, false, HTTP::respJson(['total' => sizeof(self::ENTRIES_OUT), 'entries' => self::ENTRIES_OUT])],
|
||||
["/categories/2112/entries", (clone $c)->folder(2111), $o, new ExceptionInput("idMissing"), false, V1::respError("404", 404)],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -828,17 +831,17 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
self::clearData();
|
||||
$c = new Context;
|
||||
return [
|
||||
["/entries/42", (clone $c)->article(42), [self::ENTRIES[1]], new Response(self::ENTRIES_OUT[1])],
|
||||
["/entries/2112", (clone $c)->article(2112), new ExceptionInput("subjectMissing"), new ErrorResponse("404", 404)],
|
||||
["/feeds/47/entries/42", (clone $c)->subscription(47)->article(42), [self::ENTRIES[1]], new Response(self::ENTRIES_OUT[1])],
|
||||
["/feeds/47/entries/44", (clone $c)->subscription(47)->article(44), [], new ErrorResponse("404", 404)],
|
||||
["/feeds/47/entries/2112", (clone $c)->subscription(47)->article(2112), new ExceptionInput("subjectMissing"), new ErrorResponse("404", 404)],
|
||||
["/feeds/2112/entries/47", (clone $c)->subscription(2112)->article(47), new ExceptionInput("idMissing"), new ErrorResponse("404", 404)],
|
||||
["/categories/47/entries/42", (clone $c)->folder(46)->article(42), [self::ENTRIES[1]], new Response(self::ENTRIES_OUT[1])],
|
||||
["/categories/47/entries/44", (clone $c)->folder(46)->article(44), [], new ErrorResponse("404", 404)],
|
||||
["/categories/47/entries/2112", (clone $c)->folder(46)->article(2112), new ExceptionInput("subjectMissing"), new ErrorResponse("404", 404)],
|
||||
["/categories/2112/entries/47", (clone $c)->folder(2111)->article(47), new ExceptionInput("idMissing"), new ErrorResponse("404", 404)],
|
||||
["/categories/1/entries/42", (clone $c)->folderShallow(0)->article(42), [self::ENTRIES[1]], new Response(self::ENTRIES_OUT[1])],
|
||||
["/entries/42", (clone $c)->article(42), [self::ENTRIES[1]], HTTP::respJson(self::ENTRIES_OUT[1])],
|
||||
["/entries/2112", (clone $c)->article(2112), new ExceptionInput("subjectMissing"), V1::respError("404", 404)],
|
||||
["/feeds/47/entries/42", (clone $c)->subscription(47)->article(42), [self::ENTRIES[1]], HTTP::respJson(self::ENTRIES_OUT[1])],
|
||||
["/feeds/47/entries/44", (clone $c)->subscription(47)->article(44), [], V1::respError("404", 404)],
|
||||
["/feeds/47/entries/2112", (clone $c)->subscription(47)->article(2112), new ExceptionInput("subjectMissing"), V1::respError("404", 404)],
|
||||
["/feeds/2112/entries/47", (clone $c)->subscription(2112)->article(47), new ExceptionInput("idMissing"), V1::respError("404", 404)],
|
||||
["/categories/47/entries/42", (clone $c)->folder(46)->article(42), [self::ENTRIES[1]], HTTP::respJson(self::ENTRIES_OUT[1])],
|
||||
["/categories/47/entries/44", (clone $c)->folder(46)->article(44), [], V1::respError("404", 404)],
|
||||
["/categories/47/entries/2112", (clone $c)->folder(46)->article(2112), new ExceptionInput("subjectMissing"), V1::respError("404", 404)],
|
||||
["/categories/2112/entries/47", (clone $c)->folder(2111)->article(47), new ExceptionInput("idMissing"), V1::respError("404", 404)],
|
||||
["/categories/1/entries/42", (clone $c)->folderShallow(0)->article(42), [self::ENTRIES[1]], HTTP::respJson(self::ENTRIES_OUT[1])],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -856,17 +859,17 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
public function provideEntryMarkings(): iterable {
|
||||
self::clearData();
|
||||
return [
|
||||
[['status' => "read"], null, new ErrorResponse(["MissingInputValue", 'field' => "entry_ids"], 422)],
|
||||
[['entry_ids' => [1]], null, new ErrorResponse(["MissingInputValue", 'field' => "status"], 422)],
|
||||
[['entry_ids' => [], 'status' => "read"], null, new ErrorResponse(["MissingInputValue", 'field' => "entry_ids"], 422)],
|
||||
[['entry_ids' => 1, 'status' => "read"], null, new ErrorResponse(["InvalidInputType", 'field' => "entry_ids", 'expected' => "array", 'actual' => "integer"], 422)],
|
||||
[['entry_ids' => ["1"], 'status' => "read"], null, new ErrorResponse(["InvalidInputType", 'field' => "entry_ids", 'expected' => "integer", 'actual' => "string"], 422)],
|
||||
[['entry_ids' => [1], 'status' => 1], null, new ErrorResponse(["InvalidInputType", 'field' => "status", 'expected' => "string", 'actual' => "integer"], 422)],
|
||||
[['entry_ids' => [0], 'status' => "read"], null, new ErrorResponse(["InvalidInputValue", 'field' => "entry_ids"], 422)],
|
||||
[['entry_ids' => [1], 'status' => "reread"], null, new ErrorResponse(["InvalidInputValue", 'field' => "status"], 422)],
|
||||
[['entry_ids' => [1, 2], 'status' => "read"], ['read' => true, 'hidden' => false], new EmptyResponse(204)],
|
||||
[['entry_ids' => [1, 2], 'status' => "unread"], ['read' => false, 'hidden' => false], new EmptyResponse(204)],
|
||||
[['entry_ids' => [1, 2], 'status' => "removed"], ['read' => true, 'hidden' => true], new EmptyResponse(204)],
|
||||
[['status' => "read"], null, V1::respError(["MissingInputValue", 'field' => "entry_ids"], 422)],
|
||||
[['entry_ids' => [1]], null, V1::respError(["MissingInputValue", 'field' => "status"], 422)],
|
||||
[['entry_ids' => [], 'status' => "read"], null, V1::respError(["MissingInputValue", 'field' => "entry_ids"], 422)],
|
||||
[['entry_ids' => 1, 'status' => "read"], null, V1::respError(["InvalidInputType", 'field' => "entry_ids", 'expected' => "array", 'actual' => "integer"], 422)],
|
||||
[['entry_ids' => ["1"], 'status' => "read"], null, V1::respError(["InvalidInputType", 'field' => "entry_ids", 'expected' => "integer", 'actual' => "string"], 422)],
|
||||
[['entry_ids' => [1], 'status' => 1], null, V1::respError(["InvalidInputType", 'field' => "status", 'expected' => "string", 'actual' => "integer"], 422)],
|
||||
[['entry_ids' => [0], 'status' => "read"], null, V1::respError(["InvalidInputValue", 'field' => "entry_ids"], 422)],
|
||||
[['entry_ids' => [1], 'status' => "reread"], null, V1::respError(["InvalidInputValue", 'field' => "status"], 422)],
|
||||
[['entry_ids' => [1, 2], 'status' => "read"], ['read' => true, 'hidden' => false], HTTP::respEmpty(204)],
|
||||
[['entry_ids' => [1, 2], 'status' => "unread"], ['read' => false, 'hidden' => false], HTTP::respEmpty(204)],
|
||||
[['entry_ids' => [1, 2], 'status' => "removed"], ['read' => true, 'hidden' => true], HTTP::respEmpty(204)],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -889,13 +892,13 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
self::clearData();
|
||||
$c = (new Context)->hidden(false);
|
||||
return [
|
||||
["/users/42/mark-all-as-read", $c, 1123, new EmptyResponse(204)],
|
||||
["/users/2112/mark-all-as-read", $c, null, new ErrorResponse("403", 403)],
|
||||
["/feeds/47/mark-all-as-read", (clone $c)->subscription(47), 2112, new EmptyResponse(204)],
|
||||
["/feeds/2112/mark-all-as-read", (clone $c)->subscription(2112), new ExceptionInput("idMissing"), new ErrorResponse("404", 404)],
|
||||
["/categories/47/mark-all-as-read", (clone $c)->folder(46), 1337, new EmptyResponse(204)],
|
||||
["/categories/2112/mark-all-as-read", (clone $c)->folder(2111), new ExceptionInput("idMissing"), new ErrorResponse("404", 404)],
|
||||
["/categories/1/mark-all-as-read", (clone $c)->folderShallow(0), 6666, new EmptyResponse(204)],
|
||||
["/users/42/mark-all-as-read", $c, 1123, HTTP::respEmpty(204)],
|
||||
["/users/2112/mark-all-as-read", $c, null, V1::respError("403", 403)],
|
||||
["/feeds/47/mark-all-as-read", (clone $c)->subscription(47), 2112, HTTP::respEmpty(204)],
|
||||
["/feeds/2112/mark-all-as-read", (clone $c)->subscription(2112), new ExceptionInput("idMissing"), V1::respError("404", 404)],
|
||||
["/categories/47/mark-all-as-read", (clone $c)->folder(46), 1337, HTTP::respEmpty(204)],
|
||||
["/categories/2112/mark-all-as-read", (clone $c)->folder(2111), new ExceptionInput("idMissing"), V1::respError("404", 404)],
|
||||
["/categories/1/mark-all-as-read", (clone $c)->folderShallow(0), 6666, HTTP::respEmpty(204)],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -929,26 +932,26 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
public function provideBookmarkTogglings(): iterable {
|
||||
self::clearData();
|
||||
return [
|
||||
[1, true, new EmptyResponse(204)],
|
||||
[0, false, new EmptyResponse(204)],
|
||||
[new ExceptionInput("subjectMissing"), null, new ErrorResponse("404", 404)],
|
||||
[1, true, HTTP::respEmpty(204)],
|
||||
[0, false, HTTP::respEmpty(204)],
|
||||
[new ExceptionInput("subjectMissing"), null, V1::respError("404", 404)],
|
||||
];
|
||||
}
|
||||
|
||||
public function testRefreshAFeed(): void {
|
||||
$this->dbMock->subscriptionPropertiesGet->returns([]);
|
||||
$this->assertMessage(new EmptyResponse(204), $this->req("PUT", "/feeds/47/refresh"));
|
||||
$this->assertMessage(HTTP::respEmpty(204), $this->req("PUT", "/feeds/47/refresh"));
|
||||
$this->dbMock->subscriptionPropertiesGet->calledWith(Arsse::$user->id, 47);
|
||||
}
|
||||
|
||||
public function testRefreshAMissingFeed(): void {
|
||||
$this->dbMock->subscriptionPropertiesGet->throws(new ExceptionInput("subjectMissing"));
|
||||
$this->assertMessage(new ErrorResponse("404", 404), $this->req("PUT", "/feeds/2112/refresh"));
|
||||
$this->assertMessage(V1::respError("404", 404), $this->req("PUT", "/feeds/2112/refresh"));
|
||||
$this->dbMock->subscriptionPropertiesGet->calledWith(Arsse::$user->id, 2112);
|
||||
}
|
||||
|
||||
public function testRefreshAllFeeds(): void {
|
||||
$this->assertMessage(new EmptyResponse(204), $this->req("PUT", "/feeds/refresh"));
|
||||
$this->assertMessage(HTTP::respEmpty(204), $this->req("PUT", "/feeds/refresh"));
|
||||
}
|
||||
|
||||
/** @dataProvider provideImports */
|
||||
|
@ -964,21 +967,21 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
public function provideImports(): iterable {
|
||||
self::clearData();
|
||||
return [
|
||||
[new ImportException("invalidSyntax"), new ErrorResponse("InvalidBodyXML", 400)],
|
||||
[new ImportException("invalidSemantics"), new ErrorResponse("InvalidBodyOPML", 422)],
|
||||
[new ImportException("invalidFolderName"), new ErrorResponse("InvalidImportCategory", 422)],
|
||||
[new ImportException("invalidFolderCopy"), new ErrorResponse("DuplicateImportCategory", 422)],
|
||||
[new ImportException("invalidTagName"), new ErrorResponse("InvalidImportLabel", 422)],
|
||||
[new FeedException("invalidUrl", ['url' => "http://example.com/"]), new ErrorResponse(["FailedImportFeed", 'url' => "http://example.com/", 'code' => 10502], 502)],
|
||||
[true, new Response(['message' => Arsse::$lang->msg("API.Miniflux.ImportSuccess")])],
|
||||
[new ImportException("invalidSyntax"), V1::respError("InvalidBodyXML", 400)],
|
||||
[new ImportException("invalidSemantics"), V1::respError("InvalidBodyOPML", 422)],
|
||||
[new ImportException("invalidFolderName"), V1::respError("InvalidImportCategory", 422)],
|
||||
[new ImportException("invalidFolderCopy"), V1::respError("DuplicateImportCategory", 422)],
|
||||
[new ImportException("invalidTagName"), V1::respError("InvalidImportLabel", 422)],
|
||||
[new FeedException("invalidUrl", ['url' => "http://example.com/"]), V1::respError(["FailedImportFeed", 'url' => "http://example.com/", 'code' => 10502], 502)],
|
||||
[true, HTTP::respJson(['message' => Arsse::$lang->msg("API.Miniflux.ImportSuccess")])],
|
||||
];
|
||||
}
|
||||
|
||||
public function testExport(): void {
|
||||
$opml = $this->mock(OPML::class);
|
||||
$this->objMock->get->with(OPML::class)->returns($opml);
|
||||
$opml->export->returns("EXPORT DATA");
|
||||
$this->assertMessage(new TextResponse("EXPORT DATA", 200, ['Content-Type' => "application/xml"]), $this->req("GET", "/export"));
|
||||
$opml->export->returns("<EXPORT_DATA/>");
|
||||
$this->assertMessage(HTTP::respText("<EXPORT_DATA/>", 200, ['Content-Type' => "application/xml"]), $this->req("GET", "/export"));
|
||||
$opml->export->calledWith(Arsse::$user->id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,13 +11,12 @@ use JKingWeb\Arsse\User;
|
|||
use JKingWeb\Arsse\Database;
|
||||
use JKingWeb\Arsse\Test\Result;
|
||||
use JKingWeb\Arsse\Misc\Date;
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use JKingWeb\Arsse\Context\Context;
|
||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||
use JKingWeb\Arsse\Db\Transaction;
|
||||
use JKingWeb\Arsse\REST\NextcloudNews\V1_2;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\JsonResponse as Response;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
|
||||
/** @covers \JKingWeb\Arsse\REST\NextcloudNews\V1_2<extended> */
|
||||
class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||
|
@ -336,13 +335,13 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
}
|
||||
|
||||
public function testSendAuthenticationChallenge(): void {
|
||||
$exp = new EmptyResponse(401);
|
||||
$exp = HTTP::respEmpty(401);
|
||||
$this->assertMessage($exp, $this->req("GET", "/", "", [], false));
|
||||
}
|
||||
|
||||
/** @dataProvider provideInvalidPaths */
|
||||
public function testRespondToInvalidPaths($path, $method, $code, $allow = null): void {
|
||||
$exp = new EmptyResponse($code, $allow ? ['Allow' => $allow] : []);
|
||||
$exp = HTTP::respEmpty($code, $allow ? ['Allow' => $allow] : []);
|
||||
$this->assertMessage($exp, $this->req($method, $path));
|
||||
}
|
||||
|
||||
|
@ -374,16 +373,16 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
}
|
||||
|
||||
public function testRespondToInvalidInputTypes(): void {
|
||||
$exp = new EmptyResponse(415, ['Accept' => "application/json"]);
|
||||
$exp = HTTP::respEmpty(415, ['Accept' => "application/json"]);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/folders/1", '<data/>', ['Content-Type' => "application/xml"]));
|
||||
$exp = new EmptyResponse(400);
|
||||
$exp = HTTP::respEmpty(400);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/folders/1", '<data/>'));
|
||||
$this->assertMessage($exp, $this->req("PUT", "/folders/1", '<data/>', ['Content-Type' => null]));
|
||||
}
|
||||
|
||||
/** @dataProvider provideOptionsRequests */
|
||||
public function testRespondToOptionsRequests(string $url, string $allow, string $accept): void {
|
||||
$exp = new EmptyResponse(204, [
|
||||
$exp = HTTP::respEmpty(204, [
|
||||
'Allow' => $allow,
|
||||
'Accept' => $accept,
|
||||
]);
|
||||
|
@ -408,7 +407,7 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
['id' => 12, 'name' => "Hardware"],
|
||||
];
|
||||
$this->dbMock->folderList->with($this->userId, null, false)->returns(new Result($this->v($list)));
|
||||
$exp = new Response(['folders' => $out]);
|
||||
$exp = HTTP::respJson(['folders' => $out]);
|
||||
$this->assertMessage($exp, $this->req("GET", "/folders"));
|
||||
}
|
||||
|
||||
|
@ -432,23 +431,23 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
public function provideFolderCreations(): array {
|
||||
return [
|
||||
[['name' => "Software"], true, 1, new Response(['folders' => [['id' => 1, 'name' => "Software"]]])],
|
||||
[['name' => "Software"], false, 1, new Response(['folders' => [['id' => 1, 'name' => "Software"]]])],
|
||||
[['name' => "Hardware"], true, "2", new Response(['folders' => [['id' => 2, 'name' => "Hardware"]]])],
|
||||
[['name' => "Hardware"], false, "2", new Response(['folders' => [['id' => 2, 'name' => "Hardware"]]])],
|
||||
[['name' => "Software"], true, new ExceptionInput("constraintViolation"), new EmptyResponse(409)],
|
||||
[['name' => ""], true, new ExceptionInput("whitespace"), new EmptyResponse(422)],
|
||||
[['name' => " "], true, new ExceptionInput("whitespace"), new EmptyResponse(422)],
|
||||
[['name' => null], true, new ExceptionInput("missing"), new EmptyResponse(422)],
|
||||
[['name' => "Software"], true, 1, HTTP::respJson(['folders' => [['id' => 1, 'name' => "Software"]]])],
|
||||
[['name' => "Software"], false, 1, HTTP::respJson(['folders' => [['id' => 1, 'name' => "Software"]]])],
|
||||
[['name' => "Hardware"], true, "2", HTTP::respJson(['folders' => [['id' => 2, 'name' => "Hardware"]]])],
|
||||
[['name' => "Hardware"], false, "2", HTTP::respJson(['folders' => [['id' => 2, 'name' => "Hardware"]]])],
|
||||
[['name' => "Software"], true, new ExceptionInput("constraintViolation"), HTTP::respEmpty(409)],
|
||||
[['name' => ""], true, new ExceptionInput("whitespace"), HTTP::respEmpty(422)],
|
||||
[['name' => " "], true, new ExceptionInput("whitespace"), HTTP::respEmpty(422)],
|
||||
[['name' => null], true, new ExceptionInput("missing"), HTTP::respEmpty(422)],
|
||||
];
|
||||
}
|
||||
|
||||
public function testRemoveAFolder(): void {
|
||||
$this->dbMock->folderRemove->with($this->userId, 1)->returns(true)->throws(new ExceptionInput("subjectMissing"));
|
||||
$exp = new EmptyResponse(204);
|
||||
$exp = HTTP::respEmpty(204);
|
||||
$this->assertMessage($exp, $this->req("DELETE", "/folders/1"));
|
||||
// fail on the second invocation because it no longer exists
|
||||
$exp = new EmptyResponse(404);
|
||||
$exp = HTTP::respEmpty(404);
|
||||
$this->assertMessage($exp, $this->req("DELETE", "/folders/1"));
|
||||
$this->dbMock->folderRemove->times(2)->calledWith($this->userId, 1);
|
||||
}
|
||||
|
@ -467,17 +466,17 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
public function provideFolderRenamings(): array {
|
||||
return [
|
||||
[['name' => "Software"], 1, true, new EmptyResponse(204)],
|
||||
[['name' => "Software"], 2, new ExceptionInput("constraintViolation"), new EmptyResponse(409)],
|
||||
[['name' => "Software"], 3, new ExceptionInput("subjectMissing"), new EmptyResponse(404)],
|
||||
[['name' => ""], 2, new ExceptionInput("whitespace"), new EmptyResponse(422)],
|
||||
[['name' => " "], 2, new ExceptionInput("whitespace"), new EmptyResponse(422)],
|
||||
[['name' => null], 2, new ExceptionInput("missing"), new EmptyResponse(422)],
|
||||
[['name' => "Software"], 1, true, HTTP::respEmpty(204)],
|
||||
[['name' => "Software"], 2, new ExceptionInput("constraintViolation"), HTTP::respEmpty(409)],
|
||||
[['name' => "Software"], 3, new ExceptionInput("subjectMissing"), HTTP::respEmpty(404)],
|
||||
[['name' => ""], 2, new ExceptionInput("whitespace"), HTTP::respEmpty(422)],
|
||||
[['name' => " "], 2, new ExceptionInput("whitespace"), HTTP::respEmpty(422)],
|
||||
[['name' => null], 2, new ExceptionInput("missing"), HTTP::respEmpty(422)],
|
||||
];
|
||||
}
|
||||
|
||||
public function testRetrieveServerVersion(): void {
|
||||
$exp = new Response([
|
||||
$exp = HTTP::respJson([
|
||||
'version' => V1_2::VERSION,
|
||||
'arsse_version' => Arsse::VERSION,
|
||||
]);
|
||||
|
@ -497,9 +496,9 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$this->dbMock->subscriptionList->with($this->userId)->returns(new Result([]))->returns(new Result($this->v($this->feeds['db'])));
|
||||
$this->dbMock->articleStarred->with($this->userId)->returns($this->v(['total' => 0]))->returns($this->v(['total' => 5]));
|
||||
$this->dbMock->editionLatest->with($this->userId)->returns(0)->returns(4758915);
|
||||
$exp = new Response($exp1);
|
||||
$exp = HTTP::respJson($exp1);
|
||||
$this->assertMessage($exp, $this->req("GET", "/feeds"));
|
||||
$exp = new Response($exp2);
|
||||
$exp = HTTP::respJson($exp2);
|
||||
$this->assertMessage($exp, $this->req("GET", "/feeds"));
|
||||
}
|
||||
|
||||
|
@ -538,21 +537,21 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
public function provideNewSubscriptions(): array {
|
||||
$feedException = new \JKingWeb\Arsse\Feed\Exception("", [], new \PicoFeed\Reader\SubscriptionNotFoundException);
|
||||
return [
|
||||
[['url' => "http://example.com/news.atom", 'folderId' => 3], 2112, 0, $this->feeds['db'][0], new ExceptionInput("idMissing"), new Response(['feeds' => [$this->feeds['rest'][0]]])],
|
||||
[['url' => "http://example.org/news.atom", 'folderId' => 8], 42, 4758915, $this->feeds['db'][1], true, new Response(['feeds' => [$this->feeds['rest'][1]], 'newestItemId' => 4758915])],
|
||||
[['url' => "http://example.com/news.atom", 'folderId' => 3], new ExceptionInput("constraintViolation"), 0, $this->feeds['db'][0], new ExceptionInput("idMissing"), new EmptyResponse(409)],
|
||||
[['url' => "http://example.org/news.atom", 'folderId' => 8], new ExceptionInput("constraintViolation"), 4758915, $this->feeds['db'][1], true, new EmptyResponse(409)],
|
||||
[[], $feedException, 0, [], false, new EmptyResponse(422)],
|
||||
[['url' => "http://example.net/news.atom", 'folderId' => -1], 47, 2112, $this->feeds['db'][2], new ExceptionInput("typeViolation"), new Response(['feeds' => [$this->feeds['rest'][2]], 'newestItemId' => 2112])],
|
||||
[['url' => "http://example.com/news.atom", 'folderId' => 3], 2112, 0, $this->feeds['db'][0], new ExceptionInput("idMissing"), HTTP::respJson(['feeds' => [$this->feeds['rest'][0]]])],
|
||||
[['url' => "http://example.org/news.atom", 'folderId' => 8], 42, 4758915, $this->feeds['db'][1], true, HTTP::respJson(['feeds' => [$this->feeds['rest'][1]], 'newestItemId' => 4758915])],
|
||||
[['url' => "http://example.com/news.atom", 'folderId' => 3], new ExceptionInput("constraintViolation"), 0, $this->feeds['db'][0], new ExceptionInput("idMissing"), HTTP::respEmpty(409)],
|
||||
[['url' => "http://example.org/news.atom", 'folderId' => 8], new ExceptionInput("constraintViolation"), 4758915, $this->feeds['db'][1], true, HTTP::respEmpty(409)],
|
||||
[[], $feedException, 0, [], false, HTTP::respEmpty(422)],
|
||||
[['url' => "http://example.net/news.atom", 'folderId' => -1], 47, 2112, $this->feeds['db'][2], new ExceptionInput("typeViolation"), HTTP::respJson(['feeds' => [$this->feeds['rest'][2]], 'newestItemId' => 2112])],
|
||||
];
|
||||
}
|
||||
|
||||
public function testRemoveASubscription(): void {
|
||||
$this->dbMock->subscriptionRemove->with($this->userId, 1)->returns(true)->throws(new ExceptionInput("subjectMissing"));
|
||||
$exp = new EmptyResponse(204);
|
||||
$exp = HTTP::respEmpty(204);
|
||||
$this->assertMessage($exp, $this->req("DELETE", "/feeds/1"));
|
||||
// fail on the second invocation because it no longer exists
|
||||
$exp = new EmptyResponse(404);
|
||||
$exp = HTTP::respEmpty(404);
|
||||
$this->assertMessage($exp, $this->req("DELETE", "/feeds/1"));
|
||||
$this->dbMock->subscriptionRemove->times(2)->calledWith($this->userId, 1);
|
||||
}
|
||||
|
@ -571,17 +570,17 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$this->dbMock->subscriptionPropertiesSet->with($this->userId, 1, ['folder' => 2112])->throws(new ExceptionInput("idMissing")); // folder does not exist
|
||||
$this->dbMock->subscriptionPropertiesSet->with($this->userId, 1, ['folder' => -1])->throws(new ExceptionInput("typeViolation")); // folder is invalid
|
||||
$this->dbMock->subscriptionPropertiesSet->with($this->userId, 42, $this->anything())->throws(new ExceptionInput("subjectMissing")); // subscription does not exist
|
||||
$exp = new EmptyResponse(204);
|
||||
$exp = HTTP::respEmpty(204);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/move", json_encode($in[0])));
|
||||
$exp = new EmptyResponse(204);
|
||||
$exp = HTTP::respEmpty(204);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/move", json_encode($in[1])));
|
||||
$exp = new EmptyResponse(422);
|
||||
$exp = HTTP::respEmpty(422);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/move", json_encode($in[2])));
|
||||
$exp = new EmptyResponse(404);
|
||||
$exp = HTTP::respEmpty(404);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/42/move", json_encode($in[3])));
|
||||
$exp = new EmptyResponse(422);
|
||||
$exp = HTTP::respEmpty(422);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/move", json_encode($in[4])));
|
||||
$exp = new EmptyResponse(422);
|
||||
$exp = HTTP::respEmpty(422);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/move", json_encode($in[5])));
|
||||
}
|
||||
|
||||
|
@ -601,17 +600,17 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$this->dbMock->subscriptionPropertiesSet->with($this->userId, 1, $this->identicalTo(['title' => ""]))->throws(new ExceptionInput("missing"));
|
||||
$this->dbMock->subscriptionPropertiesSet->with($this->userId, 1, $this->identicalTo(['title' => false]))->throws(new ExceptionInput("missing"));
|
||||
$this->dbMock->subscriptionPropertiesSet->with($this->userId, 42, $this->anything())->throws(new ExceptionInput("subjectMissing"));
|
||||
$exp = new EmptyResponse(422);
|
||||
$exp = HTTP::respEmpty(422);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/rename", json_encode($in[0])));
|
||||
$exp = new EmptyResponse(204);
|
||||
$exp = HTTP::respEmpty(204);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/rename", json_encode($in[1])));
|
||||
$exp = new EmptyResponse(422);
|
||||
$exp = HTTP::respEmpty(422);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/rename", json_encode($in[2])));
|
||||
$exp = new EmptyResponse(422);
|
||||
$exp = HTTP::respEmpty(422);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/rename", json_encode($in[3])));
|
||||
$exp = new EmptyResponse(404);
|
||||
$exp = HTTP::respEmpty(404);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/42/rename", json_encode($in[4])));
|
||||
$exp = new EmptyResponse(422);
|
||||
$exp = HTTP::respEmpty(422);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/rename", json_encode($in[6])));
|
||||
}
|
||||
|
||||
|
@ -627,13 +626,13 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
],
|
||||
];
|
||||
$this->dbMock->feedListStale->returns($this->v(array_column($out, "id")));
|
||||
$exp = new Response(['feeds' => $out]);
|
||||
$exp = HTTP::respJson(['feeds' => $out]);
|
||||
$this->assertMessage($exp, $this->req("GET", "/feeds/all"));
|
||||
}
|
||||
|
||||
public function testListStaleFeedsWithoutAuthority(): void {
|
||||
$this->userMock->propertiesGet->returns(['admin' => false]);
|
||||
$exp = new EmptyResponse(403);
|
||||
$exp = HTTP::respEmpty(403);
|
||||
$this->assertMessage($exp, $this->req("GET", "/feeds/all"));
|
||||
$this->dbMock->feedListStale->never()->called();
|
||||
}
|
||||
|
@ -649,11 +648,11 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$this->dbMock->feedUpdate->with(42)->returns(true);
|
||||
$this->dbMock->feedUpdate->with(2112)->throws(new ExceptionInput("subjectMissing"));
|
||||
$this->dbMock->feedUpdate->with($this->lessThan(1))->throws(new ExceptionInput("typeViolation"));
|
||||
$exp = new EmptyResponse(204);
|
||||
$exp = HTTP::respEmpty(204);
|
||||
$this->assertMessage($exp, $this->req("GET", "/feeds/update", json_encode($in[0])));
|
||||
$exp = new EmptyResponse(404);
|
||||
$exp = HTTP::respEmpty(404);
|
||||
$this->assertMessage($exp, $this->req("GET", "/feeds/update", json_encode($in[1])));
|
||||
$exp = new EmptyResponse(422);
|
||||
$exp = HTTP::respEmpty(422);
|
||||
$this->assertMessage($exp, $this->req("GET", "/feeds/update", json_encode($in[2])));
|
||||
$this->assertMessage($exp, $this->req("GET", "/feeds/update", json_encode($in[3])));
|
||||
$this->assertMessage($exp, $this->req("GET", "/feeds/update", json_encode($in[4])));
|
||||
|
@ -661,7 +660,7 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
public function testUpdateAFeedWithoutAuthority(): void {
|
||||
$this->userMock->propertiesGet->returns(['admin' => false]);
|
||||
$exp = new EmptyResponse(403);
|
||||
$exp = HTTP::respEmpty(403);
|
||||
$this->assertMessage($exp, $this->req("GET", "/feeds/update", ['feedId' => 42]));
|
||||
$this->dbMock->feedUpdate->never()->called();
|
||||
}
|
||||
|
@ -683,8 +682,8 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$c = (new Context)->hidden(false);
|
||||
$t = Date::normalize(time());
|
||||
$out = new Result($this->v($this->articles['db']));
|
||||
$r200 = new Response(['items' => $this->articles['rest']]);
|
||||
$r422 = new EmptyResponse(422);
|
||||
$r200 = HTTP::respJson(['items' => $this->articles['rest']]);
|
||||
$r422 = HTTP::respEmpty(422);
|
||||
return [
|
||||
["/items", [], clone $c, $out, $r200],
|
||||
["/items", ['type' => 0, 'id' => 42], (clone $c)->subscription(42), new ExceptionInput("idMissing"), $r422],
|
||||
|
@ -720,13 +719,13 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$in = json_encode(['newestItemId' => 2112]);
|
||||
$this->dbMock->articleMark->with($this->userId, $read, $this->equalTo((new Context)->folder(1)->editionRange(null, 2112)->hidden(false)))->returns(42);
|
||||
$this->dbMock->articleMark->with($this->userId, $read, $this->equalTo((new Context)->folder(42)->editionRange(null, 2112)->hidden(false)))->throws(new ExceptionInput("idMissing")); // folder doesn't exist
|
||||
$exp = new EmptyResponse(204);
|
||||
$exp = HTTP::respEmpty(204);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/folders/1/read", $in));
|
||||
$this->assertMessage($exp, $this->req("PUT", "/folders/1/read?newestItemId=2112"));
|
||||
$exp = new EmptyResponse(422);
|
||||
$exp = HTTP::respEmpty(422);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/folders/1/read"));
|
||||
$this->assertMessage($exp, $this->req("PUT", "/folders/1/read?newestItemId=ook"));
|
||||
$exp = new EmptyResponse(404);
|
||||
$exp = HTTP::respEmpty(404);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/folders/42/read", $in));
|
||||
}
|
||||
|
||||
|
@ -735,13 +734,13 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$in = json_encode(['newestItemId' => 2112]);
|
||||
$this->dbMock->articleMark->with($this->userId, $read, $this->equalTo((new Context)->subscription(1)->editionRange(null, 2112)->hidden(false)))->returns(42);
|
||||
$this->dbMock->articleMark->with($this->userId, $read, $this->equalTo((new Context)->subscription(42)->editionRange(null, 2112)->hidden(false)))->throws(new ExceptionInput("idMissing")); // subscription doesn't exist
|
||||
$exp = new EmptyResponse(204);
|
||||
$exp = HTTP::respEmpty(204);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/read", $in));
|
||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/read?newestItemId=2112"));
|
||||
$exp = new EmptyResponse(422);
|
||||
$exp = HTTP::respEmpty(422);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/read"));
|
||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/1/read?newestItemId=ook"));
|
||||
$exp = new EmptyResponse(404);
|
||||
$exp = HTTP::respEmpty(404);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/feeds/42/read", $in));
|
||||
}
|
||||
|
||||
|
@ -749,10 +748,10 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$read = ['read' => true];
|
||||
$in = json_encode(['newestItemId' => 2112]);
|
||||
$this->dbMock->articleMark->with($this->userId, $read, $this->equalTo((new Context)->editionRange(null, 2112)))->returns(42);
|
||||
$exp = new EmptyResponse(204);
|
||||
$exp = HTTP::respEmpty(204);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/items/read", $in));
|
||||
$this->assertMessage($exp, $this->req("PUT", "/items/read?newestItemId=2112"));
|
||||
$exp = new EmptyResponse(422);
|
||||
$exp = HTTP::respEmpty(422);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/items/read"));
|
||||
$this->assertMessage($exp, $this->req("PUT", "/items/read?newestItemId=ook"));
|
||||
}
|
||||
|
@ -770,12 +769,12 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$this->dbMock->articleMark->with($this->userId, $star, $this->equalTo((new Context)->article(2112)))->throws(new ExceptionInput("subjectMissing")); // article doesn't exist doesn't exist
|
||||
$this->dbMock->articleMark->with($this->userId, $unstar, $this->equalTo((new Context)->article(4)))->returns(42);
|
||||
$this->dbMock->articleMark->with($this->userId, $unstar, $this->equalTo((new Context)->article(1337)))->throws(new ExceptionInput("subjectMissing")); // article doesn't exist doesn't exist
|
||||
$exp = new EmptyResponse(204);
|
||||
$exp = HTTP::respEmpty(204);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/items/1/read"));
|
||||
$this->assertMessage($exp, $this->req("PUT", "/items/2/unread"));
|
||||
$this->assertMessage($exp, $this->req("PUT", "/items/1/3/star"));
|
||||
$this->assertMessage($exp, $this->req("PUT", "/items/4400/4/unstar"));
|
||||
$exp = new EmptyResponse(404);
|
||||
$exp = HTTP::respEmpty(404);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/items/42/read"));
|
||||
$this->assertMessage($exp, $this->req("PUT", "/items/47/unread"));
|
||||
$this->assertMessage($exp, $this->req("PUT", "/items/1/2112/star"));
|
||||
|
@ -801,7 +800,7 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$this->dbMock->articleMark->with($this->userId, $this->anything(), $this->anything())->returns(42);
|
||||
$this->dbMock->articleMark->with($this->userId, $this->anything(), $this->equalTo((new Context)->editions([])))->throws(new ExceptionInput("tooShort")); // data model function requires one valid integer for multiples
|
||||
$this->dbMock->articleMark->with($this->userId, $this->anything(), $this->equalTo((new Context)->articles([])))->throws(new ExceptionInput("tooShort")); // data model function requires one valid integer for multiples
|
||||
$exp = new EmptyResponse(204);
|
||||
$exp = HTTP::respEmpty(204);
|
||||
$this->assertMessage($exp, $this->req("PUT", "/items/read/multiple"));
|
||||
$this->assertMessage($exp, $this->req("PUT", "/items/unread/multiple"));
|
||||
$this->assertMessage($exp, $this->req("PUT", "/items/star/multiple"));
|
||||
|
@ -854,44 +853,44 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
];
|
||||
$arr2['warnings']['improperlyConfiguredCron'] = true;
|
||||
$arr2['warnings']['incorrectDbCharset'] = true;
|
||||
$exp = new Response($arr1);
|
||||
$exp = HTTP::respJson($arr1);
|
||||
$this->assertMessage($exp, $this->req("GET", "/status"));
|
||||
}
|
||||
|
||||
public function testCleanUpBeforeUpdate(): void {
|
||||
$this->dbMock->feedCleanup->with()->returns(true);
|
||||
$exp = new EmptyResponse(204);
|
||||
$exp = HTTP::respEmpty(204);
|
||||
$this->assertMessage($exp, $this->req("GET", "/cleanup/before-update"));
|
||||
$this->dbMock->feedCleanup->calledWith();
|
||||
}
|
||||
|
||||
public function testCleanUpBeforeUpdateWithoutAuthority(): void {
|
||||
$this->userMock->propertiesGet->returns(['admin' => false]);
|
||||
$exp = new EmptyResponse(403);
|
||||
$exp = HTTP::respEmpty(403);
|
||||
$this->assertMessage($exp, $this->req("GET", "/cleanup/before-update"));
|
||||
$this->dbMock->feedCleanup->never()->called();
|
||||
}
|
||||
|
||||
public function testCleanUpAfterUpdate(): void {
|
||||
$this->dbMock->articleCleanup->with()->returns(true);
|
||||
$exp = new EmptyResponse(204);
|
||||
$exp = HTTP::respEmpty(204);
|
||||
$this->assertMessage($exp, $this->req("GET", "/cleanup/after-update"));
|
||||
$this->dbMock->articleCleanup->calledWith();
|
||||
}
|
||||
|
||||
public function testCleanUpAfterUpdateWithoutAuthority(): void {
|
||||
$this->userMock->propertiesGet->returns(['admin' => false]);
|
||||
$exp = new EmptyResponse(403);
|
||||
$exp = HTTP::respEmpty(403);
|
||||
$this->assertMessage($exp, $this->req("GET", "/cleanup/after-update"));
|
||||
$this->dbMock->feedCleanup->never()->called();
|
||||
}
|
||||
|
||||
public function testQueryTheUserStatus(): void {
|
||||
$act = $this->req("GET", "/user");
|
||||
$exp = new Response([
|
||||
$exp = HTTP::respJson([
|
||||
'userId' => $this->userId,
|
||||
'displayName' => $this->userId,
|
||||
'lastLoginTimestamp' => $this->approximateTime($act->getPayload()['lastLoginTimestamp'], new \DateTimeImmutable),
|
||||
'lastLoginTimestamp' => $this->approximateTime(json_decode((string) $act->getBody(), true)['lastLoginTimestamp'], new \DateTimeImmutable),
|
||||
'avatar' => null,
|
||||
]);
|
||||
$this->assertMessage($exp, $act);
|
||||
|
@ -906,8 +905,8 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$this->dbMock->folderAdd->with($this->anything(), $in)->returns(1);
|
||||
$this->dbMock->folderPropertiesGet->with($this->userId, 1)->returns($this->v($out1));
|
||||
$this->dbMock->folderPropertiesGet->with($this->userId, 2)->returns($this->v($out2));
|
||||
$exp = new Response(['folders' => [$out1]]);
|
||||
$this->assertMessage($exp, $this->req("POST", "/folders?name=Hardware", json_encode($in)));
|
||||
$exp = HTTP::respJson(['folders' => [$out1]]);
|
||||
$this->assertMessage($exp, $this->req("POST", $url, json_encode($in)));
|
||||
}
|
||||
|
||||
public function testMeldJsonAndQueryParameters(): void {
|
||||
|
|
|
@ -6,10 +6,9 @@
|
|||
declare(strict_types=1);
|
||||
namespace JKingWeb\Arsse\TestCase\REST\NextcloudNews;
|
||||
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use JKingWeb\Arsse\REST\NextcloudNews\Versions;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\JsonResponse as Response;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
|
||||
/** @covers \JKingWeb\Arsse\REST\NextcloudNews\Versions */
|
||||
class TestVersions extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||
|
@ -25,24 +24,24 @@ class TestVersions extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
}
|
||||
|
||||
public function testFetchVersionList(): void {
|
||||
$exp = new Response(['apiLevels' => ['v1-2']]);
|
||||
$exp = HTTP::respJson(['apiLevels' => ['v1-2']]);
|
||||
$this->assertMessage($exp, $this->req("GET", "/"));
|
||||
$this->assertMessage($exp, $this->req("GET", "/"));
|
||||
$this->assertMessage($exp, $this->req("GET", "/"));
|
||||
}
|
||||
|
||||
public function testRespondToOptionsRequest(): void {
|
||||
$exp = new EmptyResponse(204, ['Allow' => "HEAD,GET"]);
|
||||
$exp = HTTP::respEmpty(204, ['Allow' => "HEAD,GET"]);
|
||||
$this->assertMessage($exp, $this->req("OPTIONS", "/"));
|
||||
}
|
||||
|
||||
public function testUseIncorrectMethod(): void {
|
||||
$exp = new EmptyResponse(405, ['Allow' => "HEAD,GET"]);
|
||||
$exp = HTTP::respEmpty(405, ['Allow' => "HEAD,GET"]);
|
||||
$this->assertMessage($exp, $this->req("POST", "/"));
|
||||
}
|
||||
|
||||
public function testUseIncorrectPath(): void {
|
||||
$exp = new EmptyResponse(404);
|
||||
$exp = HTTP::respEmpty(404);
|
||||
$this->assertMessage($exp, $this->req("GET", "/ook"));
|
||||
$this->assertMessage($exp, $this->req("OPTIONS", "/ook"));
|
||||
}
|
||||
|
|
|
@ -12,13 +12,12 @@ use JKingWeb\Arsse\REST;
|
|||
use JKingWeb\Arsse\REST\Exception501;
|
||||
use JKingWeb\Arsse\REST\NextcloudNews\V1_2 as NCN;
|
||||
use JKingWeb\Arsse\REST\TinyTinyRSS\API as TTRSS;
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Request;
|
||||
use Laminas\Diactoros\Response;
|
||||
use Laminas\Diactoros\ServerRequest;
|
||||
use Laminas\Diactoros\Response\TextResponse;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use GuzzleHttp\Psr7\Request;
|
||||
use GuzzleHttp\Psr7\ServerRequest;
|
||||
|
||||
/** @covers \JKingWeb\Arsse\REST */
|
||||
class TestREST extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||
|
@ -69,7 +68,7 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$this->userMock->auth->with("someone.else@example.com", "")->returns(true);
|
||||
Arsse::$user = $this->userMock->get();
|
||||
// create an input server request
|
||||
$req = new ServerRequest($serverParams);
|
||||
$req = new ServerRequest("GET", "/", [], null, "1.1", $serverParams);
|
||||
// create the expected output
|
||||
$exp = $req;
|
||||
foreach ($expAttr as $key => $value) {
|
||||
|
@ -95,7 +94,7 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
public function testSendAuthenticationChallenges(): void {
|
||||
self::setConf();
|
||||
$r = new REST;
|
||||
$in = new EmptyResponse(401);
|
||||
$in = HTTP::respEmpty(401);
|
||||
$exp = $in->withHeader("WWW-Authenticate", 'Basic realm="OOK", charset="UTF-8"');
|
||||
$act = $r->challenge($in, "OOK");
|
||||
$this->assertMessage($exp, $act);
|
||||
|
@ -155,7 +154,7 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
return $origin;
|
||||
});
|
||||
$headers = isset($origin) ? ['Origin' => $origin] : [];
|
||||
$req = new Request("", "GET", "php://memory", $headers);
|
||||
$req = new Request("GET", "", $headers);
|
||||
$act = $rMock->get()->corsNegotiate($req, $allowed, $denied);
|
||||
$this->assertSame($exp, $act);
|
||||
}
|
||||
|
@ -188,9 +187,9 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
/** @dataProvider provideCorsHeaders */
|
||||
public function testAddCorsHeaders(string $reqMethod, array $reqHeaders, array $resHeaders, array $expHeaders): void {
|
||||
$r = new REST;
|
||||
$req = new Request("", $reqMethod, "php://memory", $reqHeaders);
|
||||
$res = new EmptyResponse(204, $resHeaders);
|
||||
$exp = new EmptyResponse(204, $expHeaders);
|
||||
$req = new Request($reqMethod, "php://memory", $reqHeaders);
|
||||
$res = HTTP::respEmpty(204, $resHeaders);
|
||||
$exp = HTTP::respEmpty(204, $expHeaders);
|
||||
$act = $r->corsApply($res, $req);
|
||||
$this->assertMessage($exp, $act);
|
||||
}
|
||||
|
@ -242,7 +241,7 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
["OPTIONS", ['Origin' => "http://example", 'Access-Control-Request-Headers' => ["Content-Type", "If-None-Match"]], [], [
|
||||
'Access-Control-Allow-Origin' => "http://example",
|
||||
'Access-Control-Allow-Credentials' => "true",
|
||||
'Access-Control-Allow-Headers' => "Content-Type,If-None-Match",
|
||||
'Access-Control-Allow-Headers' => "Content-Type, If-None-Match",
|
||||
'Access-Control-Max-Age' => (string) (60 * 60 * 24),
|
||||
'Vary' => "Origin",
|
||||
]],
|
||||
|
@ -267,21 +266,21 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$stream = fopen("php://memory", "w+b");
|
||||
fwrite($stream, "ook");
|
||||
return [
|
||||
[new EmptyResponse(204), new EmptyResponse(204)],
|
||||
[new EmptyResponse(401), new EmptyResponse(401, ['WWW-Authenticate' => "Fake Value"])],
|
||||
[new EmptyResponse(204, ['Allow' => "PUT"]), new EmptyResponse(204, ['Allow' => "PUT, OPTIONS"])],
|
||||
[new EmptyResponse(204, ['Allow' => "PUT, OPTIONS"]), new EmptyResponse(204, ['Allow' => "PUT, OPTIONS"])],
|
||||
[new EmptyResponse(204, ['Allow' => "PUT,OPTIONS"]), new EmptyResponse(204, ['Allow' => "PUT, OPTIONS"])],
|
||||
[new EmptyResponse(204, ['Allow' => ["PUT", "OPTIONS"]]), new EmptyResponse(204, ['Allow' => "PUT, OPTIONS"])],
|
||||
[new EmptyResponse(204, ['Allow' => ["PUT, DELETE", "OPTIONS"]]), new EmptyResponse(204, ['Allow' => "PUT, DELETE, OPTIONS"])],
|
||||
[new EmptyResponse(204, ['Allow' => "HEAD,GET"]), new EmptyResponse(204, ['Allow' => "HEAD, GET, OPTIONS"])],
|
||||
[new EmptyResponse(204, ['Allow' => "GET"]), new EmptyResponse(204, ['Allow' => "GET, HEAD, OPTIONS"])],
|
||||
[new TextResponse("ook", 200), new TextResponse("ook", 200, ['Content-Length' => "3"])],
|
||||
[new TextResponse("", 200), new TextResponse("", 200, ['Content-Length' => "0"])],
|
||||
[new TextResponse("ook", 404), new TextResponse("ook", 404, ['Content-Length' => "3"])],
|
||||
[new TextResponse("", 404), new TextResponse("", 404)],
|
||||
[new Response($stream, 200), new Response($stream, 200, ['Content-Length' => "3"]), new Request("", "GET")],
|
||||
[new Response($stream, 200), new EmptyResponse(200, ['Content-Length' => "3"]), new Request("", "HEAD")],
|
||||
[HTTP::respEmpty(204), HTTP::respEmpty(204)],
|
||||
[HTTP::respEmpty(401), HTTP::respEmpty(401, ['WWW-Authenticate' => "Fake Value"])],
|
||||
[HTTP::respEmpty(204, ['Allow' => "PUT"]), HTTP::respEmpty(204, ['Allow' => "PUT, OPTIONS"])],
|
||||
[HTTP::respEmpty(204, ['Allow' => "PUT, OPTIONS"]), HTTP::respEmpty(204, ['Allow' => "PUT, OPTIONS"])],
|
||||
[HTTP::respEmpty(204, ['Allow' => "PUT,OPTIONS"]), HTTP::respEmpty(204, ['Allow' => "PUT, OPTIONS"])],
|
||||
[HTTP::respEmpty(204, ['Allow' => ["PUT", "OPTIONS"]]), HTTP::respEmpty(204, ['Allow' => "PUT, OPTIONS"])],
|
||||
[HTTP::respEmpty(204, ['Allow' => ["PUT, DELETE", "OPTIONS"]]), HTTP::respEmpty(204, ['Allow' => "PUT, DELETE, OPTIONS"])],
|
||||
[HTTP::respEmpty(204, ['Allow' => "HEAD,GET"]), HTTP::respEmpty(204, ['Allow' => "HEAD, GET, OPTIONS"])],
|
||||
[HTTP::respEmpty(204, ['Allow' => "GET"]), HTTP::respEmpty(204, ['Allow' => "GET, HEAD, OPTIONS"])],
|
||||
[HTTP::respText("ook", 200), HTTP::respText("ook", 200, ['Content-Length' => "3"])],
|
||||
[HTTP::respText("", 200), HTTP::respText("", 200, ['Content-Length' => "0"])],
|
||||
[HTTP::respText("ook", 404), HTTP::respText("ook", 404, ['Content-Length' => "3"])],
|
||||
[HTTP::respText("", 404), HTTP::respText("", 404)],
|
||||
[new Response(200, [], $stream), new Response(200, ['Content-Length' => "3"], $stream), new Request("GET", "")],
|
||||
[new Response(200, [], $stream), HTTP::respEmpty(200, ['Content-Length' => "3"]), new Request("HEAD", "")],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -296,7 +295,7 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
});
|
||||
if ($called) {
|
||||
$hMock = $this->mock($class);
|
||||
$hMock->dispatch->returns(new EmptyResponse(204));
|
||||
$hMock->dispatch->returns(HTTP::respEmpty(204));
|
||||
$this->objMock->get->with($class)->returns($hMock);
|
||||
Arsse::$obj = $this->objMock->get();
|
||||
}
|
||||
|
@ -317,13 +316,13 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
public function provideMockRequests(): iterable {
|
||||
return [
|
||||
[new ServerRequest([], [], "/index.php/apps/news/api/v1-2/feeds", "GET"), "GET", true, NCN::class, "/feeds"],
|
||||
[new ServerRequest([], [], "/index.php/apps/news/api/v1-2/feeds", "HEAD"), "GET", true, NCN::class, "/feeds"],
|
||||
[new ServerRequest([], [], "/index.php/apps/news/api/v1-2/feeds", "get"), "GET", true, NCN::class, "/feeds"],
|
||||
[new ServerRequest([], [], "/index.php/apps/news/api/v1-2/feeds", "head"), "GET", true, NCN::class, "/feeds"],
|
||||
[new ServerRequest([], [], "/tt-rss/api/", "POST"), "POST", true, TTRSS::class, "/"],
|
||||
[new ServerRequest([], [], "/no/such/api/", "HEAD"), "GET", false],
|
||||
[new ServerRequest([], [], "/no/such/api/", "GET"), "GET", false],
|
||||
[new ServerRequest("GET", "/index.php/apps/news/api/v1-2/feeds"), "GET", true, NCN::class, "/feeds"],
|
||||
[new ServerRequest("GET", "/index.php/apps/news/api/v1-2/feeds"), "GET", true, NCN::class, "/feeds"],
|
||||
[new ServerRequest("get", "/index.php/apps/news/api/v1-2/feeds"), "GET", true, NCN::class, "/feeds"],
|
||||
[new ServerRequest("head", "/index.php/apps/news/api/v1-2/feeds"), "GET", true, NCN::class, "/feeds"],
|
||||
[new ServerRequest("POST", "/tt-rss/api/"), "POST", true, TTRSS::class, "/"],
|
||||
[new ServerRequest("HEAD", "/no/such/api/"), "GET", false],
|
||||
[new ServerRequest("GET", "/no/such/api/"), "GET", false],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,14 +11,13 @@ use JKingWeb\Arsse\User;
|
|||
use JKingWeb\Arsse\Database;
|
||||
use JKingWeb\Arsse\Test\Result;
|
||||
use JKingWeb\Arsse\Misc\Date;
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use JKingWeb\Arsse\Context\Context;
|
||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||
use JKingWeb\Arsse\Db\Transaction;
|
||||
use JKingWeb\Arsse\REST\TinyTinyRSS\API;
|
||||
use JKingWeb\Arsse\Feed\Exception as FeedException;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\JsonResponse as Response;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
|
||||
/** @covers \JKingWeb\Arsse\REST\TinyTinyRSS\API<extended>
|
||||
* @covers \JKingWeb\Arsse\REST\TinyTinyRSS\Exception */
|
||||
|
@ -166,17 +165,17 @@ LONG_STRING;
|
|||
return $this->req($data, "POST", "", null, $user);
|
||||
}
|
||||
|
||||
protected function respGood($content = null, $seq = 0): Response {
|
||||
return new Response([
|
||||
protected function respGood($content = null, $seq = 0): ResponseInterface {
|
||||
return HTTP::respJson([
|
||||
'seq' => $seq,
|
||||
'status' => 0,
|
||||
'content' => $content,
|
||||
]);
|
||||
}
|
||||
|
||||
protected function respErr(string $msg, $content = [], $seq = 0): Response {
|
||||
protected function respErr(string $msg, $content = [], $seq = 0): ResponseInterface {
|
||||
$err = ['error' => $msg];
|
||||
return new Response([
|
||||
return HTTP::respJson([
|
||||
'seq' => $seq,
|
||||
'status' => 1,
|
||||
'content' => array_merge($err, $content, $err),
|
||||
|
@ -188,12 +187,12 @@ LONG_STRING;
|
|||
$this->assertMessage($exp, $this->req(null, "POST", "", ""));
|
||||
$this->assertMessage($exp, $this->req(null, "POST", "/", ""));
|
||||
$this->assertMessage($exp, $this->req(null, "POST", "/index.php", ""));
|
||||
$exp = new EmptyResponse(404);
|
||||
$exp = HTTP::respEmpty(404);
|
||||
$this->assertMessage($exp, $this->req(null, "POST", "/bad/path", ""));
|
||||
}
|
||||
|
||||
public function testHandleOptionsRequest(): void {
|
||||
$exp = new EmptyResponse(204, [
|
||||
$exp = HTTP::respEmpty(204, [
|
||||
'Allow' => "POST",
|
||||
'Accept' => "application/json, text/json",
|
||||
]);
|
||||
|
@ -215,7 +214,7 @@ LONG_STRING;
|
|||
$this->userMock->auth->with("jane.doe@example.com", "superman")->returns(true);
|
||||
$this->dbMock->sessionCreate->with("john.doe@example.com")->returns("PriestsOfSyrinx", "SolarFederation");
|
||||
$this->dbMock->sessionCreate->with("jane.doe@example.com")->returns("ClockworkAngels", "SevenCitiesOfGold");
|
||||
if ($sessions instanceof EmptyResponse) {
|
||||
if ($sessions instanceof ResponseInterface) {
|
||||
$exp1 = $sessions;
|
||||
$exp2 = $sessions;
|
||||
} elseif ($sessions) {
|
||||
|
@ -260,7 +259,7 @@ LONG_STRING;
|
|||
'op' => "isLoggedIn",
|
||||
'sid' => $data,
|
||||
];
|
||||
if ($result instanceof EmptyResponse) {
|
||||
if ($result instanceof ResponseInterface) {
|
||||
$exp1 = $result;
|
||||
$exp2 = null;
|
||||
} elseif ($result) {
|
||||
|
@ -333,7 +332,7 @@ LONG_STRING;
|
|||
'userHTTPAuthRequired' => true,
|
||||
'userSessionEnforced' => false,
|
||||
];
|
||||
$http401 = new EmptyResponse(401);
|
||||
$http401 = HTTP::respEmpty(401);
|
||||
if ($type === "login") {
|
||||
return [
|
||||
// conf, user, data, result
|
||||
|
@ -532,7 +531,7 @@ LONG_STRING;
|
|||
'user' => $this->userId,
|
||||
'password' => "secret",
|
||||
];
|
||||
$exp = new EmptyResponse(500);
|
||||
$exp = HTTP::respEmpty(500);
|
||||
$this->assertMessage($exp, $this->req($data));
|
||||
}
|
||||
|
||||
|
@ -1686,10 +1685,10 @@ LONG_STRING;
|
|||
$this->assertMessage($this->outputHeadlines(1), $test);
|
||||
// test 'show_content'
|
||||
$test = $this->req($in[1]);
|
||||
$this->assertArrayHasKey("content", $test->getPayload()['content'][0]);
|
||||
$this->assertArrayHasKey("content", $test->getPayload()['content'][1]);
|
||||
$this->assertArrayHasKey("content", $this->extractMessageJson($test)['content'][0]);
|
||||
$this->assertArrayHasKey("content", $this->extractMessageJson($test)['content'][1]);
|
||||
foreach ($this->generateHeadlines(1) as $key => $row) {
|
||||
$this->assertSame($row['content'], $test->getPayload()['content'][$key]['content']);
|
||||
$this->assertSame($row['content'], $this->extractMessageJson($test)['content'][$key]['content']);
|
||||
}
|
||||
// test 'include_attachments'
|
||||
$test = $this->req($in[2]);
|
||||
|
@ -1705,22 +1704,22 @@ LONG_STRING;
|
|||
'post_id' => "2112",
|
||||
],
|
||||
];
|
||||
$this->assertArrayHasKey("attachments", $test->getPayload()['content'][0]);
|
||||
$this->assertArrayHasKey("attachments", $test->getPayload()['content'][1]);
|
||||
$this->assertSame([], $test->getPayload()['content'][0]['attachments']);
|
||||
$this->assertSame($exp, $test->getPayload()['content'][1]['attachments']);
|
||||
$this->assertArrayHasKey("attachments", $this->extractMessageJson($test)['content'][0]);
|
||||
$this->assertArrayHasKey("attachments", $this->extractMessageJson($test)['content'][1]);
|
||||
$this->assertSame([], $this->extractMessageJson($test)['content'][0]['attachments']);
|
||||
$this->assertSame($exp, $this->extractMessageJson($test)['content'][1]['attachments']);
|
||||
// test 'include_header'
|
||||
$test = $this->req($in[3]);
|
||||
$exp = $this->respGood([
|
||||
['id' => -4, 'is_cat' => false, 'first_id' => 1],
|
||||
$this->outputHeadlines(1)->getPayload()['content'],
|
||||
$this->extractMessageJson($this->outputHeadlines(1))['content'],
|
||||
]);
|
||||
$this->assertMessage($exp, $test);
|
||||
// test 'include_header' with a category
|
||||
$test = $this->req($in[4]);
|
||||
$exp = $this->respGood([
|
||||
['id' => -3, 'is_cat' => true, 'first_id' => 1],
|
||||
$this->outputHeadlines(1)->getPayload()['content'],
|
||||
$this->extractMessageJson($this->outputHeadlines(1))['content'],
|
||||
]);
|
||||
$this->assertMessage($exp, $test);
|
||||
// test 'include_header' with an empty result
|
||||
|
@ -1742,7 +1741,7 @@ LONG_STRING;
|
|||
$test = $this->req($in[7]);
|
||||
$exp = $this->respGood([
|
||||
['id' => -4, 'is_cat' => false, 'first_id' => 0],
|
||||
$this->outputHeadlines(1)->getPayload()['content'],
|
||||
$this->extractMessageJson($this->outputHeadlines(1))['content'],
|
||||
]);
|
||||
$this->assertMessage($exp, $test);
|
||||
// test 'include_header' with skip
|
||||
|
@ -1750,24 +1749,24 @@ LONG_STRING;
|
|||
$test = $this->req($in[8]);
|
||||
$exp = $this->respGood([
|
||||
['id' => 42, 'is_cat' => false, 'first_id' => 1867],
|
||||
$this->outputHeadlines(1)->getPayload()['content'],
|
||||
$this->extractMessageJson($this->outputHeadlines(1))['content'],
|
||||
]);
|
||||
$this->assertMessage($exp, $test);
|
||||
// test 'include_header' with skip and ascending order
|
||||
$test = $this->req($in[9]);
|
||||
$exp = $this->respGood([
|
||||
['id' => 42, 'is_cat' => false, 'first_id' => 0],
|
||||
$this->outputHeadlines(1)->getPayload()['content'],
|
||||
$this->extractMessageJson($this->outputHeadlines(1))['content'],
|
||||
]);
|
||||
$this->assertMessage($exp, $test);
|
||||
// test 'show_excerpt'
|
||||
$exp1 = "“This & that, you know‽”";
|
||||
$exp2 = "Pour vous faire mieux connaitre d’ou\u{300} vient l’erreur de ceux qui bla\u{302}ment la volupte\u{301}, et qui louent en…";
|
||||
$test = $this->req($in[10]);
|
||||
$this->assertArrayHasKey("excerpt", $test->getPayload()['content'][0]);
|
||||
$this->assertArrayHasKey("excerpt", $test->getPayload()['content'][1]);
|
||||
$this->assertSame($exp1, $test->getPayload()['content'][0]['excerpt']);
|
||||
$this->assertSame($exp2, $test->getPayload()['content'][1]['excerpt']);
|
||||
$this->assertArrayHasKey("excerpt", $this->extractMessageJson($test)['content'][0]);
|
||||
$this->assertArrayHasKey("excerpt", $this->extractMessageJson($test)['content'][1]);
|
||||
$this->assertSame($exp1, $this->extractMessageJson($test)['content'][0]['excerpt']);
|
||||
$this->assertSame($exp2, $this->extractMessageJson($test)['content'][1]['excerpt']);
|
||||
}
|
||||
|
||||
protected function generateHeadlines(int $id): Result {
|
||||
|
@ -1815,7 +1814,7 @@ LONG_STRING;
|
|||
]));
|
||||
}
|
||||
|
||||
protected function outputHeadlines(int $id): Response {
|
||||
protected function outputHeadlines(int $id): ResponseInterface {
|
||||
return $this->respGood([
|
||||
[
|
||||
'id' => $id,
|
||||
|
|
|
@ -9,10 +9,10 @@ namespace JKingWeb\Arsse\TestCase\REST\TinyTinyRSS;
|
|||
use JKingWeb\Arsse\Arsse;
|
||||
use JKingWeb\Arsse\User;
|
||||
use JKingWeb\Arsse\Database;
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||
use JKingWeb\Arsse\REST\TinyTinyRSS\Icon;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\Response\EmptyResponse as Response;
|
||||
|
||||
/** @covers \JKingWeb\Arsse\REST\TinyTinyRSS\Icon<extended> */
|
||||
class TestIcon extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||
|
@ -51,21 +51,21 @@ class TestIcon extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$this->dbMock->subscriptionIcon->with($this->anything(), 2112, false)->returns(['url' => "http://example.net/logo.png"]);
|
||||
$this->dbMock->subscriptionIcon->with($this->anything(), 1337, false)->returns(['url' => "http://example.org/icon.gif\r\nLocation: http://bad.example.com/"]);
|
||||
// these requests should succeed
|
||||
$exp = new Response(301, ['Location' => "http://example.com/favicon.ico"]);
|
||||
$exp = HTTP::respEmpty(301, ['Location' => "http://example.com/favicon.ico"]);
|
||||
$this->assertMessage($exp, $this->req("42.ico"));
|
||||
$exp = new Response(301, ['Location' => "http://example.net/logo.png"]);
|
||||
$exp = HTTP::respEmpty(301, ['Location' => "http://example.net/logo.png"]);
|
||||
$this->assertMessage($exp, $this->req("2112.ico"));
|
||||
$exp = new Response(301, ['Location' => "http://example.org/icon.gif"]);
|
||||
$exp = HTTP::respEmpty(301, ['Location' => "http://example.org/icon.gif"]);
|
||||
$this->assertMessage($exp, $this->req("1337.ico"));
|
||||
// these requests should fail
|
||||
$exp = new Response(404);
|
||||
$exp = HTTP::respEmpty(404);
|
||||
$this->assertMessage($exp, $this->req("ook.ico"));
|
||||
$this->assertMessage($exp, $this->req("ook"));
|
||||
$this->assertMessage($exp, $this->req("47.ico"));
|
||||
$this->assertMessage($exp, $this->req("2112.png"));
|
||||
$this->assertMessage($exp, $this->req("1123.ico"));
|
||||
// only GET is allowed
|
||||
$exp = new Response(405, ['Allow' => "GET"]);
|
||||
$exp = HTTP::respEmpty(405, ['Allow' => "GET"]);
|
||||
$this->assertMessage($exp, $this->req("2112.ico", "PUT"));
|
||||
}
|
||||
|
||||
|
@ -79,32 +79,32 @@ class TestIcon extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$this->dbMock->subscriptionIcon->with(null, 2112, false)->returns($url);
|
||||
$this->dbMock->subscriptionIcon->with(null, 1337, false)->returns($url);
|
||||
// these requests should succeed
|
||||
$exp = new Response(301, ['Location' => "http://example.org/icon.gif"]);
|
||||
$exp = HTTP::respEmpty(301, ['Location' => "http://example.org/icon.gif"]);
|
||||
$this->assertMessage($exp, $this->req("42.ico"));
|
||||
$this->assertMessage($exp, $this->req("2112.ico"));
|
||||
$this->assertMessage($exp, $this->req("1337.ico"));
|
||||
$this->assertMessage($exp, $this->reqAuth("42.ico"));
|
||||
$this->assertMessage($exp, $this->reqAuth("1337.ico"));
|
||||
// these requests should fail
|
||||
$exp = new Response(404);
|
||||
$exp = HTTP::respEmpty(404);
|
||||
$this->assertMessage($exp, $this->reqAuth("2112.ico"));
|
||||
$exp = new Response(401);
|
||||
$exp = HTTP::respEmpty(401);
|
||||
$this->assertMessage($exp, $this->reqAuthFailed("42.ico"));
|
||||
$this->assertMessage($exp, $this->reqAuthFailed("1337.ico"));
|
||||
// with HTTP auth required, only authenticated requests should succeed
|
||||
self::setConf(['userHTTPAuthRequired' => true]);
|
||||
$exp = new Response(301, ['Location' => "http://example.org/icon.gif"]);
|
||||
$exp = HTTP::respEmpty(301, ['Location' => "http://example.org/icon.gif"]);
|
||||
$this->assertMessage($exp, $this->reqAuth("42.ico"));
|
||||
$this->assertMessage($exp, $this->reqAuth("1337.ico"));
|
||||
// anything else should fail
|
||||
$exp = new Response(401);
|
||||
$exp = HTTP::respEmpty(401);
|
||||
$this->assertMessage($exp, $this->req("42.ico"));
|
||||
$this->assertMessage($exp, $this->req("2112.ico"));
|
||||
$this->assertMessage($exp, $this->req("1337.ico"));
|
||||
$this->assertMessage($exp, $this->reqAuthFailed("42.ico"));
|
||||
$this->assertMessage($exp, $this->reqAuthFailed("1337.ico"));
|
||||
// resources for the wrtong user should still fail, too
|
||||
$exp = new Response(404);
|
||||
$exp = HTTP::respEmpty(404);
|
||||
$this->assertMessage($exp, $this->reqAuth("2112.ico"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,15 +17,13 @@ use JKingWeb\Arsse\Db\Driver;
|
|||
use JKingWeb\Arsse\Db\Result;
|
||||
use JKingWeb\Arsse\Factory;
|
||||
use JKingWeb\Arsse\Misc\Date;
|
||||
use JKingWeb\Arsse\Misc\ValueInfo;
|
||||
use JKingWeb\Arsse\Misc\URL;
|
||||
use JKingWeb\Arsse\Misc\HTTP;
|
||||
use Psr\Http\Message\MessageInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Laminas\Diactoros\ServerRequest;
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Laminas\Diactoros\Response\XmlResponse;
|
||||
use GuzzleHttp\Psr7\ServerRequest;
|
||||
|
||||
/** @coversNothing */
|
||||
abstract class AbstractTest extends \PHPUnit\Framework\TestCase {
|
||||
|
@ -258,7 +256,8 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase {
|
|||
}
|
||||
}
|
||||
$server = array_merge($server, $vars);
|
||||
$req = new ServerRequest($server, [], $url, $method, "php://memory", [], [], $params, $parsedBody);
|
||||
$req = new ServerRequest($method, $url, $headers, $body, "1.1", $server);
|
||||
$req = $req->withParsedBody($parsedBody)->withQueryParams($params);
|
||||
if (isset($user)) {
|
||||
if (strlen($user)) {
|
||||
$req = $req->withAttribute("authenticated", true)->withAttribute("authenticatedUser", $user);
|
||||
|
@ -337,12 +336,13 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase {
|
|||
$this->assertSame($exp->getMethod(), $act->getMethod(), $text);
|
||||
$this->assertSame($exp->getRequestTarget(), $act->getRequestTarget(), $text);
|
||||
}
|
||||
if ($exp instanceof JsonResponse) {
|
||||
$this->assertInstanceOf(JsonResponse::class, $act, $text);
|
||||
$this->assertEquals($exp->getPayload(), $act->getPayload(), $text);
|
||||
$this->assertSame($exp->getPayload(), $act->getPayload(), $text);
|
||||
} elseif ($exp instanceof XmlResponse) {
|
||||
$this->assertInstanceOf(XmlResponse::class, $act, $text);
|
||||
if ($exp instanceof ResponseInterface && HTTP::matchType($exp, "application/json", "text/json", "+json")) {
|
||||
$expBody = @json_decode((string) $exp->getBody(), true);
|
||||
$actBody = @json_decode((string) $act->getBody(), true);
|
||||
$this->assertSame(\JSON_ERROR_NONE, json_last_error(), "Response body is not valid JSON");
|
||||
$this->assertEquals($expBody, $actBody, $text);
|
||||
$this->assertSame($expBody, $actBody, $text);
|
||||
} elseif ($exp instanceof ResponseInterface && HTTP::matchType($exp, "application/xml", "text/xml", "+xml")) {
|
||||
$this->assertXmlStringEqualsXmlString((string) $exp->getBody(), (string) $act->getBody(), $text);
|
||||
} else {
|
||||
$this->assertSame((string) $exp->getBody(), (string) $act->getBody(), $text);
|
||||
|
@ -350,6 +350,16 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase {
|
|||
$this->assertEquals($exp->getHeaders(), $act->getHeaders(), $text);
|
||||
}
|
||||
|
||||
protected function extractMessageJson(MessageInterface $msg) {
|
||||
if (HTTP::matchType($msg, "application/json", "text/json", "+json")) {
|
||||
$json = @json_decode((string) $msg->getBody(), true);
|
||||
if (json_last_error() === \JSON_ERROR_NONE) {
|
||||
return $json;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function assertTime($exp, $test, string $msg = ''): void {
|
||||
$test = $this->approximateTime($exp, $test);
|
||||
$exp = Date::transform($exp, "iso8601");
|
||||
|
@ -388,7 +398,7 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase {
|
|||
}
|
||||
|
||||
/** Inserts into the database test data in the following format:
|
||||
*
|
||||
*
|
||||
* ```php
|
||||
* $data = [
|
||||
* 'some_table' => [
|
||||
|
@ -482,7 +492,7 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase {
|
|||
// now search for the actual output row in the expected output
|
||||
$found = array_keys($exp, $row, true);
|
||||
foreach ($found as $k) {
|
||||
if(!isset($act[$k])) {
|
||||
if (!isset($act[$k])) {
|
||||
$act[$k] = $row;
|
||||
// skip to the next row
|
||||
continue 2;
|
||||
|
|
|
@ -115,7 +115,6 @@
|
|||
<file>cases/REST/TestREST.php</file>
|
||||
</testsuite>
|
||||
<testsuite name="Miniflux">
|
||||
<file>cases/REST/Miniflux/TestErrorResponse.php</file>
|
||||
<file>cases/REST/Miniflux/TestStatus.php</file>
|
||||
<file>cases/REST/Miniflux/TestV1.php</file>
|
||||
<file>cases/REST/Miniflux/TestToken.php</file>
|
||||
|
|
317
vendor-bin/csfixer/composer.lock
generated
317
vendor-bin/csfixer/composer.lock
generated
|
@ -227,16 +227,16 @@
|
|||
},
|
||||
{
|
||||
"name": "doctrine/annotations",
|
||||
"version": "1.13.2",
|
||||
"version": "1.13.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/annotations.git",
|
||||
"reference": "5b668aef16090008790395c02c893b1ba13f7e08"
|
||||
"reference": "648b0343343565c4a056bfc8392201385e8d89f0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/annotations/zipball/5b668aef16090008790395c02c893b1ba13f7e08",
|
||||
"reference": "5b668aef16090008790395c02c893b1ba13f7e08",
|
||||
"url": "https://api.github.com/repos/doctrine/annotations/zipball/648b0343343565c4a056bfc8392201385e8d89f0",
|
||||
"reference": "648b0343343565c4a056bfc8392201385e8d89f0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -248,9 +248,10 @@
|
|||
"require-dev": {
|
||||
"doctrine/cache": "^1.11 || ^2.0",
|
||||
"doctrine/coding-standard": "^6.0 || ^8.1",
|
||||
"phpstan/phpstan": "^0.12.20",
|
||||
"phpstan/phpstan": "^1.4.10 || ^1.8.0",
|
||||
"phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5",
|
||||
"symfony/cache": "^4.4 || ^5.2"
|
||||
"symfony/cache": "^4.4 || ^5.2",
|
||||
"vimeo/psalm": "^4.10"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
|
@ -293,9 +294,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/doctrine/annotations/issues",
|
||||
"source": "https://github.com/doctrine/annotations/tree/1.13.2"
|
||||
"source": "https://github.com/doctrine/annotations/tree/1.13.3"
|
||||
},
|
||||
"time": "2021-08-05T19:00:23+00:00"
|
||||
"time": "2022-07-02T10:48:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/lexer",
|
||||
|
@ -375,16 +376,16 @@
|
|||
},
|
||||
{
|
||||
"name": "friendsofphp/php-cs-fixer",
|
||||
"version": "v3.8.0",
|
||||
"version": "v3.11.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git",
|
||||
"reference": "cbad1115aac4b5c3c5540e7210d3c9fba2f81fa3"
|
||||
"reference": "7dcdea3f2f5f473464e835be9be55283ff8cfdc3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/cbad1115aac4b5c3c5540e7210d3c9fba2f81fa3",
|
||||
"reference": "cbad1115aac4b5c3c5540e7210d3c9fba2f81fa3",
|
||||
"url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/7dcdea3f2f5f473464e835be9be55283ff8cfdc3",
|
||||
"reference": "7dcdea3f2f5f473464e835be9be55283ff8cfdc3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -394,7 +395,7 @@
|
|||
"ext-json": "*",
|
||||
"ext-tokenizer": "*",
|
||||
"php": "^7.4 || ^8.0",
|
||||
"php-cs-fixer/diff": "^2.0",
|
||||
"sebastian/diff": "^4.0",
|
||||
"symfony/console": "^5.4 || ^6.0",
|
||||
"symfony/event-dispatcher": "^5.4 || ^6.0",
|
||||
"symfony/filesystem": "^5.4 || ^6.0",
|
||||
|
@ -452,7 +453,7 @@
|
|||
"description": "A tool to automatically fix PHP code style",
|
||||
"support": {
|
||||
"issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues",
|
||||
"source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v3.8.0"
|
||||
"source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v3.11.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -460,59 +461,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-18T17:20:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-cs-fixer/diff",
|
||||
"version": "v2.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHP-CS-Fixer/diff.git",
|
||||
"reference": "29dc0d507e838c4580d018bd8b5cb412474f7ec3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/29dc0d507e838c4580d018bd8b5cb412474f7ec3",
|
||||
"reference": "29dc0d507e838c4580d018bd8b5cb412474f7ec3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.6 || ^7.0 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^5.7.23 || ^6.4.3 || ^7.0",
|
||||
"symfony/process": "^3.3"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"email": "sebastian@phpunit.de"
|
||||
},
|
||||
{
|
||||
"name": "Kore Nordmann",
|
||||
"email": "mail@kore-nordmann.de"
|
||||
}
|
||||
],
|
||||
"description": "sebastian/diff v3 backport support for PHP 5.6+",
|
||||
"homepage": "https://github.com/PHP-CS-Fixer",
|
||||
"keywords": [
|
||||
"diff"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/PHP-CS-Fixer/diff/issues",
|
||||
"source": "https://github.com/PHP-CS-Fixer/diff/tree/v2.0.2"
|
||||
},
|
||||
"time": "2020-10-14T08:32:19+00:00"
|
||||
"time": "2022-09-01T18:24:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/cache",
|
||||
|
@ -717,17 +666,83 @@
|
|||
"time": "2021-07-14T16:46:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v6.1.0",
|
||||
"name": "sebastian/diff",
|
||||
"version": "4.0.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "c9646197ef43b0e2ff44af61e7f0571526fd4170"
|
||||
"url": "https://github.com/sebastianbergmann/diff.git",
|
||||
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/c9646197ef43b0e2ff44af61e7f0571526fd4170",
|
||||
"reference": "c9646197ef43b0e2ff44af61e7f0571526fd4170",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d",
|
||||
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.3",
|
||||
"symfony/process": "^4.2 || ^5"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"email": "sebastian@phpunit.de"
|
||||
},
|
||||
{
|
||||
"name": "Kore Nordmann",
|
||||
"email": "mail@kore-nordmann.de"
|
||||
}
|
||||
],
|
||||
"description": "Diff implementation",
|
||||
"homepage": "https://github.com/sebastianbergmann/diff",
|
||||
"keywords": [
|
||||
"diff",
|
||||
"udiff",
|
||||
"unidiff",
|
||||
"unified diff"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/diff/issues",
|
||||
"source": "https://github.com/sebastianbergmann/diff/tree/4.0.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/sebastianbergmann",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2020-10-26T13:10:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v6.1.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "7fccea8728aa2d431a6725b02b3ce759049fc84d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/7fccea8728aa2d431a6725b02b3ce759049fc84d",
|
||||
"reference": "7fccea8728aa2d431a6725b02b3ce759049fc84d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -794,7 +809,7 @@
|
|||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v6.1.0"
|
||||
"source": "https://github.com/symfony/console/tree/v6.1.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -810,11 +825,11 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-27T06:34:22+00:00"
|
||||
"time": "2022-08-26T10:32:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
"version": "v3.1.0",
|
||||
"version": "v3.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/deprecation-contracts.git",
|
||||
|
@ -861,7 +876,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.1.0"
|
||||
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -964,7 +979,7 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher-contracts",
|
||||
"version": "v3.1.0",
|
||||
"version": "v3.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/event-dispatcher-contracts.git",
|
||||
|
@ -1023,7 +1038,7 @@
|
|||
"standards"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.1.0"
|
||||
"source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1043,16 +1058,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v6.1.0",
|
||||
"version": "v6.1.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/filesystem.git",
|
||||
"reference": "3132d2f43ca799c2aa099f9738d98228c56baa5d"
|
||||
"reference": "3f39c04d2630c34019907b02f85672dac99f8659"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/3132d2f43ca799c2aa099f9738d98228c56baa5d",
|
||||
"reference": "3132d2f43ca799c2aa099f9738d98228c56baa5d",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/3f39c04d2630c34019907b02f85672dac99f8659",
|
||||
"reference": "3f39c04d2630c34019907b02f85672dac99f8659",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1086,7 +1101,7 @@
|
|||
"description": "Provides basic utilities for the filesystem",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/filesystem/tree/v6.1.0"
|
||||
"source": "https://github.com/symfony/filesystem/tree/v6.1.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1102,20 +1117,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-21T13:34:40+00:00"
|
||||
"time": "2022-08-02T16:17:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
"version": "v6.1.0",
|
||||
"version": "v6.1.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/finder.git",
|
||||
"reference": "45b8beb69d6eb3b05a65689ebfd4222326773f8f"
|
||||
"reference": "39696bff2c2970b3779a5cac7bf9f0b88fc2b709"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/45b8beb69d6eb3b05a65689ebfd4222326773f8f",
|
||||
"reference": "45b8beb69d6eb3b05a65689ebfd4222326773f8f",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/39696bff2c2970b3779a5cac7bf9f0b88fc2b709",
|
||||
"reference": "39696bff2c2970b3779a5cac7bf9f0b88fc2b709",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1150,7 +1165,7 @@
|
|||
"description": "Finds files and directories via an intuitive fluent interface",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/finder/tree/v6.1.0"
|
||||
"source": "https://github.com/symfony/finder/tree/v6.1.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1166,7 +1181,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-04-15T08:08:08+00:00"
|
||||
"time": "2022-07-29T07:42:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/options-resolver",
|
||||
|
@ -1237,16 +1252,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
"reference": "30885182c981ab175d4d034db0f6f469898070ab"
|
||||
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab",
|
||||
"reference": "30885182c981ab175d4d034db0f6f469898070ab",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
|
||||
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1261,7 +1276,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1299,7 +1314,7 @@
|
|||
"portable"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1315,20 +1330,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-10-20T20:35:02+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-grapheme",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
|
||||
"reference": "81b86b50cf841a64252b439e738e97f4a34e2783"
|
||||
"reference": "433d05519ce6990bf3530fba6957499d327395c2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/81b86b50cf841a64252b439e738e97f4a34e2783",
|
||||
"reference": "81b86b50cf841a64252b439e738e97f4a34e2783",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2",
|
||||
"reference": "433d05519ce6990bf3530fba6957499d327395c2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1340,7 +1355,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1380,7 +1395,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1396,20 +1411,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-11-23T21:10:46+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-normalizer",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
||||
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8"
|
||||
"reference": "219aa369ceff116e673852dce47c3a41794c14bd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8",
|
||||
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
|
||||
"reference": "219aa369ceff116e673852dce47c3a41794c14bd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1421,7 +1436,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1464,7 +1479,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1480,20 +1495,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-02-19T12:13:01+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825"
|
||||
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825",
|
||||
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
|
||||
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1508,7 +1523,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1547,7 +1562,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1563,20 +1578,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-11-30T18:21:41+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c"
|
||||
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c",
|
||||
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
|
||||
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1585,7 +1600,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1630,7 +1645,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1646,20 +1661,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-04T08:16:47+00:00"
|
||||
"time": "2022-05-10T07:21:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php81",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php81.git",
|
||||
"reference": "5de4ba2d41b15f9bd0e19b2ab9674135813ec98f"
|
||||
"reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/5de4ba2d41b15f9bd0e19b2ab9674135813ec98f",
|
||||
"reference": "5de4ba2d41b15f9bd0e19b2ab9674135813ec98f",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/13f6d1271c663dc5ae9fb843a8f16521db7687a1",
|
||||
"reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1668,7 +1683,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1709,7 +1724,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php81/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-php81/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1725,20 +1740,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-09-13T13:58:11+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
"version": "v6.1.0",
|
||||
"version": "v6.1.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/process.git",
|
||||
"reference": "318718453c2be58266f1a9e74063d13cb8dd4165"
|
||||
"reference": "a6506e99cfad7059b1ab5cab395854a0a0c21292"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/318718453c2be58266f1a9e74063d13cb8dd4165",
|
||||
"reference": "318718453c2be58266f1a9e74063d13cb8dd4165",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/a6506e99cfad7059b1ab5cab395854a0a0c21292",
|
||||
"reference": "a6506e99cfad7059b1ab5cab395854a0a0c21292",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1770,7 +1785,7 @@
|
|||
"description": "Executes commands in sub-processes",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/process/tree/v6.1.0"
|
||||
"source": "https://github.com/symfony/process/tree/v6.1.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1786,20 +1801,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-11T12:12:29+00:00"
|
||||
"time": "2022-06-27T17:24:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/service-contracts",
|
||||
"version": "v3.1.0",
|
||||
"version": "v3.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/service-contracts.git",
|
||||
"reference": "d66cd8ab656780f62c4215b903a420eb86358957"
|
||||
"reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/d66cd8ab656780f62c4215b903a420eb86358957",
|
||||
"reference": "d66cd8ab656780f62c4215b903a420eb86358957",
|
||||
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/925e713fe8fcacf6bc05e936edd8dd5441a21239",
|
||||
"reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1855,7 +1870,7 @@
|
|||
"standards"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/service-contracts/tree/v3.1.0"
|
||||
"source": "https://github.com/symfony/service-contracts/tree/v3.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1871,7 +1886,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-07T08:07:09+00:00"
|
||||
"time": "2022-05-30T19:18:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/stopwatch",
|
||||
|
@ -1937,16 +1952,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/string",
|
||||
"version": "v6.1.0",
|
||||
"version": "v6.1.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/string.git",
|
||||
"reference": "d3edc75baf9f1d4f94879764dda2e1ac33499529"
|
||||
"reference": "290972cad7b364e3befaa74ba0ec729800fb161c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/d3edc75baf9f1d4f94879764dda2e1ac33499529",
|
||||
"reference": "d3edc75baf9f1d4f94879764dda2e1ac33499529",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/290972cad7b364e3befaa74ba0ec729800fb161c",
|
||||
"reference": "290972cad7b364e3befaa74ba0ec729800fb161c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2002,7 +2017,7 @@
|
|||
"utf8"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/string/tree/v6.1.0"
|
||||
"source": "https://github.com/symfony/string/tree/v6.1.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -2018,7 +2033,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-04-22T08:18:23+00:00"
|
||||
"time": "2022-08-12T18:05:43+00:00"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
|
|
277
vendor-bin/daux/composer.lock
generated
277
vendor-bin/daux/composer.lock
generated
|
@ -83,22 +83,22 @@
|
|||
},
|
||||
{
|
||||
"name": "guzzlehttp/guzzle",
|
||||
"version": "7.4.3",
|
||||
"version": "7.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/guzzle.git",
|
||||
"reference": "74a8602c6faec9ef74b7a9391ac82c5e65b1cdab"
|
||||
"reference": "b50a2a1251152e43f6a37f0fa053e730a67d25ba"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/74a8602c6faec9ef74b7a9391ac82c5e65b1cdab",
|
||||
"reference": "74a8602c6faec9ef74b7a9391ac82c5e65b1cdab",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/b50a2a1251152e43f6a37f0fa053e730a67d25ba",
|
||||
"reference": "b50a2a1251152e43f6a37f0fa053e730a67d25ba",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"guzzlehttp/promises": "^1.5",
|
||||
"guzzlehttp/psr7": "^1.8.3 || ^2.1",
|
||||
"guzzlehttp/psr7": "^1.9 || ^2.4",
|
||||
"php": "^7.2.5 || ^8.0",
|
||||
"psr/http-client": "^1.0",
|
||||
"symfony/deprecation-contracts": "^2.2 || ^3.0"
|
||||
|
@ -107,10 +107,10 @@
|
|||
"psr/http-client-implementation": "1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"bamarni/composer-bin-plugin": "^1.4.1",
|
||||
"bamarni/composer-bin-plugin": "^1.8.1",
|
||||
"ext-curl": "*",
|
||||
"php-http/client-integration-tests": "^3.0",
|
||||
"phpunit/phpunit": "^8.5.5 || ^9.3.5",
|
||||
"phpunit/phpunit": "^8.5.29 || ^9.5.23",
|
||||
"psr/log": "^1.1 || ^2.0 || ^3.0"
|
||||
},
|
||||
"suggest": {
|
||||
|
@ -120,8 +120,12 @@
|
|||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"bamarni-bin": {
|
||||
"bin-links": true,
|
||||
"forward-command": false
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-master": "7.4-dev"
|
||||
"dev-master": "7.5-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -187,7 +191,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/guzzle/guzzle/issues",
|
||||
"source": "https://github.com/guzzle/guzzle/tree/7.4.3"
|
||||
"source": "https://github.com/guzzle/guzzle/tree/7.5.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -203,20 +207,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-25T13:24:33+00:00"
|
||||
"time": "2022-08-28T15:39:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/promises",
|
||||
"version": "1.5.1",
|
||||
"version": "1.5.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/promises.git",
|
||||
"reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da"
|
||||
"reference": "b94b2807d85443f9719887892882d0329d1e2598"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/promises/zipball/fe752aedc9fd8fcca3fe7ad05d419d32998a06da",
|
||||
"reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da",
|
||||
"url": "https://api.github.com/repos/guzzle/promises/zipball/b94b2807d85443f9719887892882d0329d1e2598",
|
||||
"reference": "b94b2807d85443f9719887892882d0329d1e2598",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -271,7 +275,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/guzzle/promises/issues",
|
||||
"source": "https://github.com/guzzle/promises/tree/1.5.1"
|
||||
"source": "https://github.com/guzzle/promises/tree/1.5.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -287,20 +291,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-10-22T20:56:57+00:00"
|
||||
"time": "2022-08-28T14:55:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/psr7",
|
||||
"version": "2.2.1",
|
||||
"version": "2.4.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/psr7.git",
|
||||
"reference": "c94a94f120803a18554c1805ef2e539f8285f9a2"
|
||||
"reference": "69568e4293f4fa993f3b0e51c9723e1e17c41379"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/c94a94f120803a18554c1805ef2e539f8285f9a2",
|
||||
"reference": "c94a94f120803a18554c1805ef2e539f8285f9a2",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/69568e4293f4fa993f3b0e51c9723e1e17c41379",
|
||||
"reference": "69568e4293f4fa993f3b0e51c9723e1e17c41379",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -314,17 +318,21 @@
|
|||
"psr/http-message-implementation": "1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"bamarni/composer-bin-plugin": "^1.4.1",
|
||||
"bamarni/composer-bin-plugin": "^1.8.1",
|
||||
"http-interop/http-factory-tests": "^0.9",
|
||||
"phpunit/phpunit": "^8.5.8 || ^9.3.10"
|
||||
"phpunit/phpunit": "^8.5.29 || ^9.5.23"
|
||||
},
|
||||
"suggest": {
|
||||
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"bamarni-bin": {
|
||||
"bin-links": true,
|
||||
"forward-command": false
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-master": "2.2-dev"
|
||||
"dev-master": "2.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -386,7 +394,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/guzzle/psr7/issues",
|
||||
"source": "https://github.com/guzzle/psr7/tree/2.2.1"
|
||||
"source": "https://github.com/guzzle/psr7/tree/2.4.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -402,7 +410,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-20T21:55:58+00:00"
|
||||
"time": "2022-08-28T14:45:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/commonmark",
|
||||
|
@ -898,16 +906,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v5.4.9",
|
||||
"version": "v5.4.12",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "829d5d1bf60b2efeb0887b7436873becc71a45eb"
|
||||
"reference": "c072aa8f724c3af64e2c7a96b796a4863d24dba1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/829d5d1bf60b2efeb0887b7436873becc71a45eb",
|
||||
"reference": "829d5d1bf60b2efeb0887b7436873becc71a45eb",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/c072aa8f724c3af64e2c7a96b796a4863d24dba1",
|
||||
"reference": "c072aa8f724c3af64e2c7a96b796a4863d24dba1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -977,7 +985,7 @@
|
|||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v5.4.9"
|
||||
"source": "https://github.com/symfony/console/tree/v5.4.12"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -993,11 +1001,11 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-18T06:17:34+00:00"
|
||||
"time": "2022-08-17T13:18:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
"version": "v3.1.0",
|
||||
"version": "v3.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/deprecation-contracts.git",
|
||||
|
@ -1044,7 +1052,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.1.0"
|
||||
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1064,16 +1072,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/http-foundation",
|
||||
"version": "v5.4.9",
|
||||
"version": "v5.4.12",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/http-foundation.git",
|
||||
"reference": "6b0d0e4aca38d57605dcd11e2416994b38774522"
|
||||
"reference": "f4bfe9611b113b15d98a43da68ec9b5a00d56791"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/6b0d0e4aca38d57605dcd11e2416994b38774522",
|
||||
"reference": "6b0d0e4aca38d57605dcd11e2416994b38774522",
|
||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/f4bfe9611b113b15d98a43da68ec9b5a00d56791",
|
||||
"reference": "f4bfe9611b113b15d98a43da68ec9b5a00d56791",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1085,8 +1093,11 @@
|
|||
"require-dev": {
|
||||
"predis/predis": "~1.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",
|
||||
"symfony/mime": "^4.4|^5.0|^6.0"
|
||||
"symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4",
|
||||
"symfony/mime": "^4.4|^5.0|^6.0",
|
||||
"symfony/rate-limiter": "^5.2|^6.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/mime": "To use the file extension guesser"
|
||||
|
@ -1117,7 +1128,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.9"
|
||||
"source": "https://github.com/symfony/http-foundation/tree/v5.4.12"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1133,20 +1144,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-17T15:07:29+00:00"
|
||||
"time": "2022-08-19T07:33:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/mime",
|
||||
"version": "v5.4.9",
|
||||
"version": "v5.4.12",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/mime.git",
|
||||
"reference": "2b3802a24e48d0cfccf885173d2aac91e73df92e"
|
||||
"reference": "03876e9c5a36f5b45e7d9a381edda5421eff8a90"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/mime/zipball/2b3802a24e48d0cfccf885173d2aac91e73df92e",
|
||||
"reference": "2b3802a24e48d0cfccf885173d2aac91e73df92e",
|
||||
"url": "https://api.github.com/repos/symfony/mime/zipball/03876e9c5a36f5b45e7d9a381edda5421eff8a90",
|
||||
"reference": "03876e9c5a36f5b45e7d9a381edda5421eff8a90",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1200,7 +1211,7 @@
|
|||
"mime-type"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/mime/tree/v5.4.9"
|
||||
"source": "https://github.com/symfony/mime/tree/v5.4.12"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1216,20 +1227,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-21T10:24:18+00:00"
|
||||
"time": "2022-08-19T14:24:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
"reference": "30885182c981ab175d4d034db0f6f469898070ab"
|
||||
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab",
|
||||
"reference": "30885182c981ab175d4d034db0f6f469898070ab",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
|
||||
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1244,7 +1255,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1282,7 +1293,7 @@
|
|||
"portable"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1298,20 +1309,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-10-20T20:35:02+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-grapheme",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
|
||||
"reference": "81b86b50cf841a64252b439e738e97f4a34e2783"
|
||||
"reference": "433d05519ce6990bf3530fba6957499d327395c2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/81b86b50cf841a64252b439e738e97f4a34e2783",
|
||||
"reference": "81b86b50cf841a64252b439e738e97f4a34e2783",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2",
|
||||
"reference": "433d05519ce6990bf3530fba6957499d327395c2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1323,7 +1334,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1363,7 +1374,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1379,20 +1390,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-11-23T21:10:46+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-icu",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-icu.git",
|
||||
"reference": "c023a439b8551e320cc3c8433b198e408a623af1"
|
||||
"reference": "e407643d610e5f2c8a4b14189150f68934bf5e48"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/c023a439b8551e320cc3c8433b198e408a623af1",
|
||||
"reference": "c023a439b8551e320cc3c8433b198e408a623af1",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/e407643d610e5f2c8a4b14189150f68934bf5e48",
|
||||
"reference": "e407643d610e5f2c8a4b14189150f68934bf5e48",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1404,7 +1415,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1450,7 +1461,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1466,20 +1477,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-10-26T17:16:04+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-idn",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-idn.git",
|
||||
"reference": "749045c69efb97c70d25d7463abba812e91f3a44"
|
||||
"reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/749045c69efb97c70d25d7463abba812e91f3a44",
|
||||
"reference": "749045c69efb97c70d25d7463abba812e91f3a44",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/59a8d271f00dd0e4c2e518104cc7963f655a1aa8",
|
||||
"reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1493,7 +1504,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1537,7 +1548,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1553,20 +1564,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-09-14T14:02:44+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-normalizer",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
||||
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8"
|
||||
"reference": "219aa369ceff116e673852dce47c3a41794c14bd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8",
|
||||
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
|
||||
"reference": "219aa369ceff116e673852dce47c3a41794c14bd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1578,7 +1589,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1621,7 +1632,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1637,20 +1648,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-02-19T12:13:01+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825"
|
||||
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825",
|
||||
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
|
||||
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1665,7 +1676,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1704,7 +1715,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1720,20 +1731,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-11-30T18:21:41+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php72",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php72.git",
|
||||
"reference": "9a142215a36a3888e30d0a9eeea9766764e96976"
|
||||
"reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9a142215a36a3888e30d0a9eeea9766764e96976",
|
||||
"reference": "9a142215a36a3888e30d0a9eeea9766764e96976",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/bf44a9fd41feaac72b074de600314a93e2ae78e2",
|
||||
"reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1742,7 +1753,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1780,7 +1791,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php72/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-php72/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1796,20 +1807,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-05-27T09:17:38+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php73",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php73.git",
|
||||
"reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5"
|
||||
"reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/cc5db0e22b3cb4111010e48785a97f670b350ca5",
|
||||
"reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/e440d35fa0286f77fb45b79a03fedbeda9307e85",
|
||||
"reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1818,7 +1829,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1859,7 +1870,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php73/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-php73/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1875,20 +1886,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-06-05T21:20:04+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c"
|
||||
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c",
|
||||
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
|
||||
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1897,7 +1908,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1942,7 +1953,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1958,20 +1969,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-04T08:16:47+00:00"
|
||||
"time": "2022-05-10T07:21:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
"version": "v5.4.8",
|
||||
"version": "v5.4.11",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/process.git",
|
||||
"reference": "597f3fff8e3e91836bb0bd38f5718b56ddbde2f3"
|
||||
"reference": "6e75fe6874cbc7e4773d049616ab450eff537bf1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/597f3fff8e3e91836bb0bd38f5718b56ddbde2f3",
|
||||
"reference": "597f3fff8e3e91836bb0bd38f5718b56ddbde2f3",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/6e75fe6874cbc7e4773d049616ab450eff537bf1",
|
||||
"reference": "6e75fe6874cbc7e4773d049616ab450eff537bf1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2004,7 +2015,7 @@
|
|||
"description": "Executes commands in sub-processes",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/process/tree/v5.4.8"
|
||||
"source": "https://github.com/symfony/process/tree/v5.4.11"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -2020,20 +2031,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-04-08T05:07:18+00:00"
|
||||
"time": "2022-06-27T16:58:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/service-contracts",
|
||||
"version": "v3.1.0",
|
||||
"version": "v3.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/service-contracts.git",
|
||||
"reference": "d66cd8ab656780f62c4215b903a420eb86358957"
|
||||
"reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/d66cd8ab656780f62c4215b903a420eb86358957",
|
||||
"reference": "d66cd8ab656780f62c4215b903a420eb86358957",
|
||||
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/925e713fe8fcacf6bc05e936edd8dd5441a21239",
|
||||
"reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2089,7 +2100,7 @@
|
|||
"standards"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/service-contracts/tree/v3.1.0"
|
||||
"source": "https://github.com/symfony/service-contracts/tree/v3.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -2105,20 +2116,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-07T08:07:09+00:00"
|
||||
"time": "2022-05-30T19:18:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/string",
|
||||
"version": "v6.1.0",
|
||||
"version": "v6.1.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/string.git",
|
||||
"reference": "d3edc75baf9f1d4f94879764dda2e1ac33499529"
|
||||
"reference": "290972cad7b364e3befaa74ba0ec729800fb161c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/d3edc75baf9f1d4f94879764dda2e1ac33499529",
|
||||
"reference": "d3edc75baf9f1d4f94879764dda2e1ac33499529",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/290972cad7b364e3befaa74ba0ec729800fb161c",
|
||||
"reference": "290972cad7b364e3befaa74ba0ec729800fb161c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2174,7 +2185,7 @@
|
|||
"utf8"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/string/tree/v6.1.0"
|
||||
"source": "https://github.com/symfony/string/tree/v6.1.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -2190,20 +2201,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-04-22T08:18:23+00:00"
|
||||
"time": "2022-08-12T18:05:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v5.4.3",
|
||||
"version": "v5.4.12",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "e80f87d2c9495966768310fc531b487ce64237a2"
|
||||
"reference": "7a3aa21ac8ab1a96cc6de5bbcab4bc9fc943b18c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/e80f87d2c9495966768310fc531b487ce64237a2",
|
||||
"reference": "e80f87d2c9495966768310fc531b487ce64237a2",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/7a3aa21ac8ab1a96cc6de5bbcab4bc9fc943b18c",
|
||||
"reference": "7a3aa21ac8ab1a96cc6de5bbcab4bc9fc943b18c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2249,7 +2260,7 @@
|
|||
"description": "Loads and dumps YAML files",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/yaml/tree/v5.4.3"
|
||||
"source": "https://github.com/symfony/yaml/tree/v5.4.12"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -2265,7 +2276,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-01-26T16:32:32+00:00"
|
||||
"time": "2022-08-02T15:52:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "webuni/front-matter",
|
||||
|
|
460
vendor-bin/phpunit/composer.lock
generated
460
vendor-bin/phpunit/composer.lock
generated
|
@ -338,16 +338,16 @@
|
|||
},
|
||||
{
|
||||
"name": "mikey179/vfsstream",
|
||||
"version": "v1.6.10",
|
||||
"version": "v1.6.11",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/bovigo/vfsStream.git",
|
||||
"reference": "250c0825537d501e327df879fb3d4cd751933b85"
|
||||
"reference": "17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/bovigo/vfsStream/zipball/250c0825537d501e327df879fb3d4cd751933b85",
|
||||
"reference": "250c0825537d501e327df879fb3d4cd751933b85",
|
||||
"url": "https://api.github.com/repos/bovigo/vfsStream/zipball/17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f",
|
||||
"reference": "17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -385,7 +385,7 @@
|
|||
"source": "https://github.com/bovigo/vfsStream/tree/master",
|
||||
"wiki": "https://github.com/bovigo/vfsStream/wiki"
|
||||
},
|
||||
"time": "2021-09-25T08:05:01+00:00"
|
||||
"time": "2022-02-23T02:02:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "myclabs/deep-copy",
|
||||
|
@ -448,16 +448,16 @@
|
|||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
"version": "v4.14.0",
|
||||
"version": "v4.15.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nikic/PHP-Parser.git",
|
||||
"reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1"
|
||||
"reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/34bea19b6e03d8153165d8f30bba4c3be86184c1",
|
||||
"reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
|
||||
"reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -498,9 +498,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nikic/PHP-Parser/issues",
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v4.14.0"
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.1"
|
||||
},
|
||||
"time": "2022-05-31T20:59:12+00:00"
|
||||
"time": "2022-09-04T07:30:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phar-io/manifest",
|
||||
|
@ -613,252 +613,25 @@
|
|||
},
|
||||
"time": "2022-02-21T01:04:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/reflection-common",
|
||||
"version": "2.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
|
||||
"reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b",
|
||||
"reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-2.x": "2.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"phpDocumentor\\Reflection\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jaap van Otterdijk",
|
||||
"email": "opensource@ijaap.nl"
|
||||
}
|
||||
],
|
||||
"description": "Common reflection classes used by phpdocumentor to reflect the code structure",
|
||||
"homepage": "http://www.phpdoc.org",
|
||||
"keywords": [
|
||||
"FQSEN",
|
||||
"phpDocumentor",
|
||||
"phpdoc",
|
||||
"reflection",
|
||||
"static analysis"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/phpDocumentor/ReflectionCommon/issues",
|
||||
"source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x"
|
||||
},
|
||||
"time": "2020-06-27T09:03:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/reflection-docblock",
|
||||
"version": "5.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
|
||||
"reference": "622548b623e81ca6d78b721c5e029f4ce664f170"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170",
|
||||
"reference": "622548b623e81ca6d78b721c5e029f4ce664f170",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-filter": "*",
|
||||
"php": "^7.2 || ^8.0",
|
||||
"phpdocumentor/reflection-common": "^2.2",
|
||||
"phpdocumentor/type-resolver": "^1.3",
|
||||
"webmozart/assert": "^1.9.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "~1.3.2",
|
||||
"psalm/phar": "^4.8"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"phpDocumentor\\Reflection\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Mike van Riel",
|
||||
"email": "me@mikevanriel.com"
|
||||
},
|
||||
{
|
||||
"name": "Jaap van Otterdijk",
|
||||
"email": "account@ijaap.nl"
|
||||
}
|
||||
],
|
||||
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
|
||||
"source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0"
|
||||
},
|
||||
"time": "2021-10-19T17:43:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/type-resolver",
|
||||
"version": "1.6.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpDocumentor/TypeResolver.git",
|
||||
"reference": "77a32518733312af16a44300404e945338981de3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3",
|
||||
"reference": "77a32518733312af16a44300404e945338981de3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0",
|
||||
"phpdocumentor/reflection-common": "^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-tokenizer": "*",
|
||||
"psalm/phar": "^4.8"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-1.x": "1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"phpDocumentor\\Reflection\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Mike van Riel",
|
||||
"email": "me@mikevanriel.com"
|
||||
}
|
||||
],
|
||||
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpDocumentor/TypeResolver/issues",
|
||||
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1"
|
||||
},
|
||||
"time": "2022-03-15T21:29:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpspec/prophecy",
|
||||
"version": "v1.15.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpspec/prophecy.git",
|
||||
"reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13",
|
||||
"reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/instantiator": "^1.2",
|
||||
"php": "^7.2 || ~8.0, <8.2",
|
||||
"phpdocumentor/reflection-docblock": "^5.2",
|
||||
"sebastian/comparator": "^3.0 || ^4.0",
|
||||
"sebastian/recursion-context": "^3.0 || ^4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpspec/phpspec": "^6.0 || ^7.0",
|
||||
"phpunit/phpunit": "^8.0 || ^9.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Prophecy\\": "src/Prophecy"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Konstantin Kudryashov",
|
||||
"email": "ever.zet@gmail.com",
|
||||
"homepage": "http://everzet.com"
|
||||
},
|
||||
{
|
||||
"name": "Marcello Duarte",
|
||||
"email": "marcello.duarte@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Highly opinionated mocking framework for PHP 5.3+",
|
||||
"homepage": "https://github.com/phpspec/prophecy",
|
||||
"keywords": [
|
||||
"Double",
|
||||
"Dummy",
|
||||
"fake",
|
||||
"mock",
|
||||
"spy",
|
||||
"stub"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/phpspec/prophecy/issues",
|
||||
"source": "https://github.com/phpspec/prophecy/tree/v1.15.0"
|
||||
},
|
||||
"time": "2021-12-08T12:19:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
"version": "9.2.15",
|
||||
"version": "9.2.17",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
||||
"reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f"
|
||||
"reference": "aa94dc41e8661fe90c7316849907cba3007b10d8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2e9da11878c4202f97915c1cb4bb1ca318a63f5f",
|
||||
"reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/aa94dc41e8661fe90c7316849907cba3007b10d8",
|
||||
"reference": "aa94dc41e8661fe90c7316849907cba3007b10d8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-libxml": "*",
|
||||
"ext-xmlwriter": "*",
|
||||
"nikic/php-parser": "^4.13.0",
|
||||
"nikic/php-parser": "^4.14",
|
||||
"php": ">=7.3",
|
||||
"phpunit/php-file-iterator": "^3.0.3",
|
||||
"phpunit/php-text-template": "^2.0.2",
|
||||
|
@ -907,7 +680,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.15"
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.17"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -915,7 +688,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-07T09:28:20+00:00"
|
||||
"time": "2022-08-30T12:24:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-file-iterator",
|
||||
|
@ -1160,16 +933,16 @@
|
|||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "9.5.20",
|
||||
"version": "9.5.24",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "12bc8879fb65aef2138b26fc633cb1e3620cffba"
|
||||
"reference": "d0aa6097bef9fd42458a9b3c49da32c6ce6129c5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/12bc8879fb65aef2138b26fc633cb1e3620cffba",
|
||||
"reference": "12bc8879fb65aef2138b26fc633cb1e3620cffba",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d0aa6097bef9fd42458a9b3c49da32c6ce6129c5",
|
||||
"reference": "d0aa6097bef9fd42458a9b3c49da32c6ce6129c5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1184,7 +957,6 @@
|
|||
"phar-io/manifest": "^2.0.3",
|
||||
"phar-io/version": "^3.0.2",
|
||||
"php": ">=7.3",
|
||||
"phpspec/prophecy": "^1.12.1",
|
||||
"phpunit/php-code-coverage": "^9.2.13",
|
||||
"phpunit/php-file-iterator": "^3.0.5",
|
||||
"phpunit/php-invoker": "^3.1.1",
|
||||
|
@ -1199,13 +971,9 @@
|
|||
"sebastian/global-state": "^5.0.1",
|
||||
"sebastian/object-enumerator": "^4.0.3",
|
||||
"sebastian/resource-operations": "^3.0.3",
|
||||
"sebastian/type": "^3.0",
|
||||
"sebastian/type": "^3.1",
|
||||
"sebastian/version": "^3.0.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-pdo": "*",
|
||||
"phpspec/prophecy-phpunit": "^2.0.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-soap": "*",
|
||||
"ext-xdebug": "*"
|
||||
|
@ -1247,7 +1015,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.20"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.24"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1259,7 +1027,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-04-01T12:37:26+00:00"
|
||||
"time": "2022-08-30T07:42:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/cli-parser",
|
||||
|
@ -1430,16 +1198,16 @@
|
|||
},
|
||||
{
|
||||
"name": "sebastian/comparator",
|
||||
"version": "4.0.6",
|
||||
"version": "4.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/comparator.git",
|
||||
"reference": "55f4261989e546dc112258c7a75935a81a7ce382"
|
||||
"reference": "fa0f136dd2334583309d32b62544682ee972b51a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382",
|
||||
"reference": "55f4261989e546dc112258c7a75935a81a7ce382",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a",
|
||||
"reference": "fa0f136dd2334583309d32b62544682ee972b51a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1492,7 +1260,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/comparator/issues",
|
||||
"source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6"
|
||||
"source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1500,7 +1268,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2020-10-26T15:49:45+00:00"
|
||||
"time": "2022-09-14T12:41:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/complexity",
|
||||
|
@ -1690,16 +1458,16 @@
|
|||
},
|
||||
{
|
||||
"name": "sebastian/exporter",
|
||||
"version": "4.0.4",
|
||||
"version": "4.0.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/exporter.git",
|
||||
"reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9"
|
||||
"reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9",
|
||||
"reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
|
||||
"reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1755,7 +1523,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/exporter/issues",
|
||||
"source": "https://github.com/sebastianbergmann/exporter/tree/4.0.4"
|
||||
"source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1763,7 +1531,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2021-11-11T14:18:36+00:00"
|
||||
"time": "2022-09-14T06:03:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/global-state",
|
||||
|
@ -2118,16 +1886,16 @@
|
|||
},
|
||||
{
|
||||
"name": "sebastian/type",
|
||||
"version": "3.0.0",
|
||||
"version": "3.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/type.git",
|
||||
"reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad"
|
||||
"reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b233b84bc4465aff7b57cf1c4bc75c86d00d6dad",
|
||||
"reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
|
||||
"reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2139,7 +1907,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0-dev"
|
||||
"dev-master": "3.2-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -2162,7 +1930,7 @@
|
|||
"homepage": "https://github.com/sebastianbergmann/type",
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/type/issues",
|
||||
"source": "https://github.com/sebastianbergmann/type/tree/3.0.0"
|
||||
"source": "https://github.com/sebastianbergmann/type/tree/3.2.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -2170,7 +1938,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-15T09:54:48+00:00"
|
||||
"time": "2022-09-12T14:47:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/version",
|
||||
|
@ -2225,88 +1993,6 @@
|
|||
],
|
||||
"time": "2020-09-28T06:39:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.25.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
"reference": "30885182c981ab175d4d034db0f6f469898070ab"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab",
|
||||
"reference": "30885182c981ab175d4d034db0f6f469898070ab",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"provide": {
|
||||
"ext-ctype": "*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-ctype": "For best performance"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Ctype\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Gert de Pagter",
|
||||
"email": "BackEndTea@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for ctype functions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"ctype",
|
||||
"polyfill",
|
||||
"portable"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.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": "2021-10-20T20:35:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "theseer/tokenizer",
|
||||
"version": "1.2.1",
|
||||
|
@ -2357,64 +2043,6 @@
|
|||
],
|
||||
"time": "2021-07-28T10:34:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "webmozart/assert",
|
||||
"version": "1.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/webmozarts/assert.git",
|
||||
"reference": "6964c76c7804814a842473e0c8fd15bab0f18e25"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25",
|
||||
"reference": "6964c76c7804814a842473e0c8fd15bab0f18e25",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0",
|
||||
"symfony/polyfill-ctype": "^1.8"
|
||||
},
|
||||
"conflict": {
|
||||
"phpstan/phpstan": "<0.12.20",
|
||||
"vimeo/psalm": "<4.6.1 || 4.6.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8.5.13"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.10-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Webmozart\\Assert\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Bernhard Schussek",
|
||||
"email": "bschussek@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Assertions to validate method input/output with nice error messages.",
|
||||
"keywords": [
|
||||
"assert",
|
||||
"check",
|
||||
"validate"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/webmozarts/assert/issues",
|
||||
"source": "https://github.com/webmozarts/assert/tree/1.10.0"
|
||||
},
|
||||
"time": "2021-03-09T10:59:23+00:00"
|
||||
},
|
||||
{
|
||||
"name": "webmozart/glob",
|
||||
"version": "4.6.0",
|
||||
|
|
172
vendor-bin/robo/composer.lock
generated
172
vendor-bin/robo/composer.lock
generated
|
@ -90,16 +90,16 @@
|
|||
},
|
||||
{
|
||||
"name": "consolidation/annotated-command",
|
||||
"version": "4.5.5",
|
||||
"version": "4.5.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/consolidation/annotated-command.git",
|
||||
"reference": "67cea8e8e7656b74da651ea6f49321853996c0fd"
|
||||
"reference": "3968070538761628546270935f0733a0cc408e1f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/consolidation/annotated-command/zipball/67cea8e8e7656b74da651ea6f49321853996c0fd",
|
||||
"reference": "67cea8e8e7656b74da651ea6f49321853996c0fd",
|
||||
"url": "https://api.github.com/repos/consolidation/annotated-command/zipball/3968070538761628546270935f0733a0cc408e1f",
|
||||
"reference": "3968070538761628546270935f0733a0cc408e1f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -140,22 +140,22 @@
|
|||
"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.5.5"
|
||||
"source": "https://github.com/consolidation/annotated-command/tree/4.5.6"
|
||||
},
|
||||
"time": "2022-04-26T16:18:25+00:00"
|
||||
"time": "2022-06-22T20:17:12+00:00"
|
||||
},
|
||||
{
|
||||
"name": "consolidation/config",
|
||||
"version": "2.1.0",
|
||||
"version": "2.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/consolidation/config.git",
|
||||
"reference": "0c15841b2bf60d9af1ce29884673e7d9d50c3b75"
|
||||
"reference": "dae810c162f0e799ea3f35cc2f40b0797b6e4d26"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/consolidation/config/zipball/0c15841b2bf60d9af1ce29884673e7d9d50c3b75",
|
||||
"reference": "0c15841b2bf60d9af1ce29884673e7d9d50c3b75",
|
||||
"url": "https://api.github.com/repos/consolidation/config/zipball/dae810c162f0e799ea3f35cc2f40b0797b6e4d26",
|
||||
"reference": "dae810c162f0e799ea3f35cc2f40b0797b6e4d26",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -200,9 +200,9 @@
|
|||
"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.0"
|
||||
"source": "https://github.com/consolidation/config/tree/2.1.1"
|
||||
},
|
||||
"time": "2022-02-24T00:32:42+00:00"
|
||||
"time": "2022-06-22T19:59:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "consolidation/log",
|
||||
|
@ -1070,16 +1070,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v6.1.0",
|
||||
"version": "v6.1.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "c9646197ef43b0e2ff44af61e7f0571526fd4170"
|
||||
"reference": "7fccea8728aa2d431a6725b02b3ce759049fc84d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/c9646197ef43b0e2ff44af61e7f0571526fd4170",
|
||||
"reference": "c9646197ef43b0e2ff44af61e7f0571526fd4170",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/7fccea8728aa2d431a6725b02b3ce759049fc84d",
|
||||
"reference": "7fccea8728aa2d431a6725b02b3ce759049fc84d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1146,7 +1146,7 @@
|
|||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v6.1.0"
|
||||
"source": "https://github.com/symfony/console/tree/v6.1.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1162,11 +1162,11 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-27T06:34:22+00:00"
|
||||
"time": "2022-08-26T10:32:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
"version": "v3.1.0",
|
||||
"version": "v3.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/deprecation-contracts.git",
|
||||
|
@ -1213,7 +1213,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.1.0"
|
||||
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1316,7 +1316,7 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher-contracts",
|
||||
"version": "v3.1.0",
|
||||
"version": "v3.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/event-dispatcher-contracts.git",
|
||||
|
@ -1375,7 +1375,7 @@
|
|||
"standards"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.1.0"
|
||||
"source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1395,16 +1395,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v6.1.0",
|
||||
"version": "v6.1.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/filesystem.git",
|
||||
"reference": "3132d2f43ca799c2aa099f9738d98228c56baa5d"
|
||||
"reference": "3f39c04d2630c34019907b02f85672dac99f8659"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/3132d2f43ca799c2aa099f9738d98228c56baa5d",
|
||||
"reference": "3132d2f43ca799c2aa099f9738d98228c56baa5d",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/3f39c04d2630c34019907b02f85672dac99f8659",
|
||||
"reference": "3f39c04d2630c34019907b02f85672dac99f8659",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1438,7 +1438,7 @@
|
|||
"description": "Provides basic utilities for the filesystem",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/filesystem/tree/v6.1.0"
|
||||
"source": "https://github.com/symfony/filesystem/tree/v6.1.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1454,20 +1454,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-21T13:34:40+00:00"
|
||||
"time": "2022-08-02T16:17:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
"version": "v6.1.0",
|
||||
"version": "v6.1.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/finder.git",
|
||||
"reference": "45b8beb69d6eb3b05a65689ebfd4222326773f8f"
|
||||
"reference": "39696bff2c2970b3779a5cac7bf9f0b88fc2b709"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/45b8beb69d6eb3b05a65689ebfd4222326773f8f",
|
||||
"reference": "45b8beb69d6eb3b05a65689ebfd4222326773f8f",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/39696bff2c2970b3779a5cac7bf9f0b88fc2b709",
|
||||
"reference": "39696bff2c2970b3779a5cac7bf9f0b88fc2b709",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1502,7 +1502,7 @@
|
|||
"description": "Finds files and directories via an intuitive fluent interface",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/finder/tree/v6.1.0"
|
||||
"source": "https://github.com/symfony/finder/tree/v6.1.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1518,20 +1518,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-04-15T08:08:08+00:00"
|
||||
"time": "2022-07-29T07:42:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
"reference": "30885182c981ab175d4d034db0f6f469898070ab"
|
||||
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab",
|
||||
"reference": "30885182c981ab175d4d034db0f6f469898070ab",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
|
||||
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1546,7 +1546,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1584,7 +1584,7 @@
|
|||
"portable"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1600,20 +1600,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-10-20T20:35:02+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-grapheme",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
|
||||
"reference": "81b86b50cf841a64252b439e738e97f4a34e2783"
|
||||
"reference": "433d05519ce6990bf3530fba6957499d327395c2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/81b86b50cf841a64252b439e738e97f4a34e2783",
|
||||
"reference": "81b86b50cf841a64252b439e738e97f4a34e2783",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2",
|
||||
"reference": "433d05519ce6990bf3530fba6957499d327395c2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1625,7 +1625,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1665,7 +1665,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1681,20 +1681,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-11-23T21:10:46+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-normalizer",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
||||
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8"
|
||||
"reference": "219aa369ceff116e673852dce47c3a41794c14bd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8",
|
||||
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
|
||||
"reference": "219aa369ceff116e673852dce47c3a41794c14bd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1706,7 +1706,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1749,7 +1749,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1765,20 +1765,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-02-19T12:13:01+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825"
|
||||
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825",
|
||||
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
|
||||
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1793,7 +1793,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1832,7 +1832,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1848,20 +1848,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-11-30T18:21:41+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
"version": "v6.1.0",
|
||||
"version": "v6.1.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/process.git",
|
||||
"reference": "318718453c2be58266f1a9e74063d13cb8dd4165"
|
||||
"reference": "a6506e99cfad7059b1ab5cab395854a0a0c21292"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/318718453c2be58266f1a9e74063d13cb8dd4165",
|
||||
"reference": "318718453c2be58266f1a9e74063d13cb8dd4165",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/a6506e99cfad7059b1ab5cab395854a0a0c21292",
|
||||
"reference": "a6506e99cfad7059b1ab5cab395854a0a0c21292",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1893,7 +1893,7 @@
|
|||
"description": "Executes commands in sub-processes",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/process/tree/v6.1.0"
|
||||
"source": "https://github.com/symfony/process/tree/v6.1.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1909,20 +1909,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-11T12:12:29+00:00"
|
||||
"time": "2022-06-27T17:24:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/service-contracts",
|
||||
"version": "v3.1.0",
|
||||
"version": "v3.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/service-contracts.git",
|
||||
"reference": "d66cd8ab656780f62c4215b903a420eb86358957"
|
||||
"reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/d66cd8ab656780f62c4215b903a420eb86358957",
|
||||
"reference": "d66cd8ab656780f62c4215b903a420eb86358957",
|
||||
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/925e713fe8fcacf6bc05e936edd8dd5441a21239",
|
||||
"reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1978,7 +1978,7 @@
|
|||
"standards"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/service-contracts/tree/v3.1.0"
|
||||
"source": "https://github.com/symfony/service-contracts/tree/v3.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1994,20 +1994,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-07T08:07:09+00:00"
|
||||
"time": "2022-05-30T19:18:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/string",
|
||||
"version": "v6.1.0",
|
||||
"version": "v6.1.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/string.git",
|
||||
"reference": "d3edc75baf9f1d4f94879764dda2e1ac33499529"
|
||||
"reference": "290972cad7b364e3befaa74ba0ec729800fb161c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/d3edc75baf9f1d4f94879764dda2e1ac33499529",
|
||||
"reference": "d3edc75baf9f1d4f94879764dda2e1ac33499529",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/290972cad7b364e3befaa74ba0ec729800fb161c",
|
||||
"reference": "290972cad7b364e3befaa74ba0ec729800fb161c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2063,7 +2063,7 @@
|
|||
"utf8"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/string/tree/v6.1.0"
|
||||
"source": "https://github.com/symfony/string/tree/v6.1.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -2079,20 +2079,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-04-22T08:18:23+00:00"
|
||||
"time": "2022-08-12T18:05:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v6.1.0",
|
||||
"version": "v6.1.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "84ce4f9d2d68f306f971a39d949d8f4b5550dba2"
|
||||
"reference": "86ee4d8fa594ed45e40d86eedfda1bcb66c8d919"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/84ce4f9d2d68f306f971a39d949d8f4b5550dba2",
|
||||
"reference": "84ce4f9d2d68f306f971a39d949d8f4b5550dba2",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/86ee4d8fa594ed45e40d86eedfda1bcb66c8d919",
|
||||
"reference": "86ee4d8fa594ed45e40d86eedfda1bcb66c8d919",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2137,7 +2137,7 @@
|
|||
"description": "Loads and dumps YAML files",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/yaml/tree/v6.1.0"
|
||||
"source": "https://github.com/symfony/yaml/tree/v6.1.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -2153,7 +2153,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-04-15T14:25:02+00:00"
|
||||
"time": "2022-08-02T16:17:38+00:00"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
|
|
Loading…
Reference in a new issue