diff --git a/module/VuFind/src/VuFind/AjaxHandler/GetSaveStatuses.php b/module/VuFind/src/VuFind/AjaxHandler/GetSaveStatuses.php index f881f373e2f..d7f41895510 100644 --- a/module/VuFind/src/VuFind/AjaxHandler/GetSaveStatuses.php +++ b/module/VuFind/src/VuFind/AjaxHandler/GetSaveStatuses.php @@ -32,6 +32,7 @@ use Laminas\Mvc\Controller\Plugin\Params; use Laminas\Mvc\Controller\Plugin\Url; use VuFind\Db\Row\User; +use VuFind\Db\Service\UserResourceService; use VuFind\I18n\Translator\TranslatorAwareInterface; use VuFind\Session\Settings as SessionSettings; @@ -56,12 +57,17 @@ class GetSaveStatuses extends AbstractBase implements TranslatorAwareInterface /** * Constructor * - * @param SessionSettings $ss Session settings - * @param ?User $user Logged in user (or null) - * @param Url $urlHelper URL helper + * @param SessionSettings $ss Session settings + * @param ?User $user Logged in user (or null) + * @param UserResourceService $userResourceService UserResource database service + * @param Url $urlHelper URL helper */ - public function __construct(SessionSettings $ss, protected ?User $user, protected Url $urlHelper) - { + public function __construct( + SessionSettings $ss, + protected ?User $user, + protected UserResourceService $userResourceService, + protected Url $urlHelper + ) { $this->sessionSettings = $ss; } @@ -76,8 +82,8 @@ protected function formatListData($list) { return [ 'list_url' => - $this->urlHelper->fromRoute('userList', ['id' => $list['list_id']]), - 'list_title' => $list['list_title'], + $this->urlHelper->fromRoute('userList', ['id' => $list[0]->getList()->getId()]), + 'list_title' => $list[0]->getList()->getTitle(), ]; } @@ -100,10 +106,9 @@ protected function getDataFromUser($ids, $sources) // use the $checked flag array to avoid duplicates: if (!isset($checked[$selector])) { $checked[$selector] = true; - - $data = $this->user->getSavedData($id, null, $source); + $data = $this->userResourceService->getSavedData($id, null, $source, $this->user->id); $result[$selector] = ($data && count($data) > 0) - ? array_map([$this, 'formatListData'], $data->toArray()) : []; + ? array_map([$this, 'formatListData'], $data) : []; } } return $result; diff --git a/module/VuFind/src/VuFind/AjaxHandler/GetSaveStatusesFactory.php b/module/VuFind/src/VuFind/AjaxHandler/GetSaveStatusesFactory.php index ab3670f5a00..f682396c8e1 100644 --- a/module/VuFind/src/VuFind/AjaxHandler/GetSaveStatusesFactory.php +++ b/module/VuFind/src/VuFind/AjaxHandler/GetSaveStatusesFactory.php @@ -72,6 +72,8 @@ public function __invoke( return new $requestedName( $container->get(\VuFind\Session\Settings::class), $container->get(\VuFind\Auth\Manager::class)->getUserObject(), + $container->get(\VuFind\Db\Service\PluginManager::class) + ->get(\VuFind\Db\Service\UserResourceService::class), $container->get('ControllerPluginManager')->get('url') ); } diff --git a/module/VuFind/src/VuFind/Controller/AbstractRecord.php b/module/VuFind/src/VuFind/Controller/AbstractRecord.php index 16619c66396..4a66bf62ba2 100644 --- a/module/VuFind/src/VuFind/Controller/AbstractRecord.php +++ b/module/VuFind/src/VuFind/Controller/AbstractRecord.php @@ -497,13 +497,15 @@ public function saveAction() // Find out if the item is already part of any lists; save list info/IDs $listIds = []; - $resources = $user->getSavedData( + + $resources = $this->getDbService(\VuFind\Db\Service\UserResourceService::class)->getSavedData( $driver->getUniqueId(), null, - $driver->getSourceIdentifier() + $driver->getSourceIdentifier(), + $user->id ); foreach ($resources as $userResource) { - $listIds[] = $userResource->list_id; + $listIds[] = $userResource[0]->getList()->getId(); } // Loop through all user lists and sort out containing/non-containing lists diff --git a/module/VuFind/src/VuFind/Controller/MyResearchController.php b/module/VuFind/src/VuFind/Controller/MyResearchController.php index 1ed3e32d1c3..ccd01af65a1 100644 --- a/module/VuFind/src/VuFind/Controller/MyResearchController.php +++ b/module/VuFind/src/VuFind/Controller/MyResearchController.php @@ -1007,14 +1007,16 @@ public function editAction() } // Get saved favorites for selected list (or all lists if $listID is null) - $userResources = $user->getSavedData($id, $listID, $source); + $userResourceService = $this->getDbService(\VuFind\Db\Service\UserResourceService::class); + $userResources = $userResourceService->getSavedData($id, $listID, $source, $user->id); $savedData = []; - foreach ($userResources as $current) { + foreach ($userResources as $userResource) { + $current = $userResource[0]; $savedData[] = [ - 'listId' => $current->list_id, - 'listTitle' => $current->list_title, - 'notes' => $current->notes, - 'tags' => $user->getTagString($id, $current->list_id, $source), + 'listId' => $current->getList()->getId(), + 'listTitle' => $current->getList()->getTitle(), + 'notes' => $current->getNotes(), + 'tags' => $user->getTagString($id, $current->getList()->getId(), $source), ]; } @@ -1023,10 +1025,10 @@ public function editAction() // to a particular list ID: $containingLists = []; if (!empty($listID)) { - $userResources = $user->getSavedData($id, null, $source); + $userResources = $userResourceService->getSavedData($id, null, $source, $user->id); } foreach ($userResources as $current) { - $containingLists[] = $current->list_id; + $containingLists[] = $current[0]->getList()->getId(); } // Send non-containing lists to the view for user selection: $userLists = $this->getListService()->getListsForUser($user->id); diff --git a/module/VuFind/src/VuFind/Db/Row/User.php b/module/VuFind/src/VuFind/Db/Row/User.php index 3c20be1cfab..d22baa18789 100644 --- a/module/VuFind/src/VuFind/Db/Row/User.php +++ b/module/VuFind/src/VuFind/Db/Row/User.php @@ -334,25 +334,6 @@ public function formatTagString($tags) return trim($tagStr); } - /** - * Get information saved in a user's favorites for a particular record. - * - * @param string $resourceId ID of record being checked. - * @param int $listId Optional list ID (to limit results to a particular - * list). - * @param string $source Source of record to look up - * - * @return array - */ - public function getSavedData( - $resourceId, - $listId = null, - $source = DEFAULT_SEARCH_BACKEND - ) { - $table = $this->getDbTable('UserResource'); - return $table->getSavedData($resourceId, $source, $listId, $this->id); - } - /** * Given an array of item ids, remove them from all lists * diff --git a/module/VuFind/src/VuFind/Db/Service/UserResourceService.php b/module/VuFind/src/VuFind/Db/Service/UserResourceService.php index 0bacd481c00..64c35654d20 100644 --- a/module/VuFind/src/VuFind/Db/Service/UserResourceService.php +++ b/module/VuFind/src/VuFind/Db/Service/UserResourceService.php @@ -231,4 +231,40 @@ public function createUserResource(): UserResource $class = $this->getEntityClass(UserResource::class); return new $class(); } + + /** + * Get information saved in a user's favorites for a particular record. + * + * @param string $resourceId ID of record being checked. + * @param string $source Source of record to look up + * @param int|UserList $list Optional list (to limit results to a particular list). + * @param int|User $user Optional user (to limit results to a particular user). + * + * @return array + */ + public function getSavedData( + $resourceId, + $source = DEFAULT_SEARCH_BACKEND, + $list = null, + $user = null + ) { + $dql = 'SELECT DISTINCT(ur.id), ur FROM ' . $this->getEntityClass(UserResource::class) . ' ur ' + . 'JOIN ' . $this->getEntityClass(Resource::class) . ' r WITH r.id = ur.resource ' + . 'WHERE r.source = :source AND r.recordId = :resourceId '; + + $parameters = compact('source', 'resourceId'); + if (null !== $user) { + $dql .= 'AND ur.user = :user '; + $parameters['user'] = $user; + } + if (null !== $list) { + $dql .= 'AND ur.list = :list'; + $parameters['list'] = $list; + } + + $query = $this->entityManager->createQuery($dql); + $query->setParameters($parameters); + $result = $query->getResult(); + return $result; + } } diff --git a/module/VuFind/src/VuFind/Db/Table/UserResource.php b/module/VuFind/src/VuFind/Db/Table/UserResource.php index dfaa080e47e..468fd2b86a2 100644 --- a/module/VuFind/src/VuFind/Db/Table/UserResource.php +++ b/module/VuFind/src/VuFind/Db/Table/UserResource.php @@ -30,12 +30,8 @@ namespace VuFind\Db\Table; use Laminas\Db\Adapter\Adapter; -use Laminas\Db\Sql\Expression; -use Laminas\Db\Sql\Select; use VuFind\Db\Row\RowGateway; -use function is_array; - /** * Table Definition for user_resource * @@ -67,136 +63,4 @@ public function __construct( ) { parent::__construct($adapter, $tm, $cfg, $rowObj, $table); } - - /** - * Get information saved in a user's favorites for a particular record. - * - * @param string $resourceId ID of record being checked. - * @param string $source Source of record to look up - * @param int $listId Optional list ID (to limit results to a particular - * list). - * @param int $userId Optional user ID (to limit results to a particular - * user). - * - * @return \Laminas\Db\ResultSet\AbstractResultSet - */ - public function getSavedData( - $resourceId, - $source = DEFAULT_SEARCH_BACKEND, - $listId = null, - $userId = null - ) { - $callback = function ($select) use ($resourceId, $source, $listId, $userId) { - $select->columns( - [ - new Expression( - 'DISTINCT(?)', - ['user_resource.id'], - [Expression::TYPE_IDENTIFIER] - ), Select::SQL_STAR, - ] - ); - $select->join( - ['r' => 'resource'], - 'r.id = user_resource.resource_id', - [] - ); - $select->join( - ['ul' => 'user_list'], - 'user_resource.list_id = ul.id', - ['list_title' => 'title', 'list_id' => 'id'] - ); - $select->where->equalTo('r.source', $source) - ->equalTo('r.record_id', $resourceId); - - if (null !== $userId) { - $select->where->equalTo('user_resource.user_id', $userId); - } - if (null !== $listId) { - $select->where->equalTo('user_resource.list_id', $listId); - } - }; - return $this->select($callback); - } - - /** - * Create link if one does not exist; update notes if one does. - * - * @param string $resource_id ID of resource to link up - * @param string $user_id ID of user creating link - * @param string $list_id ID of list to link up - * @param string $notes Notes to associate with link - * - * @return \VuFind\Db\Row\UserResource - */ - public function createOrUpdateLink( - $resource_id, - $user_id, - $list_id, - $notes = '' - ) { - $params = [ - 'resource_id' => $resource_id, 'list_id' => $list_id, - 'user_id' => $user_id, - ]; - $result = $this->select($params)->current(); - - // Only create row if it does not already exist: - if (empty($result)) { - $result = $this->createRow(); - $result->resource_id = $resource_id; - $result->list_id = $list_id; - $result->user_id = $user_id; - } - - // Update the notes: - $result->notes = $notes; - $result->save(); - return $result; - } - - /** - * Unlink rows for the specified resource. This will also automatically remove - * any tags associated with the relationship. - * - * @param string|array $resource_id ID (or array of IDs) of resource(s) to - * unlink (null for ALL matching resources) - * @param string $user_id ID of user removing links - * @param string $list_id ID of list to unlink - * (null for ALL matching lists, with the destruction of all tags associated - * with the $resource_id value; true for ALL matching lists, but retaining - * any tags associated with the $resource_id independently of lists) - * - * @return void - */ - public function destroyLinks($resource_id, $user_id, $list_id = null) - { - // Remove any tags associated with the links we are removing; we don't - // want to leave orphaned tags in the resource_tags table after we have - // cleared out favorites in user_resource! - $tagService = $this->getDbService(\VuFind\Db\Service\TagService::class); - $tagService->destroyResourceLinks($resource_id, $user_id, $list_id); - - // Now build the where clause to figure out which rows to remove: - $callback = function ($select) use ($resource_id, $user_id, $list_id) { - $select->where->equalTo('user_id', $user_id); - if (null !== $resource_id) { - if (!is_array($resource_id)) { - $resource_id = [$resource_id]; - } - $select->where->in('resource_id', $resource_id); - } - // null or true values of $list_id have different meanings in the - // context of the $tagService->destroyResourceLinks() call above, since - // some tags have a null $list_id value. In the case of user_resource - // rows, however, every row has a non-null $list_id value, so the - // two cases are equivalent and may be handled identically. - if (null !== $list_id && true !== $list_id) { - $select->where->equalTo('list_id', $list_id); - } - }; - - // Delete the rows: - $this->delete($callback); - } } diff --git a/module/VuFind/src/VuFind/RecordDriver/AbstractBase.php b/module/VuFind/src/VuFind/RecordDriver/AbstractBase.php index 461469ef70d..991255c22d9 100644 --- a/module/VuFind/src/VuFind/RecordDriver/AbstractBase.php +++ b/module/VuFind/src/VuFind/RecordDriver/AbstractBase.php @@ -321,8 +321,7 @@ public function addOrUpdateRating(int $userId, ?int $rating): void */ public function getListNotes($list_id = null, $user_id = null) { - $db = $this->getDbTable('UserResource'); - $data = $db->getSavedData( + $data = $this->getDbService(\VuFind\Db\Service\UserResourceService::class)->getSavedData( $this->getUniqueId(), $this->getSourceIdentifier(), $list_id,