add guid to episode action and make it findable by it

This commit is contained in:
thrillfall 2021-08-24 23:19:21 +02:00
parent ae27f7cf34
commit 850dfd5eb4
7 changed files with 108 additions and 24 deletions

View File

@ -33,7 +33,7 @@ class EpisodeActionSaver
* *
* @return EpisodeActionEntity[] * @return EpisodeActionEntity[]
*/ */
public function saveEpisodeAction($data, string $userId): array public function saveEpisodeAction(string $data, string $userId): array
{ {
$episodeActionEntities = []; $episodeActionEntities = [];
@ -77,7 +77,7 @@ class EpisodeActionSaver
string $userId string $userId
): EpisodeActionEntity ): EpisodeActionEntity
{ {
$idEpisodeActionEntityToUpdate = $this->episodeActionRepository->findByEpisode( $idEpisodeActionEntityToUpdate = $this->episodeActionRepository->findByEpisodeIdentifier(
$episodeActionEntity->getEpisode(), $episodeActionEntity->getEpisode(),
$userId $userId
)->getId(); )->getId();

View File

@ -15,6 +15,7 @@ class EpisodeActionEntity extends Entity implements JsonSerializable {
protected $started; protected $started;
protected $total; protected $total;
protected $timestamp; protected $timestamp;
protected $guid;
protected $userId; protected $userId;
public function __construct() { public function __construct() {
@ -26,6 +27,7 @@ class EpisodeActionEntity extends Entity implements JsonSerializable {
'id' => $this->id, 'id' => $this->id,
'podcast' => $this->podcast, 'podcast' => $this->podcast,
'episode' => $this->episode, 'episode' => $this->episode,
'guid' => $this->guid,
'action' => $this->action, 'action' => $this->action,
'position' => $this->position, 'position' => $this->position,
'started' => $this->started, 'started' => $this->started,

View File

@ -8,12 +8,15 @@ use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection; use OCP\IDBConnection;
class EpisodeActionMapper extends \OCP\AppFramework\Db\QBMapper { class EpisodeActionMapper extends \OCP\AppFramework\Db\QBMapper
public function __construct(IDBConnection $db) { {
public function __construct(IDBConnection $db)
{
parent::__construct($db, 'gpodder_episode_action', EpisodeActionEntity::class); parent::__construct($db, 'gpodder_episode_action', EpisodeActionEntity::class);
} }
public function findAll(\DateTime $sinceTimestamp, string $userId): array { public function findAll(\DateTime $sinceTimestamp, string $userId): array
{
$qb = $this->db->getQueryBuilder(); $qb = $this->db->getQueryBuilder();
$qb->select('*') $qb->select('*')
@ -21,28 +24,34 @@ class EpisodeActionMapper extends \OCP\AppFramework\Db\QBMapper {
->where( ->where(
$qb->expr()->gt('timestamp', $qb->createNamedParameter($sinceTimestamp, IQueryBuilder::PARAM_DATE)) $qb->expr()->gt('timestamp', $qb->createNamedParameter($sinceTimestamp, IQueryBuilder::PARAM_DATE))
) )
->andWhere( ->andWhere(
$qb->expr()->eq('user_id', $qb->createNamedParameter($userId)) $qb->expr()->eq('user_id', $qb->createNamedParameter($userId))
); );
return $this->findEntities($qb); return $this->findEntities($qb);
} }
public function findByEpisode(string $episode, string $userId) { public function findByEpisodeIdentifier(string $episodeIdentifier, string $userId) : EpisodeActionEntity
{
$qb = $this->db->getQueryBuilder(); $qb = $this->db->getQueryBuilder();
$qb->select('*') $qb->select('*')
->from($this->getTableName()) ->from($this->getTableName())
->where( ->where(
$qb->expr()->eq('episode', $qb->createNamedParameter($episode)) $qb->expr()->orX(
$qb->expr()->eq('episode', $qb->createNamedParameter($episodeIdentifier)),
$qb->expr()->eq('guid', $qb->createNamedParameter($episodeIdentifier)))
) )
->andWhere( ->andWhere(
$qb->expr()->eq('user_id', $qb->createNamedParameter($userId)) $qb->expr()->eq('user_id', $qb->createNamedParameter($userId))
); );
try { try {
return $this->findEntity($qb); /** @var EpisodeActionEntity $episodeActionEntity*/
$episodeActionEntity = $this->findEntity($qb);
return $episodeActionEntity;
} catch (DoesNotExistException $e) { } catch (DoesNotExistException $e) {
} catch (MultipleObjectsReturnedException $e) { } catch (MultipleObjectsReturnedException $e) {
} }

View File

@ -17,7 +17,8 @@ class EpisodeActionRepository {
return $this->episodeActionMapper->findAll($sinceTimestamp, $userId); return $this->episodeActionMapper->findAll($sinceTimestamp, $userId);
} }
public function findByEpisode(string $episode, string $userId): EpisodeActionEntity { public function findByEpisodeIdentifier(string $identifier, string $userId): EpisodeActionEntity {
return $this->episodeActionMapper->findByEpisode($episode, $userId); return $this->episodeActionMapper->findByEpisodeIdentifier($identifier, $userId);
} }
} }

View File

@ -3,8 +3,6 @@ declare(strict_types=1);
namespace OCA\GPodderSync\Db\EpisodeAction; namespace OCA\GPodderSync\Db\EpisodeAction;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
class EpisodeActionWriter { class EpisodeActionWriter {
/** /**

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace OCA\GPodderSync\Migration;
use Closure;
use Doctrine\DBAL\Types\StringType;
use Doctrine\DBAL\Types\Types;
use OCP\DB\ISchemaWrapper;
use OCP\Migration\IOutput;
class Version0004Date20210823115513 extends \OCP\Migration\SimpleMigrationStep {
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();
$table = $schema->getTable('gpodder_episode_action');
$table->addColumn('guid', Types::STRING, [
'length' => 500,
'notnull' => false
]);
$table->addUniqueIndex(['guid', 'user_id'], 'gpodder_guid_user_id');
return $schema;
}
}

View File

@ -4,7 +4,9 @@ declare(strict_types=1);
namespace tests\Integration; namespace tests\Integration;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException; use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use OCA\GPodderSync\Core\EpisodeAction\EpisodeActionReader;
use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionEntity; use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionEntity;
use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionRepository;
use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionWriter; use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionWriter;
use OCP\AppFramework\App; use OCP\AppFramework\App;
use Test\TestCase; use Test\TestCase;
@ -17,12 +19,20 @@ class EpisodeActionGuidMigrationTest extends TestCase
{ {
use DatabaseTransaction; use DatabaseTransaction;
private const USER_ID_0 = "user0@127.0.0.1";
private \OCP\AppFramework\IAppContainer $container; private \OCP\AppFramework\IAppContainer $container;
/**
* @var EpisodeActionWriter
*/
private $episodeActionWriter;
public function setUp(): void { public function setUp(): void {
parent::setUp(); parent::setUp();
$app = new App('gpoddersync'); $app = new App('gpoddersync');
$this->container = $app->getContainer(); $this->container = $app->getContainer();
$this->episodeActionWriter = $this->container->get(EpisodeActionWriter::class);
} }
/** /**
@ -37,9 +47,6 @@ class EpisodeActionGuidMigrationTest extends TestCase
{ {
self::expectException(UniqueConstraintViolationException::class); self::expectException(UniqueConstraintViolationException::class);
/** @var EpisodeActionWriter $episodeActionWriter */
$episodeActionWriter = $this->container->get('OCA\GPodderSync\Db\EpisodeAction\EpisodeActionWriter');
$episodeActionEntity = new EpisodeActionEntity(); $episodeActionEntity = new EpisodeActionEntity();
$episodeActionEntity->setPodcast("https://podcast_01.url"); $episodeActionEntity->setPodcast("https://podcast_01.url");
$episodeActionEntity->setEpisode("https://episode_01.url"); $episodeActionEntity->setEpisode("https://episode_01.url");
@ -48,10 +55,50 @@ class EpisodeActionGuidMigrationTest extends TestCase
$episodeActionEntity->setStarted(0); $episodeActionEntity->setStarted(0);
$episodeActionEntity->setTotal(123); $episodeActionEntity->setTotal(123);
$episodeActionEntity->setTimestamp("Mon Aug 23 01:58:56 GMT+02:00 2021"); $episodeActionEntity->setTimestamp("Mon Aug 23 01:58:56 GMT+02:00 2021");
$episodeActionEntity->setUserId("user0@127.0.0.1"); $episodeActionEntity->setUserId(self::USER_ID_0);
$episodeActionWriter->save($episodeActionEntity); $this->episodeActionWriter->save($episodeActionEntity);
$episodeActionWriter->save($episodeActionEntity); //and save again
$this->episodeActionWriter->save($episodeActionEntity);
}
public function testFindEpisodeActionByEpisodeUrlAndThenGuid()
{
$episodeActionEntity = new EpisodeActionEntity();
$episodeActionEntity->setPodcast("https://podcast_01.url");
$episodeActionEntity->setEpisode("https://episode_01.url");
$episodeActionEntity->setAction("PLAY");
$episodeActionEntity->setPosition(5);
$episodeActionEntity->setStarted(0);
$episodeActionEntity->setTotal(123);
$episodeActionEntity->setTimestamp("Mon Aug 23 01:58:56 GMT+02:00 2021");
$episodeActionEntity->setUserId(self::USER_ID_0);
$savedEpisodeActionEntity = $this->episodeActionWriter->save($episodeActionEntity);
/** @var EpisodeActionRepository $episodeActionRepository */
$episodeActionRepository = $this->container->get(EpisodeActionRepository::class);
self::assertSame(
$savedEpisodeActionEntity->getId(),
$episodeActionRepository->findByEpisodeIdentifier($episodeActionEntity->getEpisode(), self::USER_ID_0)->getId()
);
//update same episode action again this time with guid
$episodeActionEntityWithGuid = clone $episodeActionEntity;
$episodeActionEntityWithGuid->setGuid("guid:dadsaf4f4v");
$savedEpisodeActionEntityWithGuid = $this->episodeActionWriter->update($episodeActionEntityWithGuid);
self::assertSame(
$savedEpisodeActionEntityWithGuid->getId(),
$episodeActionRepository->findByEpisodeIdentifier($episodeActionEntityWithGuid->getEpisode(), self::USER_ID_0)->getId()
);
self::assertSame(
$savedEpisodeActionEntityWithGuid->getId(),
$episodeActionRepository->findByEpisodeIdentifier($episodeActionEntityWithGuid->getGuid(), self::USER_ID_0)->getId()
);
} }