Compare commits

...

5 Commits

  1. 54
      composer.lock
  2. 10
      lib/Arsse.php
  3. 266
      tests/cases/CLI/TestCLI.php
  4. 3
      tests/cases/Database/AbstractTest.php
  5. 5
      tests/cases/Exception/TestException.php
  6. 158
      tests/cases/REST/Miniflux/TestV1.php
  7. 20
      tests/cases/TestArsse.php
  8. 428
      tests/cases/User/TestUser.php
  9. 15
      tests/lib/AbstractTest.php
  10. 403
      vendor-bin/csfixer/composer.lock
  11. 257
      vendor-bin/daux/composer.lock
  12. 1
      vendor-bin/phpstan/composer.json
  13. 18
      vendor-bin/phpstan/composer.lock
  14. 3
      vendor-bin/phpunit/composer.json
  15. 153
      vendor-bin/phpunit/composer.lock
  16. 169
      vendor-bin/robo/composer.lock

54
composer.lock

@ -55,22 +55,22 @@
},
{
"name": "guzzlehttp/guzzle",
"version": "7.7.0",
"version": "7.8.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "fb7566caccf22d74d1ab270de3551f72a58399f5"
"reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/fb7566caccf22d74d1ab270de3551f72a58399f5",
"reference": "fb7566caccf22d74d1ab270de3551f72a58399f5",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/1110f66a6530a40fe7aea0378fe608ee2b2248f9",
"reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9",
"shasum": ""
},
"require": {
"ext-json": "*",
"guzzlehttp/promises": "^1.5.3 || ^2.0",
"guzzlehttp/psr7": "^1.9.1 || ^2.4.5",
"guzzlehttp/promises": "^1.5.3 || ^2.0.1",
"guzzlehttp/psr7": "^1.9.1 || ^2.5.1",
"php": "^7.2.5 || ^8.0",
"psr/http-client": "^1.0",
"symfony/deprecation-contracts": "^2.2 || ^3.0"
@ -161,7 +161,7 @@
],
"support": {
"issues": "https://github.com/guzzle/guzzle/issues",
"source": "https://github.com/guzzle/guzzle/tree/7.7.0"
"source": "https://github.com/guzzle/guzzle/tree/7.8.0"
},
"funding": [
{
@ -177,20 +177,20 @@
"type": "tidelift"
}
],
"time": "2023-05-21T14:04:53+00:00"
"time": "2023-08-27T10:20:53+00:00"
},
{
"name": "guzzlehttp/promises",
"version": "2.0.0",
"version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6"
"reference": "111166291a0f8130081195ac4556a5587d7f1b5d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/3a494dc7dc1d7d12e511890177ae2d0e6c107da6",
"reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6",
"url": "https://api.github.com/repos/guzzle/promises/zipball/111166291a0f8130081195ac4556a5587d7f1b5d",
"reference": "111166291a0f8130081195ac4556a5587d7f1b5d",
"shasum": ""
},
"require": {
@ -244,7 +244,7 @@
],
"support": {
"issues": "https://github.com/guzzle/promises/issues",
"source": "https://github.com/guzzle/promises/tree/2.0.0"
"source": "https://github.com/guzzle/promises/tree/2.0.1"
},
"funding": [
{
@ -260,20 +260,20 @@
"type": "tidelift"
}
],
"time": "2023-05-21T13:50:22+00:00"
"time": "2023-08-03T15:11:55+00:00"
},
{
"name": "guzzlehttp/psr7",
"version": "2.5.0",
"version": "2.6.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "b635f279edd83fc275f822a1188157ffea568ff6"
"reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/b635f279edd83fc275f822a1188157ffea568ff6",
"reference": "b635f279edd83fc275f822a1188157ffea568ff6",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/be45764272e8873c72dbe3d2edcfdfcc3bc9f727",
"reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727",
"shasum": ""
},
"require": {
@ -360,7 +360,7 @@
],
"support": {
"issues": "https://github.com/guzzle/psr7/issues",
"source": "https://github.com/guzzle/psr7/tree/2.5.0"
"source": "https://github.com/guzzle/psr7/tree/2.6.1"
},
"funding": [
{
@ -376,7 +376,7 @@
"type": "tidelift"
}
],
"time": "2023-04-17T16:11:26+00:00"
"time": "2023-08-27T10:13:57+00:00"
},
{
"name": "hosteurope/password-generator",
@ -743,16 +743,16 @@
},
{
"name": "psr/http-client",
"version": "1.0.2",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-client.git",
"reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31"
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/0955afe48220520692d2d09f7ab7e0f93ffd6a31",
"reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
"shasum": ""
},
"require": {
@ -789,9 +789,9 @@
"psr-18"
],
"support": {
"source": "https://github.com/php-fig/http-client/tree/1.0.2"
"source": "https://github.com/php-fig/http-client"
},
"time": "2023-04-10T20:12:12+00:00"
"time": "2023-09-23T14:17:50+00:00"
},
{
"name": "psr/http-factory",
@ -1197,5 +1197,5 @@
"platform-overrides": {
"php": "7.3.33"
},
"plugin-api-version": "2.3.0"
"plugin-api-version": "2.6.0"
}

10
lib/Arsse.php

@ -19,15 +19,15 @@ class Arsse {
"iconv", // required by PicoFeed only
];
/** @var Factory */
/** @var Factory|\Phake\IMock */
public static $obj;
/** @var Lang */
/** @var Lang|\Phake\IMock */
public static $lang;
/** @var Conf */
/** @var Conf|\Phake\IMock */
public static $conf;
/** @var Database */
/** @var Database|\Phake\IMock */
public static $db;
/** @var User */
/** @var User|\Phake\IMock */
public static $user;
/** @codeCoverageIgnore */

266
tests/cases/CLI/TestCLI.php

