Added some test coverage for plexGuid with support for external GUID file loading.
This commit is contained in:
@@ -81,7 +81,11 @@ return (function () {
|
||||
],
|
||||
];
|
||||
|
||||
$config['guid_file'] = fixPath(env('WS_GUID_FILE', ag($config, 'path') . '/config/guid.yaml'));
|
||||
$config['guid'] = [
|
||||
'version' => '0.0',
|
||||
'file' => fixPath(env('WS_GUID_FILE', ag($config, 'path') . '/config/guid.yaml')),
|
||||
];
|
||||
|
||||
$config['backends_file'] = fixPath(env('WS_BACKENDS_FILE', ag($config, 'path') . '/config/servers.yaml'));
|
||||
|
||||
date_default_timezone_set(ag($config, 'tz', 'UTC'));
|
||||
|
||||
@@ -6,8 +6,12 @@ namespace App\Backends\Plex;
|
||||
|
||||
use App\Backends\Common\Context;
|
||||
use App\Backends\Common\GuidInterface as iGuid;
|
||||
use App\Libs\Config;
|
||||
use App\Libs\Exceptions\Backends\InvalidArgumentException;
|
||||
use App\Libs\Guid;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\LoggerInterface as iLogger;
|
||||
use Symfony\Component\Yaml\Exception\ParseException;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
use Throwable;
|
||||
|
||||
final class PlexGuid implements iGuid
|
||||
@@ -15,7 +19,7 @@ final class PlexGuid implements iGuid
|
||||
/**
|
||||
* @var array<string,string> Map plex guids to our guids.
|
||||
*/
|
||||
private const array GUID_MAPPER = [
|
||||
private array $guidMapper = [
|
||||
'imdb' => Guid::GUID_IMDB,
|
||||
'tmdb' => Guid::GUID_TMDB,
|
||||
'tvdb' => Guid::GUID_TVDB,
|
||||
@@ -29,7 +33,7 @@ final class PlexGuid implements iGuid
|
||||
/**
|
||||
* @var array<array-key,string> List of legacy plex agents.
|
||||
*/
|
||||
private const array GUID_LEGACY = [
|
||||
private array $guidLegacy = [
|
||||
'com.plexapp.agents.imdb',
|
||||
'com.plexapp.agents.tmdb',
|
||||
'com.plexapp.agents.themoviedb',
|
||||
@@ -44,7 +48,7 @@ final class PlexGuid implements iGuid
|
||||
/**
|
||||
* @var array<array-key,string> List of local plex agents.
|
||||
*/
|
||||
private const array GUID_LOCAL = [
|
||||
private array $guidLocal = [
|
||||
'plex',
|
||||
'local',
|
||||
'com.plexapp.agents.none',
|
||||
@@ -54,7 +58,7 @@ final class PlexGuid implements iGuid
|
||||
/**
|
||||
* @var array<string,string> Map guids to their replacement.
|
||||
*/
|
||||
private const array GUID_LEGACY_REPLACER = [
|
||||
private array $guidReplacer = [
|
||||
'com.plexapp.agents.themoviedb://' => 'com.plexapp.agents.tmdb://',
|
||||
'com.plexapp.agents.xbmcnfotv://' => 'com.plexapp.agents.tvdb://',
|
||||
'com.plexapp.agents.thetvdb://' => 'com.plexapp.agents.tvdb://',
|
||||
@@ -72,10 +76,189 @@ final class PlexGuid implements iGuid
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param LoggerInterface $logger Logger instance.
|
||||
* @param iLogger $logger Logger instance.
|
||||
*/
|
||||
public function __construct(protected LoggerInterface $logger)
|
||||
public function __construct(private readonly iLogger $logger)
|
||||
{
|
||||
$file = Config::get('guid.file', null);
|
||||
|
||||
try {
|
||||
if (null !== $file && true === file_exists($file)) {
|
||||
$this->parseGUIDFile($file);
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
$this->logger->error("Failed to read or parse '{guid}' file. Error '{error}'.", [
|
||||
'guid' => $file,
|
||||
'error' => $e->getMessage(),
|
||||
'exception' => [
|
||||
'message' => $e->getMessage(),
|
||||
'code' => $e->getCode(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'trace' => $e->getTrace(),
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extends WatchState GUID parsing to include external GUIDs.
|
||||
*
|
||||
* @param string $file The path to the external GUID mapping file.
|
||||
*
|
||||
* @throws InvalidArgumentException if the file does not exist or is not readable.
|
||||
* @throws InvalidArgumentException if the GUIDs file cannot be parsed.
|
||||
* @throws InvalidArgumentException if the file version is not supported.
|
||||
*/
|
||||
public function parseGUIDFile(string $file): void
|
||||
{
|
||||
if (false === file_exists($file) || false === is_readable($file)) {
|
||||
throw new InvalidArgumentException(r("The file '{file}' does not exist or is not readable.", [
|
||||
'file' => $file,
|
||||
]));
|
||||
}
|
||||
|
||||
if (filesize($file) < 1) {
|
||||
$this->logger->info("The external GUID mapping file '{file}' is empty.", ['file' => $file]);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$yaml = Yaml::parseFile($file);
|
||||
if (false === is_array($yaml)) {
|
||||
throw new InvalidArgumentException(r("The GUIDs file '{file}' is not an array.", [
|
||||
'file' => $file,
|
||||
]));
|
||||
}
|
||||
} catch (ParseException $e) {
|
||||
throw new InvalidArgumentException(r("Failed to parse GUIDs file. Error '{error}'.", [
|
||||
'error' => $e->getMessage(),
|
||||
]), code: (int)$e->getCode(), previous: $e);
|
||||
}
|
||||
|
||||
$supported = array_keys(Guid::getSupported());
|
||||
$supportedVersion = Config::get('guid.version', '0.0');
|
||||
$guidVersion = (string)ag($yaml, 'version', $supportedVersion);
|
||||
|
||||
if (true === version_compare($supportedVersion, $guidVersion, '<')) {
|
||||
throw new InvalidArgumentException(r("Unsupported file version '{version}'. Expecting '{supported}'.", [
|
||||
'version' => $guidVersion,
|
||||
'supported' => $supportedVersion,
|
||||
]));
|
||||
}
|
||||
|
||||
$mapping = ag($yaml, 'plex', []);
|
||||
|
||||
if (false === is_array($mapping)) {
|
||||
throw new InvalidArgumentException(r("The GUIDs file '{file}' plex sub key is not an array.", [
|
||||
'file' => $file,
|
||||
]));
|
||||
}
|
||||
|
||||
if (count($mapping) < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($mapping as $key => $map) {
|
||||
if (false === is_array($map)) {
|
||||
$this->logger->warning("Ignoring 'plex.{key}'. Value must be an object. '{given}' is given.", [
|
||||
'key' => $key,
|
||||
'given' => get_debug_type($map),
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (null !== ($replace = ag($map, 'replace', null))) {
|
||||
if (false === is_array($replace)) {
|
||||
$this->logger->warning(
|
||||
"Ignoring 'plex.{key}'. replace value must be an object. '{given}' is given.",
|
||||
[
|
||||
'key' => $key,
|
||||
'given' => get_debug_type($replace),
|
||||
]
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
$from = ag($replace, 'from', null);
|
||||
$to = ag($replace, 'to', null);
|
||||
|
||||
if (empty($from) || false === is_string($from)) {
|
||||
$this->logger->warning("Ignoring 'plex.{key}'. replace.from field is empty or not a string.", [
|
||||
'key' => $key,
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (false === is_string($to)) {
|
||||
$this->logger->warning("Ignoring 'plex.{key}'. replacer.to field is not a string.", [
|
||||
'key' => $key,
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->guidReplacer[$from] = $to;
|
||||
}
|
||||
|
||||
if (null !== ($mapper = ag($map, 'map', null))) {
|
||||
if (false === is_array($mapper)) {
|
||||
$this->logger->warning("Ignoring 'plex.{key}'. map value must be an object. '{given}' is given.", [
|
||||
'key' => $key,
|
||||
'given' => get_debug_type($mapper),
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$from = ag($mapper, 'from', null);
|
||||
$to = ag($mapper, 'to', null);
|
||||
|
||||
if (empty($from) || false === is_string($from)) {
|
||||
$this->logger->warning("Ignoring 'plex.{key}'. map.from field is empty or not a string.", [
|
||||
'key' => $key,
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (empty($to) || false === is_string($to)) {
|
||||
$this->logger->warning("Ignoring 'plex.{key}'. map.to field is empty or not a string.", [
|
||||
'key' => $key,
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (false === str_starts_with($to, 'guid_')) {
|
||||
$this->logger->warning("Ignoring 'plex.{key}'. map.to '{to}' field does not starts with 'guid_'.", [
|
||||
'key' => $key,
|
||||
'to' => $to,
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (false === in_array($to, $supported)) {
|
||||
$this->logger->warning("Ignoring 'plex.{key}'. map.to field is not a supported GUID type.", [
|
||||
'key' => $key,
|
||||
'to' => $to,
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (false === (bool)ag($map, 'legacy', true)) {
|
||||
$this->guidMapper[$from] = $to;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (true === in_array($from, $this->guidLegacy)) {
|
||||
$this->logger->warning("Ignoring 'plex.{key}'. map.from already exists.", [
|
||||
'key' => $key,
|
||||
'from' => $from,
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
$this->guidLegacy[] = $from;
|
||||
$agentGuid = explode('://', after($from, 'agents.'));
|
||||
$this->guidMapper[$agentGuid[0]] = $to;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,7 +305,7 @@ final class PlexGuid implements iGuid
|
||||
*/
|
||||
public function isLocal(string $guid): bool
|
||||
{
|
||||
return true === in_array(before(strtolower($guid), '://'), self::GUID_LOCAL);
|
||||
return true === in_array(before(strtolower($guid), '://'), $this->guidLocal);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,14 +342,11 @@ final class PlexGuid implements iGuid
|
||||
|
||||
if (false === str_contains($val, '://')) {
|
||||
if (true === $log) {
|
||||
$this->logger->info(
|
||||
'PlexGuid: Unable to parse [{backend}] [{agent}] identifier.',
|
||||
[
|
||||
'backend' => $this->context->backendName,
|
||||
'agent' => $val,
|
||||
...$context
|
||||
]
|
||||
);
|
||||
$this->logger->info('PlexGuid: Unable to parse [{backend}] [{agent}] identifier.', [
|
||||
'backend' => $this->context->backendName,
|
||||
'agent' => $val,
|
||||
...$context
|
||||
]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -174,15 +354,16 @@ final class PlexGuid implements iGuid
|
||||
[$key, $value] = explode('://', $val);
|
||||
$key = strtolower($key);
|
||||
|
||||
if (null === (self::GUID_MAPPER[$key] ?? null) || empty($value)) {
|
||||
if (null === ($this->guidMapper[$key] ?? null) || empty($value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (true === isIgnoredId($this->context->backendName, $type, $key, $value, $id)) {
|
||||
if (true === $log) {
|
||||
$this->logger->debug(
|
||||
'PlexGuid: Ignoring [{backend}] external id [{source}] for {item.type} [{item.title}] as requested.',
|
||||
"PlexGuid: Ignoring '{client}: {backend}' external id '{source}' for {item.type} '{item.id}: {item.title}' as requested.",
|
||||
[
|
||||
'client' => $this->context->clientName,
|
||||
'backend' => $this->context->backendName,
|
||||
'source' => $val,
|
||||
'guid' => [
|
||||
@@ -197,14 +378,15 @@ final class PlexGuid implements iGuid
|
||||
}
|
||||
|
||||
// -- Plex in their infinite wisdom, sometimes report two keys for same data source.
|
||||
if (null !== ($guid[self::GUID_MAPPER[$key]] ?? null)) {
|
||||
if (null !== ($guid[$this->guidMapper[$key]] ?? null)) {
|
||||
if (true === $log) {
|
||||
$this->logger->debug(
|
||||
'PlexGuid: [{backend}] reported multiple ids for same data source [{key}: {ids}] for {item.type} [{item.title}].',
|
||||
$this->logger->warning(
|
||||
"PlexGuid: '{client}: {backend}' reported multiple ids for same data source '{key}: {ids}' for {item.type} '{item.id}: {item.title}'.",
|
||||
[
|
||||
'client' => $this->context->clientName,
|
||||
'backend' => $this->context->backendName,
|
||||
'key' => $key,
|
||||
'ids' => sprintf('%s, %s', $guid[self::GUID_MAPPER[$key]], $value),
|
||||
'ids' => sprintf('%s, %s', $guid[$this->guidMapper[$key]], $value),
|
||||
...$context
|
||||
]
|
||||
);
|
||||
@@ -214,16 +396,16 @@ final class PlexGuid implements iGuid
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((int)$guid[self::GUID_MAPPER[$key]] < (int)$value) {
|
||||
if ((int)$guid[$this->guidMapper[$key]] < (int)$value) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$guid[self::GUID_MAPPER[$key]] = $value;
|
||||
$guid[$this->guidMapper[$key]] = $value;
|
||||
} catch (Throwable $e) {
|
||||
if (true === $log) {
|
||||
$this->logger->error(
|
||||
message: 'PlexGuid: Exception [{error.kind}] was thrown unhandled during [{client}: {backend}] parsing [{agent}] identifier. Error [{error.message} @ {error.file}:{error.line}].',
|
||||
message: "PlexGuid: Exception '{error.kind}' was thrown unhandled during '{client}: {backend}' parsing '{agent}' identifier. Error '{error.message}' at '{error.file}:{error.line}'.",
|
||||
context: [
|
||||
'backend' => $this->context->backendName,
|
||||
'client' => $this->context->clientName,
|
||||
@@ -261,12 +443,12 @@ final class PlexGuid implements iGuid
|
||||
* @param array $context Context data.
|
||||
* @param bool $log Log errors. default true.
|
||||
*
|
||||
* @return string Parsed guid.
|
||||
* @return string The parsed GUID.
|
||||
* @see https://github.com/ZeroQI/Hama.bundle/issues/510
|
||||
*/
|
||||
private function parseLegacyAgent(string $guid, array $context = [], bool $log = true): string
|
||||
{
|
||||
if (false === in_array(before($guid, '://'), self::GUID_LEGACY)) {
|
||||
if (false === in_array(before($guid, '://'), $this->guidLegacy)) {
|
||||
return $guid;
|
||||
}
|
||||
|
||||
@@ -286,7 +468,7 @@ final class PlexGuid implements iGuid
|
||||
return str_replace('tsdb', 'tmdb', $source) . '://' . before($sourceId, '?');
|
||||
}
|
||||
|
||||
$guid = strtr($guid, self::GUID_LEGACY_REPLACER);
|
||||
$guid = strtr($guid, $this->guidReplacer);
|
||||
|
||||
$agentGuid = explode('://', after($guid, 'agents.'));
|
||||
|
||||
@@ -294,7 +476,7 @@ final class PlexGuid implements iGuid
|
||||
} catch (Throwable $e) {
|
||||
if (true === $log) {
|
||||
$this->logger->error(
|
||||
message: 'PlexGuid: Exception [{error.kind}] was thrown unhandled during [{client}: {backend}] parsing legacy agent [{agent}] identifier. Error [{error.message} @ {error.file}:{error.line}].',
|
||||
message: "PlexGuid: Exception '{error.kind}' was thrown unhandled during '{client}: {backend}' parsing legacy agent '{agent}' identifier. Error '{error.message}' at '{error.file}:{error.line}.",
|
||||
context: [
|
||||
'backend' => $this->context->backendName,
|
||||
'client' => $this->context->clientName,
|
||||
@@ -319,4 +501,19 @@ final class PlexGuid implements iGuid
|
||||
return $guid;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Plex Guid configuration.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getConfig(): array
|
||||
{
|
||||
return [
|
||||
'guidMapper' => $this->guidMapper,
|
||||
'guidLegacy' => $this->guidLegacy,
|
||||
'guidLocal' => $this->guidLocal,
|
||||
'guidReplacer' => $this->guidReplacer,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,11 +233,13 @@ final class Guid implements JsonSerializable, Stringable
|
||||
]), (int)$e->getCode(), $e);
|
||||
}
|
||||
|
||||
$guidVersion = (string)ag($yaml, 'version', '0.0');
|
||||
$supportedVersion = ag(require __DIR__ . '/../../config/config.php', 'guid.version', '0.0');
|
||||
$guidVersion = (string)ag($yaml, 'version', Config::get('guid.version', '0.0'));
|
||||
|
||||
if (true === version_compare('0.0', $guidVersion, '<')) {
|
||||
throw new InvalidArgumentException(r("Unsupported file version '{version}'. Expecting '1.0'.", [
|
||||
'version' => $guidVersion
|
||||
if (true === version_compare($supportedVersion, $guidVersion, '<')) {
|
||||
throw new InvalidArgumentException(r("Unsupported file version '{version}'. Expecting '{supported}'.", [
|
||||
'version' => $guidVersion,
|
||||
'supported' => $supportedVersion,
|
||||
]));
|
||||
}
|
||||
|
||||
@@ -537,7 +539,7 @@ final class Guid implements JsonSerializable, Stringable
|
||||
|
||||
private static function loadExternalGUID(): void
|
||||
{
|
||||
$file = Config::get('guid_file', null);
|
||||
$file = Config::get('guid.file', null);
|
||||
|
||||
try {
|
||||
if (null !== $file && true === file_exists($file)) {
|
||||
|
||||
322
tests/Backends/Plex/PlexGuidTest.php
Normal file
322
tests/Backends/Plex/PlexGuidTest.php
Normal file
@@ -0,0 +1,322 @@
|
||||
<?php
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Backends\Plex;
|
||||
|
||||
use App\Backends\Plex\PlexGuid;
|
||||
use App\Libs\Config;
|
||||
use App\Libs\Exceptions\Backends\InvalidArgumentException;
|
||||
use App\Libs\Extends\LogMessageProcessor;
|
||||
use App\Libs\Guid;
|
||||
use App\Libs\TestCase;
|
||||
use Monolog\Handler\TestHandler;
|
||||
use Monolog\Level;
|
||||
use Monolog\Logger;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
class PlexGuidTest extends TestCase
|
||||
{
|
||||
protected Logger|null $logger = null;
|
||||
|
||||
private function logged(Level $level, string $message, bool $clear = false): bool
|
||||
{
|
||||
try {
|
||||
foreach ($this->handler->getRecords() as $record) {
|
||||
if ($level !== $record->level) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (null !== $record->formatted && true === str_contains($record->formatted, $message)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (true === str_contains($record->message, $message)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} finally {
|
||||
if (true === $clear) {
|
||||
$this->handler->clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function getClass(): PlexGuid
|
||||
{
|
||||
return new PlexGuid($this->logger);
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->handler = new TestHandler();
|
||||
$this->logger = new Logger('logger', processors: [new LogMessageProcessor()]);
|
||||
$this->logger->pushHandler($this->handler);
|
||||
|
||||
Guid::setLogger($this->logger);
|
||||
}
|
||||
|
||||
public function test__construct()
|
||||
{
|
||||
$oldGuidFile = Config::get('guid.file');
|
||||
|
||||
$tmpFile = tempnam(sys_get_temp_dir(), 'guid');
|
||||
try {
|
||||
file_put_contents($tmpFile, "{'foo' => 'too' }");
|
||||
Config::save('guid.file', $tmpFile);
|
||||
$this->getClass();
|
||||
$this->assertTrue(
|
||||
$this->logged(Level::Error, 'Failed to parse GUIDs file', true),
|
||||
"Assert message logged when the value type does not match the expected type."
|
||||
);
|
||||
} finally {
|
||||
if (file_exists($tmpFile)) {
|
||||
unlink($tmpFile);
|
||||
}
|
||||
Config::save('guid.file', $oldGuidFile);
|
||||
}
|
||||
}
|
||||
|
||||
public function test_parseGUIDFile()
|
||||
{
|
||||
Config::save('guid.file', null);
|
||||
|
||||
$tmpFile = tempnam(sys_get_temp_dir(), 'guid');
|
||||
try {
|
||||
$this->checkException(
|
||||
closure: function () use ($tmpFile) {
|
||||
file_put_contents($tmpFile, 'version: 2.0');
|
||||
$this->getClass()->parseGUIDFile($tmpFile);
|
||||
},
|
||||
reason: "Failed to throw exception when the GUID file version is not supported.",
|
||||
exception: InvalidArgumentException::class,
|
||||
exceptionMessage: 'Unsupported file version'
|
||||
);
|
||||
} finally {
|
||||
if (file_exists($tmpFile)) {
|
||||
unlink($tmpFile);
|
||||
}
|
||||
}
|
||||
|
||||
$this->checkException(
|
||||
closure: fn() => $this->getClass()->parseGUIDFile('not_set.yml'),
|
||||
reason: "Failed to assert that the GUID file is not found.",
|
||||
exception: InvalidArgumentException::class,
|
||||
exceptionMessage: 'does not exist'
|
||||
);
|
||||
|
||||
$tmpFile = tempnam(sys_get_temp_dir(), 'guid');
|
||||
try {
|
||||
$this->checkException(
|
||||
closure: function () use ($tmpFile) {
|
||||
file_put_contents($tmpFile, 'fff: {_]');
|
||||
$this->getClass()->parseGUIDFile($tmpFile);
|
||||
},
|
||||
reason: "Failed to throw exception when the GUID file is invalid.",
|
||||
exception: InvalidArgumentException::class,
|
||||
exceptionMessage: 'Failed to parse GUIDs file'
|
||||
);
|
||||
} finally {
|
||||
if (file_exists($tmpFile)) {
|
||||
unlink($tmpFile);
|
||||
}
|
||||
}
|
||||
|
||||
$tmpFile = tempnam(sys_get_temp_dir(), 'guid');
|
||||
try {
|
||||
$this->checkException(
|
||||
closure: function () use ($tmpFile) {
|
||||
file_put_contents($tmpFile, 'invalid');
|
||||
$this->getClass()->parseGUIDFile($tmpFile);
|
||||
},
|
||||
reason: "Failed to throw exception when the GUID file is invalid.",
|
||||
exception: InvalidArgumentException::class,
|
||||
exceptionMessage: 'is not an array'
|
||||
);
|
||||
} finally {
|
||||
if (file_exists($tmpFile)) {
|
||||
unlink($tmpFile);
|
||||
}
|
||||
}
|
||||
|
||||
$tmpFile = tempnam(sys_get_temp_dir(), 'guid');
|
||||
try {
|
||||
$this->getClass()->parseGUIDFile($tmpFile);
|
||||
$this->assertTrue(
|
||||
$this->logged(Level::Info, 'is empty', true),
|
||||
"Failed to assert that the GUID file is empty."
|
||||
);
|
||||
} finally {
|
||||
if (file_exists($tmpFile)) {
|
||||
unlink($tmpFile);
|
||||
}
|
||||
}
|
||||
|
||||
$tmpFile = tempnam(sys_get_temp_dir(), 'guid');
|
||||
try {
|
||||
$this->checkException(
|
||||
closure: function () use ($tmpFile) {
|
||||
file_put_contents($tmpFile, Yaml::dump(['plex' => 'foo']));
|
||||
$this->getClass()->parseGUIDFile($tmpFile);
|
||||
},
|
||||
reason: "Should throw an exception when there are no GUIDs mapping.",
|
||||
exception: InvalidArgumentException::class,
|
||||
exceptionMessage: 'plex sub key is not an array'
|
||||
);
|
||||
} finally {
|
||||
if (file_exists($tmpFile)) {
|
||||
unlink($tmpFile);
|
||||
}
|
||||
}
|
||||
|
||||
$tmpFile = tempnam(sys_get_temp_dir(), 'guid');
|
||||
try {
|
||||
$this->handler->clear();
|
||||
$yaml = ['plex' => [[]]];
|
||||
file_put_contents($tmpFile, Yaml::dump($yaml));
|
||||
$this->getClass()->parseGUIDFile($tmpFile);
|
||||
$this->assertCount(0, $this->handler->getRecords(), "There should be no messages logged for empty list.");
|
||||
$this->handler->clear();
|
||||
|
||||
|
||||
file_put_contents($tmpFile, Yaml::dump(ag_set($yaml, 'plex.0', 'ff')));
|
||||
$this->getClass()->parseGUIDFile($tmpFile);
|
||||
$this->assertTrue(
|
||||
$this->logged(Level::Warning, 'Value must be an object.', true),
|
||||
'Assert replace key is an object.'
|
||||
);
|
||||
|
||||
$yaml = ag_set($yaml, 'plex.0.replace', 'foo');
|
||||
file_put_contents($tmpFile, Yaml::dump($yaml));
|
||||
$this->getClass()->parseGUIDFile($tmpFile);
|
||||
$this->assertTrue(
|
||||
$this->logged(Level::Warning, 'replace value must be an object.', true),
|
||||
'Assert replace key is an object.'
|
||||
);
|
||||
|
||||
$yaml = ag_set($yaml, 'plex.0', ['replace' => []]);
|
||||
file_put_contents($tmpFile, Yaml::dump($yaml));
|
||||
$this->getClass()->parseGUIDFile($tmpFile);
|
||||
$this->assertTrue(
|
||||
$this->logged(Level::Warning, 'replace.from field is empty or not a string.', true),
|
||||
'Assert to field is a string.'
|
||||
);
|
||||
|
||||
$yaml = ag_set($yaml, 'plex.0.replace.from', 'foo');
|
||||
file_put_contents($tmpFile, Yaml::dump($yaml));
|
||||
$this->getClass()->parseGUIDFile($tmpFile);
|
||||
$this->assertTrue(
|
||||
$this->logged(Level::Warning, 'replacer.to field is not a string.', true),
|
||||
'Assert to field is a string.'
|
||||
);
|
||||
|
||||
$yaml = ag_set($yaml, 'plex.0.replace.to', 'bar');
|
||||
file_put_contents($tmpFile, Yaml::dump($yaml));
|
||||
$this->getClass()->parseGUIDFile($tmpFile);
|
||||
$this->assertCount(0, $this->handler->getRecords(), "There should be no error messages logged.");
|
||||
} finally {
|
||||
if (file_exists($tmpFile)) {
|
||||
unlink($tmpFile);
|
||||
}
|
||||
}
|
||||
|
||||
$this->handler->clear();
|
||||
|
||||
$tmpFile = tempnam(sys_get_temp_dir(), 'guid');
|
||||
try {
|
||||
$yaml = ag_set(['plex' => []], 'plex.0.map', 'foo');
|
||||
file_put_contents($tmpFile, Yaml::dump($yaml));
|
||||
$this->getClass()->parseGUIDFile($tmpFile);
|
||||
$this->assertTrue(
|
||||
$this->logged(Level::Warning, 'map value must be an object.', true),
|
||||
'Assert replace key is an object.'
|
||||
);
|
||||
|
||||
$yaml = ag_set($yaml, 'plex.0', ['map' => []]);
|
||||
file_put_contents($tmpFile, Yaml::dump($yaml));
|
||||
$this->getClass()->parseGUIDFile($tmpFile);
|
||||
$this->assertTrue(
|
||||
$this->logged(Level::Warning, 'map.from field is empty or not a string.', true),
|
||||
'Assert to field is a string.'
|
||||
);
|
||||
|
||||
$yaml = ag_set($yaml, 'plex.0.map.from', 'foo');
|
||||
file_put_contents($tmpFile, Yaml::dump($yaml));
|
||||
$this->getClass()->parseGUIDFile($tmpFile);
|
||||
$this->assertTrue(
|
||||
$this->logged(Level::Warning, 'map.to field is empty or not a string.', true),
|
||||
'Assert to field is a string.'
|
||||
);
|
||||
|
||||
$yaml = ag_set($yaml, 'plex.0.map.to', 'foobar');
|
||||
file_put_contents($tmpFile, Yaml::dump($yaml));
|
||||
$this->getClass()->parseGUIDFile($tmpFile);
|
||||
$this->assertTrue(
|
||||
$this->logged(Level::Warning, 'field does not starts with', true),
|
||||
'Assert to field is a string.'
|
||||
);
|
||||
|
||||
$yaml = ag_set($yaml, 'plex.0.map.to', 'guid_foobar');
|
||||
file_put_contents($tmpFile, Yaml::dump($yaml));
|
||||
$this->getClass()->parseGUIDFile($tmpFile);
|
||||
$this->assertTrue(
|
||||
$this->logged(Level::Warning, 'map.to field is not a supported', true),
|
||||
'Assert to field is a string.'
|
||||
);
|
||||
|
||||
$yaml = ag_set($yaml, 'plex.0.map', [
|
||||
'from' => 'com.plexapp.agents.imdb',
|
||||
'to' => 'guid_imdb',
|
||||
]);
|
||||
file_put_contents($tmpFile, Yaml::dump($yaml));
|
||||
$this->getClass()->parseGUIDFile($tmpFile);
|
||||
$this->assertTrue(
|
||||
$this->logged(Level::Warning, 'map.from already exists.', true),
|
||||
'Assert to field is a string.'
|
||||
);
|
||||
|
||||
$yaml = ag_set($yaml, 'plex.0.map', [
|
||||
'from' => 'com.plexapp.agents.ccdb',
|
||||
'to' => 'guid_imdb',
|
||||
]);
|
||||
|
||||
$this->handler->clear();
|
||||
|
||||
file_put_contents($tmpFile, Yaml::dump($yaml));
|
||||
$class = $this->getClass();
|
||||
$class->parseGUIDFile($tmpFile);
|
||||
$this->assertArrayHasKey(
|
||||
'ccdb',
|
||||
ag($class->getConfig(), 'guidMapper', []),
|
||||
'Assert that the GUID mapping has been added.'
|
||||
);
|
||||
$this->handler->clear();
|
||||
|
||||
$yaml = ag_set($yaml, 'plex.0', [
|
||||
'legacy' => false,
|
||||
'map' => [
|
||||
'from' => 'com.plexapp.agents.imthedb',
|
||||
'to' => 'guid_imdb',
|
||||
]
|
||||
]);
|
||||
file_put_contents($tmpFile, Yaml::dump($yaml));
|
||||
$class = $this->getClass();
|
||||
$class->parseGUIDFile($tmpFile);
|
||||
$this->assertArrayHasKey(
|
||||
'com.plexapp.agents.imthedb',
|
||||
ag($class->getConfig(), 'guidMapper', []),
|
||||
'Assert that the GUID mapping has been added.'
|
||||
);
|
||||
} finally {
|
||||
if (file_exists($tmpFile)) {
|
||||
unlink($tmpFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -360,10 +360,10 @@ class GuidTest extends TestCase
|
||||
public function test_reparse()
|
||||
{
|
||||
$tmpFile = tempnam(sys_get_temp_dir(), 'guid');
|
||||
$oldGuidFile = Config::get('guid_file');
|
||||
$oldGuidFile = Config::get('guid.file');
|
||||
try {
|
||||
file_put_contents($tmpFile, "{'foo' => 'too' }");
|
||||
Config::save('guid_file', $tmpFile);
|
||||
Config::save('guid.file', $tmpFile);
|
||||
Guid::setLogger($this->logger);
|
||||
Guid::reparse();
|
||||
Guid::getSupported();
|
||||
@@ -375,7 +375,7 @@ class GuidTest extends TestCase
|
||||
if (file_exists($tmpFile)) {
|
||||
unlink($tmpFile);
|
||||
}
|
||||
Config::save('guid_file', $oldGuidFile);
|
||||
Config::save('guid.file', $oldGuidFile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -392,7 +392,7 @@ class GuidTest extends TestCase
|
||||
public function test_getValidators()
|
||||
{
|
||||
$tmpFile = tempnam(sys_get_temp_dir(), 'guid');
|
||||
$oldGuidFile = Config::get('guid_file');
|
||||
$oldGuidFile = Config::get('guid.file');
|
||||
|
||||
$yaml = [
|
||||
'guids' => [
|
||||
@@ -413,7 +413,7 @@ class GuidTest extends TestCase
|
||||
|
||||
try {
|
||||
file_put_contents($tmpFile, Yaml::dump($yaml));
|
||||
Config::save('guid_file', $tmpFile);
|
||||
Config::save('guid.file', $tmpFile);
|
||||
Guid::reparse();
|
||||
$this->assertArrayHasKey(
|
||||
'guid_foobar',
|
||||
@@ -424,7 +424,7 @@ class GuidTest extends TestCase
|
||||
if (file_exists($tmpFile)) {
|
||||
unlink($tmpFile);
|
||||
}
|
||||
Config::save('guid_file', $oldGuidFile);
|
||||
Config::save('guid.file', $oldGuidFile);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user