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

View File

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

View File

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

View File

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

View File

@ -3,8 +3,6 @@ declare(strict_types=1);
namespace OCA\GPodderSync\Db\EpisodeAction;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
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;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use OCA\GPodderSync\Core\EpisodeAction\EpisodeActionReader;
use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionEntity;
use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionRepository;
use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionWriter;
use OCP\AppFramework\App;
use Test\TestCase;
@ -17,12 +19,20 @@ class EpisodeActionGuidMigrationTest extends TestCase
{
use DatabaseTransaction;
private const USER_ID_0 = "user0@127.0.0.1";
private \OCP\AppFramework\IAppContainer $container;
/**
* @var EpisodeActionWriter
*/
private $episodeActionWriter;
public function setUp(): void {
parent::setUp();
$app = new App('gpoddersync');
$this->container = $app->getContainer();
$this->episodeActionWriter = $this->container->get(EpisodeActionWriter::class);
}
/**
@ -37,9 +47,6 @@ class EpisodeActionGuidMigrationTest extends TestCase
{
self::expectException(UniqueConstraintViolationException::class);
/** @var EpisodeActionWriter $episodeActionWriter */
$episodeActionWriter = $this->container->get('OCA\GPodderSync\Db\EpisodeAction\EpisodeActionWriter');
$episodeActionEntity = new EpisodeActionEntity();
$episodeActionEntity->setPodcast("https://podcast_01.url");
$episodeActionEntity->setEpisode("https://episode_01.url");
@ -48,10 +55,50 @@ class EpisodeActionGuidMigrationTest extends TestCase
$episodeActionEntity->setStarted(0);
$episodeActionEntity->setTotal(123);
$episodeActionEntity->setTimestamp("Mon Aug 23 01:58:56 GMT+02:00 2021");
$episodeActionEntity->setUserId("user0@127.0.0.1");
$episodeActionWriter->save($episodeActionEntity);
$episodeActionEntity->setUserId(self::USER_ID_0);
$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()
);
}