Skip to content

Commit

Permalink
Merge pull request #503 from leepeuker/remove-watch-date-requirement-…
Browse files Browse the repository at this point in the history
…for-plays

Remove requirement of watch date for plays
  • Loading branch information
leepeuker authored Sep 11, 2023
2 parents 470afab + bed7425 commit 1a11e98
Show file tree
Hide file tree
Showing 20 changed files with 397 additions and 250 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php
declare(strict_types=1);

use Phinx\Migration\AbstractMigration;

final class SetWatchDateNullableForUsers extends AbstractMigration
{
public function down() : void
{
$this->execute(
<<<SQL
ALTER TABLE movie_user_watch_dates ADD PRIMARY KEY (movie_id, user_id, watched_at);
ALTER TABLE movie_user_watch_dates DROP CONSTRAINT unique_watched_dates;
ALTER TABLE movie_user_watch_dates MODIFY COLUMN watched_at DATE NOT NULL ;
SQL,
);
}

public function up() : void
{
$this->execute(
<<<SQL
ALTER TABLE movie_user_watch_dates ADD CONSTRAINT unique_watched_dates UNIQUE (movie_id, user_id, watched_at);
ALTER TABLE movie_user_watch_dates DROP PRIMARY KEY;
ALTER TABLE movie_user_watch_dates MODIFY COLUMN watched_at DATE NULL;
SQL,
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php declare(strict_types=1);

use Phinx\Migration\AbstractMigration;

final class SetWatchDateNullableForUsers extends AbstractMigration
{
public function down() : void
{
$this->execute(
<<<SQL
CREATE TABLE `movie_user_watch_dates_tmp` (
`movie_id` INTEGER NOT NULL,
`user_id` INTEGER NOT NULL,
`watched_at` TEXT NOT NULL,
`plays` INTEGER DEFAULT 1,
`comment` TEXT DEFAULT NULL,
FOREIGN KEY (`user_id`) REFERENCES user (`id`) ON DELETE CASCADE,
FOREIGN KEY (`movie_id`) REFERENCES movie (`id`) ON DELETE CASCADE
)
SQL,
);
$this->execute(
'INSERT INTO `movie_user_watch_dates_tmp` (movie_id, user_id, watched_at, plays, comment)
SELECT movie_id, user_id, watched_at, plays, comment FROM movie_user_watch_dates',
);
$this->execute('DROP TABLE `movie_user_watch_dates`');
$this->execute('ALTER TABLE `movie_user_watch_dates_tmp` RENAME TO `movie_user_watch_dates`');
}

public function up() : void
{
$this->execute(
<<<SQL
CREATE TABLE `movie_user_watch_dates_tmp` (
`movie_id` INTEGER NOT NULL,
`user_id` INTEGER NOT NULL,
`watched_at` TEXT,
`plays` INTEGER DEFAULT 1,
`comment` TEXT DEFAULT NULL,
UNIQUE(`movie_id`, `user_id`, `watched_at`),
FOREIGN KEY (`user_id`) REFERENCES user (`id`) ON DELETE CASCADE,
FOREIGN KEY (`movie_id`) REFERENCES movie (`id`) ON DELETE CASCADE
)
SQL,
);
$this->execute(
'INSERT INTO `movie_user_watch_dates_tmp` (movie_id, user_id, watched_at, plays, comment)
SELECT * FROM movie_user_watch_dates',
);
$this->execute('DROP TABLE `movie_user_watch_dates`');
$this->execute('ALTER TABLE `movie_user_watch_dates_tmp` RENAME TO `movie_user_watch_dates`');
}
}
3 changes: 2 additions & 1 deletion public/css/bootstrap-icons-1.10.2.css
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ url("../fonts/bootstrap-icons.woff?24e3eb84d0bcaf83d77f904c78ac1f47") format("wo
.bi-trash-fill::before { content: "\f5dd"; }
.bi-three-dots-vertical::before { content: "\f5d3"; }
.bi-x-circle-fill::before { content: "\f622"; }
.bi-x-lg::before { content: "\f659"; }
.bi-chevron-expand::before { content: "\f283"; }
.bi-chevron-contract::before { content: "\f27d"; }
.bi-question-lg::before { content: "\f64e"; }
.bi-filter::before{content:"\f3ca"}
.bi-filter::before{content:"\f3ca"}
8 changes: 0 additions & 8 deletions public/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -366,14 +366,6 @@ async function showLogPlayModalWithSpecificMovie(tmdbId, movieTitle, releaseYear
* Watch date logic starting here
*/
function validateWatchDate(context, watchDate) {
if (!watchDate) {
document.getElementById(context + 'WatchDateInput').style.borderStyle = 'solid'
document.getElementById(context + 'WatchDateInput').style.borderColor = '#dc3545'
document.getElementById(context + 'RatingStars').style.marginTop = '0'

return false
}

if (isValidDate(watchDate) === false) {
document.getElementById(context + 'WatchDateInput').style.borderStyle = 'solid'
document.getElementById(context + 'WatchDateInput').style.borderColor = '#dc3545'
Expand Down
2 changes: 1 addition & 1 deletion src/Command/JellyfinExport.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ protected function execute(InputInterface $input, OutputInterface $output) : int

$this->jellyfinMoviesExporter->exportMoviesWatchStateToJellyfin(
$userId,
$this->movieHistoryApi->fetchMovieIdsWithWatchHistoryByUserId($userId), false,
$this->movieHistoryApi->fetchMovieIdsWithWatchDatesByUserId($userId), false,
);
} catch (Throwable $t) {
$this->generateOutput($output, 'ERROR: Could not complete Jellyfin export.');
Expand Down
63 changes: 36 additions & 27 deletions src/Domain/Movie/History/MovieHistoryApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public function __construct(
) {
}

public function create(int $movieId, int $userId, Date $watchedAt, int $plays, ?string $comment = null) : void
public function create(int $movieId, int $userId, ?Date $watchedAt, int $plays, ?string $comment = null) : void
{
$this->repository->create($movieId, $userId, $watchedAt, $plays, $comment);

Expand All @@ -45,7 +45,7 @@ public function deleteByUserId(int $userId) : void
$this->repository->deleteByUserId($userId);
}

public function deleteHistoryByIdAndDate(int $movieId, int $userId, Date $watchedAt) : void
public function deleteHistoryByIdAndDate(int $movieId, int $userId, ?Date $watchedAt) : void
{
$this->repository->deleteHistoryByIdAndDate($movieId, $userId, $watchedAt);

Expand Down Expand Up @@ -164,11 +164,6 @@ public function fetchHistoryCount(int $userId, ?string $searchTerm = null) : int
return $this->movieRepository->fetchHistoryCount($userId, $searchTerm);
}

public function fetchHistoryOrderedByWatchedAtDesc(int $userId) : array
{
return $this->movieRepository->fetchHistoryOrderedByWatchedAtDesc($userId);
}

public function fetchHistoryPaginated(int $userId, int $limit, int $page, ?string $searchTerm = null) : array
{
$historyEntries = $this->movieRepository->fetchHistoryPaginated($userId, $limit, $page, $searchTerm);
Expand Down Expand Up @@ -226,6 +221,11 @@ public function fetchMostWatchedReleaseYears(int $userId) : array
return $this->movieRepository->fetchMostWatchedReleaseYears($userId);
}

public function fetchMovieIdsWithWatchDatesByUserId(int $userId) : array
{
return $this->movieRepository->fetchMovieIdsWithWatchDatesByUserId($userId);
}

public function fetchTmdbIdsToLastWatchDatesMap(int $userId, array $tmdbIds) : array
{
$map = [];
Expand All @@ -237,20 +237,14 @@ public function fetchTmdbIdsToLastWatchDatesMap(int $userId, array $tmdbIds) : a
return $map;
}

public function fetchTmdbIdsWithWatchHistoryByUserIdAndMovieIds(int $userId, array $movieIds) : array
public function fetchTmdbIdsWithWatchDatesByUserIdAndMovieIds(int $userId, array $movieIds) : array
{
return $this->movieRepository->fetchTmdbIdsWithWatchHistoryByUserIdAndMovieIds($userId, $movieIds);
return $this->movieRepository->fetchTmdbIdsWithWatchDatesByUserIdAndMovieIds($userId, $movieIds);
}


public function fetchMovieIdsWithWatchHistoryByUserId(int $userId) : array
public function fetchTmdbIdsWithoutWatchDateByUserId(int $userId, array $movieIds) : array
{
return $this->movieRepository->fetchMovieIdsWithWatchHistoryByUserId($userId);
}

public function fetchTmdbIdsWithoutWatchHistoryByUserId(int $userId, array $movieIds) : array
{
return $this->movieRepository->fetchTmdbIdsWithoutWatchHistoryByUserId($userId, $movieIds);
return $this->movieRepository->fetchTmdbIdsWithoutWatchDateByUserId($userId, $movieIds);
}

public function fetchTotalHoursWatched(int $userId) : int
Expand All @@ -260,6 +254,16 @@ public function fetchTotalHoursWatched(int $userId) : int
return (int)round($minutes / 60);
}

public function fetchTotalPlayCount(int $userId) : int
{
return $this->movieRepository->fetchTotalPlayCount($userId);
}

public function fetchTotalPlayCountUnique(int $userId) : int
{
return $this->movieRepository->fetchTotalPlayCountUnique($userId);
}

public function fetchTotalPlaysForMovieAndUserId(int $movieId, int $userId) : int
{
return $this->movieRepository->fetchTotalPlaysForMovieAndUserId($movieId, $userId);
Expand Down Expand Up @@ -308,11 +312,6 @@ public function fetchUniqueMovieGenres(int $userId) : array
return $this->movieRepository->fetchUniqueMovieGenres($userId);
}

public function fetchUniqueMovieInHistoryCount(int $userId, ?string $searchTerm = null, ?Year $releaseYear = null, ?string $language = null, ?string $genre = null) : int
{
return $this->movieRepository->fetchUniqueMovieInHistoryCount($userId, $searchTerm, $releaseYear, $language, $genre);
}

public function fetchUniqueMovieLanguages(int $userId) : array
{
$uniqueLanguages = [];
Expand All @@ -337,7 +336,12 @@ public function fetchUniqueMovieReleaseYears(int $userId) : array
return $this->movieRepository->fetchUniqueMovieReleaseYears($userId);
}

public function fetchUniqueMoviesPaginated(
public function fetchUniqueWatchedMoviesCount(int $userId, ?string $searchTerm = null, ?Year $releaseYear = null, ?string $language = null, ?string $genre = null) : int
{
return $this->movieRepository->fetchUniqueWatchedMoviesCount($userId, $searchTerm, $releaseYear, $language, $genre);
}

public function fetchUniqueWatchedMoviesPaginated(
int $userId,
int $limit,
int $page,
Expand All @@ -352,7 +356,7 @@ public function fetchUniqueMoviesPaginated(
$sortOrder = SortOrder::createAsc();
}

$movies = $this->movieRepository->fetchUniqueMoviesPaginated(
$movies = $this->movieRepository->fetchUniqueWatchedMoviesPaginated(
$userId,
$limit,
$page,
Expand All @@ -367,17 +371,22 @@ public function fetchUniqueMoviesPaginated(
return $this->urlGenerator->replacePosterPathWithImageSrcUrl($movies);
}

public function findHistoryEntryForMovieByUserOnDate(int $movieId, int $userId, Date $watchedAt) : ?MovieHistoryEntity
public function fetchWatchDatesOrderedByWatchedAtDesc(int $userId) : array
{
return $this->movieRepository->fetchWatchDatesOrderedByWatchedAtDesc($userId);
}

public function findHistoryEntryForMovieByUserOnDate(int $movieId, int $userId, ?Date $watchedAt) : ?MovieHistoryEntity
{
return $this->movieRepository->findHistoryEntryForMovieByUserOnDate($movieId, $userId, $watchedAt);
}

public function update(int $movieId, int $userId, Date $watchedAt, int $plays, ?string $comment = null) : void
public function update(int $movieId, int $userId, ?Date $watchedAt, int $plays, ?string $comment = null) : void
{
$this->repository->update($movieId, $userId, $watchedAt, $plays, $comment);
}

public function updateHistoryComment(int $movieId, int $userId, Date $watchAt, ?string $comment) : void
public function updateHistoryComment(int $movieId, int $userId, ?Date $watchAt, ?string $comment) : void
{
$this->repository->updateHistoryComment($movieId, $userId, $watchAt, $comment);
}
Expand Down
6 changes: 3 additions & 3 deletions src/Domain/Movie/History/MovieHistoryEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class MovieHistoryEntity
{
private function __construct(
private readonly int $movieId,
private readonly Date $watchedAt,
private readonly ?Date $watchedAt,
private readonly int $plays,
private readonly ?string $comment,
) {
Expand All @@ -18,7 +18,7 @@ public static function createFromArray(array $data) : self
{
return new self(
(int)$data['movie_id'],
Date::createFromString($data['watched_at']),
$data['watched_at'] == null ? null : Date::createFromString($data['watched_at']),
$data['plays'],
$data['comment'],
);
Expand All @@ -39,7 +39,7 @@ public function getPlays() : int
return $this->plays;
}

public function getWatchedAt() : Date
public function getWatchedAt() : ?Date
{
return $this->watchedAt;
}
Expand Down
48 changes: 43 additions & 5 deletions src/Domain/Movie/History/MovieHistoryRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ public function __construct(private readonly Connection $dbConnection)
{
}

public function create(int $movieId, int $userId, Date $watchedAt, int $plays, ?string $comment) : void
public function create(int $movieId, int $userId, ?Date $watchedAt, int $plays, ?string $comment) : void
{
$this->dbConnection->executeStatement(
'INSERT INTO movie_user_watch_dates (movie_id, user_id, watched_at, plays, `comment`) VALUES (?, ?, ?, ?, ?)',
[
$movieId,
$userId,
(string)$watchedAt,
$watchedAt !== null ? (string)$watchedAt : null,
(string)$plays,
$comment,
],
Expand All @@ -38,8 +38,19 @@ public function deleteByUserId(int $userId) : void
$this->dbConnection->delete('movie_user_watch_dates', ['user_id' => $userId]);
}

public function deleteHistoryByIdAndDate(int $movieId, int $userId, Date $watchedAt) : void
public function deleteHistoryByIdAndDate(int $movieId, int $userId, ?Date $watchedAt) : void
{
if ($watchedAt === null) {
$this->dbConnection->executeStatement(
'DELETE
FROM movie_user_watch_dates
WHERE movie_id = ? AND watched_at IS NULL AND user_id = ?',
[$movieId, $userId],
);

return;
}

$this->dbConnection->executeStatement(
'DELETE
FROM movie_user_watch_dates
Expand All @@ -48,8 +59,22 @@ public function deleteHistoryByIdAndDate(int $movieId, int $userId, Date $watche
);
}

public function update(int $movieId, int $userId, Date $watchedAt, int $plays, ?string $comment) : void
public function update(int $movieId, int $userId, ?Date $watchedAt, int $plays, ?string $comment) : void
{
if ($watchedAt === null) {
$this->dbConnection->executeStatement(
'UPDATE movie_user_watch_dates SET `comment` = ?, `plays` = ? WHERE movie_id = ? AND user_id = ? AND watched_at IS NULL',
[
$comment,
$plays,
$movieId,
$userId,
],
);

return;
}

$this->dbConnection->executeStatement(
'UPDATE movie_user_watch_dates SET `comment` = ?, `plays` = ? WHERE movie_id = ? AND user_id = ? AND watched_at = ?',
[
Expand All @@ -62,8 +87,21 @@ public function update(int $movieId, int $userId, Date $watchedAt, int $plays, ?
);
}

public function updateHistoryComment(int $movieId, int $userId, Date $watchedAt, ?string $comment) : void
public function updateHistoryComment(int $movieId, int $userId, ?Date $watchedAt, ?string $comment) : void
{
if ($watchedAt === null) {
$this->dbConnection->executeStatement(
'UPDATE movie_user_watch_dates SET `comment` = ? WHERE movie_id = ? AND user_id = ? AND watched_at IS NULL ',
[
$comment,
$movieId,
$userId,
],
);

return;
}

$this->dbConnection->executeStatement(
'UPDATE movie_user_watch_dates SET `comment` = ? WHERE movie_id = ? AND user_id = ? AND watched_at = ?',
[
Expand Down
Loading

0 comments on commit 1a11e98

Please sign in to comment.