Skip to content

Commit

Permalink
fix(Kobo): Sync bookmark and progression
Browse files Browse the repository at this point in the history
  • Loading branch information
ragusa87 committed Aug 12, 2024
1 parent 83370fd commit cfba902
Show file tree
Hide file tree
Showing 7 changed files with 337 additions and 14 deletions.
35 changes: 35 additions & 0 deletions migrations/Version20240812195147.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace DoctrineMigrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20240812195147 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add bookmarks';
}

public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE TABLE bookmark_user (id INT AUTO_INCREMENT NOT NULL, user_id INT NOT NULL, book_id INT NOT NULL, percent DOUBLE PRECISION DEFAULT NULL, source_percent DOUBLE PRECISION DEFAULT NULL, location_value VARCHAR(255) DEFAULT NULL, location_type VARCHAR(255) DEFAULT NULL, location_source VARCHAR(255) DEFAULT NULL, updated DATETIME DEFAULT NULL, INDEX IDX_6F0BEE95A76ED395 (user_id), INDEX IDX_6F0BEE9516A2B381 (book_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB');
$this->addSql('ALTER TABLE bookmark_user ADD CONSTRAINT FK_6F0BEE95A76ED395 FOREIGN KEY (user_id) REFERENCES `user` (id)');
$this->addSql('ALTER TABLE bookmark_user ADD CONSTRAINT FK_6F0BEE9516A2B381 FOREIGN KEY (book_id) REFERENCES book (id)');
}

public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE bookmark_user DROP FOREIGN KEY FK_6F0BEE95A76ED395');
$this->addSql('ALTER TABLE bookmark_user DROP FOREIGN KEY FK_6F0BEE9516A2B381');
$this->addSql('DROP TABLE bookmark_user');
}
}
23 changes: 23 additions & 0 deletions src/Controller/Kobo/KoboStateController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
namespace App\Controller\Kobo;

use App\Entity\Book;
use App\Entity\BookmarkUser;
use App\Entity\KoboDevice;
use App\Kobo\Proxy\KoboStoreProxy;
use App\Kobo\Request\Bookmark;
use App\Kobo\Request\ReadingStates;
use App\Kobo\Request\ReadingStateStatusInfo;
use App\Kobo\Response\StateResponse;
Expand Down Expand Up @@ -72,6 +74,9 @@ public function state(KoboDevice $kobo, string $uuid, Request $request): Respons
case null:
break;
}

$this->handleBookmark($kobo, $book, $state->currentBookmark);

$this->em->flush();

return new StateResponse($book);
Expand All @@ -88,4 +93,22 @@ public function getState(KoboDevice $kobo, string $uuid, Request $request): Resp
}
throw new HttpException(200, 'Not implemented');
}

private function handleBookmark(KoboDevice $kobo, Book $book, ?Bookmark $currentBookmark): void
{
if (!$currentBookmark instanceof Bookmark) {
$kobo->getUser()->removeBookmarkForBook($book);

return;
}

$bookmark = $kobo->getUser()->getBookmarkForBook($book) ?? new BookmarkUser($book, $kobo->getUser());
$this->em->persist($bookmark);

$bookmark->setPercent($currentBookmark->progressPercent === null ? null : $currentBookmark->progressPercent / 100);
$bookmark->setLocationType($currentBookmark->location?->type);
$bookmark->setLocationSource($currentBookmark->location?->source);
$bookmark->setLocationValue($currentBookmark->location?->value);
$bookmark->setSourcePercent($currentBookmark->contentSourceProgressPercent === null ? null : $currentBookmark->contentSourceProgressPercent / 100);
}
}
25 changes: 24 additions & 1 deletion src/Entity/Book.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,11 @@ class Book
#[ORM\OneToMany(mappedBy: 'book', targetEntity: BookInteraction::class, cascade: ['remove'], orphanRemoval: true)]
#[ORM\OrderBy(['updated' => 'ASC'])]
private Collection $bookInteractions;

/**
* @var Collection<int, BookmarkUser>
*/
#[ORM\OneToMany(mappedBy: 'book', targetEntity: BookmarkUser::class, orphanRemoval: true)]
private Collection $bookmarkUsers;
/**
* @var array<string>|null
*/
Expand Down Expand Up @@ -120,6 +124,7 @@ public function __construct()
$this->shelves = new ArrayCollection();
$this->uuid = $this->generateUuid();
$this->koboSyncedBooks = new ArrayCollection();
$this->bookmarkUsers = new ArrayCollection();
}

public function getId(): ?int
Expand Down Expand Up @@ -566,4 +571,22 @@ public function setUuid(?string $uuid): self

return $this;
}

/**
* @return Collection<int, BookmarkUser>
*/
public function getBookmarkUsers(): Collection
{
return $this->bookmarkUsers;
}