@ -15,6 +15,7 @@ use JKingWeb\Arsse\User;
use JKingWeb\Arsse\Database;
use JKingWeb\Arsse\Service;
use JKingWeb\Arsse\CLI;
use JKingWeb\Arsse\Factory;
use JKingWeb\Arsse\REST\Fever\User as FeverUser;
use JKingWeb\Arsse\REST\Miniflux\Token as MinifluxToken;
use JKingWeb\Arsse\ImportExport\OPML;
@ -25,16 +26,17 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
protected $cli;
public function setUp(): void {
parent::setUp();
$this->cli = $this->partialMock(CLI::class);
$this->cli->logError->returns(null);
$this->cli->loadConf->returns(true);
$this->dbMock = $this->mock(Database::class);
Arsse::$db = \Phake::mock(Database::class);
Arsse::$obj = \Phake::mock(Factory::class);
\Phake::when(Arsse::$obj)->get->thenReturnCallback(function($c) {
return new $c;
});
$this->cli = \Phake::partialMock(CLI::class);
\Phake::when($this->cli)->logError->thenReturn(null);
\Phake::when($this->cli)->loadConf->thenReturn(true);
}
public function assertConsole(string $command, int $exitStatus, string $output = "", bool $pattern = false): void {
Arsse::$obj = $this->objMock->get();
Arsse::$db = $this->dbMock->get();
$argv = \Clue\Arguments\split($command);
$output = strlen($output) ? $output.\PHP_EOL : "";
if ($pattern) {
@ -42,18 +44,18 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
} else {
$this->expectOutputString($output);
}
$this->assertSame($exitStatus, $this->cli->get()->dispatch($argv));
$this->assertSame($exitStatus, $this->cli->dispatch($argv));
}
public function testPrintVersion(): void {
$this->assertConsole("arsse.php --version", 0, Arsse::VERSION);
$this->cli->loadConf->never()->called();
\Phake::verify($this->cli, \Phake::never())->loadConf();
}
/** @dataProvider provideHelpText */
public function testPrintHelp(string $cmd, string $name): void {
$this->assertConsole($cmd, 0, str_replace("arsse.php", $name, CLI::USAGE));
$this->cli->loadConf->never()->called();
\Phake::verify($this->cli, \Phake::never())->loadConf();
}
public function provideHelpText(): iterable {
@ -68,64 +70,64 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
}
public function testStartTheDaemon(): void {
$srv = $this->mock(Service::class);
$srv->watch->returns(new \DateTimeImmutable);
$this->objMock->get->with(Service::class)->returns($srv->get());
$srv = \Phake::mock(Service::class);
\Phake::when($srv)->watch->thenReturn(new \DateTimeImmutable);
\Phake::when(Arsse::$obj)->get(Service::class)->thenReturn($srv);
$this->assertConsole("arsse.php daemon", 0);
$this->cli->loadConf->called();
$srv->watch->calledWith(true);
\Phake::verify($this->cli)->loadConf();
\Phake::verify($srv)->watch(true);
}
public function testStartTheForkingDaemon(): void {
$f = tempnam(sys_get_temp_dir(), "arsse");
$srv = $this->mock(Service::class);
$srv->watch->returns(new \DateTimeImmutable);
$daemon = $this->mock(Daemon::class);
$daemon->checkPIDFilePath->returns($f);
$daemon->fork->returns(null);
$this->objMock->get->with(Service::class)->returns($srv->get());
$this->objMock->get->with(Daemon::class)->returns($daemon->get());
$srv = \Phake::mock(Service::class);
$daemon = \Phake::mock(Daemon::class);
\Phake::when($srv)->watch->thenReturn(new \DateTimeImmutable);
\Phake::when($daemon)->checkPIDFilePath->thenReturn($f);
\Phake::when($daemon)->fork->thenReturn(null);
\Phake::when(Arsse::$obj)->get(Service::class)->thenReturn($srv);
\Phake::when(Arsse::$obj)->get(Daemon::class)->thenReturn($daemon);
$this->assertConsole("arsse.php daemon --fork=arsse.pid", 0);
$this->assertFileDoesNotExist($f);
Phony::inOrder(
$daemon->checkPIDFilePath->calledWith("arsse.pid"),
$daemon->fork->calledWith($f),
$this->cli->loadConf->called(),
$srv->watch->calledWith(true)
\Phake::inOrder(
\Phake::verify($daemon)->checkPIDFilePath("arsse.pid"),
\Phake::verify($daemon)->fork($f),
\Phake::verify($this->cli)->loadConf(),
\Phake::verify($srv)->watch(true)
);
}
public function testFailToStartTheForkingDaemon(): void {
$srv = $this->mock(Service::class);
$srv->watch->returns(new \DateTimeImmutable);
$daemon = $this->mock(Daemon::class);
$daemon->checkPIDFilePath->throws(new Service\Exception("pidDuplicate", ['pid' => 2112]));
$daemon->fork->returns(null);
$this->objMock->get->with(Service::class)->returns($srv->get());
$this->objMock->get->with(Daemon::class)->returns($daemon->get());
$srv = \Phake::mock(Service::class);
$daemon = \Phake::mock(Daemon::class);
\Phake::when($srv)->watch->thenReturns(new \DateTimeImmutable);
\Phake::when($daemon)->checkPIDFilePath->throws(new Service\Exception("pidDuplicate", ['pid' => 2112]));
\Phake::when($daemon)->fork->returns(null);
\Phake::when(Arsse::$obj)->get(Service::class)->returns($srv);
\Phake::when(Arsse::$obj)->get(Daemon::class)->returns($daemon);
$this->assertConsole("arsse.php daemon --fork=arsse.pid", 10809);
$daemon->checkPIDFilePath->calledWith("arsse.pid");
$daemon->fork->never()->called();
$this->cli->loadConf->never()->called();
$srv->watch->never()->called();
\Phake::verify($daemon)->checkPIDFilePath("arsse.pid");
\Phake::verify($daemon, \Phake::never())->fork($this->anything());
\Phake::verify($this->cli, \Phake::never())->loadConf();
\Phake::verify($srv, \Phake::never())->watch($this->anything());
}
public function testRefreshAllFeeds(): void {
$srv = $this->mock(Service::class);
$srv->watch->returns(new \DateTimeImmutable);
$this->objMock->get->with(Service::class)->returns($srv->get());
$srv = \Phake::mock(Service::class);
\Phake::when($srv)->watch->thenReturn(new \DateTimeImmutable);
\Phake::when(Arsse::$obj)->get(Service::class)->thenReturn($srv);
$this->assertConsole("arsse.php feed refresh-all", 0);
$this->cli->loadConf->called();
$srv->watch->calledWith(false);
\Phake::verify($this->cli)->loadConf();
\Phake::verify($srv)->watch(false);
}
/** @dataProvider provideFeedUpdates */
public function testRefreshAFeed(string $cmd, int $exitStatus, string $output): void {
$this->dbMock->feedUpdate->with(1, true)->returns(true);
$this->dbMock->feedUpdate->with(2, true)->throws(new \JKingWeb\Arsse\Feed\Exception("", ['url' => "http://example.com/"], $this->mockGuzzleException(ClientException::class, "", 404)));
\Phake::when(Arsse::$db)->feedUpdate(1, true)->thenReturn(true);
\Phake::when(Arsse::$db)->feedUpdate(2, true)->thenThrow(new \JKingWeb\Arsse\Feed\Exception("", ['url' => "http://example.com/"], $this->mockGuzzleException(ClientException::class, "", 404)));
$this->assertConsole($cmd, $exitStatus, $output);
$this->cli->loadConf->called();
$this->dbMock->feedUpdate->called();
\Phake::verify($this->cli)->loadConf();
\Phake::verify($this->dbMock)->feedUpdate();
}
public function provideFeedUpdates(): iterable {
@ -137,14 +139,14 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
/** @dataProvider provideDefaultConfigurationSaves */
public function testSaveTheDefaultConfiguration(string $cmd, int $exitStatus, string $file): void {
$conf = $this->mock(Conf::class);
$conf->exportFile->with("php://output", true)->returns(true);
$conf->exportFile->with("good.conf", true)->returns(true);
$conf->exportFile->with("bad.conf", true)->throws(new \JKingWeb\Arsse\Conf\Exception("fileUnwritable"));
$this->objMock->get->with(Conf::class)->returns($conf->get());
$conf = \Phake::mock(Conf::class);
\Phake::when($conf)->exportFile("php://output", true)->thenReturn(true);
\Phake::when($conf)->exportFile("good.conf", true)->thenReturn(true);
\Phake::when($conf)->exportFile("bad.conf", true)->thenThrow(new \JKingWeb\Arsse\Conf\Exception("fileUnwritable"));
\Phake::when(Arsse::$obj)->get(Conf::class)->thenReturn($conf);
$this->assertConsole($cmd, $exitStatus);
$this->cli->loadConf->never()->called();
$conf->exportFile->calledWith($file, true);
\Phake::verify($this->cli)->loadConf();
\Phake::verify($conf)->exportFile($file, true);
}
public function provideDefaultConfigurationSaves(): iterable {
@ -158,9 +160,8 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
/** @dataProvider provideUserList */
public function testListUsers(string $cmd, array $list, int $exitStatus, string $output): void {
// FIXME: Phake is somehow unable to mock the User class correctly, so we use PHPUnit's mocks instead
Arsse::$user = $this->createMock(User::class);
Arsse::$user->method("list")->willReturn($list);
Arsse::$user = \Phake::mock(User::class);
\Phake::when(Arsse::$user)->list()->thenReturn($list);
$this->assertConsole($cmd, $exitStatus, $output);
}
@ -177,16 +178,12 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
/** @dataProvider provideUserAdditions */
public function testAddAUser(string $cmd, int $exitStatus, string $output): void {
// FIXME: Phake is somehow unable to mock the User class correctly, so we use PHPUnit's mocks instead
Arsse::$user = $this->createMock(User::class);
Arsse::$user->method("add")->will($this->returnCallback(function($user, $pass = null) {
switch ($user) {
case "john.doe@example.com":
throw new \JKingWeb\Arsse\User\ExceptionConflict("alreadyExists");
case "jane.doe@example.com":
return is_null($pass) ? "random password" : $pass;
}
}));
Arsse::$user = \Phake::mock(User::class);
\Phake::when(Arsse::$user)->add("john.doe@example.com", $this->anything())->thenThrow(new \JKingWeb\Arsse\User\ExceptionConflict("alreadyExists"));
\Phake::when(Arsse::$user)->add("jane.doe@example.com", $this->anything())->thenReturnCallback(function($u, $p) {
return $p;
});
\Phake::when(Arsse::$user)->add("jane.doe@example.com", null)->thenReturn("random password");
$this->assertConsole($cmd, $exitStatus, $output);
}
@ -199,29 +196,25 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
}
public function testAddAUserAsAdministrator(): void {
Arsse::$user = $this->createMock(User::class);
Arsse::$user->method("add")->willReturn("random password");
Arsse::$user->method("propertiesSet")->willReturn([]);
Arsse::$user->expects($this->exactly(1))->method("add")->with("jane.doe@example.com", null);
Arsse::$user->expects($this->exactly(1))->method("propertiesSet")->with("jane.doe@example.com", ['admin' => true]);
Arsse::$user = \Phake::mock(User::class);
\Phake::when(Arsse::$user)->add->thenReturn("random password");
\Phake::when(Arsse::$user)->propertiesSet->thenReturn([]);
$this->assertConsole("arsse.php user add jane.doe@example.com --admin", 0, "random password");
\Phake::verify(Arsse::$user)->add("jane.doe@example.com", null);
\Phake::verify(Arsse::$user)->propertiesSet("jane.doe@example.com", ['admin' => true]);
}
/** @dataProvider provideUserAuthentication */
public function testAuthenticateAUser(string $cmd, int $exitStatus, string $output): void {
// FIXME: Phake is somehow unable to mock the User class correctly, so we use PHPUnit's mocks instead
Arsse::$user = $this->createMock(User::class);
Arsse::$user->method("auth")->will($this->returnCallback(function($user, $pass) {
return
($user === "john.doe@example.com" && $pass === "secret") ||
($user === "jane.doe@example.com" && $pass === "superman")
;
}));
Arsse::$user = \Phake::mock(User::class);
\Phake::when(Arsse::$user)->auth->thenReturn(false);
\Phake::when(Arsse::$user)->auth("john.doe@example.com", "secret")->thenReturn(true);
\Phake::when(Arsse::$user)->auth("jane.doe@example.com", "superman")->thenReturn(true);
$fever = $this->mock(FeverUser::class);
$fever->authenticate->returns(false);
$fever->authenticate->with("john.doe@example.com", "ashalla")->returns(true);
$fever->authenticate->with("jane.doe@example.com", "thx1138")->returns(true);
$this->objMock->get->with(FeverUser::class)->returns($fever->get());
\Phake::when($fever)->authenticate->thenReturn(false);
\Phake::when($fever)->authenticate("john.doe@example.com", "ashalla")->thenReturn(true);
\Phake::when($fever)->authenticate("jane.doe@example.com", "thx1138")->thenReturn(true);
\Phake::when(Arsse::$obj)->get(FeverUser::class)->thenReturn($fever);
$this->assertConsole($cmd, $exitStatus, $output);
}
@ -243,14 +236,9 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
/** @dataProvider provideUserRemovals */
public function testRemoveAUser(string $cmd, int $exitStatus, string $output): void {
// FIXME: Phake is somehow unable to mock the User class correctly, so we use PHPUnit's mocks instead
Arsse::$user = $this->createMock(User::class);
Arsse::$user->method("remove")->will($this->returnCallback(function($user) {
if ($user === "john.doe@example.com") {
return true;
}
throw new \JKingWeb\Arsse\User\ExceptionConflict("doesNotExist");
}));
Arsse::$user = \Phake::mock(User::class);
\Phake::when(Arsse::$user)->remove->thenThrow(new \JKingWeb\Arsse\User\ExceptionConflict("doesNotExist"));
\Phake::when(Arsse::$user)->remove("john.doe@example.com")->thenReturn(true);
$this->assertConsole($cmd, $exitStatus, $output);
}
@ -271,12 +259,11 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
return is_null($pass) ? "random password" : $pass;
}
};
// FIXME: Phake is somehow unable to mock the User class correctly, so we use PHPUnit's mocks instead
Arsse::$user = $this->createMock(User::class);
Arsse::$user->method("passwordSet")->will($this->returnCallback($passwordChange));
$fever = $this->mock(FeverUser::class);
$fever->register->does($passwordChange);
$this->objMock->get->with(FeverUser::class)->returns($fever->get());
Arsse::$user = \Phake::mock(User::class);
\Phake::when(Arsse::$user)->passwordSet->thenReturnCallback($passwordChange);
$fever = \Phake::mock(FeverUser::class);
\Phake::when($fever)->register->thenReturnCallback($passwordChange);
\Phake::when(Arsse::$obj)->get(FeverUser::class)->returns($fever);
$this->assertConsole($cmd, $exitStatus, $output);
}
@ -301,12 +288,11 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
return true;
}
};
// FIXME: Phake is somehow unable to mock the User class correctly, so we use PHPUnit's mocks instead
Arsse::$user = $this->createMock(User::class);
Arsse::$user->method("passwordUnset")->will($this->returnCallback($passwordClear));
$fever = $this->mock(FeverUser::class);
$fever->unregister->does($passwordClear);
$this->objMock->get->with(FeverUser::class)->returns($fever->get());
Arsse::$user = \Phake::mock(User::class);
\Phake::when(Arsse::$user)->passwordUnset->thenReturnCallback($passwordClear);
$fever = \Phake::mock(FeverUser::class);
\Phake::when($fever)->unregister->thenReturnCallback($passwordClear);
\Phake::when(Arsse::$obj)->get(FeverUser::class)->thenReturn($fever);
$this->assertConsole($cmd, $exitStatus, $output);
}
@ -321,14 +307,14 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
/** @dataProvider provideOpmlExports */
public function testExportToOpml(string $cmd, int $exitStatus, string $file, string $user, bool $flat): void {
$opml = $this->mock(OPML::class);
$opml->exportFile->with("php://output", $user, $flat)->returns(true);
$opml->exportFile->with("good.opml", $user, $flat)->returns(true);
$opml->exportFile->with("bad.opml", $user, $flat)->throws(new \JKingWeb\Arsse\ImportExport\Exception("fileUnwritable"));
$this->objMock->get->with(OPML::class)->returns($opml->get());
$opml = \Phake::mock(OPML::class);
\Phake::when($opml)->exportFile("php://output", $user, $flat)->thenReturn(true);
\Phake::when($opml)->exportFile("good.opml", $user, $flat)->thenRreturn(true);
\Phake::when($opml)->exportFile("bad.opml", $user, $flat)->thenThrow(new \JKingWeb\Arsse\ImportExport\Exception("fileUnwritable"));
\Phake::when(Arsse::$obj)->get(OPML::class)->returns($opml);
$this->assertConsole($cmd, $exitStatus);
$this->cli->loadConf->called();
$opml->exportFile->calledWith($file, $user, $flat);
\Phake::verify($this->cli)->loadConf();
\Phake::verify($opml)->exportFile($file, $user, $flat);
}
public function provideOpmlExports(): iterable {
@ -362,14 +348,14 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
/** @dataProvider provideOpmlImports */
public function testImportFromOpml(string $cmd, int $exitStatus, string $file, string $user, bool $flat, bool $replace): void {
$opml = $this->mock(OPML::class);
$opml->importFile->with("php://input", $user, $flat, $replace)->returns(true);
$opml->importFile->with("good.opml", $user, $flat, $replace)->returns(true);
$opml->importFile->with("bad.opml", $user, $flat, $replace)->throws(new \JKingWeb\Arsse\ImportExport\Exception("fileUnreadable"));
$this->objMock->get->with(OPML::class)->returns($opml->get());
$opml = \Phake::mock(OPML::class);
\Phake::when($opml)->importFile("php://input", $user, $flat, $replace)->thenReturn(true);
\Phake::when($opml)->importFile("good.opml", $user, $flat, $replace)->thenReturn(true);
\Phake::when($opml)->importFile("bad.opml", $user, $flat, $replace)->thenThrow(new \JKingWeb\Arsse\ImportExport\Exception("fileUnreadable"));
\Phake::when(Arsse::$obj)->get(OPML::class)->thenReturn($opml);
$this->assertConsole($cmd, $exitStatus);
$this->cli->loadConf->called();
$opml->importFile->calledWith($file, $user, $flat, $replace);
\Phake::verify($this->cli)->loadConf();
\Phake::verify($opml)->importFile($file, $user, $flat, $replace);
}
public function provideOpmlImports(): iterable {
@ -438,18 +424,18 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
"reading_time false",
"stylesheet 'body {color:gray}'",
]);
Arsse::$user = $this->createMock(User::class);
Arsse::$user->method("propertiesGet")->willReturn($data);
Arsse::$user->expects($this->once())->method("propertiesGet")->with("john.doe@example.com", true);
Arsse::$user = \Phake::mock(User::class);
\Phake::when(Arsse::$user)->propertiesGet->thenReturn($data);
$this->assertConsole("arsse.php user show john.doe@example.com", 0, $exp);
\Phake::verify(Arsse::$user)->propertiesGet("john.doe@example.com");
}
/** @dataProvider provideMetadataChanges */
public function testSetMetadataOfAUser(string $cmd, string $user, array $in, array $out, int $exp): void {
Arsse::$user = $this->createMock(User::class);
Arsse::$user->method("propertiesSet")->willReturn($out);
Arsse::$user->expects($this->once())->method("propertiesSet")->with($user, $in);
Arsse::$user = \Phake::mock(User::class);
\Phake::when(Arsse::$user)->propertiesSet->thenReturn($out);
$this->assertConsole($cmd, $exp, "");
\Phake::verify(Arsse::$user)->propertiesSet($user, $in);
}
public function provideMetadataChanges(): iterable {
@ -474,38 +460,38 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest {
"TOKEN 2 Eek",
"TOKEN 1 Ook",
]);
$t = $this->mock(MinifluxToken::class);
$t->tokenList->returns($data);
$this->objMock->get->with(MinifluxToken::class)->returns($t->get());
$t = \Phake::mock(MinifluxToken::class);
\Phake::when($t)->tokenList->thenReturn($data);
\Phake::when(Arsse::$obj)->get(MinifluxToken::class)->thenReturn($t);
$this->assertConsole("arsse.php token list john", 0, $exp);
$t->tokenList->calledWith("john");
\Phake::verify($t)->tokenList("john");
}
public function testCreateToken(): void {
$t = $this->mock(MinifluxToken::class);
$t->tokenGenerate->returns("RANDOM TOKEN");
$this->objMock->get->with(MinifluxToken::class)->returns($t->get());
$t = \Phake::mock(MinifluxToken::class);
\Phake::when($t)->tokenGenerate->thenReturn("RANDOM TOKEN");
\Phake::when(Arsse::$obj)->get(MinifluxToken::class)->thenReturn($t);
$this->assertConsole("arse.php token create jane", 0, "RANDOM TOKEN");
$t->tokenGenerate->calledWith("jane", null);
\Phake::verify($t)->tokenGenerate("jane", null);
}
public function testCreateTokenWithLabel(): void {
$t = $this->mock(MinifluxToken::class);
$t->tokenGenerate->returns("RANDOM TOKEN");
$this->objMock->get->with(MinifluxToken::class)->returns($t->get());
$t = \Phake::mock(MinifluxToken::class);
\Phake::when($t)->tokenGenerate->thenReturn("RANDOM TOKEN");
\Phake::when(Arsse::$obj)->get(MinifluxToken::class)->thenReturn($t);
$this->assertConsole("arse.php token create jane Ook", 0, "RANDOM TOKEN");
$t->tokenGenerate->calledWith("jane", "Ook");
\Phake::verify($t)->tokenGenerate("jane", "Ook");
}
public function testRevokeAToken(): void {
$this->dbMock->tokenRevoke->returns(true);
\Phake::when(Arsse::$db)->tokenRevoke->thenReturn(true);
$this->assertConsole("arse.php token revoke jane TOKEN_ID", 0);
$this->dbMock->tokenRevoke->calledWith("jane", "miniflux.login", "TOKEN_ID");
\Phake::verify(Arsse::$db)->tokenRevoke("jane", "miniflux.login", "TOKEN_ID");
}
public function testRevokeAllTokens(): void {
$this->dbMock->tokenRevoke->returns(true);
\Phake::when(Arsse::$db)->tokenRevoke->thenReturn(true);
$this->assertConsole("arse.php token revoke jane", 0);
$this->dbMock->tokenRevoke->calledWith("jane", "miniflux.login", null);
\Phake::verify(Arsse::$db)->tokenRevoke("jane", "miniflux.login", null);
}
}

3
tests/cases/Database/AbstractTest.php

