From 499d11d2097f1bc51724753845ff6eaf55b4d5df Mon Sep 17 00:00:00 2001 From: thrillfall Date: Wed, 6 Oct 2021 14:02:31 +0200 Subject: [PATCH] query episode actions by unix timestamp (instead of datetime object) --- lib/Controller/EpisodeActionController.php | 24 ++--- lib/Core/EpisodeAction/EpisodeAction.php | 16 ++++ lib/Db/EpisodeAction/EpisodeActionMapper.php | 4 +- .../EpisodeAction/EpisodeActionRepository.php | 11 ++- .../EpisodeActionControllerTest.php | 94 +++++++++++++++++++ .../Migration/TimestampMigrationTest.php | 14 +-- 6 files changed, 135 insertions(+), 28 deletions(-) create mode 100644 tests/Integration/Controller/EpisodeActionControllerTest.php diff --git a/lib/Controller/EpisodeActionController.php b/lib/Controller/EpisodeActionController.php index 020c296..a184635 100644 --- a/lib/Controller/EpisodeActionController.php +++ b/lib/Controller/EpisodeActionController.php @@ -5,6 +5,7 @@ namespace OCA\GPodderSync\Controller; use DateTime; use GuzzleHttp\Psr7\Response; +use OCA\GPodderSync\Core\EpisodeAction\EpisodeAction; use OCA\GPodderSync\Core\EpisodeAction\EpisodeActionSaver; use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionRepository; use OCP\AppFramework\Controller; @@ -54,23 +55,16 @@ class EpisodeActionController extends Controller { * @return JSONResponse */ public function list(int $since): JSONResponse { - $sinceDatetime = $this->createDateTimeFromTimestamp($since); + $episodeActions = $this->episodeActionRepository->findAll($since, $this->userId); + $untypedEpisodeActionData = []; + + foreach ($episodeActions as $episodeAction) { + $untypedEpisodeActionData[] = $episodeAction->toArray(); + } + return new JSONResponse([ - "actions" => $this->episodeActionRepository->findAll($sinceDatetime, $this->userId), + "actions" => $untypedEpisodeActionData, "timestamp" => time() ]); } - - /** - * @param int|null $since - * - * @return DateTime - */ - private function createDateTimeFromTimestamp(?int $since): DateTime { - return ($since !== null) - ? (new \DateTime)->setTimestamp($since) - : (new \DateTime('-1 week')); - } - - } diff --git a/lib/Core/EpisodeAction/EpisodeAction.php b/lib/Core/EpisodeAction/EpisodeAction.php index 40ce336..97b33e4 100644 --- a/lib/Core/EpisodeAction/EpisodeAction.php +++ b/lib/Core/EpisodeAction/EpisodeAction.php @@ -99,5 +99,21 @@ class EpisodeAction { return $this->id; } + public function toArray() + { + return + [ + 'id' => $this->id, + 'podcast' => $this->getPodcast(), + 'episode' => $this->getEpisode(), + 'timestamp' => $this->getTimestamp(), + 'guid' => $this->getGuid(), + 'position' => $this->getPosition(), + 'started' => $this->getStarted(), + 'total' => $this->getTotal(), + 'action' => $this->getAction(), + ]; + } + } diff --git a/lib/Db/EpisodeAction/EpisodeActionMapper.php b/lib/Db/EpisodeAction/EpisodeActionMapper.php index 26d85c0..a482284 100644 --- a/lib/Db/EpisodeAction/EpisodeActionMapper.php +++ b/lib/Db/EpisodeAction/EpisodeActionMapper.php @@ -17,14 +17,14 @@ class EpisodeActionMapper extends \OCP\AppFramework\Db\QBMapper parent::__construct($db, 'gpodder_episode_action', EpisodeActionEntity::class); } - public function findAll(\DateTime $sinceTimestamp, string $userId): array + public function findAll(int $sinceTimestamp, string $userId): array { $qb = $this->db->getQueryBuilder(); $qb->select('*') ->from($this->getTableName()) ->where( - $qb->expr()->gt('timestamp', $qb->createNamedParameter($sinceTimestamp, IQueryBuilder::PARAM_DATE)) + $qb->expr()->gt('timestamp_epoch', $qb->createNamedParameter($sinceTimestamp, IQueryBuilder::PARAM_INT)) ) ->andWhere( $qb->expr()->eq('user_id', $qb->createNamedParameter($userId)) diff --git a/lib/Db/EpisodeAction/EpisodeActionRepository.php b/lib/Db/EpisodeAction/EpisodeActionRepository.php index cea3e1c..542c2f6 100644 --- a/lib/Db/EpisodeAction/EpisodeActionRepository.php +++ b/lib/Db/EpisodeAction/EpisodeActionRepository.php @@ -15,9 +15,16 @@ class EpisodeActionRepository { $this->episodeActionMapper = $episodeActionMapper; } - public function findAll(\DateTime $sinceTimestamp, string $userId) : array { + /** + * @param int $sinceEpoch + * @param string $userId + * + * @return EpisodeAction[] + * @throws \Safe\Exceptions\DatetimeException + */ + public function findAll(int $sinceEpoch, string $userId) : array { $episodeActions = []; - foreach ($this->episodeActionMapper->findAll($sinceTimestamp, $userId) as $entity) { + foreach ($this->episodeActionMapper->findAll($sinceEpoch, $userId) as $entity) { $episodeActions[] = $this->mapEntityToEpisodeAction($entity); } return $episodeActions; diff --git a/tests/Integration/Controller/EpisodeActionControllerTest.php b/tests/Integration/Controller/EpisodeActionControllerTest.php new file mode 100644 index 0000000..5bfc18f --- /dev/null +++ b/tests/Integration/Controller/EpisodeActionControllerTest.php @@ -0,0 +1,94 @@ +container = $app->getContainer(); + } + + /** + * @before + */ + public function before() + { + $this->startTransaction(); + } + + + public function testEpisodeActionListAction() + { + $userId = uniqid("test_user"); + $episodeActionController = new EpisodeActionController( + "gpoddersync", + new Request([], new SecureRandom(), self::getMockBuilder(IConfig::class)->getMock()), + $userId, + $this->container->get(EpisodeActionRepository::class), + $this->container->get(EpisodeActionSaver::class) + ); + + /** @var EpisodeActionWriter $episodeActionWriter */ + $episodeActionWriter = $this->container->get(EpisodeActionWriter::class); + + $mark = 1633520363; + $episodeActionEntity = new EpisodeActionEntity(); + $expectedPodcast = uniqid("test"); + $episodeActionEntity->setPodcast($expectedPodcast); + $expectedEpisode = uniqid("test"); + $episodeActionEntity->setEpisode($expectedEpisode); + $episodeActionEntity->setAction("PLAY"); + $episodeActionEntity->setPosition(5); + $episodeActionEntity->setStarted(0); + $episodeActionEntity->setTotal(123); + $episodeActionEntity->setTimestampEpoch($mark+600); + $episodeActionEntity->setUserId($userId); + $episodeActionEntity->setGuid(self::TEST_GUID); + $episodeActionWriter->save($episodeActionEntity); + + $response = $episodeActionController->list($mark); + self::assertCount(1, $response->getData()['actions']); + + $episodeActionInResponse = $response->getData()['actions'][0]; + self::assertSame("2021-10-06T11:49:23", $episodeActionInResponse['timestamp']); + self::assertSame($expectedEpisode, $episodeActionInResponse['episode']); + self::assertSame($expectedPodcast, $episodeActionInResponse['podcast']); + self::assertSame(self::TEST_GUID, $episodeActionInResponse['guid']); + self::assertSame(5, $episodeActionInResponse['position']); + self::assertSame(0, $episodeActionInResponse['started']); + self::assertSame(123, $episodeActionInResponse['total']); + self::assertSame("PLAY", $episodeActionInResponse['action']); + } + + /** + * @after + */ + public function after() + { + $this->rollbackTransation(); + } +} diff --git a/tests/Integration/Migration/TimestampMigrationTest.php b/tests/Integration/Migration/TimestampMigrationTest.php index 5bfee24..89012c4 100644 --- a/tests/Integration/Migration/TimestampMigrationTest.php +++ b/tests/Integration/Migration/TimestampMigrationTest.php @@ -7,11 +7,8 @@ use Doctrine\DBAL\Platforms\PostgreSQL100Platform; use OC\AllConfig; use OC\Log; use OC\Migration\SimpleOutput; -use OC\OCS\Exception; -use OC\OCS\Result; use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionEntity; use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionMapper; -use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionRepository; use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionWriter; use OCA\GPodderSync\Migration\TimestampMigration; use OCP\AppFramework\App; @@ -36,15 +33,14 @@ class TimestampMigrationTest extends TestCase private IDBConnection $dbConnection; private IConfig $migrationConfig; - public function setUp(): void { parent::setUp(); $app = new App('gpoddersync'); - $this->container = $app->getContainer(); - $this->episodeActionWriter = $this->container->get(EpisodeActionWriter::class); - $this->episodeActionMapper = $this->container->get(EpisodeActionMapper::class); - $this->dbConnection = $this->container->get(IDBConnection::class); - $this->migrationConfig = $this->container->get(AllConfig::class ); + $container = $app->getContainer(); + $this->episodeActionWriter = $container->get(EpisodeActionWriter::class); + $this->episodeActionMapper = $container->get(EpisodeActionMapper::class); + $this->dbConnection = $container->get(IDBConnection::class); + $this->migrationConfig = $container->get(AllConfig::class ); } /**