/**
* @param Collection<int, BookmarkUser> $bookmarkUsers
*/
public function setBookmarkUsers(Collection $bookmarkUsers): self
{
$this->bookmarkUsers = $bookmarkUsers;

return $this;
}
}
154 changes: 154 additions & 0 deletions src/Entity/BookmarkUser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
<?php

namespace App\Entity;

use App\Repository\BookmarkUserRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;

#[ORM\Entity(repositoryClass: BookmarkUserRepository::class)]
class BookmarkUser
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;

#[ORM\Column(nullable: true)]
private ?float $percent = null;

#[ORM\Column(nullable: true)]
private ?float $sourcePercent = null;

#[ORM\Column(length: 255, nullable: true)]
private ?string $locationValue = null;

#[ORM\Column(length: 255, nullable: true)]
private ?string $locationType = null;

#[ORM\Column(length: 255, nullable: true)]
private ?string $locationSource = null;

#[ORM\ManyToOne(inversedBy: 'bookmarkUsers')]
#[ORM\JoinColumn(nullable: false)]
private ?User $user;

#[ORM\ManyToOne(inversedBy: 'bookmarkUsers')]
#[ORM\JoinColumn(nullable: false)]
private ?Book $book;

#[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)]
#[Gedmo\Timestampable(on: 'update')]
private ?\DateTimeInterface $updated;

public function __construct(?Book $book, ?User $user)
{
$this->book = $book;
$this->user = $user;
}

public function getId(): ?int
{
return $this->id;
}

public function getPercent(): ?float
{
return $this->percent;
}

public function setPercent(?float $percent): static
{
$this->percent = $percent;

return $this;
}

public function getSourcePercent(): ?float
{
return $this->sourcePercent;
}

public function setSourcePercent(?float $sourcePercent): static
{
$this->sourcePercent = $sourcePercent;

return $this;
}

public function getLocationValue(): ?string
{
return $this->locationValue;
}

public function setLocationValue(?string $locationValue): static
{
$this->locationValue = $locationValue;

return $this;
}

public function getLocationType(): ?string
{
return $this->locationType;
}

public function setLocationType(?string $locationType): static
{
$this->locationType = $locationType;

return $this;
}

public function getLocationSource(): ?string
{
return $this->locationSource;
}

public function setLocationSource(?string $locationSource): static
{
$this->locationSource = $locationSource;

return $this;
}

public function getUser(): ?User
{
return $this->user;
}

public function setUser(?User $user): static
{
$this->user = $user;

return $this;
}

public function hasLocation(): bool
{
return $this->locationValue !== null;
}

public function setBook(?Book $book): self
{
$this->book = $book;

return $this;
}

public function getBook(): ?Book
{
return $this->book;
}

public function getUpdated(): ?\DateTimeInterface
{
return $this->updated;
}

public function setUpdated(?\DateTimeInterface $updated): void
{
$this->updated = $updated;
}
}
53 changes: 53 additions & 0 deletions src/Entity/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,18 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
#[ORM\Column]
private bool $useKoboDevices = true;

/**
* @var Collection<int, BookmarkUser>
*/
#[ORM\OneToMany(mappedBy: 'user', targetEntity: BookmarkUser::class, orphanRemoval: true)]
private Collection $bookmarkUsers;

public function __construct()
{
$this->bookInteractions = new ArrayCollection();
$this->shelves = new ArrayCollection();
$this->kobos = new ArrayCollection();
$this->bookmarkUsers = new ArrayCollection();
}

public function getId(): ?int
Expand Down Expand Up @@ -434,4 +441,50 @@ public function setUseKoboDevices(bool $useKoboDevices): static

return $this;
}

/**
* @return Collection<int, BookmarkUser>
*/
public function getBookmarkUsers(): Collection
{
return $this->bookmarkUsers;
}

public function addBookmarkUser(BookmarkUser $bookmarkUser): static
{
if (!$this->bookmarkUsers->contains($bookmarkUser)) {
$this->bookmarkUsers->add($bookmarkUser);
$bookmarkUser->setUser($this);
}

return $this;
}

public function removeBookmarkUser(BookmarkUser $bookmarkUser): static
{
// set the owning side to null (unless already changed)
if ($this->bookmarkUsers->removeElement($bookmarkUser) && $bookmarkUser->getUser() === $this) {
$bookmarkUser->setUser(null);
}

return $this;
}

public function getBookmarkForBook(Book $book): ?BookmarkUser
{
foreach ($this->bookmarkUsers as $bookmarkUser) {
if ($bookmarkUser->getBook() === $book) {
return $bookmarkUser;
}
}

return null;
}

public function removeBookmarkForBook(Book $book): self
{
$this->getBookmarkForBook($book)?->setUser(null)->setBook(null);

return $this;
}
}
Loading

0 comments on commit cfba902

Please sign in to comment.