@ -78,8 +78,7 @@ abstract class AbstractTest extends \JKingWeb\Arsse\Test\AbstractTest {
Arsse::$db = new Database(static::$drv);
Arsse::$db->driverSchemaUpdate();
// create a mock user manager
$this->userMock = $this->mock(User::class);
Arsse::$user = $this->userMock->get();
Arsse::$user = \Phake::mock(User::class);
// call the series-specific setup method
$setUp = "setUp".$this->series;
$this->$setUp();

5
tests/cases/Exception/TestException.php

@ -17,9 +17,8 @@ class TestException extends \JKingWeb\Arsse\Test\AbstractTest {
public function setUp(): void {
self::clearData(false);
// create a mock Lang object so as not to create a dependency loop
$this->langMock = $this->mock(Lang::class);
$this->langMock->msg->returns("");
Arsse::$lang = $this->langMock->get();
Arsse::$lang = \Phake::mock(Lang::class);
\Phake::when(Arsse::$lang)->msg->thenReturn("");
}
public function testBaseClass(): void {

158
tests/cases/REST/Miniflux/TestV1.php

@ -86,10 +86,10 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
$this->transaction = $this->mock(Transaction::class);
$this->dbMock = $this->mock(Database::class);
$this->dbMock->begin->returns($this->transaction->get());
// create a mock user manager; we use a PHPUnitmock because Phake for reasons unknown is unable to mock the User class correctly, sometimes
Arsse::$user = $this->createMock(User::class);
Arsse::$user->method("propertiesGet")->willReturn(['num' => 42, 'admin' => false, 'root_folder_name' => null, 'tz' => "Asia/Gaza"]);
Arsse::$user->method("begin")->willReturn($this->transaction->get());
// create a mock user manager
Arsse::$user = \Phake::mock(User::class);
\Phake::when(Arsse::$user)->propertiesGet->thenReturn(['num' => 42, 'admin' => false, 'root_folder_name' => null, 'tz' => "Asia/Gaza"]);
\Phake::when(Arsse::$user)->begin->thenReturn($this->transaction->get());
//initialize a handler
$this->h = new V1();
}
@ -198,32 +198,19 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
/** @dataProvider provideUserQueries */
public function testQueryUsers(bool $admin, string $route, ResponseInterface $exp): void {
$u = [
new ExceptionConflict("doesNotExist"),
['num' => 1, 'admin' => true, 'theme' => "custom", 'lang' => "fr_CA", 'tz' => "Asia/Gaza", 'sort_asc' => true, 'page_size' => 200, 'shortcuts' => false, 'reading_time' => false, 'swipe' => false, 'stylesheet' => "p {}"],
['num' => 2, 'admin' => false, 'theme' => null, 'lang' => null, 'tz' => null, 'sort_asc' => null, 'page_size' => null, 'shortcuts' => null, 'reading_time' => null, 'swipe' => null, 'stylesheet' => null],
new ExceptionConflict("doesNotExist"),
];
$user = $admin ? "john.doe@example.com" : "jane.doe@example.com";
// FIXME: Phake is somehow unable to mock the User class correctly, so we use PHPUnit's mocks instead
Arsse::$user = $this->createMock(User::class);
Arsse::$user->method("list")->willReturn(["john.doe@example.com", "jane.doe@example.com", "admin@example.com"]);
Arsse::$user->method("propertiesGet")->willReturnCallback(function(string $user, bool $includeLerge = true) use ($u) {
if ($user === "john.doe@example.com") {
return $u[0];
} elseif ($user === "jane.doe@example.com") {
return $u[1];
} else {
throw $u[2];
}
});
Arsse::$user->method("lookup")->willReturnCallback(function(int $num) use ($u) {
if ($num === 1) {
return "john.doe@example.com";
} elseif ($num === 2) {
return "jane.doe@example.com";
} else {
throw $u[2];
}
});
Arsse::$user = \Phake::mock(User::class);
\Phake::when(Arsse::$user)->list->thenReturn(["john.doe@example.com", "jane.doe@example.com", "admin@example.com"]);
\Phake::when(Arsse::$user)->propertiesGet->thenThrow($u[0]);
\Phake::when(Arsse::$user)->propertiesGet("john.doe@example.com", $this->anything())->thenReturn($u[1]);
\Phake::when(Arsse::$user)->propertiesGet("jane.doe@example.com", $this->anything())->thenReturn($u[2]);
\Phake::when(Arsse::$user)->lookup->thenThrow($u[0]);
\Phake::when(Arsse::$user)->lookup(1)->thenReturn("john.doe@example.com");
\Phake::when(Arsse::$user)->lookup(2)->thenReturn("jane.doe@example.com");
$this->assertMessage($exp, $this->req("GET", $route, "", [], $user));
}
@ -251,57 +238,47 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
/** @dataProvider provideUserModifications */
public function testModifyAUser(bool $admin, string $url, array $body, $in1, $out1, $in2, $out2, $in3, $out3, ResponseInterface $exp): void {
Arsse::$user = $this->createMock(User::class);
Arsse::$user->method("begin")->willReturn($this->transaction->get());
Arsse::$user->method("propertiesGet")->willReturnCallback(function(string $u, bool $includeLarge) use ($admin) {
if ($u === "john.doe@example.com" || $u === "ook") {
return ['num' => 2, 'admin' => $admin];
} else {
return ['num' => 1, 'admin' => true];
}
});
Arsse::$user->method("lookup")->willReturnCallback(function(int $u) {
if ($u === 1) {
return "jane.doe@example.com";
} elseif ($u === 2) {
return "john.doe@example.com";
} else {
throw new ExceptionConflict("doesNotExist");
}
});
Arsse::$user = \Phake::mock(User::class);
\Phake::when(Arsse::$user)->begin->thenReturn($this->transaction->get());
\Phake::when(Arsse::$user)->propertiesGet->thenReturn(['num' => 1, 'admin' => true]);
\Phake::when(Arsse::$user)->propertiesGet("john.doe@example.com", $this->anything())->thenReturn(['num' => 2, 'admin' => $admin]);
\Phake::when(Arsse::$user)->propertiesGet("ook", $this->anything())->thenReturn(['num' => 2, 'admin' => $admin]);
\Phake::when(Arsse::$user)->lookup->thenThrow(new ExceptionConflict("doesNotExist"));
\Phake::when(Arsse::$user)->lookup(1)->thenReturn("jane.doe@example.com");
\Phake::when(Arsse::$user)->lookup(2)->thenReturn("john.doe@example.com");
if ($out1 instanceof \Exception) {
Arsse::$user->method("rename")->willThrowException($out1);
\Phake::when(Arsse::$user)->rename->thenThrow($out1);
} else {
Arsse::$user->method("rename")->willReturn($out1 ?? false);
\Phake::when(Arsse::$user)->rename->thenReturn($out1 ?? false);
}
if ($out2 instanceof \Exception) {
Arsse::$user->method("passwordSet")->willThrowException($out2);
\Phake::when(Arsse::$user)->passwordSet->thenThrow($out2);
} else {
Arsse::$user->method("passwordSet")->willReturn($out2 ?? "");
\Phake::when(Arsse::$user)->passwordSet->thenReturn($out2 ?? "");
}
if ($out3 instanceof \Exception) {
Arsse::$user->method("propertiesSet")->willThrowException($out3);
\Phake::when(Arsse::$user)->propertiesSet->thenThrow($out3);
} else {
Arsse::$user->method("propertiesSet")->willReturn($out3 ?? []);
\Phake::when(Arsse::$user)->propertiesSet->thenReturn($out3 ?? []);
}
$this->assertMessage($exp, $this->req("PUT", $url, $body));
$user = $url === "/users/1" ? "jane.doe@example.com" : "john.doe@example.com";
if ($in1 === null) {
Arsse::$user->expects($this->exactly(0))->method("rename");
\Phake::verify(Arsse::$user, \Phake::never())->rename($this->anything(), $this->anything());
} else {
Arsse::$user->expects($this->exactly(1))->method("rename")->with($user, $in1);
\Phake::verify(Arsse::$user)->rename($user, $in1);
$user = $in1;
}
if ($in2 === null) {
Arsse::$user->expects($this->exactly(0))->method("passwordSet");
\Phake::verify(Arsse::$user, \Phake::never())->passwordSet($this->anything(), $this->anything());
} else {
Arsse::$user->expects($this->exactly(1))->method("passwordSet")->with($user, $in2);
\Phake::verify(Arsse::$user)->passwordSet($user, $in2);
}
if ($in3 === null) {
Arsse::$user->expects($this->exactly(0))->method("propertiesSet");
\Phake::verify(Arsse::$user, \Phake::never())->propertiesSet($this->anything(), $this->anything());
} else {
Arsse::$user->expects($this->exactly(1))->method("propertiesSet")->with($user, $in3);
\Phake::verify(Arsse::$user)->propertiesSet($user, $in3);
}
$this->assertMessage($exp, $this->req("PUT", $url, $body));
}
public function provideUserModifications(): iterable {
@ -330,36 +307,31 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
/** @dataProvider provideUserAdditions */
public function testAddAUser(array $body, $in1, $out1, $in2, $out2, ResponseInterface $exp): void {
Arsse::$user = $this->createMock(User::class);
Arsse::$user->method("begin")->willReturn($this->transaction->get());
Arsse::$user->method("propertiesGet")->willReturnCallback(function(string $u, bool $includeLarge) {
if ($u === "john.doe@example.com") {
return ['num' => 1, 'admin' => true];
} else {
return ['num' => 2, 'admin' => false];
}
});
Arsse::$user = \Phake::mock(User::class);
\Phake::when(Arsse::$user)->begin->thenReturn($this->transaction->get());
\Phake::when(Arsse::$user)->propertiesGet->thenReturn(['num' => 2, 'admin' => false]);
\Phake::when(Arsse::$user)->propertiesGet("john.doe@example.com", $this->anything())->thenReturn(['num' => 1, 'admin' => true]);
if ($out1 instanceof \Exception) {
Arsse::$user->method("add")->willThrowException($out1);
\Phake::when(Arsse::$user)->add->thenThrow($out1);
} else {
Arsse::$user->method("add")->willReturn($in1[1] ?? "");
\Phake::when(Arsse::$user)->add->thenReturn($in1[1] ?? "");
}
if ($out2 instanceof \Exception) {
Arsse::$user->method("propertiesSet")->willThrowException($out2);
\Phake::when(Arsse::$user)->propertiesSet->thenThrow($out2);
} else {
Arsse::$user->method("propertiesSet")->willReturn($out2 ?? []);
\Phake::when(Arsse::$user)->propertiesSet->thenReturn($out2 ?? []);
}
$this->assertMessage($exp, $this->req("POST", "/users", $body));
if ($in1 === null) {
Arsse::$user->expects($this->exactly(0))->method("add");
\Phake::verify(Arsse::$user, \Phake::never())->add($this->anything(), $this->anything());
} else {
Arsse::$user->expects($this->exactly(1))->method("add")->with(...($in1 ?? []));
\Phake::verify(Arsse::$user)->add(...$in1);
}
if ($in2 === null) {
Arsse::$user->expects($this->exactly(0))->method("propertiesSet");
\Phake::verify(Arsse::$user, \Phake::never())->propertiesSet($this->anything(), $this->anything());
} else {
Arsse::$user->expects($this->exactly(1))->method("propertiesSet")->with($body['username'], $in2);
\Phake::verify(Arsse::$user)->propertiesSet($body['username'], $in2);
}
$this->assertMessage($exp, $this->req("POST", "/users", $body));
}
public function provideUserAdditions(): iterable {
@ -380,29 +352,29 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
}
public function testDeleteAUser(): void {
Arsse::$user = $this->createMock(User::class);
Arsse::$user->method("propertiesGet")->willReturn(['admin' => true]);
Arsse::$user->method("lookup")->willReturn("john.doe@example.com");
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");
Arsse::$user = \Phake::mock(User::class);
\Phake::when(Arsse::$user)->propertiesGet->thenReturn(['admin' => true]);
\Phake::when(Arsse::$user)->lookup->thenReturn("john.doe@example.com");
\Phake::when(Arsse::$user)->remove->thenReturn(true);
$this->assertMessage(HTTP::respEmpty(204), $this->req("DELETE", "/users/2112"));
\Phake::verify(Arsse::$user)->lookup(2112);
\Phake::verify(Arsse::$user)->remove("john.doe@example.com");
}
public function testDeleteAMissingUser(): void {
Arsse::$user = $this->createMock(User::class);
Arsse::$user->method("propertiesGet")->willReturn(['admin' => true]);
Arsse::$user->method("lookup")->willThrowException(new ExceptionConflict("doesNotExist"));
Arsse::$user->method("remove")->willReturn(true);
Arsse::$user->expects($this->exactly(1))->method("lookup")->with(2112);
Arsse::$user->expects($this->exactly(0))->method("remove");
Arsse::$user = \Phake::mock(User::class);
\Phake::when(Arsse::$user)->propertiesGet->thenReturn(['admin' => true]);
\Phake::when(Arsse::$user)->lookup->thenThrow(new ExceptionConflict("doesNotExist"));
\Phake::when(Arsse::$user)->remove->thenReturn(true);
$this->assertMessage(V1::respError("404", 404), $this->req("DELETE", "/users/2112"));
\Phake::verify(Arsse::$user)->lookup(2112);
\Phake::verify(Arsse::$user, \Phake::never())->remove($this->anything());
}
public function testDeleteAUserWithoutAuthority(): void {
Arsse::$user->expects($this->exactly(0))->method("lookup");
Arsse::$user->expects($this->exactly(0))->method("remove");
$this->assertMessage(V1::respError("403", 403), $this->req("DELETE", "/users/2112"));
\Phake::verify(Arsse::$user, \Phake::never())->lookup($this->anything());
\Phake::verify(Arsse::$user, \Phake::never())->remove($this->anything());
}
public function testListCategories(): void {
@ -418,8 +390,8 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
$this->assertMessage($exp, $this->req("GET", "/categories"));
$this->dbMock->folderList->calledWith("john.doe@example.com", null, false);
// 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"]);
Arsse::$user = \Phake::mock(User::class);
\Phake::when(Arsse::$user)->propertiesGet->thenReturn(['num' => 47, 'admin' => false, 'root_folder_name' => "Uncategorized"]);
$exp = HTTP::respJson([
['id' => 1, 'title' => "Uncategorized", 'user_id' => 47],
['id' => 2, 'title' => "Science", 'user_id' => 47],
@ -455,15 +427,15 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
/** @dataProvider provideCategoryUpdates */
public function testRenameACategory(int $id, $title, $out, ResponseInterface $exp): void {
Arsse::$user->method("propertiesSet")->willReturn(['root_folder_name' => $title]);
\Phake::when(Arsse::$user)->propertiesSet->thenReturn(['root_folder_name' => $title]);
if (is_string($out)) {
$this->dbMock->folderPropertiesSet->throws(new ExceptionInput($out));
} else {
$this->dbMock->folderPropertiesSet->returns($out);
}
$times = (int) ($id === 1 && is_string($title) && strlen(trim($title)));
Arsse::$user->expects($this->exactly($times))->method("propertiesSet")->with("john.doe@example.com", ['root_folder_name' => $title]);
$this->assertMessage($exp, $this->req("PUT", "/categories/$id", ['title' => $title]));
\Phake::verify(Arsse::$user, \Phake::times($times))->propertiesSet("john.doe@example.com", ['root_folder_name' => $title]);
$times = (int) ($id !== 1 && is_string($title));
$this->dbMock->folderPropertiesSet->times($times)->calledWith("john.doe@example.com", $id - 1, ['name' => $title]);
}

20
tests/cases/TestArsse.php

@ -21,21 +21,17 @@ class TestArsse extends \JKingWeb\Arsse\Test\AbstractTest {
}
public function testLoadExistingData(): void {
$lang = $this->mock(Lang::class);
$db = $this->mock(Database::class);
$user = $this->mock(User::class);
$conf1 = $this->mock(Conf::class);
Arsse::$lang = $lang->get();
Arsse::$db = $db->get();
Arsse::$user = $user->get();
Arsse::$conf = $conf1->get();
Arsse::$conf = \Phake::mock(Conf::class);
$lang = Arsse::$lang = \Phake::mock(Lang::class);
$db = Arsse::$db = \Phake::mock(Database::class);
$user = Arsse::$user = \Phake::mock(User::class);
$conf2 = (new Conf)->import(['lang' => "test"]);
Arsse::load($conf2);
$this->assertSame($conf2, Arsse::$conf);
$this->assertSame($lang->get(), Arsse::$lang);
$this->assertSame($db->get(), Arsse::$db);
$this->assertSame($user->get(), Arsse::$user);
$lang->set->calledWith("test");
$this->assertSame($lang, Arsse::$lang);
$this->assertSame($db, Arsse::$db);
$this->assertSame($user, Arsse::$user);
\Phake::verify($lang)->set("test");
}
public function testLoadNewData(): void {

428
tests/cases/User/TestUser.php

@ -21,28 +21,16 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
protected $drv;
public function setUp(): void {
parent::setUp();
self::setConf();
// create a mock database interface
$this->dbMock = $this->mock(Database::class);
$this->dbMock->begin->returns($this->mock(\JKingWeb\Arsse\Db\Transaction::class));
Arsse::$db = \Phake::mock(Database::class);
\Phake::when(Arsse::$db)->begin->thenReturn(\Phake::mock(\JKingWeb\Arsse\Db\Transaction::class));
// create a mock user driver
$this->drv = $this->mock(Driver::class);
}
protected function prepTest(?\Closure $partialMockDef = null): User {
Arsse::$db = $this->dbMock->get();
if ($partialMockDef) {
$this->userMock = $this->partialMock(User::class, $this->drv->get());
$partialMockDef($this->userMock);
return $this->userMock->get();
} else {
return new User($this->drv->get());
}
$this->drv = \Phake::mock(Driver::class);
}
public function testConstruct(): void {
$this->assertInstanceOf(User::class, new User($this->drv->get()));
$this->assertInstanceOf(User::class, new User($this->drv));
$this->assertInstanceOf(User::class, new User);
}
@ -55,13 +43,13 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
}
public function testStartATransaction(): void {
$u = $this->prepTest();
$u = new User($this->drv);
$this->assertInstanceOf(Transaction::class, $u->begin());
$this->dbMock->begin->calledWith();
\Phake::verify(Arsse::$db)->begin();
}
public function testGeneratePasswords(): void {
$u = $this->prepTest();
$u = new User($this->drv);
$pass1 = $u->generatePassword();
$pass2 = $u->generatePassword();
$this->assertNotEquals($pass1, $pass2);
@ -70,18 +58,18 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
/** @dataProvider provideAuthentication */
public function testAuthenticateAUser(bool $preAuth, string $user, string $password, bool $exp): void {
Arsse::$conf->userPreAuth = $preAuth;
$this->drv->auth->returns(false);
$this->drv->auth->with("john.doe@example.com", "secret")->returns(true);
$this->drv->auth->with("jane.doe@example.com", "superman")->returns(true);
$this->dbMock->userExists->with("john.doe@example.com")->returns(true);
$this->dbMock->userExists->with("jane.doe@example.com")->returns(false);
$this->dbMock->userAdd->returns("");
$u = $this->prepTest();
\Phake::when($this->drv)->auth->thenReturn(false);
\Phake::when($this->drv)->auth("john.doe@example.com", "secret")->thenReturn(true);
\Phake::when($this->drv)->auth("jane.doe@example.com", "superman")->thenReturn(true);
\Phake::when(Arsse::$db)->userExists("john.doe@example.com")->thenReturn(true);
\Phake::when(Arsse::$db)->userExists("jane.doe@example.com")->thenReturn(false);
\Phake::when(Arsse::$db)->userAdd->thenReturn("");
$u = new User($this->drv);
$this->assertSame($exp, $u->auth($user, $password));
$this->assertNull($u->id);
$this->drv->auth->times((int) !$preAuth)->called();
$this->dbMock->userExists->times($exp ? 1 : 0)->calledWith($user);
$this->dbMock->userAdd->times($exp && $user === "jane.doe@example.com" ? 1 : 0)->calledWith($user, $password);
\Phake::verify($this->drv, \Phake::times((int) !$preAuth))->auth($this->anything(), $this->anything());
\Phake::verify(Arsse::$db, \Phake::times($exp ? 1 : 0))->userExists($user);
\Phake::verify(Arsse::$db, \Phake::times($exp && $user === "jane.doe@example.com" ? 1 : 0))->userAdd($user, $password);
}
public function provideAuthentication(): iterable {
@ -101,77 +89,77 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
public function testListUsers(): void {
$exp = ["john.doe@example.com", "jane.doe@example.com"];
$this->drv->userList->returns(["john.doe@example.com", "jane.doe@example.com"]);
$u = $this->prepTest();
\Phake::when($this->drv)->userList->thenReturn(["john.doe@example.com", "jane.doe@example.com"]);
$u = new User($this->drv);
$this->assertSame($exp, $u->list());
$this->drv->userList->calledWith();
\Phake::verify($this->drv)->userList();
}
public function testLookUpAUserByNumber(): void {
$exp = "john.doe@example.com";
$this->dbMock->userLookup->returns($exp);
$u = $this->prepTest();
\Phake::when(Arsse::$db)->userLookup->thenReturn($exp);
$u = new User($this->drv);
$this->assertSame($exp, $u->lookup(2112));
$this->dbMock->userLookup->calledWith(2112);
\Phake::verify(Arsse::$db)->userLookup(2112);
}
public function testAddAUser(): void {
$user = "john.doe@example.com";
$pass = "secret";
$this->drv->userAdd->returns($pass);
$this->dbMock->userExists->returns(true);
$u = $this->prepTest();
\Phake::when($this->drv)->userAdd->thenReturn($pass);
\Phake::when(Arsse::$db)->userExists->thenReturn(true);
$u = new User($this->drv);
$this->assertSame($pass, $u->add($user, $pass));
$this->drv->userAdd->calledWith($user, $pass);
$this->dbMock->userExists->calledWith($user);
\Phake::verify($this->drv)->userAdd($user, $pass);
\Phake::verify(Arsse::$db)->userExists($user);
}
public function testAddAUserWeDoNotKnow(): void {
$user = "john.doe@example.com";
$pass = "secret";
$this->drv->userAdd->returns($pass);
$this->dbMock->userExists->returns(false);
$u = $this->prepTest();
\Phake::when($this->drv)->userAdd->thenReturn($pass);
\Phake::when(Arsse::$db)->userExists->thenReturn(false);
$u = new User($this->drv);
$this->assertSame($pass, $u->add($user, $pass));
$this->drv->userAdd->calledWith($user, $pass);
$this->dbMock->userExists->calledWith($user);
$this->dbMock->userAdd->calledWith($user, $pass);
\Phake::verify($this->drv)->userAdd($user, $pass);
\Phake::verify(Arsse::$db)->userExists($user);
\Phake::verify(Arsse::$db)->userAdd($user, $pass);
}
public function testAddADuplicateUser(): void {
$user = "john.doe@example.com";
$pass = "secret";
$this->drv->userAdd->throws(new ExceptionConflict("alreadyExists"));
$this->dbMock->userExists->returns(true);
$u = $this->prepTest();
\Phake::when($this->drv)->userAdd->thenThrow(new ExceptionConflict("alreadyExists"));
\Phake::when(Arsse::$db)->userExists->thenReturn(true);
$u = new User($this->drv);
$this->assertException("alreadyExists", "User", "ExceptionConflict");
try {
$u->add($user, $pass);
} finally {
$this->dbMock->userExists->calledWith($user);
$this->drv->userAdd->calledWith($user, $pass);
\Phake::verify(Arsse::$db)->userExists($user);
\Phake::verify($this->drv)->userAdd($user, $pass);
}
}
public function testAddADuplicateUserWeDoNotKnow(): void {
$user = "john.doe@example.com";
$pass = "secret";
$this->drv->userAdd->throws(new ExceptionConflict("alreadyExists"));
$this->dbMock->userExists->returns(false);
$u = $this->prepTest();
\Phake::when($this->drv)->userAdd->thenThrow(new ExceptionConflict("alreadyExists"));
\Phake::when(Arsse::$db)->userExists->thenReturn(false);
$u = new User($this->drv);
$this->assertException("alreadyExists", "User", "ExceptionConflict");
try {
$u->add($user, $pass);
} finally {
$this->dbMock->userExists->calledWith($user);
$this->dbMock->userAdd->calledWith($user, null);
$this->drv->userAdd->calledWith($user, $pass);
\Phake::verify(Arsse::$db)->userExists($user);
\Phake::verify(Arsse::$db)->userAdd($user, null);
\Phake::verify($this->drv)->userAdd($user, $pass);
}
}
/** @dataProvider provideInvalidUserNames */
public function testAddAnInvalidUser(string $user): void {
$u = $this->prepTest();
$u = new User($this->drv);
$this->assertException("invalidUsername", "User", "ExceptionInput");
$u->add($user, "secret");
}
@ -190,237 +178,231 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
public function testAddAUserWithARandomPassword(): void {
$user = "john.doe@example.com";
$pass = "random password";
$this->drv->userAdd->returns(null)->returns($pass);
$this->dbMock->userExists->returns(true);
$u = $this->prepTest(function($u) use ($pass) {
$u->generatePassword->returns($pass);
});
$u = \Phake::partialMock(User::class, $this->drv);
\Phake::when($u)->generatePassword->thenReturn($pass);
\Phake::when($this->drv)->userAdd->thenReturn(null)->thenReturn($pass);
\Phake::when(Arsse::$db)->userExists->thenReturn(true);
$this->assertSame($pass, $u->add($user));
$this->drv->userAdd->calledWith($user, null);
$this->drv->userAdd->calledWith($user, $pass);
$this->dbMock->userExists->calledWith($user);
\Phake::verify($this->drv)->userAdd($user, null);
\Phake::verify($this->drv)->userAdd($user, $pass);
\Phake::verify(Arsse::$db)->userExists($user);
}
public function testRenameAUser(): void {
$tr = $this->mock(Transaction::class);
$this->dbMock->begin->returns($tr);
$this->dbMock->userExists->returns(true);
$this->dbMock->userAdd->returns(true);
$this->dbMock->userRename->returns(true);
$this->drv->userRename->returns(true);
$u = $this->prepTest();
$tr = \Phake::mock(Transaction::class);
\Phake::when(Arsse::$db)->begin->thenReturn($tr);
\Phake::when(Arsse::$db)->userExists->thenReturn(true);
\Phake::when(Arsse::$db)->userAdd->thenReturn(true);
\Phake::when(Arsse::$db)->userRename->thenReturn(true);
\Phake::when($this->drv)->userRename->thenReturn(true);
$u = new User($this->drv);
$old = "john.doe@example.com";
$new = "jane.doe@example.com";
$this->assertTrue($u->rename($old, $new));
Phony::inOrder(
$this->drv->userRename->calledWith($old, $new),
$this->dbMock->begin->calledWith(),
$this->dbMock->userExists->calledWith($old),
$this->dbMock->userRename->calledWith($old, $new),
$this->dbMock->sessionDestroy->calledWith($new),
$this->dbMock->tokenRevoke->calledWith($new, "fever.login"),
$tr->commit->called()
\Phake::inOrder(
\Phake::verify($this->drv)->userRename($old, $new),
\Phake::verify(Arsse::$db)->begin(),
\Phake::verify(Arsse::$db)->userExists($old),
\Phake::verify(Arsse::$db)->userRename($old, $new),
\Phake::verify(Arsse::$db)->sessionDestroy($new),
\Phake::verify(Arsse::$db)->tokenRevoke($new, "fever.login"),
\Phake::verify($tr)->commit()
);
}
public function testRenameAUserWeDoNotKnow(): void {
$tr = $this->mock(Transaction::class);
$this->dbMock->begin->returns($tr);
$this->dbMock->userExists->returns(false);
$this->dbMock->userAdd->returns(true);
$this->dbMock->userRename->returns(true);
$this->drv->userRename->returns(true);
$u = $this->prepTest();
$tr = \Phake::mock(Transaction::class);
\Phake::when(Arsse::$db)->begin->thenReturn($tr);
\Phake::when(Arsse::$db)->userExists->thenReturn(false);
\Phake::when(Arsse::$db)->userAdd->thenReturn(true);
\Phake::when(Arsse::$db)->userRename->thenReturn(true);
\Phake::when($this->drv)->userRename->thenReturn(true);
$u = new User($this->drv);
$old = "john.doe@example.com";
$new = "jane.doe@example.com";
$this->assertTrue($u->rename($old, $new));
Phony::inOrder(
$this->drv->userRename->calledWith($old, $new),
$this->dbMock->begin->calledWith(),
$this->dbMock->userExists->calledWith($old),
$this->dbMock->userAdd->calledWith($new, null),
$tr->commit->called()
\Phake::inOrder(
\Phake::verify($this->drv)->userRename($old, $new),
\Phake::verify(Arsse::$db)->begin(),
\Phake::verify(Arsse::$db)->userExists($old),
\Phake::verify(Arsse::$db)->userAdd($new, null),
\Phake::verify($tr)->commit()
);
}
public function testRenameAUserWithoutEffect(): void {
$this->dbMock->userExists->returns(false);
$this->dbMock->userAdd->returns(true);
$this->dbMock->userRename->returns(true);
$this->drv->userRename->returns(false);
$u = $this->prepTest();
\Phake::when(Arsse::$db)->userExists->thenReturn(false);
\Phake::when(Arsse::$db)->userAdd->thenReturn(true);
\Phake::when(Arsse::$db)->userRename->thenReturn(true);
\Phake::when($this->drv)->userRename->thenReturn(false);
$u = new User($this->drv);
$old = "john.doe@example.com";
$this->assertFalse($u->rename($old, $old));
$this->drv->userRename->calledWith($old, $old);
\Phake::verify($this->drv)->userRename($old, $old);
}
/** @dataProvider provideInvalidUserNames */
public function testRenameAUserToAnInvalidName(string $new): void {
$u = $this->prepTest();
$u = new User($this->drv);
$this->assertException("invalidUsername", "User", "ExceptionInput");
$u->rename("john.doe@example.com", $new);
}
public function testRemoveAUser(): void {
$user = "john.doe@example.com";
$this->drv->userRemove->returns(true);
$this->dbMock->userExists->returns(true);
$u = $this->prepTest();
\Phake::when($this->drv)->userRemove->thenReturn(true);
\Phake::when(Arsse::$db)->userExists->thenReturn(true);
$u = new User($this->drv);
$this->assertTrue($u->remove($user));
$this->dbMock->userExists->calledWith($user);
$this->dbMock->userRemove->calledWith($user);
$this->drv->userRemove->calledWith($user);
\Phake::verify(Arsse::$db)->userExists($user);
\Phake::verify(Arsse::$db)->userRemove($user);
\Phake::verify($this->drv)->userRemove($user);
}
public function testRemoveAUserWeDoNotKnow(): void {
$user = "john.doe@example.com";
$this->drv->userRemove->returns(true);
$this->dbMock->userExists->returns(false);
$u = $this->prepTest();
\Phake::when($this->drv)->userRemove->thenReturn(true);
\Phake::when(Arsse::$db)->userExists->thenReturn(false);
$u = new User($this->drv);
$this->assertTrue($u->remove($user));
$this->dbMock->userExists->calledWith($user);
$this->drv->userRemove->calledWith($user);
\Phake::verify(Arsse::$db)->userExists($user);
\Phake::verify($this->drv)->userRemove($user);
}
public function testRemoveAMissingUser(): void {
$user = "john.doe@example.com";
$pass = "secret";
$this->drv->userRemove->throws(new ExceptionConflict("doesNotExist"));
$this->dbMock->userExists->returns(true);
$u = $this->prepTest();
\Phake::when($this->drv)->userRemove->thenThrow(new ExceptionConflict("doesNotExist"));
\Phake::when(Arsse::$db)->userExists->thenReturn(true);
$u = new User($this->drv);
$this->assertException("doesNotExist", "User", "ExceptionConflict");
try {
$u->remove($user);
} finally {
$this->dbMock->userExists->calledWith($user);
$this->dbMock->userRemove->calledWith($user);
$this->drv->userRemove->calledWith($user);
\Phake::verify(Arsse::$db)->userExists($user);
\Phake::verify(Arsse::$db)->userRemove($user);
\Phake::verify($this->drv)->userRemove($user);
}
}
public function testRemoveAMissingUserWeDoNotKnow(): void {
$user = "john.doe@example.com";
$pass = "secret";
$this->drv->userRemove->throws(new ExceptionConflict("doesNotExist"));
$this->dbMock->userExists->returns(false);
$u = $this->prepTest();
\Phake::when($this->drv)->userRemove->thenThrow(new ExceptionConflict("doesNotExist"));
\Phake::when(Arsse::$db)->userExists->thenReturn(false);
$u = new User($this->drv);
$this->assertException("doesNotExist", "User", "ExceptionConflict");
try {
$u->remove($user);
} finally {
$this->dbMock->userExists->calledWith($user);
$this->drv->userRemove->calledWith($user);
\Phake::verify(Arsse::$db)->userExists($user);
\Phake::verify($this->drv)->userRemove($user);
}
}
public function testSetAPassword(): void {
$user = "john.doe@example.com";
$pass = "secret";
$this->drv->userPasswordSet->returns($pass);
$this->dbMock->userPasswordSet->returns($pass);
$this->dbMock->userExists->returns(true);
$u = $this->prepTest();
\Phake::when($this->drv)->userPasswordSet->thenReturn($pass);
\Phake::when(Arsse::$db)->userPasswordSet->thenReturn($pass);
\Phake::when(Arsse::$db)->userExists->thenReturn(true);
$u = new User($this->drv);
$this->assertSame($pass, $u->passwordSet($user, $pass));
$this->drv->userPasswordSet->calledWith($user, $pass, null);
$this->dbMock->userPasswordSet->calledWith($user, $pass);
$this->dbMock->sessionDestroy->calledWith($user);
$this->dbMock->userExists->calledWith($user);
\Phake::verify($this->drv)->userPasswordSet($user, $pass, null);
\Phake::verify(Arsse::$db)->userPasswordSet($user, $pass);
\Phake::verify(Arsse::$db)->sessionDestroy($user);
\Phake::verify(Arsse::$db)->userExists($user);
}
public function testSetARandomPassword(): void {
$user = "john.doe@example.com";
$pass = "random password";
$this->drv->userPasswordSet->returns(null)->returns($pass);
$this->dbMock->userPasswordSet->returns($pass);
$this->dbMock->userExists->returns(true);
$u = $this->prepTest(function($u) use ($pass) {
$u->generatePassword->returns($pass);
});
$u = \Phake::partialMock(User::class, $this->drv);
\Phake::when($u)->generatePassword->thenReturn($pass);
\Phake::when($this->drv)->userPasswordSet->thenReturn(null)->thenReturn($pass);
\Phake::when(Arsse::$db)->userPasswordSet->thenReturn($pass);
\Phake::when(Arsse::$db)->userExists->thenReturn(true);
$this->assertSame($pass, $u->passwordSet($user, null));
$this->drv->userPasswordSet->calledWith($user, null, null);
$this->drv->userPasswordSet->calledWith($user, $pass, null);
$this->dbMock->userPasswordSet->calledWith($user, $pass);
$this->dbMock->sessionDestroy->calledWith($user);
$this->dbMock->userExists->calledWith($user);
\Phake::verify($this->drv)->userPasswordSet($user, null, null);
\Phake::verify($this->drv)->userPasswordSet($user, $pass, null);
\Phake::verify(Arsse::$db)->userPasswordSet($user, $pass);
\Phake::verify(Arsse::$db)->sessionDestroy($user);
\Phake::verify(Arsse::$db)->userExists($user);
}
public function testSetAPasswordForAUserWeDoNotKnow(): void {
$user = "john.doe@example.com";
$pass = "secret";
$this->drv->userPasswordSet->returns($pass);
$this->dbMock->userPasswordSet->returns($pass);
$this->dbMock->userExists->returns(false);
$u = $this->prepTest();
\Phake::when($this->drv)->userPasswordSet->thenReturn($pass);
\Phake::when(Arsse::$db)->userPasswordSet->thenReturn($pass);
\Phake::when(Arsse::$db)->userExists->thenReturn(false);
$u = new User($this->drv);
$this->assertSame($pass, $u->passwordSet($user, $pass));
$this->drv->userPasswordSet->calledWith($user, $pass, null);
$this->dbMock->userAdd->calledWith($user, $pass);
$this->dbMock->userExists->calledWith($user);
\Phake::verify($this->drv)->userPasswordSet($user, $pass, null);
\Phake::verify(Arsse::$db)->userAdd($user, $pass);
\Phake::verify(Arsse::$db)->userExists($user);
}
public function testSetARandomPasswordForAUserWeDoNotKnow(): void {
$user = "john.doe@example.com";
$pass = "random password";
$this->drv->userPasswordSet->returns(null)->returns($pass);
$this->dbMock->userPasswordSet->returns($pass);
$this->dbMock->userExists->returns(false);
$u = $this->prepTest(function($u) use ($pass) {
$u->generatePassword->returns($pass);
});
$u = \Phake::partialMock(User::class, $this->drv);
\Phake::when($u)->generatePassword->thenReturn($pass);
\Phake::when($this->drv)->userPasswordSet->thenReturn(null)->thenReturn($pass);
\Phake::when(Arsse::$db)->userPasswordSet->thenReturn($pass);
\Phake::when(Arsse::$db)->userExists->thenReturn(false);
$this->assertSame($pass, $u->passwordSet($user, null));
$this->drv->userPasswordSet->calledWith($user, null, null);
$this->drv->userPasswordSet->calledWith($user, $pass, null);
$this->dbMock->userAdd->calledWith($user, $pass);
$this->dbMock->userExists->calledWith($user);
\Phake::verify($this->drv)->userPasswordSet($user, null, null);
\Phake::verify($this->drv)->userPasswordSet($user, $pass, null);
\Phake::verify(Arsse::$db)->userAdd($user, $pass);
\Phake::verify(Arsse::$db)->userExists($user);
}
public function testSetARandomPasswordForAMissingUser(): void {
$user = "john.doe@example.com";
$pass = "random password";
$this->drv->userPasswordSet->throws(new ExceptionConflict("doesNotExist"));
$u = $this->prepTest(function($u) use ($pass) {
$u->generatePassword->returns($pass);
});
$u = \Phake::partialMock(User::class, $this->drv);
\Phake::when($u)->generatePassword->thenReturn($pass);
\Phake::when($this->drv)->userPasswordSet->thenThrow(new ExceptionConflict("doesNotExist"));
$this->assertException("doesNotExist", "User", "ExceptionConflict");
try {
$u->passwordSet($user, null);
} finally {
$this->drv->userPasswordSet->calledWith($user, null, null);
\Phake::verify($this->drv)->userPasswordSet($user, null, null);
}
}
public function testUnsetAPassword(): void {
$user = "john.doe@example.com";
$this->drv->userPasswordUnset->returns(true);
$this->dbMock->userPasswordSet->returns(true);
$this->dbMock->userExists->returns(true);
$u = $this->prepTest();
\Phake::when($this->drv)->userPasswordUnset->thenReturn(true);
\Phake::when(Arsse::$db)->userPasswordSet->thenReturn(true);
\Phake::when(Arsse::$db)->userExists->thenReturn(true);
$u = new User($this->drv);
$this->assertTrue($u->passwordUnset($user));
$this->drv->userPasswordUnset->calledWith($user, null);
$this->dbMock->userPasswordSet->calledWith($user, null);
$this->dbMock->sessionDestroy->calledWith($user);
$this->dbMock->userExists->calledWith($user);
\Phake::verify($this->drv)->userPasswordUnset($user, null);
\Phake::verify(Arsse::$db)->userPasswordSet($user, null);
\Phake::verify(Arsse::$db)->sessionDestroy($user);
\Phake::verify(Arsse::$db)->userExists($user);
}
public function testUnsetAPasswordForAUserWeDoNotKnow(): void {
$user = "john.doe@example.com";
$this->drv->userPasswordUnset->returns(true);
$this->dbMock->userPasswordSet->returns(true);
$this->dbMock->userExists->returns(false);
$u = $this->prepTest();
\Phake::when($this->drv)->userPasswordUnset->thenReturn(true);
\Phake::when(Arsse::$db)->userPasswordSet->thenReturn(true);
\Phake::when(Arsse::$db)->userExists->thenReturn(false);
$u = new User($this->drv);
$this->assertTrue($u->passwordUnset($user));
$this->drv->userPasswordUnset->calledWith($user, null);
$this->dbMock->userExists->calledWith($user);
\Phake::verify($this->drv)->userPasswordUnset($user, null);
\Phake::verify(Arsse::$db)->userExists($user);
}
public function testUnsetAPasswordForAMissingUser(): void {
$user = "john.doe@example.com";
$this->drv->userPasswordUnset->throws(new ExceptionConflict("doesNotExist"));
$u = $this->prepTest();
\Phake::when($this->drv)->userPasswordUnset->thenThrow(new ExceptionConflict("doesNotExist"));
$u = new User($this->drv);
$this->assertException("doesNotExist", "User", "ExceptionConflict");
try {
$u->passwordUnset($user);
} finally {
$this->drv->userPasswordUnset->calledWith($user, null);
\Phake::verify($this->drv)->userPasswordUnset($user, null);
}
}
@ -428,14 +410,14 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
public function testGetThePropertiesOfAUser(array $exp, array $base, array $extra): void {
$user = "john.doe@example.com";
$exp = array_merge(['num' => null], array_combine(array_keys(User::PROPERTIES), array_fill(0, sizeof(User::PROPERTIES), null)), $exp);
$this->drv->userPropertiesGet->returns($extra);
$this->dbMock->userPropertiesGet->returns($base);
$this->dbMock->userExists->returns(true);
$u = $this->prepTest();
\Phake::when($this->drv)->userPropertiesGet->thenReturn($extra);
\Phake::when(Arsse::$db)->userPropertiesGet->thenReturn($base);
\Phake::when(Arsse::$db)->userExists->thenReturn(true);
$u = new User($this->drv);
$this->assertSame($exp, $u->propertiesGet($user));
$this->drv->userPropertiesGet->calledWith($user, true);
$this->dbMock->userPropertiesGet->calledWith($user, true);
$this->dbMock->userExists->calledWith($user);
\Phake::verify($this->drv)->userPropertiesGet($user, true);
\Phake::verify(Arsse::$db)->userPropertiesGet($user, true);
\Phake::verify(Arsse::$db)->userExists($user);
}
public function provideProperties(): iterable {
@ -454,28 +436,28 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
$base = ['num' => 47, 'admin' => false, 'lang' => null, 'tz' => "Etc/UTC", 'sort_asc' => false];
$exp = ['num' => 47, 'admin' => false, 'lang' => null, 'tz' => "Europe/Istanbul", 'sort_asc' => false];
$exp = array_merge(['num' => null], array_combine(array_keys(User::PROPERTIES), array_fill(0, sizeof(User::PROPERTIES), null)), $exp);
$this->drv->userPropertiesGet->returns($extra);
$this->dbMock->userPropertiesGet->returns($base);
$this->dbMock->userAdd->returns(true);
$this->dbMock->userExists->returns(false);
$u = $this->prepTest();
\Phake::when($this->drv)->userPropertiesGet->thenReturn($extra);
\Phake::when(Arsse::$db)->userPropertiesGet->thenReturn($base);
\Phake::when(Arsse::$db)->userAdd->thenReturn(true);
\Phake::when(Arsse::$db)->userExists->thenReturn(false);
$u = new User($this->drv);
$this->assertSame($exp, $u->propertiesGet($user));
$this->drv->userPropertiesGet->calledWith($user, true);
$this->dbMock->userPropertiesGet->calledWith($user, true);
$this->dbMock->userPropertiesSet->calledWith($user, $extra);
$this->dbMock->userAdd->calledWith($user, null);
$this->dbMock->userExists->calledWith($user);
\Phake::verify($this->drv)->userPropertiesGet($user, true);
\Phake::verify(Arsse::$db)->userPropertiesGet($user, true);
\Phake::verify(Arsse::$db)->userPropertiesSet($user, $extra);
\Phake::verify(Arsse::$db)->userAdd($user, null);
\Phake::verify(Arsse::$db)->userExists($user);
}
public function testGetThePropertiesOfAMissingUser(): void {
$user = "john.doe@example.com";
$this->drv->userPropertiesGet->throws(new ExceptionConflict("doesNotExist"));
$u = $this->prepTest();
\Phake::when($this->drv)->userPropertiesGet->thenThrow(new ExceptionConflict("doesNotExist"));
$u = new User($this->drv);
$this->assertException("doesNotExist", "User", "ExceptionConflict");
try {
$u->propertiesGet($user);
} finally {
$this->drv->userPropertiesGet->calledWith($user, true);
\Phake::verify($this->drv)->userPropertiesGet($user, true);
}
}
@ -483,18 +465,18 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
public function testSetThePropertiesOfAUser(array $in, $out): void {
$user = "john.doe@example.com";
if ($out instanceof \Exception) {
$u = $this->prepTest();
$u = new User($this->drv);
$this->assertException($out);
$u->propertiesSet($user, $in);
} else {
$this->dbMock->userExists->returns(true);
$this->drv->userPropertiesSet->returns($out);
$this->dbMock->userPropertiesSet->returns(true);
$u = $this->prepTest();
\Phake::when(Arsse::$db)->userExists->thenReturn(true);
\Phake::when($this->drv)->userPropertiesSet->thenReturn($out);
\Phake::when(Arsse::$db)->userPropertiesSet->thenReturn(true);
$u = new User($this->drv);
$this->assertSame($out, $u->propertiesSet($user, $in));
$this->drv->userPropertiesSet->calledWith($user, $in);
$this->dbMock->userPropertiesSet->calledWith($user, $out);
$this->dbMock->userExists->calledWith($user);
\Phake::verify($this->drv)->userPropertiesSet($user, $in);
\Phake::verify(Arsse::$db)->userPropertiesSet($user, $out);
\Phake::verify(Arsse::$db)->userExists($user);
}
}
@ -502,19 +484,19 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
public function testSetThePropertiesOfAUserWeDoNotKnow(array $in, $out): void {
$user = "john.doe@example.com";
if ($out instanceof \Exception) {
$u = $this->prepTest();
$u = new User($this->drv);
$this->assertException($out);
$u->propertiesSet($user, $in);
} else {
$this->dbMock->userExists->returns(false);
$this->drv->userPropertiesSet->returns($out);
$this->dbMock->userPropertiesSet->returns(true);
$u = $this->prepTest();
\Phake::when(Arsse::$db)->userExists->thenReturn(false);
\Phake::when($this->drv)->userPropertiesSet->thenReturn($out);
\Phake::when(Arsse::$db)->userPropertiesSet->thenReturn(true);
$u = new User($this->drv);
$this->assertSame($out, $u->propertiesSet($user, $in));
$this->drv->userPropertiesSet->calledWith($user, $in);
$this->dbMock->userPropertiesSet->calledWith($user, $out);
$this->dbMock->userExists->calledWith($user);
$this->dbMock->userAdd->calledWith($user, null);
\Phake::when($this->drv)->userPropertiesSet($user, $in);
\Phake::when(Arsse::$db)->userPropertiesSet($user, $out);
\Phake::when(Arsse::$db)->userExists($user);
\Phake::when(Arsse::$db)->userAdd($user, null);
}
}
@ -535,13 +517,13 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
public function testSetThePropertiesOfAMissingUser(): void {
$user = "john.doe@example.com";
$in = ['admin' => true];
$this->drv->userPropertiesSet->throws(new ExceptionConflict("doesNotExist"));
$u = $this->prepTest();
\Phake::when($this->drv)->userPropertiesSet->thenThrow(new ExceptionConflict("doesNotExist"));
$u = new User($this->drv);
$this->assertException("doesNotExist", "User", "ExceptionConflict");
try {
$u->propertiesSet($user, $in);
} finally {
$this->drv->userPropertiesSet->calledWith($user, $in);
\Phake::verify($this->drv)->userPropertiesSet($user, $in);
}
}
}

15
tests/lib/AbstractTest.php

@ -31,21 +31,6 @@ use GuzzleHttp\Psr7\ServerRequest;
abstract class AbstractTest extends \PHPUnit\Framework\TestCase {
use \DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
protected $objMock;
protected $confMock;
protected $langMock;
protected $dbMock;
protected $userMock;
public function setUp(): void {
self::clearData();
// create the object factory as a mock
$this->objMock = Arsse::$obj = $this->mock(Factory::class);
$this->objMock->get->does(function(string $class) {
return new $class;
});
}
public static function clearData(bool $loadLang = true): void {
date_default_timezone_set("America/Toronto");
$r = new \ReflectionClass(\JKingWeb\Arsse\Arsse::class);

403
vendor-bin/csfixer/composer.lock

@ -9,16 +9,16 @@
"packages-dev": [
{
"name": "composer/pcre",
"version": "3.1.0",
"version": "3.1.1",
"source": {
"type": "git",
"url": "https://github.com/composer/pcre.git",
"reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2"
"reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/pcre/zipball/4bff79ddd77851fe3cdd11616ed3f92841ba5bd2",
"reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2",
"url": "https://api.github.com/repos/composer/pcre/zipball/00104306927c7a0919b4ced2aaa6782c1e61a3c9",
"reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9",
"shasum": ""
},
"require": {
@ -60,7 +60,7 @@
],
"support": {
"issues": "https://github.com/composer/pcre/issues",
"source": "https://github.com/composer/pcre/tree/3.1.0"
"source": "https://github.com/composer/pcre/tree/3.1.1"
},
"funding": [
{
@ -76,20 +76,20 @@
"type": "tidelift"
}
],
"time": "2022-11-17T09:50:14+00:00"
"time": "2023-10-11T07:11:09+00:00"
},
{
"name": "composer/semver",
"version": "3.3.2",
"version": "3.4.0",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
"reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9"
"reference": "35e8d0af4486141bc745f23a29cc2091eb624a32"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9",
"reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9",
"url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32",
"reference": "35e8d0af4486141bc745f23a29cc2091eb624a32",
"shasum": ""
},
"require": {
@ -139,9 +139,9 @@
"versioning"
],
"support": {
"irc": "irc://irc.freenode.org/composer",
"irc": "ircs://irc.libera.chat:6697/composer",
"issues": "https://github.com/composer/semver/issues",
"source": "https://github.com/composer/semver/tree/3.3.2"
"source": "https://github.com/composer/semver/tree/3.4.0"
},
"funding": [
{
@ -157,7 +157,7 @@
"type": "tidelift"
}
],
"time": "2022-04-01T19:23:25+00:00"
"time": "2023-08-31T09:50:34+00:00"
},
{
"name": "composer/xdebug-handler",
@ -225,178 +225,23 @@
],
"time": "2022-02-25T21:32:43+00:00"
},
{
"name": "doctrine/annotations",
"version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/annotations.git",
"reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/annotations/zipball/e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f",
"reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f",
"shasum": ""
},
"require": {
"doctrine/lexer": "^2 || ^3",
"ext-tokenizer": "*",
"php": "^7.2 || ^8.0",
"psr/cache": "^1 || ^2 || ^3"
},
"require-dev": {
"doctrine/cache": "^2.0",
"doctrine/coding-standard": "^10",
"phpstan/phpstan": "^1.8.0",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
"symfony/cache": "^5.4 || ^6",
"vimeo/psalm": "^4.10"
},
"suggest": {
"php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "Docblock Annotations Parser",
"homepage": "https://www.doctrine-project.org/projects/annotations.html",
"keywords": [
"annotations",
"docblock",
"parser"
],
"support": {
"issues": "https://github.com/doctrine/annotations/issues",
"source": "https://github.com/doctrine/annotations/tree/2.0.1"
},
"time": "2023-02-02T22:02:53+00:00"
},
{
"name": "doctrine/lexer",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/lexer.git",
"reference": "84a527db05647743d50373e0ec53a152f2cde568"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/lexer/zipball/84a527db05647743d50373e0ec53a152f2cde568",
"reference": "84a527db05647743d50373e0ec53a152f2cde568",
"shasum": ""
},
"require": {
"php": "^8.1"
},
"require-dev": {
"doctrine/coding-standard": "^10",
"phpstan/phpstan": "^1.9",
"phpunit/phpunit": "^9.5",
"psalm/plugin-phpunit": "^0.18.3",
"vimeo/psalm": "^5.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Common\\Lexer\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.",
"homepage": "https://www.doctrine-project.org/projects/lexer.html",
"keywords": [
"annotations",
"docblock",
"lexer",
"parser",
"php"
],
"support": {
"issues": "https://github.com/doctrine/lexer/issues",
"source": "https://github.com/doctrine/lexer/tree/3.0.0"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer",
"type": "tidelift"
}
],
"time": "2022-12-15T16:57:16+00:00"
},
{
"name": "friendsofphp/php-cs-fixer",
"version": "v3.17.0",
"version": "v3.38.0",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "3f0ed862f22386c55a767461ef5083bddceeed79"
"reference": "7e6070026e76aa09d77a47519625c86593fb8e31"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/3f0ed862f22386c55a767461ef5083bddceeed79",
"reference": "3f0ed862f22386c55a767461ef5083bddceeed79",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/7e6070026e76aa09d77a47519625c86593fb8e31",
"reference": "7e6070026e76aa09d77a47519625c86593fb8e31",
"shasum": ""
},
"require": {
"composer/semver": "^3.3",
"composer/xdebug-handler": "^3.0.3",
"doctrine/annotations": "^2",
"doctrine/lexer": "^2 || ^3",
"ext-json": "*",
"ext-tokenizer": "*",
"php": "^7.4 || ^8.0",
@ -413,6 +258,7 @@
"symfony/stopwatch": "^5.4 || ^6.0"
},
"require-dev": {
"facile-it/paraunit": "^1.3 || ^2.0",
"justinrainbow/json-schema": "^5.2",
"keradus/cli-executor": "^2.0",
"mikey179/vfsstream": "^1.6.11",
@ -423,8 +269,6 @@
"phpspec/prophecy": "^1.16",
"phpspec/prophecy-phpunit": "^2.0",
"phpunit/phpunit": "^9.5",
"phpunitgoodpractices/polyfill": "^1.6",
"phpunitgoodpractices/traits": "^1.9.2",
"symfony/phpunit-bridge": "^6.2.3",
"symfony/yaml": "^5.4 || ^6.0"
},
@ -464,7 +308,7 @@
],
"support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.17.0"
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.38.0"
},
"funding": [
{
@ -472,56 +316,7 @@
"type": "github"
}
],
"time": "2023-05-22T19:59:32+00:00"
},
{
"name": "psr/cache",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/cache.git",
"reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
"reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
"shasum": ""
},
"require": {
"php": ">=8.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Cache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for caching libraries",
"keywords": [
"cache",
"psr",
"psr-6"
],
"support": {
"source": "https://github.com/php-fig/cache/tree/3.0.0"
},
"time": "2021-02-03T23:26:27+00:00"
"time": "2023-11-07T08:44:54+00:00"
},
{
"name": "psr/container",
@ -745,16 +540,16 @@
},
{
"name": "symfony/console",
"version": "v6.3.0",
"version": "v6.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7"
"reference": "eca495f2ee845130855ddf1cf18460c38966c8b6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7",
"reference": "8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7",
"url": "https://api.github.com/repos/symfony/console/zipball/eca495f2ee845130855ddf1cf18460c38966c8b6",
"reference": "eca495f2ee845130855ddf1cf18460c38966c8b6",
"shasum": ""
},
"require": {
@ -815,7 +610,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v6.3.0"
"source": "https://github.com/symfony/console/tree/v6.3.4"
},
"funding": [
{
@ -831,7 +626,7 @@
"type": "tidelift"
}
],
"time": "2023-05-29T12:49:39+00:00"
"time": "2023-08-16T10:10:12+00:00"
},
{
"name": "symfony/deprecation-contracts",
@ -902,16 +697,16 @@
},
{
"name": "symfony/event-dispatcher",
"version": "v6.3.0",
"version": "v6.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "3af8ac1a3f98f6dbc55e10ae59c9e44bfc38dfaa"
"reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/3af8ac1a3f98f6dbc55e10ae59c9e44bfc38dfaa",
"reference": "3af8ac1a3f98f6dbc55e10ae59c9e44bfc38dfaa",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/adb01fe097a4ee930db9258a3cc906b5beb5cf2e",
"reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e",
"shasum": ""
},
"require": {
@ -962,7 +757,7 @@
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/event-dispatcher/tree/v6.3.0"
"source": "https://github.com/symfony/event-dispatcher/tree/v6.3.2"
},
"funding": [
{
@ -978,7 +773,7 @@
"type": "tidelift"
}
],
"time": "2023-04-21T14:41:17+00:00"
"time": "2023-07-06T06:56:43+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
@ -1058,16 +853,16 @@
},
{
"name": "symfony/filesystem",
"version": "v6.3.0",
"version": "v6.3.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "97b698e1d77d356304def77a8d0cd73090b359ea"
"reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/97b698e1d77d356304def77a8d0cd73090b359ea",
"reference": "97b698e1d77d356304def77a8d0cd73090b359ea",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae",
"reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae",
"shasum": ""
},
"require": {
@ -1101,7 +896,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/filesystem/tree/v6.3.0"
"source": "https://github.com/symfony/filesystem/tree/v6.3.1"
},
"funding": [
{
@ -1117,20 +912,20 @@
"type": "tidelift"
}
],
"time": "2023-05-30T17:12:32+00:00"
"time": "2023-06-01T08:30:39+00:00"
},
{
"name": "symfony/finder",
"version": "v6.3.0",
"version": "v6.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "d9b01ba073c44cef617c7907ce2419f8d00d75e2"
"reference": "a1b31d88c0e998168ca7792f222cbecee47428c4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/d9b01ba073c44cef617c7907ce2419f8d00d75e2",
"reference": "d9b01ba073c44cef617c7907ce2419f8d00d75e2",
"url": "https://api.github.com/repos/symfony/finder/zipball/a1b31d88c0e998168ca7792f222cbecee47428c4",
"reference": "a1b31d88c0e998168ca7792f222cbecee47428c4",
"shasum": ""
},
"require": {
@ -1165,7 +960,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/finder/tree/v6.3.0"
"source": "https://github.com/symfony/finder/tree/v6.3.5"
},
"funding": [
{
@ -1181,7 +976,7 @@
"type": "tidelift"
}
],
"time": "2023-04-02T01:25:41+00:00"
"time": "2023-09-26T12:56:25+00:00"
},
{
"name": "symfony/options-resolver",
@ -1252,16 +1047,16 @@
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
"reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
"reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
"shasum": ""
},
"require": {
@ -1276,7 +1071,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1314,7 +1109,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0"
},
"funding": [
{
@ -1330,20 +1125,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "511a08c03c1960e08a883f4cffcacd219b758354"
"reference": "875e90aeea2777b6f135677f618529449334a612"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354",
"reference": "511a08c03c1960e08a883f4cffcacd219b758354",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612",
"reference": "875e90aeea2777b6f135677f618529449334a612",
"shasum": ""
},
"require": {
@ -1355,7 +1150,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1395,7 +1190,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0"
},
"funding": [
{
@ -1411,20 +1206,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
"reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92",
"reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92",
"shasum": ""
},
"require": {
@ -1436,7 +1231,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1479,7 +1274,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0"
},
"funding": [
{
@ -1495,20 +1290,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
"reference": "42292d99c55abe617799667f454222c54c60e229"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229",
"reference": "42292d99c55abe617799667f454222c54c60e229",
"shasum": ""
},
"require": {
@ -1523,7 +1318,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1562,7 +1357,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0"
},
"funding": [
{
@ -1578,20 +1373,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-07-28T09:04:16+00:00"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
"reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
"reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
"shasum": ""
},
"require": {
@ -1600,7 +1395,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1645,7 +1440,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0"
},
"funding": [
{
@ -1661,20 +1456,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-php81",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php81.git",
"reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a"
"reference": "7581cd600fa9fd681b797d00b02f068e2f13263b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a",
"reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a",
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/7581cd600fa9fd681b797d00b02f068e2f13263b",
"reference": "7581cd600fa9fd681b797d00b02f068e2f13263b",
"shasum": ""
},
"require": {
@ -1683,7 +1478,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1724,7 +1519,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-php81/tree/v1.28.0"
},
"funding": [
{
@ -1740,20 +1535,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/process",
"version": "v6.3.0",
"version": "v6.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "8741e3ed7fe2e91ec099e02446fb86667a0f1628"
"reference": "0b5c29118f2e980d455d2e34a5659f4579847c54"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/8741e3ed7fe2e91ec099e02446fb86667a0f1628",
"reference": "8741e3ed7fe2e91ec099e02446fb86667a0f1628",
"url": "https://api.github.com/repos/symfony/process/zipball/0b5c29118f2e980d455d2e34a5659f4579847c54",
"reference": "0b5c29118f2e980d455d2e34a5659f4579847c54",
"shasum": ""
},
"require": {
@ -1785,7 +1580,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/process/tree/v6.3.0"
"source": "https://github.com/symfony/process/tree/v6.3.4"
},
"funding": [
{
@ -1801,7 +1596,7 @@
"type": "tidelift"
}
],
"time": "2023-05-19T08:06:44+00:00"
"time": "2023-08-07T10:39:22+00:00"
},
{
"name": "symfony/service-contracts",
@ -1949,16 +1744,16 @@
},
{
"name": "symfony/string",
"version": "v6.3.0",
"version": "v6.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f"
"reference": "13d76d0fb049051ed12a04bef4f9de8715bea339"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/f2e190ee75ff0f5eced645ec0be5c66fac81f51f",
"reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f",
"url": "https://api.github.com/repos/symfony/string/zipball/13d76d0fb049051ed12a04bef4f9de8715bea339",
"reference": "13d76d0fb049051ed12a04bef4f9de8715bea339",
"shasum": ""
},
"require": {
@ -2015,7 +1810,7 @@
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v6.3.0"
"source": "https://github.com/symfony/string/tree/v6.3.5"
},
"funding": [
{
@ -2031,7 +1826,7 @@
"type": "tidelift"
}
],
"time": "2023-03-21T21:06:29+00:00"
"time": "2023-09-18T10:38:32+00:00"
}
],
"aliases": [],
@ -2041,5 +1836,5 @@
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"plugin-api-version": "2.3.0"
"plugin-api-version": "2.6.0"
}

257
vendor-bin/daux/composer.lock

@ -83,22 +83,22 @@
},
{
"name": "guzzlehttp/guzzle",
"version": "7.7.0",
"version": "7.8.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "fb7566caccf22d74d1ab270de3551f72a58399f5"
"reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/fb7566caccf22d74d1ab270de3551f72a58399f5",
"reference": "fb7566caccf22d74d1ab270de3551f72a58399f5",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/1110f66a6530a40fe7aea0378fe608ee2b2248f9",
"reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9",
"shasum": ""
},
"require": {
"ext-json": "*",
"guzzlehttp/promises": "^1.5.3 || ^2.0",
"guzzlehttp/psr7": "^1.9.1 || ^2.4.5",
"guzzlehttp/promises": "^1.5.3 || ^2.0.1",
"guzzlehttp/psr7": "^1.9.1 || ^2.5.1",
"php": "^7.2.5 || ^8.0",
"psr/http-client": "^1.0",
"symfony/deprecation-contracts": "^2.2 || ^3.0"
@ -189,7 +189,7 @@
],
"support": {
"issues": "https://github.com/guzzle/guzzle/issues",
"source": "https://github.com/guzzle/guzzle/tree/7.7.0"
"source": "https://github.com/guzzle/guzzle/tree/7.8.0"
},
"funding": [
{
@ -205,20 +205,20 @@
"type": "tidelift"
}
],
"time": "2023-05-21T14:04:53+00:00"
"time": "2023-08-27T10:20:53+00:00"
},
{
"name": "guzzlehttp/promises",
"version": "2.0.0",
"version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6"
"reference": "111166291a0f8130081195ac4556a5587d7f1b5d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/3a494dc7dc1d7d12e511890177ae2d0e6c107da6",
"reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6",
"url": "https://api.github.com/repos/guzzle/promises/zipball/111166291a0f8130081195ac4556a5587d7f1b5d",
"reference": "111166291a0f8130081195ac4556a5587d7f1b5d",
"shasum": ""
},
"require": {
@ -272,7 +272,7 @@
],
"support": {
"issues": "https://github.com/guzzle/promises/issues",
"source": "https://github.com/guzzle/promises/tree/2.0.0"
"source": "https://github.com/guzzle/promises/tree/2.0.1"
},
"funding": [
{
@ -288,20 +288,20 @@
"type": "tidelift"
}
],
"time": "2023-05-21T13:50:22+00:00"
"time": "2023-08-03T15:11:55+00:00"
},
{
"name": "guzzlehttp/psr7",
"version": "2.5.0",
"version": "2.6.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "b635f279edd83fc275f822a1188157ffea568ff6"
"reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/b635f279edd83fc275f822a1188157ffea568ff6",
"reference": "b635f279edd83fc275f822a1188157ffea568ff6",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/be45764272e8873c72dbe3d2edcfdfcc3bc9f727",
"reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727",
"shasum": ""
},
"require": {
@ -388,7 +388,7 @@
],
"support": {
"issues": "https://github.com/guzzle/psr7/issues",
"source": "https://github.com/guzzle/psr7/tree/2.5.0"
"source": "https://github.com/guzzle/psr7/tree/2.6.1"
},
"funding": [
{
@ -404,7 +404,7 @@
"type": "tidelift"
}
],
"time": "2023-04-17T16:11:26+00:00"
"time": "2023-08-27T10:13:57+00:00"
},
{
"name": "league/commonmark",
@ -618,16 +618,16 @@
},
{
"name": "psr/http-client",
"version": "1.0.2",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-client.git",
"reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31"
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/0955afe48220520692d2d09f7ab7e0f93ffd6a31",
"reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
"shasum": ""
},
"require": {
@ -664,9 +664,9 @@
"psr-18"
],
"support": {
"source": "https://github.com/php-fig/http-client/tree/1.0.2"
"source": "https://github.com/php-fig/http-client"
},
"time": "2023-04-10T20:12:12+00:00"
"time": "2023-09-23T14:17:50+00:00"
},
{
"name": "psr/http-factory",
@ -900,16 +900,16 @@
},
{
"name": "symfony/console",
"version": "v5.4.24",
"version": "v5.4.28",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "560fc3ed7a43e6d30ea94a07d77f9a60b8ed0fb8"
"reference": "f4f71842f24c2023b91237c72a365306f3c58827"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/560fc3ed7a43e6d30ea94a07d77f9a60b8ed0fb8",
"reference": "560fc3ed7a43e6d30ea94a07d77f9a60b8ed0fb8",
"url": "https://api.github.com/repos/symfony/console/zipball/f4f71842f24c2023b91237c72a365306f3c58827",
"reference": "f4f71842f24c2023b91237c72a365306f3c58827",
"shasum": ""
},
"require": {
@ -979,7 +979,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v5.4.24"
"source": "https://github.com/symfony/console/tree/v5.4.28"
},
"funding": [
{
@ -995,7 +995,7 @@
"type": "tidelift"
}
],
"time": "2023-05-26T05:13:16+00:00"
"time": "2023-08-07T06:12:30+00:00"
},
{
"name": "symfony/deprecation-contracts",
@ -1066,16 +1066,16 @@
},
{
"name": "symfony/http-foundation",
"version": "v5.4.24",
"version": "v5.4.30",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
"reference": "3c59f97f6249ce552a44f01b93bfcbd786a954f5"
"reference": "671769f79de0532da1478c60968b42506e185d2e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/3c59f97f6249ce552a44f01b93bfcbd786a954f5",
"reference": "3c59f97f6249ce552a44f01b93bfcbd786a954f5",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/671769f79de0532da1478c60968b42506e185d2e",
"reference": "671769f79de0532da1478c60968b42506e185d2e",
"shasum": ""
},
"require": {
@ -1122,7 +1122,7 @@
"description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/http-foundation/tree/v5.4.24"
"source": "https://github.com/symfony/http-foundation/tree/v5.4.30"
},
"funding": [
{
@ -1138,20 +1138,20 @@
"type": "tidelift"
}
],
"time": "2023-05-19T07:21:23+00:00"
"time": "2023-10-28T23:35:12+00:00"
},
{
"name": "symfony/mime",
"version": "v5.4.23",
"version": "v5.4.26",
"source": {
"type": "git",
"url": "https://github.com/symfony/mime.git",
"reference": "ae0a1032a450a3abf305ee44fc55ed423fbf16e3"
"reference": "2ea06dfeee20000a319d8407cea1d47533d5a9d2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/mime/zipball/ae0a1032a450a3abf305ee44fc55ed423fbf16e3",
"reference": "ae0a1032a450a3abf305ee44fc55ed423fbf16e3",
"url": "https://api.github.com/repos/symfony/mime/zipball/2ea06dfeee20000a319d8407cea1d47533d5a9d2",
"reference": "2ea06dfeee20000a319d8407cea1d47533d5a9d2",
"shasum": ""
},
"require": {
@ -1166,7 +1166,7 @@
"phpdocumentor/reflection-docblock": "<3.2.2",
"phpdocumentor/type-resolver": "<1.4.0",
"symfony/mailer": "<4.4",
"symfony/serializer": "<5.4.14|>=6.0,<6.0.14|>=6.1,<6.1.6"
"symfony/serializer": "<5.4.26|>=6,<6.2.13|>=6.3,<6.3.2"
},
"require-dev": {
"egulias/email-validator": "^2.1.10|^3.1|^4",
@ -1174,7 +1174,7 @@
"symfony/dependency-injection": "^4.4|^5.0|^6.0",
"symfony/property-access": "^4.4|^5.1|^6.0",
"symfony/property-info": "^4.4|^5.1|^6.0",
"symfony/serializer": "^5.4.14|~6.0.14|^6.1.6"
"symfony/serializer": "^5.4.26|~6.2.13|^6.3.2"
},
"type": "library",
"autoload": {
@ -1206,7 +1206,7 @@
"mime-type"
],
"support": {
"source": "https://github.com/symfony/mime/tree/v5.4.23"
"source": "https://github.com/symfony/mime/tree/v5.4.26"
},
"funding": [
{
@ -1222,20 +1222,20 @@
"type": "tidelift"
}
],
"time": "2023-04-19T09:49:13+00:00"
"time": "2023-07-27T06:29:31+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
"reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
"reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
"shasum": ""
},
"require": {
@ -1250,7 +1250,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1288,7 +1288,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0"
},
"funding": [
{
@ -1304,20 +1304,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "511a08c03c1960e08a883f4cffcacd219b758354"
"reference": "875e90aeea2777b6f135677f618529449334a612"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354",
"reference": "511a08c03c1960e08a883f4cffcacd219b758354",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612",
"reference": "875e90aeea2777b6f135677f618529449334a612",
"shasum": ""
},
"require": {
@ -1329,7 +1329,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1369,7 +1369,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0"
},
"funding": [
{
@ -1385,20 +1385,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-intl-icu",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-icu.git",
"reference": "a3d9148e2c363588e05abbdd4ee4f971f0a5330c"
"reference": "e46b4da57951a16053cd751f63f4a24292788157"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/a3d9148e2c363588e05abbdd4ee4f971f0a5330c",
"reference": "a3d9148e2c363588e05abbdd4ee4f971f0a5330c",
"url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/e46b4da57951a16053cd751f63f4a24292788157",
"reference": "e46b4da57951a16053cd751f63f4a24292788157",
"shasum": ""
},
"require": {
@ -1410,7 +1410,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1456,7 +1456,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.28.0"
},
"funding": [
{
@ -1472,20 +1472,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-03-21T17:27:24+00:00"
},
{
"name": "symfony/polyfill-intl-idn",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "639084e360537a19f9ee352433b84ce831f3d2da"
"reference": "ecaafce9f77234a6a449d29e49267ba10499116d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/639084e360537a19f9ee352433b84ce831f3d2da",
"reference": "639084e360537a19f9ee352433b84ce831f3d2da",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/ecaafce9f77234a6a449d29e49267ba10499116d",
"reference": "ecaafce9f77234a6a449d29e49267ba10499116d",
"shasum": ""
},
"require": {
@ -1499,7 +1499,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1543,7 +1543,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.28.0"
},
"funding": [
{
@ -1559,20 +1559,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:30:37+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
"reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92",
"reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92",
"shasum": ""
},
"require": {
@ -1584,7 +1584,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1627,7 +1627,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0"
},
"funding": [
{
@ -1643,20 +1643,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
"reference": "42292d99c55abe617799667f454222c54c60e229"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229",
"reference": "42292d99c55abe617799667f454222c54c60e229",
"shasum": ""
},
"require": {
@ -1671,7 +1671,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1710,7 +1710,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0"
},
"funding": [
{
@ -1726,20 +1726,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-07-28T09:04:16+00:00"
},
{
"name": "symfony/polyfill-php72",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97"
"reference": "70f4aebd92afca2f865444d30a4d2151c13c3179"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97",
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/70f4aebd92afca2f865444d30a4d2151c13c3179",
"reference": "70f4aebd92afca2f865444d30a4d2151c13c3179",
"shasum": ""
},
"require": {
@ -1748,7 +1748,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1786,7 +1786,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-php72/tree/v1.28.0"
},
"funding": [
{
@ -1802,20 +1802,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-php73",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php73.git",
"reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9"
"reference": "fe2f306d1d9d346a7fee353d0d5012e401e984b5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9",
"reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9",
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fe2f306d1d9d346a7fee353d0d5012e401e984b5",
"reference": "fe2f306d1d9d346a7fee353d0d5012e401e984b5",
"shasum": ""
},
"require": {
@ -1824,7 +1824,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1865,7 +1865,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-php73/tree/v1.28.0"
},
"funding": [
{
@ -1881,20 +1881,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
"reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
"reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
"shasum": ""
},
"require": {
@ -1903,7 +1903,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1948,7 +1948,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0"
},
"funding": [
{
@ -1964,20 +1964,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/process",
"version": "v5.4.24",
"version": "v5.4.28",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "e3c46cc5689c8782944274bb30702106ecbe3b64"
"reference": "45261e1fccad1b5447a8d7a8e67aa7b4a9798b7b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/e3c46cc5689c8782944274bb30702106ecbe3b64",
"reference": "e3c46cc5689c8782944274bb30702106ecbe3b64",
"url": "https://api.github.com/repos/symfony/process/zipball/45261e1fccad1b5447a8d7a8e67aa7b4a9798b7b",
"reference": "45261e1fccad1b5447a8d7a8e67aa7b4a9798b7b",
"shasum": ""
},
"require": {
@ -2010,7 +2010,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/process/tree/v5.4.24"
"source": "https://github.com/symfony/process/tree/v5.4.28"
},
"funding": [
{
@ -2026,7 +2026,7 @@
"type": "tidelift"
}
],
"time": "2023-05-17T11:26:05+00:00"
"time": "2023-08-07T10:36:04+00:00"
},
{
"name": "symfony/service-contracts",
@ -2112,16 +2112,16 @@
},
{
"name": "symfony/string",
"version": "v6.3.0",
"version": "v6.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f"
"reference": "13d76d0fb049051ed12a04bef4f9de8715bea339"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/f2e190ee75ff0f5eced645ec0be5c66fac81f51f",
"reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f",
"url": "https://api.github.com/repos/symfony/string/zipball/13d76d0fb049051ed12a04bef4f9de8715bea339",
"reference": "13d76d0fb049051ed12a04bef4f9de8715bea339",
"shasum": ""
},
"require": {
@ -2178,7 +2178,7 @@
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v6.3.0"
"source": "https://github.com/symfony/string/tree/v6.3.5"
},
"funding": [
{
@ -2194,24 +2194,25 @@
"type": "tidelift"
}
],
"time": "2023-03-21T21:06:29+00:00"
"time": "2023-09-18T10:38:32+00:00"
},
{
"name": "symfony/yaml",
"version": "v6.3.0",
"version": "v6.3.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "a9a8337aa641ef2aa39c3e028f9107ec391e5927"
"reference": "9758b6c69d179936435d0ffb577c3708d57e38a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/a9a8337aa641ef2aa39c3e028f9107ec391e5927",
"reference": "a9a8337aa641ef2aa39c3e028f9107ec391e5927",
"url": "https://api.github.com/repos/symfony/yaml/zipball/9758b6c69d179936435d0ffb577c3708d57e38a8",
"reference": "9758b6c69d179936435d0ffb577c3708d57e38a8",
"shasum": ""
},
"require": {
"php": ">=8.1",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-ctype": "^1.8"
},
"conflict": {
@ -2249,7 +2250,7 @@
"description": "Loads and dumps YAML files",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/yaml/tree/v6.3.0"
"source": "https://github.com/symfony/yaml/tree/v6.3.7"
},
"funding": [
{
@ -2265,7 +2266,7 @@
"type": "tidelift"
}
],
"time": "2023-04-28T13:28:14+00:00"
"time": "2023-10-28T23:31:00+00:00"
},
{
"name": "webuni/front-matter",
@ -2347,5 +2348,5 @@
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"plugin-api-version": "2.3.0"
"plugin-api-version": "2.6.0"
}

1
vendor-bin/phpstan/composer.json

@ -0,0 +1 @@
{}

18
vendor-bin/phpstan/composer.lock

@ -0,0 +1,18 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "d751713988987e9331980363e24189ce",
"packages": [],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"plugin-api-version": "2.6.0"
}

3
vendor-bin/phpunit/composer.json

@ -5,6 +5,7 @@
"clue/arguments": "^2.0",
"mikey179/vfsstream": "^1.6",
"webmozart/glob": "^4.1",
"eloquent/phony-phpunit": "^6.0 || ^7.0"
"eloquent/phony-phpunit": "^6.0 || ^7.0",
"phake/phake": "^4.4 | ^3.1.9"
}
}

153
vendor-bin/phpunit/composer.lock

@ -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": "834109e2eab8d2bc0a89ab4d28c12f75",
"content-hash": "7f36badf6779ffc9f136290679dc0855",
"packages": [],
"packages-dev": [
{
@ -121,30 +121,30 @@
},
{
"name": "doctrine/instantiator",
"version": "2.0.0",
"version": "1.5.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
"reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0"
"reference": "0a0fa9780f5d4e507415a065172d26a98d02047b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0",
"reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b",
"reference": "0a0fa9780f5d4e507415a065172d26a98d02047b",
"shasum": ""
},
"require": {
"php": "^8.1"
"php": "^7.1 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^11",
"doctrine/coding-standard": "^9 || ^11",
"ext-pdo": "*",
"ext-phar": "*",
"phpbench/phpbench": "^1.2",
"phpstan/phpstan": "^1.9.4",
"phpstan/phpstan-phpunit": "^1.3",
"phpunit/phpunit": "^9.5.27",
"vimeo/psalm": "^5.4"
"phpbench/phpbench": "^0.16 || ^1",
"phpstan/phpstan": "^1.4",
"phpstan/phpstan-phpunit": "^1",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
"vimeo/psalm": "^4.30 || ^5.4"
},
"type": "library",
"autoload": {
@ -171,7 +171,7 @@
],
"support": {
"issues": "https://github.com/doctrine/instantiator/issues",
"source": "https://github.com/doctrine/instantiator/tree/2.0.0"
"source": "https://github.com/doctrine/instantiator/tree/1.5.0"
},
"funding": [
{
@ -187,7 +187,7 @@
"type": "tidelift"
}
],
"time": "2022-12-30T00:23:10+00:00"
"time": "2022-12-30T00:15:36+00:00"
},
{
"name": "eloquent/phony",
@ -261,6 +261,7 @@
"issues": "https://github.com/eloquent/phony/issues",
"source": "https://github.com/eloquent/phony/tree/5.0.2"
},
"abandoned": true,
"time": "2021-02-17T01:45:10+00:00"
},
{
@ -334,6 +335,7 @@
"issues": "https://github.com/eloquent/phony-phpunit/issues",
"source": "https://github.com/eloquent/phony-phpunit/tree/7.1.0"
},
"abandoned": true,
"time": "2020-12-21T09:36:47+00:00"
},
{
@ -448,16 +450,16 @@
},
{
"name": "nikic/php-parser",
"version": "v4.15.5",
"version": "v4.17.1",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e"
"reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/11e2663a5bc9db5d714eedb4277ee300403b4a9e",
"reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d",
"reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d",
"shasum": ""
},
"require": {
@ -498,9 +500,79 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.5"
"source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1"
},
"time": "2023-08-13T19:53:39+00:00"
},
{
"name": "phake/phake",
"version": "v4.4.0",
"source": {
"type": "git",
"url": "https://github.com/phake/phake.git",
"reference": "5c8954791645d9b7fc027bf76822a221a5a4de8a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phake/phake/zipball/5c8954791645d9b7fc027bf76822a221a5a4de8a",
"reference": "5c8954791645d9b7fc027bf76822a221a5a4de8a",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.4",
"php": "^7.1|^8.0",
"sebastian/comparator": "^1.1|^2.0|^3.0|^4.0|^5.0"
},
"require-dev": {
"doctrine/annotations": "^1.13",
"hamcrest/hamcrest-php": "1.1.*",
"phpunit/phpunit": "^6.5|^7.0|^8.0|^9.0|^10.0",
"psalm/phar": "^4.18"
},
"suggest": {
"doctrine/annotations": "Allows mock annotations to use import statements for classes.",
"hamcrest/hamcrest-php": "Use Hamcrest matchers."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.4-dev"
}
},
"autoload": {
"files": [
"src/Phake.php"
],
"psr-4": {
"Phake\\": "src/Phake"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Mike Lively",
"email": "m@digitalsandwich.com"
}
],
"description": "The Phake mock testing library",
"homepage": "https://phake.github.io",
"keywords": [
"mock",
"phake",
"spy",
"stub",
"test-doubles",
"testing"
],
"support": {
"docs": "https://phake.github.io/doc/",
"issues": "https://github.com/phake/phake/issues",
"source": "https://github.com/phake/phake/tree/v4.4.0"
},
"time": "2023-05-19T20:20:00+00:00"
"time": "2023-02-10T20:32:41+00:00"
},
{
"name": "phar-io/manifest",
@ -615,16 +687,16 @@
},
{
"name": "phpunit/php-code-coverage",
"version": "9.2.26",
"version": "9.2.29",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1"
"reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/443bc6912c9bd5b409254a40f4b0f4ced7c80ea1",
"reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6a3a87ac2bbe33b25042753df8195ba4aa534c76",
"reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76",
"shasum": ""
},
"require": {
@ -680,7 +752,8 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.26"
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.29"
},
"funding": [
{
@ -688,7 +761,7 @@
"type": "github"
}
],
"time": "2023-03-06T12:58:08+00:00"
"time": "2023-09-19T04:57:46+00:00"
},
{
"name": "phpunit/php-file-iterator",
@ -933,16 +1006,16 @@
},
{
"name": "phpunit/phpunit",
"version": "9.6.9",
"version": "9.6.13",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "a9aceaf20a682aeacf28d582654a1670d8826778"
"reference": "f3d767f7f9e191eab4189abe41ab37797e30b1be"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a9aceaf20a682aeacf28d582654a1670d8826778",
"reference": "a9aceaf20a682aeacf28d582654a1670d8826778",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f3d767f7f9e191eab4189abe41ab37797e30b1be",
"reference": "f3d767f7f9e191eab4189abe41ab37797e30b1be",
"shasum": ""
},
"require": {
@ -957,7 +1030,7 @@
"phar-io/manifest": "^2.0.3",
"phar-io/version": "^3.0.2",
"php": ">=7.3",
"phpunit/php-code-coverage": "^9.2.13",
"phpunit/php-code-coverage": "^9.2.28",
"phpunit/php-file-iterator": "^3.0.5",
"phpunit/php-invoker": "^3.1.1",
"phpunit/php-text-template": "^2.0.3",
@ -1016,7 +1089,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.9"
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.13"
},
"funding": [
{
@ -1032,7 +1105,7 @@
"type": "tidelift"
}
],
"time": "2023-06-11T06:13:56+00:00"
"time": "2023-09-19T05:39:22+00:00"
},
{
"name": "sebastian/cli-parser",
@ -1540,16 +1613,16 @@
},
{
"name": "sebastian/global-state",
"version": "5.0.5",
"version": "5.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2"
"reference": "bde739e7565280bda77be70044ac1047bc007e34"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2",
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34",
"reference": "bde739e7565280bda77be70044ac1047bc007e34",
"shasum": ""
},
"require": {
@ -1592,7 +1665,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
"source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5"
"source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6"
},
"funding": [
{
@ -1600,7 +1673,7 @@
"type": "github"
}
],
"time": "2022-02-14T08:28:10+00:00"
"time": "2023-08-02T09:26:13+00:00"
},
{
"name": "sebastian/lines-of-code",
@ -2105,5 +2178,5 @@
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"plugin-api-version": "2.3.0"
"plugin-api-version": "2.6.0"
}

