From 6da5a09c49e1ee75a6166ffa1fe5dc5d1785482c Mon Sep 17 00:00:00 2001 From: "Abdulmhsen B. A. A" Date: Mon, 25 Apr 2022 22:32:50 +0300 Subject: [PATCH 1/3] We no longer use caddy, instead we switched to nginx. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0734e323..d5ae6a81 100644 --- a/README.md +++ b/README.md @@ -153,7 +153,7 @@ valid cron expression. for example, `0 */3 * * *` it will run every three hours By default, the official container includes a small http server exposed at port `80`, we officially don't support HTTPS inside the container for the HTTP server. However, for the adventurous people we expose port 443 as well, as such you -can customize the Caddyfile to support SSL. and do the necessary adjustments. However, do not expect us to help with it. +can customize the `docker/files/nginx.conf` to support SSL. and do the necessary adjustments. However, do not expect us to help with it. #### Example nginx reverse proxy. From f1d48297313a1a14dbef9628829658c1ea8539a9 Mon Sep 17 00:00:00 2001 From: "Abdulmhsen B. A. A" Date: Tue, 26 Apr 2022 00:24:53 +0300 Subject: [PATCH 2/3] Updated README.md --- README.md | 46 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index d5ae6a81..f9747286 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,12 @@ -# Watch State Sync +# WatchState -CLI based tool to sync watch state between different media servers. +WatchState is a CLI based tool to sync your watch state between different media servers, without relying on 3rd parties +services, like trakt.tv, This tool support `Plex Media Server`, `Emby` and `Jellyfin` out of the box currently, with +plans for future expansion for other media servers. -# Introduction +# Install -Ever wanted to sync your watch state without having to rely on 3rd party service like trakt.tv? then this tool is for -you. I had multiple problems with Plex trakt.tv plugin which led to my account being banned at trakt.tv, and on top of -that the plugin no longer supported. And I like to keep my own data locally if possible. - -# Supported media servers. - -* Plex -* Emby -* Jellyfin - -## Install - -create your `docker-compose.yaml` file +create your `docker-compose.yaml` file: ```yaml version: '3.3' @@ -26,7 +16,7 @@ services: container_name: watchstate restart: unless-stopped environment: - # For more ENV variables please read at the bottom of README.md + # For more environment variables please read at the bottom of this page. WS_UID: ${UID:-1000} # Set container operation user id. WS_GID: ${GID:-1000} # Set container operation group id. ports: @@ -43,7 +33,7 @@ $ docker-compose up -d # First time -Please run the following command to see all available commands you can also run help on each command to get more info. +Run the following command to see all available commands you can also run help on each command to get more info. ```bash # Show all commands. @@ -153,7 +143,8 @@ valid cron expression. for example, `0 */3 * * *` it will run every three hours By default, the official container includes a small http server exposed at port `80`, we officially don't support HTTPS inside the container for the HTTP server. However, for the adventurous people we expose port 443 as well, as such you -can customize the `docker/files/nginx.conf` to support SSL. and do the necessary adjustments. However, do not expect us to help with it. +can customize the `docker/files/nginx.conf` to support SSL. and do the necessary adjustments. However, do not expect us +to help with it. #### Example nginx reverse proxy. @@ -194,8 +185,8 @@ it's more secure that way. #### [WEBHOOK_TOKEN] -Should match the server specific ``webhook.token`` value. in `server.yaml`. if the key does not exist please refer to -the steps described at **Steps to enable webhook servers**. +Should match the server specific ``webhook.token`` value. Refer to the steps described +at **[Steps to enable webhook servers](#enable-webhooks-events-for-specific-server)**. # Configuring Media servers to send webhook events. @@ -272,8 +263,8 @@ Click `Save Changes` Does not send webhooks events for "marked as watched/unwatched", or you added more than 1 item at time i.e. folder import. -If you have multiuser setup, please will still report the admin account user_id as 1 even though when you get the list -of users ids it shows completely different user ID, so when you initially set up your server for multiuser, select your +If you have multi-user setup, Plex will still report the admin account user id as 1 even though when you get the list +of users ids it shows completely different user ID, so when you initially set up your server for multi-user, select your admin account and after finishing you have to set the value manually to `1`. to do so please do the following ```bash @@ -289,9 +280,10 @@ Emby does not send webhooks events for newly added items. # Jellyfin -None that we are aware of. +If you don't select a user id there, sometimes the plugin will send itemAdd event without user info, and thus will fail +the check if you happen to enable `match user id`. -# Globally supported environment variables. +# Tool specific environment variables. - (string) `WS_DATA_PATH` Where key data stored (config|db). - (string) `WS_TMP_DIR` Where temp data stored. (logs|cache). Defaults to `WS_DATA_PATH` if not set. @@ -327,7 +319,7 @@ None that we are aware of. follows php [strtotime](https://www.php.net/strtotime) function rules. - (bool) `WS_DEBUG_IMPORT` Whether to log invalid GUID items from server in `${WS_TMP_DIR}/debug`. -# Container specific environment variables +# Container specific environment variables. - (int) `WS_NO_CHOWN` do not change ownership needed paths inside container. - (int) `WS_DISABLE_HTTP` disable included HTTP Server. @@ -339,4 +331,4 @@ None that we are aware of. # FAQ -For some common questions, Please take look at this [frequently asked questions](FAQ.md) page. +For some common questions, Take look at this [frequently asked questions](FAQ.md) page. From 47778bb13ac0acc183f402faf9c6cdfb3c8cf798 Mon Sep 17 00:00:00 2001 From: "Abdulmhsen B. A. A" Date: Tue, 26 Apr 2022 19:09:04 +0300 Subject: [PATCH 3/3] Dropped support for alternative database engine. --- README.md | 3 - config/config.php | 26 ++-- config/services.php | 22 ++- .../sqlite_1644418046_create_state_table.sql | 0 src/Commands/Config/EnvCommand.php | 3 +- .../mysql_1644418046_create_state_table.sql | 32 ----- .../pgsql_1644418046_create_state_table.sql | 35 ----- src/Libs/Storage/PDO/PDOAdapter.php | 130 +----------------- src/Libs/Storage/PDO/PDOMigrations.php | 21 +-- src/Libs/Storage/StorageInterface.php | 9 -- tests/Mappers/Export/ExportMapperTest.php | 4 +- tests/Mappers/Import/DirectMapperTest.php | 4 +- tests/Mappers/Import/MemoryMapperTest.php | 4 +- tests/Storage/PDOAdapterTest.php | 93 +------------ 14 files changed, 46 insertions(+), 340 deletions(-) rename {src/Libs/Storage/PDO/Migrations => migrations}/sqlite_1644418046_create_state_table.sql (100%) delete mode 100644 src/Libs/Storage/PDO/Migrations/mysql_1644418046_create_state_table.sql delete mode 100644 src/Libs/Storage/PDO/Migrations/pgsql_1644418046_create_state_table.sql diff --git a/README.md b/README.md index f9747286..ba5dafff 100644 --- a/README.md +++ b/README.md @@ -287,9 +287,6 @@ the check if you happen to enable `match user id`. - (string) `WS_DATA_PATH` Where key data stored (config|db). - (string) `WS_TMP_DIR` Where temp data stored. (logs|cache). Defaults to `WS_DATA_PATH` if not set. -- (string) `WS_STORAGE_PDO_DSN` PDO Data source Name, if you want to change from sqlite. -- (string) `WS_STORAGE_PDO_USERNAME` PDO username -- (string) `WS_STORAGE_PDO_PASSWORD` PDO password - (string) `WS_TZ` Set timezone for example, `UTC` - (bool) `WS_WEBHOOK_DEBUG` enable debug mode for webhook events. - (bool) `WS_REQUEST_DEBUG` enable debug mode for pre webhook request. diff --git a/config/config.php b/config/config.php index e70397bd..39152c19 100644 --- a/config/config.php +++ b/config/config.php @@ -19,7 +19,7 @@ return (function () { $config = [ 'name' => 'WatchState', 'version' => 'v0.0.0', - 'tz' => env('WS_TS', 'UTC'), + 'tz' => env('WS_TZ', 'UTC'), 'path' => fixPath(env('WS_DATA_PATH', fn() => env('IN_DOCKER') ? '/config' : realpath(__DIR__ . '/../var'))), 'logs' => [ 'prune' => [ @@ -31,18 +31,18 @@ return (function () { $config['tmpDir'] = fixPath(env('WS_TMP_DIR', fn() => ag($config, 'path'))); $config['storage'] = [ - 'opts' => [ - 'dsn' => env('WS_STORAGE_PDO_DSN', fn() => 'sqlite:' . ag($config, 'path') . '/db/watchstate.db'), - 'username' => env('WS_STORAGE_PDO_USERNAME', null), - 'password' => env('WS_STORAGE_PDO_PASSWORD', null), - 'exec' => [ - 'sqlite' => [ - 'PRAGMA journal_mode=MEMORY', - 'PRAGMA SYNCHRONOUS=OFF' - ], - 'pgsql' => [], - 'mysql' => [], - ], + 'dsn' => 'sqlite:' . ag($config, 'path') . '/db/watchstate.db', + 'username' => null, + 'password' => null, + 'options' => [ + PDO::ATTR_EMULATE_PREPARES => false, + PDO::ATTR_STRINGIFY_FETCHES => false, + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + ], + 'exec' => [ + 'PRAGMA journal_mode=MEMORY', + 'PRAGMA SYNCHRONOUS=OFF' ], ]; diff --git a/config/services.php b/config/services.php index b3719e9e..230b21e7 100644 --- a/config/services.php +++ b/config/services.php @@ -51,9 +51,26 @@ return (function (): array { 'shared' => false, ], + PDO::class => [ + 'class' => function (): PDO { + $pdo = new PDO(dsn: Config::get('storage.dsn'), options: [ + PDO::ATTR_EMULATE_PREPARES => false, + PDO::ATTR_STRINGIFY_FETCHES => false, + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + ]); + + foreach (Config::get('storage.exec', []) as $cmd) { + $pdo->exec($cmd); + } + + return $pdo; + }, + ], + StorageInterface::class => [ - 'class' => function (LoggerInterface $logger): StorageInterface { - $adapter = (new PDOAdapter($logger))->setUp(Config::get('storage.opts', [])); + 'class' => function (LoggerInterface $logger, PDO $pdo): StorageInterface { + $adapter = new PDOAdapter($logger, $pdo); if (true !== $adapter->isMigrated()) { $adapter->migrations(StorageInterface::MIGRATE_UP); @@ -63,6 +80,7 @@ return (function (): array { }, 'args' => [ LoggerInterface::class, + PDO::class, ], ], diff --git a/src/Libs/Storage/PDO/Migrations/sqlite_1644418046_create_state_table.sql b/migrations/sqlite_1644418046_create_state_table.sql similarity index 100% rename from src/Libs/Storage/PDO/Migrations/sqlite_1644418046_create_state_table.sql rename to migrations/sqlite_1644418046_create_state_table.sql diff --git a/src/Commands/Config/EnvCommand.php b/src/Commands/Config/EnvCommand.php index e565b493..de3e7881 100644 --- a/src/Commands/Config/EnvCommand.php +++ b/src/Commands/Config/EnvCommand.php @@ -29,11 +29,10 @@ final class EnvCommand extends Command } (new Table($output))->setStyle('box') - ->setHeaders(['Key', 'Value']) + ->setHeaders(['Environment Key', 'Environment Value']) ->setRows($keys) ->render(); return self::SUCCESS; } - } diff --git a/src/Libs/Storage/PDO/Migrations/mysql_1644418046_create_state_table.sql b/src/Libs/Storage/PDO/Migrations/mysql_1644418046_create_state_table.sql deleted file mode 100644 index 1060be36..00000000 --- a/src/Libs/Storage/PDO/Migrations/mysql_1644418046_create_state_table.sql +++ /dev/null @@ -1,32 +0,0 @@ --- # migrate_up - -CREATE TABLE `state` -( - `id` int(11) NOT NULL AUTO_INCREMENT, - `type` varchar(50) NOT NULL, - `updated` int(11) NOT NULL, - `watched` tinyint(4) NOT NULL DEFAULT 0, - `meta` text DEFAULT NULL, - `guid_plex` varchar(255) DEFAULT NULL, - `guid_imdb` varchar(255) DEFAULT NULL, - `guid_tvdb` varchar(255) DEFAULT NULL, - `guid_tmdb` varchar(255) DEFAULT NULL, - `guid_tvmaze` varchar(255) DEFAULT NULL, - `guid_tvrage` varchar(255) DEFAULT NULL, - `guid_anidb` varchar(255) DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `type` (`type`), - KEY `watched` (`watched`), - KEY `updated` (`updated`), - KEY `guid_plex` (`guid_plex`), - KEY `guid_imdb` (`guid_imdb`), - KEY `guid_tvdb` (`guid_tvdb`), - KEY `guid_tmdb` (`guid_tmdb`), - KEY `guid_tvmaze` (`guid_tvmaze`), - KEY `guid_tvrage` (`guid_tvrage`), - KEY `guid_anidb` (`guid_anidb`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - --- # migrate_down - -DROP TABLE IF EXISTS `state`; diff --git a/src/Libs/Storage/PDO/Migrations/pgsql_1644418046_create_state_table.sql b/src/Libs/Storage/PDO/Migrations/pgsql_1644418046_create_state_table.sql deleted file mode 100644 index dec2f4df..00000000 --- a/src/Libs/Storage/PDO/Migrations/pgsql_1644418046_create_state_table.sql +++ /dev/null @@ -1,35 +0,0 @@ --- # migrate_up - -CREATE SEQUENCE state_id_seq INCREMENT 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1; - -CREATE TABLE "state" ( - "id" integer DEFAULT nextval('state_id_seq') NOT NULL, - "type" character varying NOT NULL, - "updated" integer NOT NULL, - "watched" smallint NOT NULL, - "meta" json, - "guid_plex" character varying, - "guid_imdb" character varying, - "guid_tvdb" character varying, - "guid_tmdb" character varying, - "guid_tvmaze" character varying, - "guid_tvrage" character varying, - "guid_anidb" character varying, - CONSTRAINT "state_pkey" PRIMARY KEY ("id") -) WITH (oids = false); - -CREATE INDEX "state_guid_anidb" ON "state" USING btree ("guid_anidb"); -CREATE INDEX "state_guid_imdb" ON "state" USING btree ("guid_imdb"); -CREATE INDEX "state_guid_plex" ON "state" USING btree ("guid_plex"); -CREATE INDEX "state_guid_tmdb" ON "state" USING btree ("guid_tmdb"); -CREATE INDEX "state_guid_tvdb" ON "state" USING btree ("guid_tvdb"); -CREATE INDEX "state_guid_tvmaze" ON "state" USING btree ("guid_tvmaze"); -CREATE INDEX "state_guid_tvrage" ON "state" USING btree ("guid_tvrage"); -CREATE INDEX "state_type" ON "state" USING btree ("type"); -CREATE INDEX "state_updated" ON "state" USING btree ("updated"); -CREATE INDEX "state_watched" ON "state" USING btree ("watched"); - --- # migrate_down - -DROP TABLE IF EXISTS "state"; -DROP SEQUENCE IF EXISTS state_id_seq; diff --git a/src/Libs/Storage/PDO/PDOAdapter.php b/src/Libs/Storage/PDO/PDOAdapter.php index e202079f..4a100c40 100644 --- a/src/Libs/Storage/PDO/PDOAdapter.php +++ b/src/Libs/Storage/PDO/PDOAdapter.php @@ -18,13 +18,6 @@ use Psr\Log\LoggerInterface; final class PDOAdapter implements StorageInterface { - private array $supported = [ - 'sqlite', - 'mysql', - 'pgsql' - ]; - - private PDO|null $pdo = null; private bool $viaCommit = false; private bool $singleTransaction = false; @@ -39,57 +32,12 @@ final class PDOAdapter implements StorageInterface 'update' => null, ]; - public function __construct(private LoggerInterface $logger) + public function __construct(private LoggerInterface $logger, private PDO $pdo) { } - public function setUp(array $opts): StorageInterface - { - if (null === ($opts['dsn'] ?? null)) { - throw new StorageException('No storage.opts.dsn (Data Source Name) was provided.', 10); - } - - try { - $this->pdo = new PDO( - $opts['dsn'], $opts['username'] ?? null, $opts['password'] ?? null, - array_replace_recursive( - [ - PDO::ATTR_EMULATE_PREPARES => false, - PDO::ATTR_STRINGIFY_FETCHES => false, - PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, - PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, - ], - $opts['options'] ?? [] - ) - ); - } catch (PDOException $e) { - throw new StorageException(sprintf('Unable to connect to storage backend. \'%s\'.', $e->getMessage())); - } - - $driver = $this->getDriver(); - - if (!in_array($driver, $this->supported)) { - throw new StorageException(sprintf('%s Driver is not supported.', $driver), 11); - } - - if (null !== ($exec = ag($opts, "exec.{$driver}")) && is_array($exec)) { - foreach ($exec as $cmd) { - $this->pdo->exec($cmd); - } - } - - return $this; - } - public function insert(StateInterface $entity): StateInterface { - if (null === $this->pdo) { - throw new StorageException( - afterLast(__CLASS__, '\\') . '->setUp(): method was not called.', - StorageException::SETUP_NOT_CALLED - ); - } - try { $data = $entity->getAll(); @@ -146,13 +94,6 @@ final class PDOAdapter implements StorageInterface public function getAll(DateTimeInterface|null $date = null, StateInterface|null $class = null): array { - if (null === $this->pdo) { - throw new StorageException( - afterLast(__CLASS__, '\\') . '->setUp(): method was not called.', - StorageException::SETUP_NOT_CALLED - ); - } - $arr = []; $sql = 'SELECT * FROM state'; @@ -174,13 +115,6 @@ final class PDOAdapter implements StorageInterface public function update(StateInterface $entity): StateInterface { - if (null === $this->pdo) { - throw new StorageException( - afterLast(__CLASS__, '\\') . '->setUp(): method was not called.', - StorageException::SETUP_NOT_CALLED - ); - } - try { $data = $entity->getAll(); @@ -213,13 +147,6 @@ final class PDOAdapter implements StorageInterface public function matchAnyId(array $ids, StateInterface|null $class = null): StateInterface|null { - if (null === $this->pdo) { - throw new StorageException( - afterLast(__CLASS__, '\\') . '->setUp(): method was not called.', - StorageException::SETUP_NOT_CALLED - ); - } - if (null === $class) { $class = Container::get(StateInterface::class); } @@ -277,13 +204,6 @@ final class PDOAdapter implements StorageInterface public function remove(StateInterface $entity): bool { - if (null === $this->pdo) { - throw new StorageException( - afterLast(__CLASS__, '\\') . '->setUp(): method was not called.', - StorageException::SETUP_NOT_CALLED - ); - } - if (null === $entity->id && !$entity->hasGuids()) { return false; } @@ -309,13 +229,6 @@ final class PDOAdapter implements StorageInterface public function commit(array $entities): array { - if (null === $this->pdo) { - throw new StorageException( - afterLast(__CLASS__, '\\') . '->setUp(): method was not called.', - StorageException::SETUP_NOT_CALLED - ); - } - return $this->transactional(function () use ($entities) { $list = [ StateInterface::TYPE_MOVIE => ['added' => 0, 'updated' => 0, 'failed' => 0], @@ -360,13 +273,6 @@ final class PDOAdapter implements StorageInterface public function migrations(string $dir, array $opts = []): mixed { - if (null === $this->pdo) { - throw new StorageException( - afterLast(__CLASS__, '\\') . '->setUp(): method was not called.', - StorageException::SETUP_NOT_CALLED - ); - } - $class = new PDOMigrations($this->pdo, $this->logger); return match (strtolower($dir)) { @@ -378,13 +284,6 @@ final class PDOAdapter implements StorageInterface public function isMigrated(): bool { - if (null === $this->pdo) { - throw new StorageException( - afterLast(__CLASS__, '\\') . '->setUp(): method was not called.', - StorageException::SETUP_NOT_CALLED - ); - } - return (new PDOMigrations($this->pdo, $this->logger))->isMigrated(); } @@ -393,13 +292,6 @@ final class PDOAdapter implements StorageInterface */ public function makeMigration(string $name, array $opts = []): mixed { - if (null === $this->pdo) { - throw new StorageException( - afterLast(__CLASS__, '\\') . '->setUp(): method was not called.', - StorageException::SETUP_NOT_CALLED - ); - } - return (new PDOMigrations($this->pdo, $this->logger))->make($name); } @@ -417,10 +309,6 @@ final class PDOAdapter implements StorageInterface public function getPdo(): PDO { - if (null === $this->pdo) { - throw new \RuntimeException('PDO is not initialized yet.'); - } - return $this->pdo; } @@ -469,22 +357,6 @@ final class PDOAdapter implements StorageInterface } } - /** - * Get PDO Driver. - * - * @return string - */ - private function getDriver(): string - { - $driver = $this->pdo->getAttribute($this->pdo::ATTR_DRIVER_NAME); - - if (empty($driver) || !is_string($driver)) { - $driver = 'unknown'; - } - - return strtolower($driver); - } - /** * Generate SQL Insert Statement. * diff --git a/src/Libs/Storage/PDO/PDOMigrations.php b/src/Libs/Storage/PDO/PDOMigrations.php index e6ef2650..2d72f803 100644 --- a/src/Libs/Storage/PDO/PDOMigrations.php +++ b/src/Libs/Storage/PDO/PDOMigrations.php @@ -4,7 +4,6 @@ declare(strict_types=1); namespace App\Libs\Storage\PDO; -use App\Libs\Config; use App\Libs\Storage\StorageInterface; use Exception; use PDO; @@ -14,15 +13,13 @@ use RuntimeException; final class PDOMigrations { private string $path; - private string $versionFile; private string $driver; private array $files = []; public function __construct(private PDO $pdo, private LoggerInterface $logger) { - $this->path = __DIR__ . '/Migrations'; + $this->path = __DIR__ . '/../../../../migrations'; $this->driver = $this->getDriver(); - $this->versionFile = Config::get('path') . sprintf('/db/%s.migration', $this->driver); } public function setLogger(LoggerInterface $logger): self @@ -142,24 +139,12 @@ final class PDOMigrations private function getVersion(): int { - if ('sqlite' === $this->driver) { - return (int)$this->pdo->query('PRAGMA user_version')->fetchColumn(); - } - - if (file_exists($this->versionFile)) { - return (int)file_get_contents($this->versionFile); - } - - return 0; + return (int)$this->pdo->query('PRAGMA user_version')->fetchColumn(); } private function setVersion(int $version): void { - if ('sqlite' === $this->driver) { - $this->pdo->exec('PRAGMA user_version = ' . $version); - } else { - file_put_contents($this->versionFile, $version); - } + $this->pdo->exec('PRAGMA user_version = ' . $version); } private function getDriver(): string diff --git a/src/Libs/Storage/StorageInterface.php b/src/Libs/Storage/StorageInterface.php index 71be6004..3b916cb6 100644 --- a/src/Libs/Storage/StorageInterface.php +++ b/src/Libs/Storage/StorageInterface.php @@ -16,15 +16,6 @@ interface StorageInterface public const MIGRATE_DOWN = 'down'; - /** - * Initiate Driver. - * - * @param array $opts - * - * @return $this - */ - public function setUp(array $opts): self; - /** * Insert Entity immediately. * diff --git a/tests/Mappers/Export/ExportMapperTest.php b/tests/Mappers/Export/ExportMapperTest.php index dc8eb2d7..7be01bc6 100644 --- a/tests/Mappers/Export/ExportMapperTest.php +++ b/tests/Mappers/Export/ExportMapperTest.php @@ -9,6 +9,7 @@ use App\Libs\Extends\CliLogger; use App\Libs\Mappers\Export\ExportMapper; use App\Libs\Storage\PDO\PDOAdapter; use App\Libs\Storage\StorageInterface; +use PDO; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\NullOutput; @@ -31,8 +32,7 @@ class ExportMapperTest extends TestCase $logger = new CliLogger($this->output); - $this->storage = new PDOAdapter($logger); - $this->storage->setUp(['dsn' => 'sqlite::memory:']); + $this->storage = new PDOAdapter($logger, new PDO('sqlite::memory:')); $this->storage->migrations('up'); $this->mapper = new ExportMapper($this->storage); diff --git a/tests/Mappers/Import/DirectMapperTest.php b/tests/Mappers/Import/DirectMapperTest.php index a83a9726..7969b872 100644 --- a/tests/Mappers/Import/DirectMapperTest.php +++ b/tests/Mappers/Import/DirectMapperTest.php @@ -10,6 +10,7 @@ use App\Libs\Extends\CliLogger; use App\Libs\Mappers\Import\DirectMapper; use App\Libs\Storage\PDO\PDOAdapter; use App\Libs\Storage\StorageInterface; +use PDO; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\NullOutput; @@ -32,8 +33,7 @@ class DirectMapperTest extends TestCase $logger = new CliLogger($this->output); - $this->storage = new PDOAdapter($logger); - $this->storage->setUp(['dsn' => 'sqlite::memory:']); + $this->storage = new PDOAdapter($logger, new PDO('sqlite::memory:')); $this->storage->migrations('up'); $this->mapper = new DirectMapper($logger, $this->storage); diff --git a/tests/Mappers/Import/MemoryMapperTest.php b/tests/Mappers/Import/MemoryMapperTest.php index e7f005db..cd3f8f44 100644 --- a/tests/Mappers/Import/MemoryMapperTest.php +++ b/tests/Mappers/Import/MemoryMapperTest.php @@ -10,6 +10,7 @@ use App\Libs\Extends\CliLogger; use App\Libs\Mappers\Import\MemoryMapper; use App\Libs\Storage\PDO\PDOAdapter; use App\Libs\Storage\StorageInterface; +use PDO; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\NullOutput; @@ -32,8 +33,7 @@ class MemoryMapperTest extends TestCase $logger = new CliLogger($this->output); - $this->storage = new PDOAdapter($logger); - $this->storage->setUp(['dsn' => 'sqlite::memory:']); + $this->storage = new PDOAdapter($logger, new PDO('sqlite::memory:')); $this->storage->migrations('up'); $this->mapper = new MemoryMapper($logger, $this->storage); diff --git a/tests/Storage/PDOAdapterTest.php b/tests/Storage/PDOAdapterTest.php index 1fed6fc9..c273f134 100644 --- a/tests/Storage/PDOAdapterTest.php +++ b/tests/Storage/PDOAdapterTest.php @@ -12,6 +12,7 @@ use App\Libs\Storage\StorageException; use App\Libs\Storage\StorageInterface; use DateTimeImmutable; use Error; +use PDO; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\NullOutput; @@ -31,37 +32,10 @@ class PDOAdapterTest extends TestCase $this->testMovie = require __DIR__ . '/../Fixtures/MovieEntity.php'; $this->testEpisode = require __DIR__ . '/../Fixtures/EpisodeEntity.php'; - $this->storage = new PDOAdapter(new CliLogger($this->output)); - $this->storage->setUp(['dsn' => 'sqlite::memory:']); + $this->storage = new PDOAdapter(new CliLogger($this->output), new PDO('sqlite::memory:')); $this->storage->migrations('up'); } - /** StorageInterface::setUp */ - public function test_setup_throw_exception_if_no_dsn(): void - { - $this->expectException(StorageException::class); - $this->expectExceptionCode(10); - $storage = new PDOAdapter(new CliLogger($this->output)); - $storage->setUp([]); - } - - public function test_setup_throw_exception_if_invalid_dsn(): void - { - $this->expectException(StorageException::class); - $storage = new PDOAdapter(new CliLogger($this->output)); - $storage->setUp(['dsn' => 'not_real_driver::foo']); - } - - /** StorageInterface::insert */ - public function test_insert_call_without_setup_exception(): void - { - $this->expectException(StorageException::class); - $this->expectExceptionCode(StorageException::SETUP_NOT_CALLED); - $storage = new PDOAdapter(new CliLogger($this->output)); - - $storage->insert(new StateEntity([])); - } - public function test_insert_throw_exception_if_has_id(): void { $this->expectException(StorageException::class); @@ -77,15 +51,6 @@ class PDOAdapterTest extends TestCase $this->assertSame(1, $item->id); } - /** StorageInterface::get */ - public function test_get_call_without_setup_exception(): void - { - $this->expectException(StorageException::class); - $this->expectExceptionCode(StorageException::SETUP_NOT_CALLED); - $storage = new PDOAdapter(new CliLogger($this->output)); - $storage->get(new StateEntity([])); - } - public function test_get_conditions(): void { $item = new StateEntity($this->testEpisode); @@ -102,15 +67,6 @@ class PDOAdapterTest extends TestCase $this->assertSame($modified->getAll(), $this->storage->get($modified)->getAll()); } - /** StorageInterface::getAll */ - public function test_getAll_call_without_setup_exception(): void - { - $this->expectException(StorageException::class); - $this->expectExceptionCode(StorageException::SETUP_NOT_CALLED); - $storage = new PDOAdapter(new CliLogger($this->output)); - $storage->getAll(); - } - public function test_getAll_call_without_initialized_container(): void { $this->expectException(Error::class); @@ -132,15 +88,6 @@ class PDOAdapterTest extends TestCase $this->assertCount(0, $this->storage->getAll(date: new DateTimeImmutable('now'), class: $item)); } - /** StorageInterface::update */ - public function test_update_call_without_setup_exception(): void - { - $this->expectException(StorageException::class); - $this->expectExceptionCode(StorageException::SETUP_NOT_CALLED); - $storage = new PDOAdapter(new CliLogger($this->output)); - $storage->update(new StateEntity([])); - } - public function test_update_call_without_id_exception(): void { $this->expectException(StorageException::class); @@ -161,15 +108,6 @@ class PDOAdapterTest extends TestCase $this->assertSame($updatedItem->getAll(), $this->storage->get($item)->getAll()); } - /** StorageInterface::update */ - public function test_matchAnyId_call_without_setup_exception(): void - { - $this->expectException(StorageException::class); - $this->expectExceptionCode(StorageException::SETUP_NOT_CALLED); - $storage = new PDOAdapter(new CliLogger($this->output)); - $storage->matchAnyId([]); - } - public function test_matchAnyId_call_without_initialized_container(): void { $this->expectException(Error::class); @@ -209,15 +147,6 @@ class PDOAdapterTest extends TestCase ); } - /** StorageInterface::remove */ - public function test_remove_call_without_setup_exception(): void - { - $this->expectException(StorageException::class); - $this->expectExceptionCode(StorageException::SETUP_NOT_CALLED); - $storage = new PDOAdapter(new CliLogger($this->output)); - $storage->remove(new StateEntity([])); - } - public function test_remove_conditions(): void { $item1 = new StateEntity($this->testEpisode); @@ -237,15 +166,6 @@ class PDOAdapterTest extends TestCase $this->assertFalse($this->storage->remove($item3)); } - /** StorageInterface::commit */ - public function test_commit_call_without_setup_exception(): void - { - $this->expectException(StorageException::class); - $this->expectExceptionCode(StorageException::SETUP_NOT_CALLED); - $storage = new PDOAdapter(new CliLogger($this->output)); - $storage->commit([]); - } - public function test_commit_conditions(): void { $item1 = new StateEntity($this->testEpisode); @@ -271,15 +191,6 @@ class PDOAdapterTest extends TestCase ); } - /** StorageInterface::migrations */ - public function test_migrations_call_without_setup_exception(): void - { - $this->expectException(StorageException::class); - $this->expectExceptionCode(StorageException::SETUP_NOT_CALLED); - $storage = new PDOAdapter(new CliLogger($this->output)); - $storage->migrations('f'); - } - public function test_migrations_call_with_wrong_direction_exception(): void { $this->expectException(StorageException::class);