diff --git a/module/VuFind/src/VuFind/Controller/Plugin/Favorites.php b/module/VuFind/src/VuFind/Controller/Plugin/Favorites.php index 94c08d16bb1..0992cb75fdb 100644 --- a/module/VuFind/src/VuFind/Controller/Plugin/Favorites.php +++ b/module/VuFind/src/VuFind/Controller/Plugin/Favorites.php @@ -150,16 +150,17 @@ public function saveBulk($params, $user) [$source, $id] = explode('|', $current, 2); // Get or create a resource object as needed: - $resourceTable = $this->getController()->getTable('Resource'); - $resource = $resourceTable->findResource($id, $source); + $resourceService = $this->getController()->getDbService(\VuFind\Db\Service\ResourceService::class); + $resource = $resourceService->findResource($id, $source); // Add the information to the user's account: $tags = isset($params['mytags']) ? $this->tags->parse($params['mytags']) : []; - $user->saveResource($resource, $list->getId(), $tags, '', false); + $userService = $this->getController()->getDbService(\VuFind\Db\Service\UserService::class); + $userService->saveResource($resource, $user->id, $list, $tags, '', false); // Collect record IDs for caching - if ($this->cache->isCachable($resource->source)) { + if ($this->cache->isCachable($resource->getSource())) { $cacheRecordIds[] = $current; } } diff --git a/module/VuFind/src/VuFind/Db/Entity/Ratings.php b/module/VuFind/src/VuFind/Db/Entity/Ratings.php index f078eca5f40..3687e61ce28 100644 --- a/module/VuFind/src/VuFind/Db/Entity/Ratings.php +++ b/module/VuFind/src/VuFind/Db/Entity/Ratings.php @@ -29,6 +29,7 @@ namespace VuFind\Db\Entity; +use DateTime; use Doctrine\ORM\Mapping as ORM; /** @@ -107,6 +108,16 @@ class Ratings implements EntityInterface */ protected $created = '2000-01-01 00:00:00'; + /** + * Id getter + * + * @return ?int + */ + public function getId(): ?int + { + return $this->id; + } + /** * Get user. * @@ -116,4 +127,86 @@ public function getUser() { return $this->user; } + + /** + * User setter + * + * @param User $user User + * + * @return Ratings + */ + public function setUser(User $user): Ratings + { + $this->user = $user; + return $this; + } + + /** + * Rating setter + * + * @param int $rating Rating + * + * @return Ratings + */ + public function setRating(int $rating): Ratings + { + $this->rating = $rating; + return $this; + } + + /** + * Rating getter + * + * @return int + */ + public function getRating(): int + { + return $this->rating; + } + + /** + * Resource setter + * + * @param Resource $resource Resource + * + * @return Ratings + */ + public function setResource(Resource $resource): Ratings + { + $this->resource = $resource; + return $this; + } + + /** + * Resource getter + * + * @return Resource + */ + public function getResource(): Resource + { + return $this->resource; + } + + /** + * Created setter. + * + * @param Datetime $dateTime Created date + * + * @return UserList + */ + public function setCreated(DateTime $dateTime): Ratings + { + $this->created = $dateTime; + return $this; + } + + /** + * Created getter + * + * @return Datetime + */ + public function getCreated(): Datetime + { + return $this->created; + } } diff --git a/module/VuFind/src/VuFind/Db/Entity/Resource.php b/module/VuFind/src/VuFind/Db/Entity/Resource.php index 2ee8b579a55..28fe3cdf9e2 100644 --- a/module/VuFind/src/VuFind/Db/Entity/Resource.php +++ b/module/VuFind/src/VuFind/Db/Entity/Resource.php @@ -170,6 +170,16 @@ public function setTitle(string $title): Resource return $this; } + /** + * Title getter + * + * @return string + */ + public function getTitle(): string + { + return $this->title; + } + /** * Author setter * @@ -231,4 +241,14 @@ public function setExtraMetadata(?string $extraMetadata): Resource $this->extraMetadata = $extraMetadata; return $this; } + + /** + * Extra Metadata getter + * + * @return ?string + */ + public function getExtraMetadata(): ?string + { + return $this->extraMetadata; + } } diff --git a/module/VuFind/src/VuFind/Db/Row/PluginManager.php b/module/VuFind/src/VuFind/Db/Row/PluginManager.php index 6033ad29139..95937dd9bff 100644 --- a/module/VuFind/src/VuFind/Db/Row/PluginManager.php +++ b/module/VuFind/src/VuFind/Db/Row/PluginManager.php @@ -49,7 +49,6 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager 'accesstoken' => AccessToken::class, 'externalsession' => ExternalSession::class, 'ratings' => Ratings::class, - 'resource' => Resource::class, 'search' => Search::class, 'session' => Session::class, 'user' => User::class, @@ -66,7 +65,6 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager AuthHash::class => RowGatewayFactory::class, ExternalSession::class => RowGatewayFactory::class, Ratings::class => RowGatewayFactory::class, - Resource::class => RowGatewayFactory::class, Search::class => RowGatewayFactory::class, Session::class => RowGatewayFactory::class, User::class => UserFactory::class, diff --git a/module/VuFind/src/VuFind/Db/Row/Resource.php b/module/VuFind/src/VuFind/Db/Row/Resource.php deleted file mode 100644 index 5a6f30bd713..00000000000 --- a/module/VuFind/src/VuFind/Db/Row/Resource.php +++ /dev/null @@ -1,242 +0,0 @@ - - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org Main Site - */ - -namespace VuFind\Db\Row; - -use VuFind\Date\DateException; -use VuFind\Exception\LoginRequired as LoginRequiredException; - -use function intval; -use function is_object; -use function strlen; - -/** - * Row Definition for resource - * - * @category VuFind - * @package Db_Row - * @author Demian Katz - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org Main Site - * - * @property int $id - * @property string $record_id - * @property string $title - * @property ?string $author - * @property ?int $year - * @property string $source - * @property ?string $extra_metadata - */ -class Resource extends RowGateway implements - \VuFind\Db\Table\DbTableAwareInterface, - \VuFind\Db\Service\ServiceAwareInterface -{ - use \VuFind\Db\Table\DbTableAwareTrait; - use \VuFind\Db\Service\ServiceAwareTrait; - - /** - * Constructor - * - * @param \Laminas\Db\Adapter\Adapter $adapter Database adapter - */ - public function __construct($adapter) - { - parent::__construct('id', 'resource', $adapter); - } - - /** - * Remove tags from the current resource. - * - * @param \VuFind\Db\Row\User $user The user deleting the tags. - * @param string $list_id The list associated with the tags - * (optional -- omitting this will delete ALL of the user's tags). - * - * @return void - */ - public function deleteTags($user, $list_id = null) - { - $unlinker = $this->getDbService(\VuFind\Db\Service\TagService::class); - $unlinker->destroyResourceLinks($this->id, $user->id, $list_id); - } - - /** - * Add a tag to the current resource. - * - * @param string $tagText The tag to save. - * @param \VuFind\Db\Row\User $user The user posting the tag. - * @param string $list_id The list associated with the tag - * (optional). - * - * @return void - */ - public function addTag($tagText, $user, $list_id = null) - { - $tagText = trim($tagText); - if (!empty($tagText)) { - $tagService = $this->getDbService(\VuFind\Db\Service\TagService::class); - $tag = $tagService->getByText($tagText); - - $tagService->createLink( - $tag, - $this->id, - is_object($user) ? $user->id : null, - $list_id - ); - } - } - - /** - * Remove a tag from the current resource. - * - * @param string $tagText The tag to delete. - * @param \VuFind\Db\Row\User $user The user deleting the tag. - * @param string $list_id The list associated with the tag - * (optional). - * - * @return void - */ - public function deleteTag($tagText, $user, $list_id = null) - { - $tagText = trim($tagText); - $tagService = $this->getDbService(\VuFind\Db\Service\TagService::class); - if (!empty($tagText)) { - $tagIds = []; - foreach ($tagService->getByText($tagText, false, false) as $tag) { - $tagIds[] = $tag->getId(); - } - if (!empty($tagIds)) { - $tagService->destroyResourceLinks( - $this->id, - $user->id, - $list_id, - $tagIds - ); - } - } - } - - /** - * Add or update user's rating for the current resource. - * - * @param int $userId User ID - * @param ?int $rating Rating (null to delete) - * - * @throws LoginRequiredException - * @throws \Exception - * @return int ID of rating added, deleted or updated - */ - public function addOrUpdateRating(int $userId, ?int $rating): int - { - if (null !== $rating && ($rating < 0 || $rating > 100)) { - throw new \Exception('Rating value out of range'); - } - - $ratings = $this->getDbTable('Ratings'); - $callback = function ($select) use ($userId) { - $select->where->equalTo('ratings.resource_id', $this->id); - $select->where->equalTo('ratings.user_id', $userId); - }; - if ($existing = $ratings->select($callback)->current()) { - if (null === $rating) { - $existing->delete(); - } else { - $existing->rating = $rating; - $existing->save(); - } - return $existing->id; - } - - if (null === $rating) { - return 0; - } - - $row = $ratings->createRow(); - $row->user_id = $userId; - $row->resource_id = $this->id; - $row->rating = $rating; - $row->created = date('Y-m-d H:i:s'); - $row->save(); - return $row->id; - } - - /** - * Use a record driver to assign metadata to the current row. Return the - * current object to allow fluent interface. - * - * @param \VuFind\RecordDriver\AbstractBase $driver The record driver - * @param \VuFind\Date\Converter $converter Date converter - * - * @return \VuFind\Db\Row\Resource - */ - public function assignMetadata($driver, \VuFind\Date\Converter $converter) - { - // Grab title -- we have to have something in this field! - $this->title = mb_substr( - $driver->tryMethod('getSortTitle'), - 0, - 255, - 'UTF-8' - ); - if (empty($this->title)) { - $this->title = $driver->getBreadcrumb(); - } - - // Try to find an author; if not available, just leave the default null: - $author = mb_substr( - $driver->tryMethod('getPrimaryAuthor'), - 0, - 255, - 'UTF-8' - ); - if (!empty($author)) { - $this->author = $author; - } - - // Try to find a year; if not available, just leave the default null: - $dates = $driver->tryMethod('getPublicationDates'); - if (isset($dates[0]) && strlen($dates[0]) > 4) { - try { - $year = $converter->convertFromDisplayDate('Y', $dates[0]); - } catch (DateException $e) { - // If conversion fails, don't store a date: - $year = ''; - } - } else { - $year = $dates[0] ?? ''; - } - if (!empty($year)) { - $this->year = intval($year); - } - - if ($extra = $driver->tryMethod('getExtraResourceMetadata')) { - $this->extra_metadata = json_encode($extra); - } - return $this; - } -} diff --git a/module/VuFind/src/VuFind/Db/Row/User.php b/module/VuFind/src/VuFind/Db/Row/User.php index 1bbc6a9caad..d1571383b37 100644 --- a/module/VuFind/src/VuFind/Db/Row/User.php +++ b/module/VuFind/src/VuFind/Db/Row/User.php @@ -324,42 +324,6 @@ public function getSavedData( return $table->getSavedData($resourceId, $source, $listId, $this->id); } - /** - * Add/update a resource in the user's account. - * - * @param \VuFind\Db\Row\Resource $resource The resource to add/update - * @param int $list The list to store the resource in. - * @param array $tagArray An array of tags to associate with the resource. - * @param string $notes User notes about the resource. - * @param bool $replaceExisting Whether to replace all - * existing tags (true) or append to the existing list (false). - * - * @return void - */ - public function saveResource( - $resource, - $list, - $tagArray, - $notes, - $replaceExisting = true - ) { - // Create the resource link if it doesn't exist and update the notes in any - // case: - $linkTable = $this->getDbTable('UserResource'); - $linkTable->createOrUpdateLink($resource->id, $this->id, $list, $notes); - - // If we're replacing existing tags, delete the old ones before adding the - // new ones: - if ($replaceExisting) { - $resource->deleteTags($this, $list); - } - - // Add the new tags: - foreach ($tagArray as $tag) { - $resource->addTag($tag, $this, $list); - } - } - /** * Given an array of item ids, remove them from all lists * @@ -371,18 +335,13 @@ public function saveResource( public function removeResourcesById($ids, $source = DEFAULT_SEARCH_BACKEND) { // Retrieve a list of resource IDs: - $resourceTable = $this->getDbTable('Resource'); - $resources = $resourceTable->findResources($ids, $source); - - $resourceIDs = []; - foreach ($resources as $current) { - $resourceIDs[] = $current->id; - } + $resourceService = $this->getDbService(\VuFind\Db\Service\ResourceService::class); + $resources = $resourceService->findResources($ids, $source); // Remove Resource (related tags are also removed implicitly) - $userResourceTable = $this->getDbTable('UserResource'); + $userResourceService = $this->getDbService(\VuFind\Db\Service\UserResourceService::class); // true here makes sure that only tags in lists are deleted - $userResourceTable->destroyLinks($resourceIDs, $this->id, true); + $userResourceService->destroyLinks($this->id, $resources, true); } /** diff --git a/module/VuFind/src/VuFind/Db/Service/RatingsService.php b/module/VuFind/src/VuFind/Db/Service/RatingsService.php index c24862e8187..53de08c3bd8 100644 --- a/module/VuFind/src/VuFind/Db/Service/RatingsService.php +++ b/module/VuFind/src/VuFind/Db/Service/RatingsService.php @@ -29,7 +29,14 @@ namespace VuFind\Db\Service; +use Laminas\Log\LoggerAwareInterface; use VuFind\Db\Entity\Ratings; +use VuFind\Db\Entity\Resource; +use VuFind\Db\Entity\User; +use VuFind\Exception\LoginRequired as LoginRequiredException; +use VuFind\Log\LoggerAwareTrait; + +use function is_object; /** * Database service for Ratings. @@ -40,9 +47,10 @@ * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License * @link https://vufind.org/wiki/development:plugins:database_gateways Wiki */ -class RatingsService extends AbstractService implements \VuFind\Db\Service\ServiceAwareInterface +class RatingsService extends AbstractService implements \VuFind\Db\Service\ServiceAwareInterface, LoggerAwareInterface { use \VuFind\Db\Service\ServiceAwareTrait; + use LoggerAwareTrait; /** * Get average rating and rating count associated with the specified resource. @@ -179,4 +187,73 @@ public function getStatistics(): array $stats = current($query->getResult()); return $stats; } + + /** + * Add or update user's rating for a resource. + * + * @param Resource $resource Resource to add or update rating. + * @param int|User $user User + * @param ?int $rating Rating (null to delete) + * + * @throws LoginRequiredException + * @throws \Exception + * @return int ID of rating added, deleted or updated + */ + public function addOrUpdateRating($resource, $user, $rating): int + { + if (null !== $rating && ($rating < 0 || $rating > 100)) { + throw new \Exception('Rating value out of range'); + } + + $dql = 'SELECT r ' + . 'FROM ' . $this->getEntityClass(Ratings::class) . ' r ' + . 'WHERE r.user = :user AND r.resource = :resource'; + $parameters = compact('resource', 'user'); + $query = $this->entityManager->createQuery($dql); + $query->setParameters($parameters); + + if ($existing = current($query->getResult())) { + if (null === $rating) { + $this->entityManager->remove($existing); + } else { + $existing->setRating($rating); + } + $updatedRatingId = $existing->getId(); + try { + $this->entityManager->flush(); + } catch (\Exception $e) { + $this->logError('Rating update failed: ' . $e->getMessage()); + throw $e; + } + return $updatedRatingId; + } + + if (null === $rating) { + return 0; + } + + $row = $this->createRatings() + ->setResource($resource) + ->setUser(is_object($user) ? $user : $this->entityManager->getReference(User::class, $user)) + ->setRating($rating) + ->setCreated(new \DateTime()); + try { + $this->persistEntity($row); + } catch (\Exception $e) { + $this->logError('Could not save rating: ' . $e->getMessage()); + return 0; + } + return $row->getId(); + } + + /** + * Create a ratings entity. + * + * @return Ratings + */ + public function createRatings(): Ratings + { + $class = $this->getEntityClass(Ratings::class); + return new $class(); + } } diff --git a/module/VuFind/src/VuFind/Db/Service/ResourceService.php b/module/VuFind/src/VuFind/Db/Service/ResourceService.php index 8d7f58e394d..ef1dc592a02 100644 --- a/module/VuFind/src/VuFind/Db/Service/ResourceService.php +++ b/module/VuFind/src/VuFind/Db/Service/ResourceService.php @@ -36,7 +36,7 @@ use VuFind\Db\Entity\PluginManager as EntityPluginManager; use VuFind\Db\Entity\Resource; use VuFind\Db\Entity\User; -use VuFind\Db\Entity\UserList; +use VuFind\Db\Entity\UserResource; use VuFind\Exception\LoginRequired as LoginRequiredException; use VuFind\Log\LoggerAwareTrait; use VuFind\Record\Loader; @@ -368,29 +368,137 @@ public function findResources($ids, $source = DEFAULT_SEARCH_BACKEND) } /** - * Add a tag to the current resource. + * Update the database to reflect a changed record identifier. * - * @param Resource|int $resource Resource associated. - * @param string $tagText The tag to save. - * @param User|int $user The user posting the tag. - * @param ?UserList $list The list associated with the tag - * (optional). + * @param string $oldId Original record ID + * @param string $newId Revised record ID + * @param string $source Record source * * @return void */ - public function addTag($resource, $tagText, $user, $list = null) + public function updateRecordId($oldId, $newId, $source = DEFAULT_SEARCH_BACKEND) { - $tagText = trim($tagText); - if (!empty($tagText)) { - $tagService = $this->getDbService(\VuFind\Db\Service\TagService::class); - $tag = $tagService->getByText($tagText); - - $tagService->createLink( - $tag, - $resource, - $user, - $list - ); + if ( + $oldId !== $newId + && $resource = $this->findResource($oldId, $source, false) + ) { + // Do this as a transaction to prevent odd behavior: + $this->entityManager->getConnection()->beginTransaction(); + // Does the new ID already exist? + $deduplicate = false; + if ($newResource = $this->findResource($newId, $source, false)) { + // Special case: merge new ID and old ID: + $entitiesToUpdate = [ + \VuFind\Db\Entity\Comments::class, + \VuFind\Db\Entity\UserResource::class, + \VuFind\Db\Entity\ResourceTags::class, + ]; + foreach ($entitiesToUpdate as $entityToUpdate) { + $this->updateResource($entityToUpdate, $newResource, $resource); + } + $this->entityManager->remove($resource); + $deduplicate = true; + } else { + // Default case: just update the record ID: + $resource->setRecordId($newId); + } + // Done -- commit the transaction: + try { + $this->entityManager->flush(); + $this->entityManager->getConnection()->commit(); + } catch (\Exception $e) { + $this->logError('Could not update the record: ' . $e->getMessage()); + $this->entityManager->getConnection()->rollBack(); + throw $e; + } + // Deduplicate rows where necessary (this can be safely done outside of the transaction): + if ($deduplicate) { + $tagService = $this->getDbService(\VuFind\Db\Service\TagService::class); + $tagService->deduplicateResourceLinks(); + $userResourceService = $this->getDbService(\VuFind\Db\Service\UserResourceService::class); + $userResourceService->deduplicate(); + } + } + } + + /** + * Get a set of records from the requested favorite list. + * + * @param int|User $user ID of user owning favorite list + * @param int|UserList $list ID of list to retrieve (null for all favorites) + * @param array $tags Tags to use for limiting results + * @param string $sort Resource table field to use for sorting (null for + * no particular sort). + * @param int $offset Offset for results + * @param int $limit Limit for results (null for none) + * + * @return \Laminas\Db\ResultSet\AbstractResultSet + */ + public function getFavorites( + $user, + $list = null, + $tags = [], + $sort = null, + $offset = 0, + $limit = null + ) { + $dql = 'SELECT DISTINCT(r.id), r ' + . 'FROM ' . $this->getEntityClass(Resource::class) . ' r ' + . 'JOIN ' . $this->getEntityClass(UserResource::class) . ' ur WITH r.id = ur.resource '; + $dqlWhere = []; + $dqlWhere[] = 'ur.user = :user'; + $parameters = compact('user'); + if (null !== $list) { + $dqlWhere[] = 'ur.list = :list'; + $parameters['list'] = $list; } + + // Adjust for tags if necessary: + if (!empty($tags)) { + $linkingTable = $this->getDbService(\VuFind\Db\Service\TagService::class); + $matches = []; + foreach ($tags as $tag) { + $matches[] = $linkingTable + ->getResourceIDsForTag($tag, $user, $list); + } + $dqlWhere[] = 'r.id IN (:ids)'; + $parameters['ids'] = $matches; + } + $dql .= ' WHERE ' . implode(' AND ', $dqlWhere); + if (!empty($sort)) { + $dql .= ResourceService::getOrderByClause($sort); + } + + $query = $this->entityManager->createQuery($dql); + $query->setParameters($parameters); + + if ($offset > 0) { + $query->setFirstResult($offset); + } + if (null !== $limit) { + $query->setMaxResults($limit); + } + + $result = $query->getResult(); + return $result; + } + + /** + * Delete a resource by source and id + * + * @param string $id Resource ID + * @param string $source Resource source + * + * @return mixed + */ + public function deleteResource($id, $source) + { + $dql = 'DELETE FROM ' . $this->getEntityClass(Resource::class) . ' r ' + . 'WHERE r.recordId = :id AND r.source = :source'; + $parameters = compact('id', 'source'); + $query = $this->entityManager->createQuery($dql); + $query->setParameters($parameters); + $result = $query->execute(); + return $result; } } diff --git a/module/VuFind/src/VuFind/Db/Service/TagService.php b/module/VuFind/src/VuFind/Db/Service/TagService.php index 796ef881ee0..2f746e42aac 100644 --- a/module/VuFind/src/VuFind/Db/Service/TagService.php +++ b/module/VuFind/src/VuFind/Db/Service/TagService.php @@ -1179,4 +1179,60 @@ public function fixDuplicateTags() $this->fixDuplicateTag($dupe['tag']); } } + + /** + * Remove a tag from the resource. + * + * @param Resource $resource Resource from which tag should be deleted. + * @param string $tagText The tag to delete. + * @param int|User $user The user deleting the tag. + * @param string $list_id The list associated with the tag + * (optional). + * + * @return void + */ + public function deleteTag($resource, $tagText, $user, $list_id = null) + { + $tagText = trim($tagText); + if (!empty($tagText)) { + $tagIds = []; + foreach ($this->getByText($tagText, false, false) as $tag) { + $tagIds[] = $tag->getId(); + } + if (!empty($tagIds)) { + $this->destroyResourceLinks( + $resource, + $user, + $list_id, + $tagIds + ); + } + } + } + + /** + * Add a tag to the resource. + * + * @param Resource|int $resource Resource associated. + * @param string $tagText The tag to save. + * @param User|int $user The user posting the tag. + * @param ?UserList $list The list associated with the tag + * (optional). + * + * @return void + */ + public function addTag($resource, $tagText, $user, $list = null) + { + $tagText = trim($tagText); + if (!empty($tagText)) { + $tag = $this->getByText($tagText); + + $this->createLink( + $tag, + $resource, + $user, + $list + ); + } + } } diff --git a/module/VuFind/src/VuFind/Db/Service/UserService.php b/module/VuFind/src/VuFind/Db/Service/UserService.php index 90e35d30418..990a4af3cc8 100644 --- a/module/VuFind/src/VuFind/Db/Service/UserService.php +++ b/module/VuFind/src/VuFind/Db/Service/UserService.php @@ -192,15 +192,11 @@ public function encryptOrDecrypt($text, $encrypt = true) * * @param Resource|int $resource The resource to add/update * @param User|int $user Logged in user - * @param UserList|int $list The list to store the resource - * in. - * @param array $tagArray An array of tags to associate - * with the resource. + * @param UserList|int $list The list to store the resource in. + * @param array $tagArray An array of tags to associate with the resource. * @param string $notes User notes about the resource. - * @param bool $replaceExisting Whether to replace all - * existing tags (true) - * or append to the - * existing list (false). + * @param bool $replaceExisting Whether to replace all existing tags (true) or append to the + * existing list (false). * * @return void */ @@ -212,13 +208,11 @@ public function saveResource( $notes, $replaceExisting = true ) { - // Create the resource link if it doesn't exist and update the notes in any - // case: + // Create the resource link if it doesn't exist and update the notes in any case: $linkService = $this->getDbService(\VuFind\Db\Service\UserResourceService::class); $linkService->createOrUpdateLink($resource, $user, $list, $notes); - // If we're replacing existing tags, delete the old ones before adding the - // new ones: + // If we're replacing existing tags, delete the old ones before adding the new ones: if ($replaceExisting) { $unlinker = $this->getDbService(\VuFind\Db\Service\TagService::class); $unlinker->destroyResourceLinks($resource, $user, $list); @@ -226,8 +220,8 @@ public function saveResource( // Add the new tags: foreach ($tagArray as $tag) { - $resourceService = $this->getDbService(\VuFind\Db\Service\ResourceService::class); - $resourceService->addTag($resource, $tag, $user, $list); + $tagService = $this->getDbService(\VuFind\Db\Service\TagService::class); + $tagService->addTag($resource, $tag, $user, $list); } } } diff --git a/module/VuFind/src/VuFind/Db/Table/PluginManager.php b/module/VuFind/src/VuFind/Db/Table/PluginManager.php index 471cc6d2890..9688da36856 100644 --- a/module/VuFind/src/VuFind/Db/Table/PluginManager.php +++ b/module/VuFind/src/VuFind/Db/Table/PluginManager.php @@ -49,7 +49,6 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager 'accesstoken' => AccessToken::class, 'externalsession' => ExternalSession::class, 'ratings' => Ratings::class, - 'resource' => Resource::class, 'search' => Search::class, 'session' => Session::class, 'user' => User::class, @@ -66,7 +65,6 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager AuthHash::class => GatewayFactory::class, ExternalSession::class => GatewayFactory::class, Ratings::class => GatewayFactory::class, - Resource::class => ResourceFactory::class, Search::class => GatewayFactory::class, Session::class => GatewayFactory::class, User::class => UserFactory::class, diff --git a/module/VuFind/src/VuFind/Db/Table/Resource.php b/module/VuFind/src/VuFind/Db/Table/Resource.php deleted file mode 100644 index e3a8b74ba72..00000000000 --- a/module/VuFind/src/VuFind/Db/Table/Resource.php +++ /dev/null @@ -1,323 +0,0 @@ - - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org Main Site - */ - -namespace VuFind\Db\Table; - -use Laminas\Db\Adapter\Adapter; -use Laminas\Db\Sql\Expression; -use Laminas\Db\Sql\Select; -use VuFind\Date\Converter as DateConverter; -use VuFind\Db\Row\RowGateway; -use VuFind\Db\Service\ServiceAwareInterface; -use VuFind\Db\Service\ServiceAwareTrait; -use VuFind\Record\Loader; - -use function in_array; - -/** - * Table Definition for resource - * - * @category VuFind - * @package Db_Table - * @author Demian Katz - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org Main Site - */ -class Resource extends Gateway implements ServiceAwareInterface -{ - use ServiceAwareTrait; - - /** - * Date converter - * - * @var DateConverter - */ - protected $dateConverter; - - /** - * Record loader - * - * @var Loader - */ - protected $recordLoader; - - /** - * Constructor - * - * @param Adapter $adapter Database adapter - * @param PluginManager $tm Table manager - * @param array $cfg Laminas configuration - * @param RowGateway $rowObj Row prototype object (null for default) - * @param DateConverter $converter Date converter - * @param Loader $loader Record loader - * @param string $table Name of database table to interface with - */ - public function __construct( - Adapter $adapter, - PluginManager $tm, - $cfg, - ?RowGateway $rowObj, - DateConverter $converter, - Loader $loader, - $table = 'resource' - ) { - $this->dateConverter = $converter; - $this->recordLoader = $loader; - parent::__construct($adapter, $tm, $cfg, $rowObj, $table); - } - - /** - * Look up a row for the specified resource. - * - * @param string $id Record ID to look up - * @param string $source Source of record to look up - * @param bool $create If true, create the row if it - * does not yet exist. - * @param \VuFind\RecordDriver\AbstractBase $driver A record driver for the - * resource being created (optional -- improves efficiency if provided, but will - * be auto-loaded as needed if left null). - * - * @return \VuFind\Db\Row\Resource|null Matching row if found or created, null - * otherwise. - */ - public function findResource( - $id, - $source = DEFAULT_SEARCH_BACKEND, - $create = true, - $driver = null - ) { - if (empty($id)) { - throw new \Exception('Resource ID cannot be empty'); - } - $select = $this->select(['record_id' => $id, 'source' => $source]); - $result = $select->current(); - - // Create row if it does not already exist and creation is enabled: - if (empty($result) && $create) { - $result = $this->createRow(); - $result->record_id = $id; - $result->source = $source; - - // Load record if it was not provided: - if (null === $driver) { - $driver = $this->recordLoader->load($id, $source); - } - - // Load metadata into the database for sorting/failback purposes: - $result->assignMetadata($driver, $this->dateConverter); - - // Save the new row. - $result->save(); - } - return $result; - } - - /** - * Look up a rowset for a set of specified resources. - * - * @param array $ids Array of IDs - * @param string $source Source of records to look up - * - * @return \Laminas\Db\ResultSet\AbstractResultSet - */ - public function findResources($ids, $source = DEFAULT_SEARCH_BACKEND) - { - $callback = function ($select) use ($ids, $source) { - $select->where->in('record_id', $ids); - $select->where->equalTo('source', $source); - }; - return $this->select($callback); - } - - /** - * Get a set of records from the requested favorite list. - * - * @param string $user ID of user owning favorite list - * @param string $list ID of list to retrieve (null for all favorites) - * @param array $tags Tags to use for limiting results - * @param string $sort Resource table field to use for sorting (null for - * no particular sort). - * @param int $offset Offset for results - * @param int $limit Limit for results (null for none) - * - * @return \Laminas\Db\ResultSet\AbstractResultSet - */ - public function getFavorites( - $user, - $list = null, - $tags = [], - $sort = null, - $offset = 0, - $limit = null - ) { - return $this->select( - function ($s) use ($user, $list, $tags, $sort, $offset, $limit) { - $s->columns( - [ - new Expression( - 'DISTINCT(?)', - ['resource.id'], - [Expression::TYPE_IDENTIFIER] - ), Select::SQL_STAR, - ] - ); - $s->join( - ['ur' => 'user_resource'], - 'resource.id = ur.resource_id', - [] - ); - $s->where->equalTo('ur.user_id', $user); - - // Adjust for list if necessary: - if (null !== $list) { - $s->where->equalTo('ur.list_id', $list); - } - - if ($offset > 0) { - $s->offset($offset); - } - if (null !== $limit) { - $s->limit($limit); - } - - // Adjust for tags if necessary: - if (!empty($tags)) { - $linkingTable = $this->getDbService(\VuFind\Db\Service\TagService::class); - foreach ($tags as $tag) { - $matches = $linkingTable - ->getResourceIDsForTag($tag, $user, $list); - - $s->where->in('resource.id', $matches); - } - } - - // Apply sorting, if necessary: - if (!empty($sort)) { - Resource::applySort($s, $sort); - } - } - ); - } - - /** - * Update the database to reflect a changed record identifier. - * - * @param string $oldId Original record ID - * @param string $newId Revised record ID - * @param string $source Record source - * - * @return void - */ - public function updateRecordId($oldId, $newId, $source = DEFAULT_SEARCH_BACKEND) - { - if ( - $oldId !== $newId - && $resource = $this->findResource($oldId, $source, false) - ) { - // Do this as a transaction to prevent odd behavior: - $connection = $this->getAdapter()->getDriver()->getConnection(); - $connection->beginTransaction(); - // Does the new ID already exist? - $deduplicate = false; - if ($newResource = $this->findResource($newId, $source, false)) { - // Special case: merge new ID and old ID: - $resourceService = $this->getDbService(\VuFind\Db\Service\ResourceService::class); - $entitiesToUpdate = [ - \VuFind\Db\Entity\Comments::class, - \VuFind\Db\Entity\UserResource::class, - \VuFind\Db\Entity\ResourceTags::class, - ]; - foreach ($entitiesToUpdate as $entityToUpdate) { - $resourceService->updateResource($entityToUpdate, $newResource->id, $resource->id); - } - $resource->delete(); - $deduplicate = true; - } else { - // Default case: just update the record ID: - $resource->record_id = $newId; - $resource->save(); - } - // Done -- commit the transaction: - $connection->commit(); - - // Deduplicate rows where necessary (this can be safely done outside - // of the transaction): - if ($deduplicate) { - $tagService = $this->getDbService(\VuFind\Db\Service\TagService::class); - $tagService->deduplicateResourceLinks(); - $userResourceService = $this->getDbService(\VuFind\Db\Service\UserResourceService::class); - $userResourceService->deduplicate(); - } - } - } - - /** - * Apply a sort parameter to a query on the resource table. - * - * @param \Laminas\Db\Sql\Select $query Query to modify - * @param string $sort Field to use for sorting (may include - * 'desc' qualifier) - * @param string $alias Alias to the resource table (defaults to - * 'resource') - * - * @return void - */ - public static function applySort($query, $sort, $alias = 'resource') - { - // Apply sorting, if necessary: - $legalSorts = [ - 'title', 'title desc', 'author', 'author desc', 'year', 'year desc', - ]; - if (!empty($sort) && in_array(strtolower($sort), $legalSorts)) { - // Strip off 'desc' to obtain the raw field name -- we'll need it - // to sort null values to the bottom: - $parts = explode(' ', $sort); - $rawField = trim($parts[0]); - - // Start building the list of sort fields: - $order = []; - - // The title field can't be null, so don't bother with the extra - // isnull() sort in that case. - if (strtolower($rawField) != 'title') { - $order[] = new Expression( - 'isnull(?)', - [$alias . '.' . $rawField], - [Expression::TYPE_IDENTIFIER] - ); - } - - // Apply the user-specified sort: - $order[] = $alias . '.' . $sort; - - // Inject the sort preferences into the query object: - $query->order($order); - } - } -} diff --git a/module/VuFind/src/VuFind/Db/Table/ResourceFactory.php b/module/VuFind/src/VuFind/Db/Table/ResourceFactory.php deleted file mode 100644 index 64d3c0f7ce8..00000000000 --- a/module/VuFind/src/VuFind/Db/Table/ResourceFactory.php +++ /dev/null @@ -1,74 +0,0 @@ - - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org/wiki/development Wiki - */ - -namespace VuFind\Db\Table; - -use Laminas\ServiceManager\Exception\ServiceNotCreatedException; -use Laminas\ServiceManager\Exception\ServiceNotFoundException; -use Psr\Container\ContainerExceptionInterface as ContainerException; -use Psr\Container\ContainerInterface; - -/** - * Resource table gateway factory. - * - * @category VuFind - * @package Db_Table - * @author Demian Katz - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org/wiki/development Wiki - */ -class ResourceFactory extends GatewayFactory -{ - /** - * Create an object - * - * @param ContainerInterface $container Service manager - * @param string $requestedName Service being created - * @param null|array $options Extra options (optional) - * - * @return object - * - * @throws ServiceNotFoundException if unable to resolve the service. - * @throws ServiceNotCreatedException if an exception is raised when - * creating a service. - * @throws ContainerException&\Throwable if any other error occurs - */ - public function __invoke( - ContainerInterface $container, - $requestedName, - array $options = null - ) { - if (!empty($options)) { - throw new \Exception('Unexpected options sent to factory!'); - } - $converter = $container->get(\VuFind\Date\Converter::class); - $loader = $container->get(\VuFind\Record\Loader::class); - return parent::__invoke($container, $requestedName, [$converter, $loader]); - } -} diff --git a/module/VuFind/src/VuFind/Favorites/FavoritesService.php b/module/VuFind/src/VuFind/Favorites/FavoritesService.php index fc0c48d87a6..b8d911e6523 100644 --- a/module/VuFind/src/VuFind/Favorites/FavoritesService.php +++ b/module/VuFind/src/VuFind/Favorites/FavoritesService.php @@ -31,7 +31,6 @@ use VuFind\Db\Service\ServiceAwareInterface; use VuFind\Db\Service\ServiceAwareTrait; -use VuFind\Db\Table\Resource as ResourceTable; use VuFind\Exception\LoginRequired as LoginRequiredException; use VuFind\Record\Cache as RecordCache; use VuFind\RecordDriver\AbstractBase as RecordDriver; @@ -57,25 +56,15 @@ class FavoritesService implements \VuFind\I18n\Translator\TranslatorAwareInterfa */ protected $recordCache = null; - /** - * Resource database table - * - * @var ResourceTable - */ - protected $resourceTable; - /** * Constructor * - * @param ResourceTable $resource Resource table object - * @param RecordCache $cache Record cache + * @param RecordCache $cache Record cache */ public function __construct( - ResourceTable $resource, RecordCache $cache = null ) { $this->recordCache = $cache; - $this->resourceTable = $resource; } /** @@ -109,20 +98,20 @@ public function getListObject($listId, \VuFind\Db\Row\User $user) /** * Persist a resource to the record cache (if applicable). * - * @param RecordDriver $driver Record driver to persist - * @param \VuFind\Db\Row\Resource $resource Resource row + * @param RecordDriver $driver Record driver to persist + * @param \VuFind\Db\Entity\Resource $resource Resource object * * @return void */ protected function persistToCache( RecordDriver $driver, - \VuFind\Db\Row\Resource $resource + \VuFind\Db\Entity\Resource $resource ) { if ($this->recordCache) { $this->recordCache->setContext(RecordCache::CONTEXT_FAVORITE); $this->recordCache->createOrUpdate( - $resource->record_id, - $resource->source, + $resource->getRecordId(), + $resource->getSource(), $driver->getRawData() ); } @@ -159,7 +148,7 @@ public function save( ); // Get or create a resource object as needed: - $resource = $this->resourceTable->findResource( + $resource = $this->getDbService(\VuFind\Db\Service\ResourceService::class)->findResource( $driver->getUniqueId(), $driver->getSourceIdentifier(), true, @@ -172,7 +161,7 @@ public function save( // Add the information to the user's account: $userService = $this->getDbService(\VuFind\Db\Service\UserService::class); $userService->saveResource( - $resource->id, + $resource, $user->id, $list, $params['mytags'] ?? [], diff --git a/module/VuFind/src/VuFind/Favorites/FavoritesServiceFactory.php b/module/VuFind/src/VuFind/Favorites/FavoritesServiceFactory.php index ec96d035541..595aad5db49 100644 --- a/module/VuFind/src/VuFind/Favorites/FavoritesServiceFactory.php +++ b/module/VuFind/src/VuFind/Favorites/FavoritesServiceFactory.php @@ -58,9 +58,7 @@ class FavoritesServiceFactory implements FactoryInterface */ public function __invoke(ContainerInterface $sm, $name, array $options = null) { - $tableManager = $sm->get(\VuFind\Db\Table\PluginManager::class); return new FavoritesService( - $tableManager->get('resource'), $sm->get(\VuFind\Record\Cache::class) ); } diff --git a/module/VuFind/src/VuFind/Record/FallbackLoader/AbstractFallbackLoader.php b/module/VuFind/src/VuFind/Record/FallbackLoader/AbstractFallbackLoader.php index 5818d2adc28..d694a83ec98 100644 --- a/module/VuFind/src/VuFind/Record/FallbackLoader/AbstractFallbackLoader.php +++ b/module/VuFind/src/VuFind/Record/FallbackLoader/AbstractFallbackLoader.php @@ -29,7 +29,7 @@ namespace VuFind\Record\FallbackLoader; -use VuFind\Db\Table\Resource; +use VuFind\Db\Service\ResourceService as ResourceService; use VuFind\RecordDriver\AbstractBase as RecordDriver; use VuFind\RecordDriver\Feature\PreviousUniqueIdInterface; use VuFindSearch\Service; @@ -53,11 +53,11 @@ abstract class AbstractFallbackLoader implements FallbackLoaderInterface protected $source = DEFAULT_SEARCH_BACKEND; /** - * Resource table + * Resource database service * - * @var Resource + * @var ResourceService */ - protected $table; + protected $resourceService; /** * Search service @@ -69,12 +69,12 @@ abstract class AbstractFallbackLoader implements FallbackLoaderInterface /** * Constructor * - * @param Resource $table Resource database table object - * @param Service $searchService Search service + * @param ResourceService $resourceService Resource database service + * @param Service $searchService Search service */ - public function __construct(Resource $table, Service $searchService) + public function __construct(ResourceService $resourceService, Service $searchService) { - $this->table = $table; + $this->resourceService = $resourceService; $this->searchService = $searchService; } @@ -122,7 +122,6 @@ protected function updateRecord($record, $previousId) $record->setPreviousUniqueId($previousId); // Update the database to replace the obsolete identifier... - $this->table - ->updateRecordId($previousId, $record->getUniqueId(), $this->source); + $this->resourceService->updateRecordId($previousId, $record->getUniqueId(), $this->source); } } diff --git a/module/VuFind/src/VuFind/Record/FallbackLoader/AbstractFallbackLoaderFactory.php b/module/VuFind/src/VuFind/Record/FallbackLoader/AbstractFallbackLoaderFactory.php index 0f7033ce48e..1bafe3a0fc2 100644 --- a/module/VuFind/src/VuFind/Record/FallbackLoader/AbstractFallbackLoaderFactory.php +++ b/module/VuFind/src/VuFind/Record/FallbackLoader/AbstractFallbackLoaderFactory.php @@ -66,7 +66,8 @@ public function __invoke( array $options = null ) { return new $requestedName( - $container->get(\VuFind\Db\Table\PluginManager::class)->get('resource'), + $container->get(\VuFind\Db\Service\PluginManager::class) + ->get(\VuFind\Db\Service\ResourceService::class), $container->get(\VuFindSearch\Service::class), ...$options ?? [] ); diff --git a/module/VuFind/src/VuFind/Record/FallbackLoader/Solr.php b/module/VuFind/src/VuFind/Record/FallbackLoader/Solr.php index 2cee8b80973..80715fcc6d8 100644 --- a/module/VuFind/src/VuFind/Record/FallbackLoader/Solr.php +++ b/module/VuFind/src/VuFind/Record/FallbackLoader/Solr.php @@ -29,7 +29,7 @@ namespace VuFind\Record\FallbackLoader; -use VuFind\Db\Table\Resource; +use VuFind\Db\Service\ResourceService as ResourceService; use VuFindSearch\Command\SearchCommand; use VuFindSearch\Service; @@ -61,17 +61,17 @@ class Solr extends AbstractFallbackLoader /** * Constructor * - * @param Resource $table Resource database table object - * @param Service $searchService Search service - * @param ?string $legacyIdField Solr field containing legacy IDs (null to - * disable lookups) + * @param ResourceService $resourceService Resource database service object + * @param Service $searchService Search service + * @param ?string $legacyIdField Solr field containing legacy IDs (null to + * disable lookups) */ public function __construct( - Resource $table, + ResourceService $resourceService, Service $searchService, ?string $legacyIdField = 'previous_id_str_mv' ) { - parent::__construct($table, $searchService); + parent::__construct($resourceService, $searchService); $this->legacyIdField = $legacyIdField; } diff --git a/module/VuFind/src/VuFind/Record/FallbackLoader/Summon.php b/module/VuFind/src/VuFind/Record/FallbackLoader/Summon.php index 9ebe0beecf9..124f8536f53 100644 --- a/module/VuFind/src/VuFind/Record/FallbackLoader/Summon.php +++ b/module/VuFind/src/VuFind/Record/FallbackLoader/Summon.php @@ -62,8 +62,8 @@ class Summon extends AbstractFallbackLoader */ protected function fetchSingleRecord($id) { - $resource = $this->table->findResource($id, 'Summon'); - if ($resource && ($extra = json_decode($resource->extra_metadata, true))) { + $resource = $this->resourceService->findResource($id, 'Summon'); + if ($resource && ($extra = json_decode($resource->getExtraMetadata(), true))) { $bookmark = $extra['bookmark'] ?? ''; if (strlen($bookmark) > 0) { $params = new ParamBag( diff --git a/module/VuFind/src/VuFind/RecordDriver/AbstractBase.php b/module/VuFind/src/VuFind/RecordDriver/AbstractBase.php index b502344ef47..ea3cdd92003 100644 --- a/module/VuFind/src/VuFind/RecordDriver/AbstractBase.php +++ b/module/VuFind/src/VuFind/RecordDriver/AbstractBase.php @@ -214,13 +214,14 @@ public function getTags( */ public function addTags($user, $tags) { - $resources = $this->getDbTable('Resource'); - $resource = $resources->findResource( + $resourceService = $this->getDbService(\VuFind\Db\Service\ResourceService::class); + $resource = $resourceService->findResource( $this->getUniqueId(), $this->getSourceIdentifier() ); + $tagService = $this->getDbService(\VuFind\Db\Service\TagService::class); foreach ($tags as $tag) { - $resource->addTag($tag, $user); + $tagService->addTag($resource, $tag, $user->id); } } @@ -234,13 +235,14 @@ public function addTags($user, $tags) */ public function deleteTags($user, $tags) { - $resources = $this->getDbTable('Resource'); - $resource = $resources->findResource( + $resourceService = $this->getDbService(\VuFind\Db\Service\ResourceService::class); + $resource = $resourceService->findResource( $this->getUniqueId(), $this->getSourceIdentifier() ); + $tagService = $this->getDbService(\VuFind\Db\Service\TagService::class); foreach ($tags as $tag) { - $resource->deleteTag($tag, $user); + $tagService->deleteTag($resource, $tag, $user->id); } } @@ -311,12 +313,11 @@ public function addOrUpdateRating(int $userId, ?int $rating): void { // Clear rating cache: $this->ratingCache = []; - $resources = $this->getDbTable('Resource'); - $resource = $resources->findResource( + $resource = $this->getDbService(\VuFind\Db\Service\ResourceService::class)->findResource( $this->getUniqueId(), $this->getSourceIdentifier() ); - $resource->addOrUpdateRating($userId, $rating); + $this->getDbService(\VuFind\Db\Service\RatingsService::class)->addOrUpdateRating($resource, $userId, $rating); } /** diff --git a/module/VuFind/src/VuFind/RecordDriver/Missing.php b/module/VuFind/src/VuFind/RecordDriver/Missing.php index 9bad5900a27..455c1b3040f 100644 --- a/module/VuFind/src/VuFind/RecordDriver/Missing.php +++ b/module/VuFind/src/VuFind/RecordDriver/Missing.php @@ -72,11 +72,10 @@ public function determineMissingTitle() // If available, load title from database: $id = $this->getUniqueId(); if ($id) { - $table = $this->getDbTable('Resource'); - $resource = $table - ->findResource($id, $this->getSourceIdentifier(), false); - if (!empty($resource) && !empty($resource->title)) { - return $resource->title; + $resourceService = $this->getDbService(\VuFind\Db\Service\ResourceService::class); + $resource = $resourceService->findResource($id, $this->getSourceIdentifier(), false); + if (!empty($resource) && !empty($resource->getTitle())) { + return $resource->getTitle(); } } diff --git a/module/VuFind/src/VuFind/Search/Favorites/Results.php b/module/VuFind/src/VuFind/Search/Favorites/Results.php index 4c8fd531da3..78c98e8b24b 100644 --- a/module/VuFind/src/VuFind/Search/Favorites/Results.php +++ b/module/VuFind/src/VuFind/Search/Favorites/Results.php @@ -31,8 +31,8 @@ use LmcRbacMvc\Service\AuthorizationServiceAwareInterface; use LmcRbacMvc\Service\AuthorizationServiceAwareTrait; +use VuFind\Db\Service\ResourceService as ResourceService; use VuFind\Db\Service\UserListService as ListService; -use VuFind\Db\Table\Resource as ResourceTable; use VuFind\Exception\ListPermission as ListPermissionException; use VuFind\Record\Cache; use VuFind\Record\Loader; @@ -69,11 +69,11 @@ class Results extends BaseResults implements AuthorizationServiceAwareInterface protected $list = false; /** - * Resource table + * Resource database service * - * @var ResourceTable + * @var ResourceService */ - protected $resourceTable; + protected $resourceService; /** * UserList database service @@ -92,22 +92,22 @@ class Results extends BaseResults implements AuthorizationServiceAwareInterface /** * Constructor * - * @param \VuFind\Search\Base\Params $params Object representing user - * search parameters. - * @param SearchService $searchService Search service - * @param Loader $recordLoader Record loader - * @param ResourceTable $resourceTable Resource table - * @param ListService $listService UserList service + * @param \VuFind\Search\Base\Params $params Object representing user + * search parameters. + * @param SearchService $searchService Search service + * @param Loader $recordLoader Record loader + * @param ResourceService $resourceService Resource database service + * @param ListService $listService UserList service */ public function __construct( \VuFind\Search\Base\Params $params, SearchService $searchService, Loader $recordLoader, - ResourceTable $resourceTable, + ResourceService $resourceService, ListService $listService ) { parent::__construct($params, $searchService, $recordLoader); - $this->resourceTable = $resourceTable; + $this->resourceService = $resourceService; $this->listService = $listService; } @@ -200,7 +200,7 @@ protected function performSearch() // How many results were there? $userId = null === $list ? $this->user->id : $list->getUser()->getId(); $listId = null === $list ? null : $list->getId(); - $rawResults = $this->resourceTable->getFavorites( + $rawResults = $this->resourceService->getFavorites( $userId, $listId, $this->getTagFilters(), @@ -211,7 +211,7 @@ protected function performSearch() // Apply offset and limit if necessary! $limit = $this->getParams()->getLimit(); if ($this->resultTotal > $limit) { - $rawResults = $this->resourceTable->getFavorites( + $rawResults = $this->resourceService->getFavorites( $userId, $listId, $this->getTagFilters(), @@ -224,10 +224,11 @@ protected function performSearch() // Retrieve record drivers for the selected items. $recordsToRequest = []; foreach ($rawResults as $row) { + $resource = $row[0]; $recordsToRequest[] = [ - 'id' => $row->record_id, 'source' => $row->source, + 'id' => $resource->getRecordId(), 'source' => $resource->getSource(), 'extra_fields' => [ - 'title' => $row->title, + 'title' => $resource->getTitle(), ], ]; } diff --git a/module/VuFind/src/VuFind/Search/Favorites/ResultsFactory.php b/module/VuFind/src/VuFind/Search/Favorites/ResultsFactory.php index ab005e6f8b1..9aa7cb6a43c 100644 --- a/module/VuFind/src/VuFind/Search/Favorites/ResultsFactory.php +++ b/module/VuFind/src/VuFind/Search/Favorites/ResultsFactory.php @@ -73,7 +73,7 @@ public function __invoke( $container, $requestedName, [ - $tm->get('Resource'), + $sm->get(\VuFind\Db\Service\ResourceService::class), $sm->get(\VuFind\Db\Service\UserListService::class), ] ); diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Record/FallbackLoader/SolrTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Record/FallbackLoader/SolrTest.php index d60eb65e0e0..9e804298e58 100644 --- a/module/VuFind/tests/unit-tests/src/VuFindTest/Record/FallbackLoader/SolrTest.php +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Record/FallbackLoader/SolrTest.php @@ -76,15 +76,15 @@ public function testEnabledLoader(): void $search->expects($this->once())->method('invoke') ->with($this->callback($checkCommand)) ->will($this->returnValue($commandObj)); - $resource = $this->getMockBuilder(\VuFind\Db\Table\Resource::class) + $resourceService = $this->getMockBuilder(\VuFind\Db\Service\ResourceService::class) ->disableOriginalConstructor()->getMock(); - $resource->expects($this->once())->method('updateRecordId') + $resourceService->expects($this->once())->method('updateRecordId') ->with( $this->equalTo('oldId'), $this->equalTo('newId'), $this->equalTo('Solr') ); - $loader = new Solr($resource, $search); + $loader = new Solr($resourceService, $search); $this->assertEquals([$record], $loader->load(['oldId'])); } @@ -97,9 +97,9 @@ public function testDisabledLoader(): void { $search = $this->getMockBuilder(\VuFindSearch\Service::class) ->disableOriginalConstructor()->getMock(); - $resource = $this->getMockBuilder(\VuFind\Db\Table\Resource::class) + $resourceService = $this->getMockBuilder(\VuFind\Db\Service\ResourceService::class) ->disableOriginalConstructor()->getMock(); - $loader = new Solr($resource, $search, null); + $loader = new Solr($resourceService, $search, null); $this->assertCount(0, $loader->load(['oldId'])); } } diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Record/FallbackLoader/SummonTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Record/FallbackLoader/SummonTest.php index ad32b1afa7a..141d0b52fd5 100644 --- a/module/VuFind/tests/unit-tests/src/VuFindTest/Record/FallbackLoader/SummonTest.php +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Record/FallbackLoader/SummonTest.php @@ -83,23 +83,22 @@ public function testLoader(): void ->with($this->callback($checkCommand)) ->will($this->returnValue($commandObj)); - $resource = $this->getMockBuilder(\VuFind\Db\Table\Resource::class) + $resourceService = $this->getMockBuilder(\VuFind\Db\Service\ResourceService::class) ->disableOriginalConstructor()->getMock(); - $resource->expects($this->once())->method('updateRecordId') + $resourceService->expects($this->once())->method('updateRecordId') ->with( $this->equalTo('oldId'), $this->equalTo('newId'), $this->equalTo('Summon') ); - $row = $this->getMockBuilder(\VuFind\Db\Row\Resource::class) + $row = $this->getMockBuilder(\VuFind\Db\Entity\Resource::class) ->disableOriginalConstructor()->getMock(); - $row->expects($this->once())->method('__get') - ->with($this->equalTo('extra_metadata')) + $row->expects($this->once())->method('getExtraMetadata') ->will($this->returnValue('{ "bookmark": "bar" }')); - $resource->expects($this->once())->method('findResource') + $resourceService->expects($this->once())->method('findResource') ->with($this->equalTo('oldId'), $this->equalTo('Summon')) ->will($this->returnValue($row)); - $loader = new Summon($resource, $search); + $loader = new Summon($resourceService, $search); $this->assertEquals([$record], $loader->load(['oldId'])); } } diff --git a/module/VuFindConsole/src/VuFindConsole/Command/Util/PurgeCachedRecordCommand.php b/module/VuFindConsole/src/VuFindConsole/Command/Util/PurgeCachedRecordCommand.php index 50dba4c83f9..f12a9ca4926 100644 --- a/module/VuFindConsole/src/VuFindConsole/Command/Util/PurgeCachedRecordCommand.php +++ b/module/VuFindConsole/src/VuFindConsole/Command/Util/PurgeCachedRecordCommand.php @@ -35,7 +35,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use VuFind\Db\Service\RecordService; -use VuFind\Db\Table\Resource; +use VuFind\Db\Service\ResourceService; /** * Console command: purge a record from cache @@ -63,27 +63,27 @@ class PurgeCachedRecordCommand extends Command protected $recordService; /** - * Resource table object + * Resource service object * - * @var Resource + * @var ResourceService */ - protected $resourceTable; + protected $resourceService; /** * Constructor * - * @param Record $recordService Record service object - * @param Resource $resource Resource table object - * @param string|null $name The name of the command; passing null means it - * must be set in configure() + * @param RecordService $recordService Record service object + * @param ResourceService $resourceService Resource service object + * @param string|null $name The name of the command; + * passing null means it must be set in configure() */ public function __construct( RecordService $recordService, - Resource $resource, + ResourceService $resourceService, $name = null ) { $this->recordService = $recordService; - $this->resourceTable = $resource; + $this->resourceService = $resourceService; parent::__construct($name); } @@ -126,7 +126,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $output->writeln('No cached record found'); } if ($input->getOption('purge-resource')) { - if ($this->resourceTable->delete(['source' => $source, 'record_id' => $id])) { + if ($this->resourceService->deleteResource($id, $source)) { $output->writeln('Resource deleted'); } else { $output->writeln('No resource found'); diff --git a/module/VuFindConsole/src/VuFindConsole/Command/Util/PurgeCachedRecordCommandFactory.php b/module/VuFindConsole/src/VuFindConsole/Command/Util/PurgeCachedRecordCommandFactory.php index efbb940fd6b..817852dd8c3 100644 --- a/module/VuFindConsole/src/VuFindConsole/Command/Util/PurgeCachedRecordCommandFactory.php +++ b/module/VuFindConsole/src/VuFindConsole/Command/Util/PurgeCachedRecordCommandFactory.php @@ -70,7 +70,7 @@ public function __invoke( ); return new $requestedName( $servicePluginManager->get(\VuFind\Db\Service\RecordService::class), - $container->get(\VuFind\Db\Table\PluginManager::class)->get('Resource'), + $servicePluginManager->get(\VuFind\Db\Service\ResourceService::class), ...($options ?? []) ); } diff --git a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Util/PurgeCachedRecordCommandTest.php b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Util/PurgeCachedRecordCommandTest.php index a3a912c4e65..135c704b4a6 100644 --- a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Util/PurgeCachedRecordCommandTest.php +++ b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Util/PurgeCachedRecordCommandTest.php @@ -89,10 +89,10 @@ public function testBasicOperation( ->with($this->equalTo('123'), $this->equalTo('Solr')) ->willReturn($recordRetVal); - $resourceTable = $this->getMockBuilder(\VuFind\Db\Table\Resource::class) + $resourceService = $this->getMockBuilder(\VuFind\Db\Service\ResourceService::class) ->disableOriginalConstructor()->getMock(); if (null !== $resourceRetVal) { - $resourceTable->expects($this->once())->method('delete') + $resourceService->expects($this->once())->method('deleteResource') ->willReturn($resourceRetVal); } $params = compact('source', 'id'); @@ -100,7 +100,7 @@ public function testBasicOperation( $params['--purge-resource'] = true; } - $command = new PurgeCachedRecordCommand($recordService, $resourceTable); + $command = new PurgeCachedRecordCommand($recordService, $resourceService); $commandTester = new CommandTester($command); $commandTester->execute($params); $expected = $recordRetVal ? "Cached record deleted\n" : "No cached record found\n";