169
vendor-bin/robo/composer.lock

@ -9,16 +9,16 @@
"packages-dev": [
{
"name": "composer/semver",
"version": "3.3.2",
"version": "3.4.0",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
"reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9"
"reference": "35e8d0af4486141bc745f23a29cc2091eb624a32"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9",
"reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9",
"url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32",
"reference": "35e8d0af4486141bc745f23a29cc2091eb624a32",
"shasum": ""
},
"require": {
@ -68,9 +68,9 @@
"versioning"
],
"support": {
"irc": "irc://irc.freenode.org/composer",
"irc": "ircs://irc.libera.chat:6697/composer",
"issues": "https://github.com/composer/semver/issues",
"source": "https://github.com/composer/semver/tree/3.3.2"
"source": "https://github.com/composer/semver/tree/3.4.0"
},
"funding": [
{
@ -86,7 +86,7 @@
"type": "tidelift"
}
],
"time": "2022-04-01T19:23:25+00:00"
"time": "2023-08-31T09:50:34+00:00"
},
{
"name": "consolidation/annotated-command",
@ -258,16 +258,16 @@
},
{
"name": "consolidation/output-formatters",
"version": "4.3.1",
"version": "4.3.2",
"source": {
"type": "git",
"url": "https://github.com/consolidation/output-formatters.git",
"reference": "f65524e9ecd2bd0021c4b18710005caaa6dcbd86"
"reference": "06711568b4cd169700ff7e8075db0a9a341ceb58"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/consolidation/output-formatters/zipball/f65524e9ecd2bd0021c4b18710005caaa6dcbd86",
"reference": "f65524e9ecd2bd0021c4b18710005caaa6dcbd86",
"url": "https://api.github.com/repos/consolidation/output-formatters/zipball/06711568b4cd169700ff7e8075db0a9a341ceb58",
"reference": "06711568b4cd169700ff7e8075db0a9a341ceb58",
"shasum": ""
},
"require": {
@ -306,9 +306,9 @@
"description": "Format text by applying transformations provided by plug-in formatters.",
"support": {
"issues": "https://github.com/consolidation/output-formatters/issues",
"source": "https://github.com/consolidation/output-formatters/tree/4.3.1"
"source": "https://github.com/consolidation/output-formatters/tree/4.3.2"
},
"time": "2023-05-20T03:23:06+00:00"
"time": "2023-07-06T04:45:41+00:00"
},
{
"name": "consolidation/robo",
@ -1066,16 +1066,16 @@
},
{
"name": "symfony/console",
"version": "v6.3.0",
"version": "v6.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7"
"reference": "eca495f2ee845130855ddf1cf18460c38966c8b6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7",
"reference": "8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7",
"url": "https://api.github.com/repos/symfony/console/zipball/eca495f2ee845130855ddf1cf18460c38966c8b6",
"reference": "eca495f2ee845130855ddf1cf18460c38966c8b6",
"shasum": ""
},
"require": {
@ -1136,7 +1136,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v6.3.0"
"source": "https://github.com/symfony/console/tree/v6.3.4"
},
"funding": [
{
@ -1152,7 +1152,7 @@
"type": "tidelift"
}
],
"time": "2023-05-29T12:49:39+00:00"
"time": "2023-08-16T10:10:12+00:00"
},
{
"name": "symfony/deprecation-contracts",
@ -1223,16 +1223,16 @@
},
{
"name": "symfony/event-dispatcher",
"version": "v6.3.0",
"version": "v6.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "3af8ac1a3f98f6dbc55e10ae59c9e44bfc38dfaa"
"reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/3af8ac1a3f98f6dbc55e10ae59c9e44bfc38dfaa",
"reference": "3af8ac1a3f98f6dbc55e10ae59c9e44bfc38dfaa",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/adb01fe097a4ee930db9258a3cc906b5beb5cf2e",
"reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e",
"shasum": ""
},
"require": {
@ -1283,7 +1283,7 @@
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/event-dispatcher/tree/v6.3.0"
"source": "https://github.com/symfony/event-dispatcher/tree/v6.3.2"
},
"funding": [
{
@ -1299,7 +1299,7 @@
"type": "tidelift"
}
],
"time": "2023-04-21T14:41:17+00:00"
"time": "2023-07-06T06:56:43+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
@ -1379,16 +1379,16 @@
},
{
"name": "symfony/filesystem",
"version": "v6.3.0",
"version": "v6.3.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "97b698e1d77d356304def77a8d0cd73090b359ea"
"reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/97b698e1d77d356304def77a8d0cd73090b359ea",
"reference": "97b698e1d77d356304def77a8d0cd73090b359ea",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae",
"reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae",
"shasum": ""
},
"require": {
@ -1422,7 +1422,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/filesystem/tree/v6.3.0"
"source": "https://github.com/symfony/filesystem/tree/v6.3.1"
},
"funding": [
{
@ -1438,20 +1438,20 @@
"type": "tidelift"
}
],
"time": "2023-05-30T17:12:32+00:00"
"time": "2023-06-01T08:30:39+00:00"
},
{
"name": "symfony/finder",
"version": "v6.3.0",
"version": "v6.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "d9b01ba073c44cef617c7907ce2419f8d00d75e2"
"reference": "a1b31d88c0e998168ca7792f222cbecee47428c4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/d9b01ba073c44cef617c7907ce2419f8d00d75e2",
"reference": "d9b01ba073c44cef617c7907ce2419f8d00d75e2",
"url": "https://api.github.com/repos/symfony/finder/zipball/a1b31d88c0e998168ca7792f222cbecee47428c4",
"reference": "a1b31d88c0e998168ca7792f222cbecee47428c4",
"shasum": ""
},
"require": {
@ -1486,7 +1486,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/finder/tree/v6.3.0"
"source": "https://github.com/symfony/finder/tree/v6.3.5"
},
"funding": [
{
@ -1502,20 +1502,20 @@
"type": "tidelift"
}
],
"time": "2023-04-02T01:25:41+00:00"
"time": "2023-09-26T12:56:25+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
"reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
"reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
"shasum": ""
},
"require": {
@ -1530,7 +1530,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1568,7 +1568,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0"
},
"funding": [
{
@ -1584,20 +1584,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "511a08c03c1960e08a883f4cffcacd219b758354"
"reference": "875e90aeea2777b6f135677f618529449334a612"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354",
"reference": "511a08c03c1960e08a883f4cffcacd219b758354",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612",
"reference": "875e90aeea2777b6f135677f618529449334a612",
"shasum": ""
},
"require": {
@ -1609,7 +1609,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1649,7 +1649,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0"
},
"funding": [
{
@ -1665,20 +1665,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
"reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92",
"reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92",
"shasum": ""
},
"require": {
@ -1690,7 +1690,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1733,7 +1733,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0"
},
"funding": [
{
@ -1749,20 +1749,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
"reference": "42292d99c55abe617799667f454222c54c60e229"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229",
"reference": "42292d99c55abe617799667f454222c54c60e229",
"shasum": ""
},
"require": {
@ -1777,7 +1777,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1816,7 +1816,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0"
},
"funding": [
{
@ -1832,20 +1832,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-07-28T09:04:16+00:00"
},
{
"name": "symfony/process",
"version": "v6.3.0",
"version": "v6.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "8741e3ed7fe2e91ec099e02446fb86667a0f1628"
"reference": "0b5c29118f2e980d455d2e34a5659f4579847c54"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/8741e3ed7fe2e91ec099e02446fb86667a0f1628",
"reference": "8741e3ed7fe2e91ec099e02446fb86667a0f1628",
"url": "https://api.github.com/repos/symfony/process/zipball/0b5c29118f2e980d455d2e34a5659f4579847c54",
"reference": "0b5c29118f2e980d455d2e34a5659f4579847c54",
"shasum": ""
},
"require": {
@ -1877,7 +1877,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/process/tree/v6.3.0"
"source": "https://github.com/symfony/process/tree/v6.3.4"
},
"funding": [
{
@ -1893,7 +1893,7 @@
"type": "tidelift"
}
],
"time": "2023-05-19T08:06:44+00:00"
"time": "2023-08-07T10:39:22+00:00"
},
{
"name": "symfony/service-contracts",
@ -1979,16 +1979,16 @@
},
{
"name": "symfony/string",
"version": "v6.3.0",
"version": "v6.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f"
"reference": "13d76d0fb049051ed12a04bef4f9de8715bea339"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/f2e190ee75ff0f5eced645ec0be5c66fac81f51f",
"reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f",
"url": "https://api.github.com/repos/symfony/string/zipball/13d76d0fb049051ed12a04bef4f9de8715bea339",
"reference": "13d76d0fb049051ed12a04bef4f9de8715bea339",
"shasum": ""
},
"require": {
@ -2045,7 +2045,7 @@
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v6.3.0"
"source": "https://github.com/symfony/string/tree/v6.3.5"
},
"funding": [
{
@ -2061,24 +2061,25 @@
"type": "tidelift"
}
],
"time": "2023-03-21T21:06:29+00:00"
"time": "2023-09-18T10:38:32+00:00"
},
{
"name": "symfony/yaml",
"version": "v6.3.0",
"version": "v6.3.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "a9a8337aa641ef2aa39c3e028f9107ec391e5927"
"reference": "9758b6c69d179936435d0ffb577c3708d57e38a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/a9a8337aa641ef2aa39c3e028f9107ec391e5927",
"reference": "a9a8337aa641ef2aa39c3e028f9107ec391e5927",
"url": "https://api.github.com/repos/symfony/yaml/zipball/9758b6c69d179936435d0ffb577c3708d57e38a8",
"reference": "9758b6c69d179936435d0ffb577c3708d57e38a8",
"shasum": ""
},
"require": {
"php": ">=8.1",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-ctype": "^1.8"
},
"conflict": {
@ -2116,7 +2117,7 @@
"description": "Loads and dumps YAML files",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/yaml/tree/v6.3.0"
"source": "https://github.com/symfony/yaml/tree/v6.3.7"
},
"funding": [
{
@ -2132,7 +2133,7 @@
"type": "tidelift"
}
],
"time": "2023-04-28T13:28:14+00:00"
"time": "2023-10-28T23:31:00+00:00"
}
],
"aliases": [],
@ -2142,5 +2143,5 @@
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"plugin-api-version": "2.3.0"
"plugin-api-version": "2.6.0"
}

Loading…
Cancel
Save