diff --git a/modules/bookmarks/lib/Module/Bookmarks/BookmarksContainerRegistrar.php b/modules/bookmarks/lib/Module/Bookmarks/BookmarksContainerRegistrar.php index b7617e4..c9c9f48 100644 --- a/modules/bookmarks/lib/Module/Bookmarks/BookmarksContainerRegistrar.php +++ b/modules/bookmarks/lib/Module/Bookmarks/BookmarksContainerRegistrar.php @@ -4,18 +4,23 @@ namespace MintyPHP\Module\Bookmarks; use MintyPHP\App\AppContainer; use MintyPHP\App\Container\ContainerRegistrar; -use MintyPHP\Module\Bookmarks\Service\BookmarkRepositoryFactory; +use MintyPHP\Module\Bookmarks\Repository\BookmarkGroupRepository; +use MintyPHP\Module\Bookmarks\Repository\BookmarkNavigationRepository; +use MintyPHP\Module\Bookmarks\Repository\BookmarkRepository; use MintyPHP\Module\Bookmarks\Service\BookmarkService; -use MintyPHP\Module\Bookmarks\Service\BookmarkServicesFactory; final class BookmarksContainerRegistrar implements ContainerRegistrar { public function register(AppContainer $container): void { - $container->set(BookmarkRepositoryFactory::class, static fn (): BookmarkRepositoryFactory => new BookmarkRepositoryFactory()); - $container->set(BookmarkServicesFactory::class, static fn (AppContainer $c): BookmarkServicesFactory => new BookmarkServicesFactory( - $c->get(BookmarkRepositoryFactory::class) + $container->set(BookmarkRepository::class, static fn (): BookmarkRepository => new BookmarkRepository()); + $container->set(BookmarkGroupRepository::class, static fn (): BookmarkGroupRepository => new BookmarkGroupRepository()); + $container->set(BookmarkNavigationRepository::class, static fn (): BookmarkNavigationRepository => new BookmarkNavigationRepository()); + + $container->set(BookmarkService::class, static fn (AppContainer $c): BookmarkService => new BookmarkService( + $c->get(BookmarkRepository::class), + $c->get(BookmarkGroupRepository::class), + $c->get(BookmarkNavigationRepository::class) )); - $container->set(BookmarkService::class, static fn (AppContainer $c): BookmarkService => $c->get(BookmarkServicesFactory::class)->createBookmarkService()); } } diff --git a/modules/bookmarks/lib/Module/Bookmarks/Repository/BookmarkGroupRepository.php b/modules/bookmarks/lib/Module/Bookmarks/Repository/BookmarkGroupRepository.php index b8909bb..0d6789c 100644 --- a/modules/bookmarks/lib/Module/Bookmarks/Repository/BookmarkGroupRepository.php +++ b/modules/bookmarks/lib/Module/Bookmarks/Repository/BookmarkGroupRepository.php @@ -6,8 +6,15 @@ use MintyPHP\DB; use MintyPHP\Repository\Support\RepoQuery; use MintyPHP\Repository\Support\RepositoryArrayHelper; -class BookmarkGroupRepository implements BookmarkGroupRepositoryInterface +class BookmarkGroupRepository { + use SortOrderTrait; + + protected function sortOrderTableName(): string + { + return 'user_bookmark_groups'; + } + private function unwrapList(mixed $rows): array { return RepositoryArrayHelper::unwrapList($rows, 'user_bookmark_groups'); @@ -125,66 +132,4 @@ class BookmarkGroupRepository implements BookmarkGroupRepositoryInterface return $deleted !== false && (int) $deleted > 0; } - public function updateSortOrders(int $userId, array $idOrderPairs): bool - { - if ($userId <= 0 || $idOrderPairs === []) { - return false; - } - - $idList = []; - foreach ($idOrderPairs as $pair) { - $id = (int) $pair['id']; - if ($id <= 0) { - return false; - } - $idList[] = $id; - } - $idList = array_values(array_unique($idList)); - - $existingCount = DB::selectValue( - 'select count(*) from user_bookmark_groups where user_id = ? and id in (???)', - (string) $userId, - array_map('strval', $idList) - ); - - if ((int) $existingCount !== count($idList)) { - return false; - } - - $db = DB::handle(); - try { - $db->begin_transaction(); - - foreach ($idOrderPairs as $pair) { - $id = (int) $pair['id']; - $sortOrder = (int) $pair['sort_order']; - if ($id <= 0 || $sortOrder <= 0) { - $db->rollback(); - return false; - } - - $updated = DB::update( - 'update user_bookmark_groups set sort_order = ? where id = ? and user_id = ?', - (string) $sortOrder, - (string) $id, - (string) $userId - ); - - if ($updated === false) { - $db->rollback(); - return false; - } - } - - $db->commit(); - return true; - } catch (\Throwable) { - try { - $db->rollback(); - } catch (\Throwable) { - // no-op - } - return false; - } - } } diff --git a/modules/bookmarks/lib/Module/Bookmarks/Repository/BookmarkGroupRepositoryInterface.php b/modules/bookmarks/lib/Module/Bookmarks/Repository/BookmarkGroupRepositoryInterface.php deleted file mode 100644 index 0517aff..0000000 --- a/modules/bookmarks/lib/Module/Bookmarks/Repository/BookmarkGroupRepositoryInterface.php +++ /dev/null @@ -1,26 +0,0 @@ -> - */ - public function listByUser(int $userId, array $options = []): array; - - public function countByUser(int $userId): int; - - /** @return array|false */ - public function findById(int $id, int $userId): array|false; - - public function create(array $data): int|false; - - public function update(int $id, int $userId, array $data): bool; - - public function delete(int $id, int $userId): bool; - - /** @param list $idOrderPairs */ - public function updateSortOrders(int $userId, array $idOrderPairs): bool; -} diff --git a/modules/bookmarks/lib/Module/Bookmarks/Repository/BookmarkNavigationRepository.php b/modules/bookmarks/lib/Module/Bookmarks/Repository/BookmarkNavigationRepository.php index c067e0c..b8a2d27 100644 --- a/modules/bookmarks/lib/Module/Bookmarks/Repository/BookmarkNavigationRepository.php +++ b/modules/bookmarks/lib/Module/Bookmarks/Repository/BookmarkNavigationRepository.php @@ -4,7 +4,7 @@ namespace MintyPHP\Module\Bookmarks\Repository; use MintyPHP\DB; -class BookmarkNavigationRepository implements BookmarkNavigationRepositoryInterface +class BookmarkNavigationRepository { public function nextRootSortOrder(int $userId): int { diff --git a/modules/bookmarks/lib/Module/Bookmarks/Repository/BookmarkNavigationRepositoryInterface.php b/modules/bookmarks/lib/Module/Bookmarks/Repository/BookmarkNavigationRepositoryInterface.php deleted file mode 100644 index 990318d..0000000 --- a/modules/bookmarks/lib/Module/Bookmarks/Repository/BookmarkNavigationRepositoryInterface.php +++ /dev/null @@ -1,11 +0,0 @@ - $rootOrderPairs */ - public function updateRootSortOrders(int $userId, array $rootOrderPairs): bool; -} diff --git a/modules/bookmarks/lib/Module/Bookmarks/Repository/BookmarkRepository.php b/modules/bookmarks/lib/Module/Bookmarks/Repository/BookmarkRepository.php index 85e266d..06813c3 100644 --- a/modules/bookmarks/lib/Module/Bookmarks/Repository/BookmarkRepository.php +++ b/modules/bookmarks/lib/Module/Bookmarks/Repository/BookmarkRepository.php @@ -6,8 +6,15 @@ use MintyPHP\DB; use MintyPHP\Repository\Support\RepoQuery; use MintyPHP\Repository\Support\RepositoryArrayHelper; -class BookmarkRepository implements BookmarkRepositoryInterface +class BookmarkRepository { + use SortOrderTrait; + + protected function sortOrderTableName(): string + { + return 'user_bookmarks'; + } + private function unwrapList(mixed $rows): array { return RepositoryArrayHelper::unwrapList($rows, 'user_bookmarks'); @@ -182,68 +189,6 @@ class BookmarkRepository implements BookmarkRepositoryInterface return $deleted !== false && (int) $deleted > 0; } - public function updateSortOrders(int $userId, array $idOrderPairs): bool - { - if ($userId <= 0 || $idOrderPairs === []) { - return false; - } - - $idList = []; - foreach ($idOrderPairs as $pair) { - $id = (int) $pair['id']; - if ($id <= 0) { - return false; - } - $idList[] = $id; - } - $idList = array_values(array_unique($idList)); - - $existingCount = DB::selectValue( - 'select count(*) from user_bookmarks where user_id = ? and id in (???)', - (string) $userId, - array_map('strval', $idList) - ); - - if ((int) $existingCount !== count($idList)) { - return false; - } - - $db = DB::handle(); - try { - $db->begin_transaction(); - - foreach ($idOrderPairs as $pair) { - $id = (int) $pair['id']; - $sortOrder = (int) $pair['sort_order']; - if ($id <= 0 || $sortOrder <= 0) { - $db->rollback(); - return false; - } - - $updated = DB::update( - 'update user_bookmarks set sort_order = ? where id = ? and user_id = ?', - (string) $sortOrder, - (string) $id, - (string) $userId - ); - if ($updated === false) { - $db->rollback(); - return false; - } - } - - $db->commit(); - return true; - } catch (\Throwable) { - try { - $db->rollback(); - } catch (\Throwable) { - // no-op - } - return false; - } - } - /** @return list> */ public function listByGroup(int $userId, int $groupId): array { diff --git a/modules/bookmarks/lib/Module/Bookmarks/Repository/BookmarkRepositoryInterface.php b/modules/bookmarks/lib/Module/Bookmarks/Repository/BookmarkRepositoryInterface.php deleted file mode 100644 index 1f3d7d0..0000000 --- a/modules/bookmarks/lib/Module/Bookmarks/Repository/BookmarkRepositoryInterface.php +++ /dev/null @@ -1,36 +0,0 @@ -> - */ - public function listByUser(int $userId, array $options = []): array; - - public function nextBookmarkSortOrder(int $userId, ?int $groupId): int; - - public function countByUser(int $userId): int; - - /** @return array|false */ - public function findById(int $id, int $userId): array|false; - - /** @return array|false */ - public function findByUserAndUrl(int $userId, string $url): array|false; - - public function create(array $data): int|false; - - public function update(int $id, int $userId, array $data): bool; - - public function delete(int $id, int $userId): bool; - - /** @param list $idOrderPairs */ - public function updateSortOrders(int $userId, array $idOrderPairs): bool; - - /** @return list> */ - public function listByGroup(int $userId, int $groupId): array; - - public function unsetGroupId(int $bookmarkId, int $userId, int $sortOrder): bool; -} diff --git a/modules/bookmarks/lib/Module/Bookmarks/Repository/SortOrderTrait.php b/modules/bookmarks/lib/Module/Bookmarks/Repository/SortOrderTrait.php new file mode 100644 index 0000000..fa2da62 --- /dev/null +++ b/modules/bookmarks/lib/Module/Bookmarks/Repository/SortOrderTrait.php @@ -0,0 +1,75 @@ + $idOrderPairs */ + public function updateSortOrders(int $userId, array $idOrderPairs): bool + { + if ($userId <= 0 || $idOrderPairs === []) { + return false; + } + + $idList = []; + foreach ($idOrderPairs as $pair) { + $id = (int) $pair['id']; + if ($id <= 0) { + return false; + } + $idList[] = $id; + } + $idList = array_values(array_unique($idList)); + + $table = $this->sortOrderTableName(); + + $existingCount = DB::selectValue( + 'select count(*) from ' . $table . ' where user_id = ? and id in (???)', + (string) $userId, + array_map('strval', $idList) + ); + + if ((int) $existingCount !== count($idList)) { + return false; + } + + $db = DB::handle(); + try { + $db->begin_transaction(); + + foreach ($idOrderPairs as $pair) { + $id = (int) $pair['id']; + $sortOrder = (int) $pair['sort_order']; + if ($id <= 0 || $sortOrder <= 0) { + $db->rollback(); + return false; + } + + $updated = DB::update( + 'update ' . $table . ' set sort_order = ? where id = ? and user_id = ?', + (string) $sortOrder, + (string) $id, + (string) $userId + ); + if ($updated === false) { + $db->rollback(); + return false; + } + } + + $db->commit(); + return true; + } catch (\Throwable) { + try { + $db->rollback(); + } catch (\Throwable) { + // no-op + } + return false; + } + } +} diff --git a/modules/bookmarks/lib/Module/Bookmarks/Service/BookmarkRepositoryFactory.php b/modules/bookmarks/lib/Module/Bookmarks/Service/BookmarkRepositoryFactory.php deleted file mode 100644 index b83e39c..0000000 --- a/modules/bookmarks/lib/Module/Bookmarks/Service/BookmarkRepositoryFactory.php +++ /dev/null @@ -1,32 +0,0 @@ -bookmarkRepository ??= new BookmarkRepository(); - } - - public function createBookmarkGroupRepository(): BookmarkGroupRepositoryInterface - { - return $this->groupRepository ??= new BookmarkGroupRepository(); - } - - public function createBookmarkNavigationRepository(): BookmarkNavigationRepositoryInterface - { - return $this->navigationRepository ??= new BookmarkNavigationRepository(); - } -} diff --git a/modules/bookmarks/lib/Module/Bookmarks/Service/BookmarkService.php b/modules/bookmarks/lib/Module/Bookmarks/Service/BookmarkService.php index f27efc9..b29c971 100644 --- a/modules/bookmarks/lib/Module/Bookmarks/Service/BookmarkService.php +++ b/modules/bookmarks/lib/Module/Bookmarks/Service/BookmarkService.php @@ -2,9 +2,9 @@ namespace MintyPHP\Module\Bookmarks\Service; -use MintyPHP\Module\Bookmarks\Repository\BookmarkGroupRepositoryInterface; -use MintyPHP\Module\Bookmarks\Repository\BookmarkNavigationRepositoryInterface; -use MintyPHP\Module\Bookmarks\Repository\BookmarkRepositoryInterface; +use MintyPHP\Module\Bookmarks\Repository\BookmarkGroupRepository; +use MintyPHP\Module\Bookmarks\Repository\BookmarkNavigationRepository; +use MintyPHP\Module\Bookmarks\Repository\BookmarkRepository; use MintyPHP\Module\Bookmarks\Support\BookmarkUrlNormalizer; class BookmarkService @@ -23,9 +23,9 @@ class BookmarkService ]; public function __construct( - private readonly BookmarkRepositoryInterface $bookmarkRepository, - private readonly BookmarkGroupRepositoryInterface $groupRepository, - private readonly BookmarkNavigationRepositoryInterface $navigationRepository + private readonly BookmarkRepository $bookmarkRepository, + private readonly BookmarkGroupRepository $groupRepository, + private readonly BookmarkNavigationRepository $navigationRepository ) { } @@ -35,6 +35,33 @@ class BookmarkService return self::ALLOWED_GROUP_ICONS; } + /** @return array icon class => translated label */ + public static function allowedGroupIconLabels(): array + { + return [ + 'bi-house' => t('Icon: Home'), + 'bi-people' => t('Icon: People'), + 'bi-person' => t('Icon: Person'), + 'bi-folder' => t('Icon: Folder'), + 'bi-file-text' => t('Icon: Document'), + 'bi-gear' => t('Icon: Settings'), + 'bi-shield-lock' => t('Icon: Security'), + 'bi-bar-chart' => t('Icon: Chart'), + 'bi-envelope' => t('Icon: Mail'), + 'bi-calendar' => t('Icon: Calendar'), + 'bi-clock' => t('Icon: Clock'), + 'bi-star' => t('Icon: Star'), + 'bi-heart' => t('Icon: Heart'), + 'bi-flag' => t('Icon: Flag'), + 'bi-bookmark' => t('Icon: Bookmark'), + 'bi-pin-map' => t('Icon: Location'), + 'bi-lightning' => t('Icon: Lightning'), + 'bi-database' => t('Icon: Database'), + 'bi-globe' => t('Icon: Globe'), + 'bi-code-slash' => t('Icon: Code'), + ]; + } + /** * @return array{groups: list>, ungrouped: list>} */ diff --git a/modules/bookmarks/lib/Module/Bookmarks/Service/BookmarkServicesFactory.php b/modules/bookmarks/lib/Module/Bookmarks/Service/BookmarkServicesFactory.php deleted file mode 100644 index 2e93709..0000000 --- a/modules/bookmarks/lib/Module/Bookmarks/Service/BookmarkServicesFactory.php +++ /dev/null @@ -1,22 +0,0 @@ -bookmarkService ??= new BookmarkService( - $this->bookmarkRepositoryFactory->createBookmarkRepository(), - $this->bookmarkRepositoryFactory->createBookmarkGroupRepository(), - $this->bookmarkRepositoryFactory->createBookmarkNavigationRepository() - ); - } -} diff --git a/modules/bookmarks/templates/bookmark-dialogs.phtml b/modules/bookmarks/templates/bookmark-dialogs.phtml index a941db2..8fcd755 100644 --- a/modules/bookmarks/templates/bookmark-dialogs.phtml +++ b/modules/bookmarks/templates/bookmark-dialogs.phtml @@ -7,29 +7,7 @@ $bookmarkNav = is_array($layoutNav['bookmarks.nav'] ?? null) ? $layoutNav['bookm $bookmarkData = is_array($bookmarkNav['grouped'] ?? null) ? $bookmarkNav['grouped'] : []; $bookmarkGroups = is_array($bookmarkData['groups'] ?? null) ? $bookmarkData['groups'] : []; -// Human-readable icon labels — keep in sync with BookmarkService::ALLOWED_GROUP_ICONS -$iconLabels = [ - 'bi-house' => t('Icon: Home'), - 'bi-people' => t('Icon: People'), - 'bi-person' => t('Icon: Person'), - 'bi-folder' => t('Icon: Folder'), - 'bi-file-text' => t('Icon: Document'), - 'bi-gear' => t('Icon: Settings'), - 'bi-shield-lock' => t('Icon: Security'), - 'bi-bar-chart' => t('Icon: Chart'), - 'bi-envelope' => t('Icon: Mail'), - 'bi-calendar' => t('Icon: Calendar'), - 'bi-clock' => t('Icon: Clock'), - 'bi-star' => t('Icon: Star'), - 'bi-heart' => t('Icon: Heart'), - 'bi-flag' => t('Icon: Flag'), - 'bi-bookmark' => t('Icon: Bookmark'), - 'bi-pin-map' => t('Icon: Location'), - 'bi-lightning' => t('Icon: Lightning'), - 'bi-database' => t('Icon: Database'), - 'bi-globe' => t('Icon: Globe'), - 'bi-code-slash' => t('Icon: Code'), -]; +$iconLabels = BookmarkService::allowedGroupIconLabels(); ?> bookmarkRepo = $this->createMock(BookmarkRepositoryInterface::class); - $this->groupRepo = $this->createMock(BookmarkGroupRepositoryInterface::class); - $this->navigationRepo = $this->createMock(BookmarkNavigationRepositoryInterface::class); + $this->bookmarkRepo = $this->createMock(BookmarkRepository::class); + $this->groupRepo = $this->createMock(BookmarkGroupRepository::class); + $this->navigationRepo = $this->createMock(BookmarkNavigationRepository::class); $this->service = new BookmarkService($this->bookmarkRepo, $this->groupRepo, $this->navigationRepo); }