query episode actions by unix timestamp (instead of datetime object)

This commit is contained in:
thrillfall 2021-10-06 14:02:31 +02:00
parent 2a988e91a6
commit 499d11d209
6 changed files with 135 additions and 28 deletions

View File

@ -5,6 +5,7 @@ namespace OCA\GPodderSync\Controller;
use DateTime; use DateTime;
use GuzzleHttp\Psr7\Response; use GuzzleHttp\Psr7\Response;
use OCA\GPodderSync\Core\EpisodeAction\EpisodeAction;
use OCA\GPodderSync\Core\EpisodeAction\EpisodeActionSaver; use OCA\GPodderSync\Core\EpisodeAction\EpisodeActionSaver;
use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionRepository; use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionRepository;
use OCP\AppFramework\Controller; use OCP\AppFramework\Controller;
@ -54,23 +55,16 @@ class EpisodeActionController extends Controller {
* @return JSONResponse * @return JSONResponse
*/ */
public function list(int $since): 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([ return new JSONResponse([
"actions" => $this->episodeActionRepository->findAll($sinceDatetime, $this->userId), "actions" => $untypedEpisodeActionData,
"timestamp" => time() "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'));
}
} }

View File

@ -99,5 +99,21 @@ class EpisodeAction {
return $this->id; 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(),
];
}
} }

View File

@ -17,14 +17,14 @@ class EpisodeActionMapper extends \OCP\AppFramework\Db\QBMapper
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(int $sinceTimestamp, string $userId): array
{ {
$qb = $this->db->getQueryBuilder(); $qb = $this->db->getQueryBuilder();
$qb->select('*') $qb->select('*')
->from($this->getTableName()) ->from($this->getTableName())
->where( ->where(
$qb->expr()->gt('timestamp', $qb->createNamedParameter($sinceTimestamp, IQueryBuilder::PARAM_DATE)) $qb->expr()->gt('timestamp_epoch', $qb->createNamedParameter($sinceTimestamp, IQueryBuilder::PARAM_INT))
) )
->andWhere( ->andWhere(
$qb->expr()->eq('user_id', $qb->createNamedParameter($userId)) $qb->expr()->eq('user_id', $qb->createNamedParameter($userId))

View File

@ -15,9 +15,16 @@ class EpisodeActionRepository {
$this->episodeActionMapper = $episodeActionMapper; $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 = []; $episodeActions = [];
foreach ($this->episodeActionMapper->findAll($sinceTimestamp, $userId) as $entity) { foreach ($this->episodeActionMapper->findAll($sinceEpoch, $userId) as $entity) {
$episodeActions[] = $this->mapEntityToEpisodeAction($entity); $episodeActions[] = $this->mapEntityToEpisodeAction($entity);
} }
return $episodeActions; return $episodeActions;

View File

@ -0,0 +1,94 @@
<?php
declare(strict_types=1);
namespace tests\Integration\Controller;
use OC\AppFramework\Http\Request;
use OC\Security\SecureRandom;
use OCA\GPodderSync\Controller\EpisodeActionController;
use OCA\GPodderSync\Core\EpisodeAction\EpisodeActionSaver;
use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionEntity;
use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionRepository;
use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionWriter;
use OCP\AppFramework\App;
use OCP\AppFramework\IAppContainer;
use OCP\IConfig;
use tests\Helper\DatabaseTransaction;
/**
* @group DB
*/
class EpisodeActionControllerTest extends \Test\TestCase
{
use DatabaseTransaction;
const TEST_GUID = "test_guid_123q45345";
private IAppContainer $container;
public function setUp(): void {
parent::setUp();
$app = new App('gpoddersync');
$this->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();
}
}

View File

@ -7,11 +7,8 @@ use Doctrine\DBAL\Platforms\PostgreSQL100Platform;
use OC\AllConfig; use OC\AllConfig;
use OC\Log; use OC\Log;
use OC\Migration\SimpleOutput; use OC\Migration\SimpleOutput;
use OC\OCS\Exception;
use OC\OCS\Result;
use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionEntity; use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionEntity;
use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionMapper; use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionMapper;
use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionRepository;
use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionWriter; use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionWriter;
use OCA\GPodderSync\Migration\TimestampMigration; use OCA\GPodderSync\Migration\TimestampMigration;
use OCP\AppFramework\App; use OCP\AppFramework\App;
@ -36,15 +33,14 @@ class TimestampMigrationTest extends TestCase
private IDBConnection $dbConnection; private IDBConnection $dbConnection;
private IConfig $migrationConfig; private IConfig $migrationConfig;
public function setUp(): void { public function setUp(): void {
parent::setUp(); parent::setUp();
$app = new App('gpoddersync'); $app = new App('gpoddersync');
$this->container = $app->getContainer(); $container = $app->getContainer();
$this->episodeActionWriter = $this->container->get(EpisodeActionWriter::class); $this->episodeActionWriter = $container->get(EpisodeActionWriter::class);
$this->episodeActionMapper = $this->container->get(EpisodeActionMapper::class); $this->episodeActionMapper = $container->get(EpisodeActionMapper::class);
$this->dbConnection = $this->container->get(IDBConnection::class); $this->dbConnection = $container->get(IDBConnection::class);
$this->migrationConfig = $this->container->get(AllConfig::class ); $this->migrationConfig = $container->get(AllConfig::class );
} }
/** /**