Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
15.79% |
6 / 38 |
|
25.00% |
2 / 8 |
CRAP | |
0.00% |
0 / 1 |
UserListService | |
15.79% |
6 / 38 |
|
25.00% |
2 / 8 |
189.58 | |
0.00% |
0 / 1 |
createEntity | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
deleteUserList | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
getUserListById | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
getPublicLists | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
20 | |||
getUserListsAndCountsByUser | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
12 | |||
getUserListsByTagAndId | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
getUserListsByUser | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
getListsContainingRecord | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | |
3 | /** |
4 | * Database service for UserList. |
5 | * |
6 | * PHP version 8 |
7 | * |
8 | * Copyright (C) Villanova University 2023. |
9 | * |
10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License version 2, |
12 | * as published by the Free Software Foundation. |
13 | * |
14 | * This program is distributed in the hope that it will be useful, |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | * GNU General Public License for more details. |
18 | * |
19 | * You should have received a copy of the GNU General Public License |
20 | * along with this program; if not, write to the Free Software |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
22 | * |
23 | * @category VuFind |
24 | * @package Database |
25 | * @author Sudharma Kellampalli <skellamp@villanova.edu> |
26 | * @author Demian Katz <demian.katz@villanova.edu> |
27 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License |
28 | * @link https://vufind.org/wiki/development:plugins:database_gateways Wiki |
29 | */ |
30 | |
31 | namespace VuFind\Db\Service; |
32 | |
33 | use Exception; |
34 | use Laminas\Db\Sql\Expression; |
35 | use Laminas\Db\Sql\ExpressionInterface; |
36 | use Laminas\Db\Sql\Select; |
37 | use VuFind\Db\Entity\UserEntityInterface; |
38 | use VuFind\Db\Entity\UserListEntityInterface; |
39 | use VuFind\Db\Table\DbTableAwareInterface; |
40 | use VuFind\Db\Table\DbTableAwareTrait; |
41 | use VuFind\Exception\RecordMissing as RecordMissingException; |
42 | |
43 | use function is_int; |
44 | |
45 | /** |
46 | * Database service for UserList. |
47 | * |
48 | * @category VuFind |
49 | * @package Database |
50 | * @author Sudharma Kellampalli <skellamp@villanova.edu> |
51 | * @author Demian Katz <demian.katz@villanova.edu> |
52 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License |
53 | * @link https://vufind.org/wiki/development:plugins:database_gateways Wiki |
54 | */ |
55 | class UserListService extends AbstractDbService implements DbTableAwareInterface, UserListServiceInterface |
56 | { |
57 | use DbTableAwareTrait; |
58 | |
59 | /** |
60 | * Create a UserList entity object. |
61 | * |
62 | * @return UserListEntityInterface |
63 | */ |
64 | public function createEntity(): UserListEntityInterface |
65 | { |
66 | return $this->getDbTable('UserList')->createRow(); |
67 | } |
68 | |
69 | /** |
70 | * Delete a user list entity. |
71 | * |
72 | * @param UserListEntityInterface|int $listOrId List entity object or ID to delete |
73 | * |
74 | * @return void |
75 | */ |
76 | public function deleteUserList(UserListEntityInterface|int $listOrId): void |
77 | { |
78 | $listId = $listOrId instanceof UserListEntityInterface ? $listOrId->getId() : $listOrId; |
79 | $this->getDbTable('UserList')->delete(['id' => $listId]); |
80 | } |
81 | |
82 | /** |
83 | * Retrieve a list object. |
84 | * |
85 | * @param int $id Numeric ID for existing list. |
86 | * |
87 | * @return UserListEntityInterface |
88 | * @throws RecordMissingException |
89 | */ |
90 | public function getUserListById(int $id): UserListEntityInterface |
91 | { |
92 | $result = $this->getDbTable('UserList')->select(['id' => $id])->current(); |
93 | if (empty($result)) { |
94 | throw new RecordMissingException('Cannot load list ' . $id); |
95 | } |
96 | return $result; |
97 | } |
98 | |
99 | /** |
100 | * Get public lists. |
101 | * |
102 | * @param array $includeFilter List of list ids or entities to include in result. |
103 | * @param array $excludeFilter List of list ids or entities to exclude from result. |
104 | * |
105 | * @return UserListEntityInterface[] |
106 | */ |
107 | public function getPublicLists(array $includeFilter = [], array $excludeFilter = []): array |
108 | { |
109 | $callback = function ($listOrId) { |
110 | return $listOrId instanceof UserListEntityInterface ? $listOrId->getId() : $listOrId; |
111 | }; |
112 | $includeIds = array_map($callback, $includeFilter); |
113 | $excludeIds = array_map($callback, $excludeFilter); |
114 | $callback = function ($select) use ($includeIds, $excludeIds) { |
115 | $select->where->equalTo('public', 1); |
116 | if ($excludeIds) { |
117 | $select->where->notIn('id', $excludeIds); |
118 | } |
119 | if ($includeIds) { |
120 | $select->where->in('id', $includeIds); |
121 | } |
122 | }; |
123 | return iterator_to_array($this->getDbTable('UserList')->select($callback)); |
124 | } |
125 | |
126 | /** |
127 | * Get lists belonging to the user and their count. Returns an array of arrays with |
128 | * list_entity and count keys. |
129 | * |
130 | * @param UserEntityInterface|int $userOrId User entity object or ID |
131 | * |
132 | * @return array |
133 | * @throws Exception |
134 | */ |
135 | public function getUserListsAndCountsByUser(UserEntityInterface|int $userOrId): array |
136 | { |
137 | $userId = $userOrId instanceof UserEntityInterface ? $userOrId->getId() : $userOrId; |
138 | $callback = function (Select $select) use ($userId) { |
139 | $select->columns( |
140 | [ |
141 | Select::SQL_STAR, |
142 | 'cnt' => new Expression( |
143 | 'COUNT(DISTINCT(?))', |
144 | ['ur.resource_id'], |
145 | [ExpressionInterface::TYPE_IDENTIFIER] |
146 | ), |
147 | ] |
148 | ); |
149 | $select->join( |
150 | ['ur' => 'user_resource'], |
151 | 'user_list.id = ur.list_id', |
152 | [], |
153 | $select::JOIN_LEFT |
154 | ); |
155 | $select->where->equalTo('user_list.user_id', $userId); |
156 | $select->group( |
157 | [ |
158 | 'user_list.id', 'user_list.user_id', 'title', 'description', |
159 | 'created', 'public', |
160 | ] |
161 | ); |
162 | $select->order(['title']); |
163 | }; |
164 | |
165 | $result = []; |
166 | foreach ($this->getDbTable('UserList')->select($callback) as $row) { |
167 | $result[] = ['list_entity' => $row, 'count' => $row->cnt]; |
168 | } |
169 | return $result; |
170 | } |
171 | |
172 | /** |
173 | * Get lists associated with a particular tag and/or list of IDs. If IDs and |
174 | * tags are both provided, only the intersection of matches will be returned. |
175 | * |
176 | * @param string|string[]|null $tag Tag or tags to match (by text, not ID; null for all) |
177 | * @param int|int[]|null $listId List ID or IDs to match (null for all) |
178 | * @param bool $publicOnly Whether to return only public lists |
179 | * @param bool $andTags Use AND operator when filtering by tag. |
180 | * @param bool $caseSensitiveTags Should we treat tags case-sensitively? |
181 | * |
182 | * @return UserListEntityInterface[] |
183 | */ |
184 | public function getUserListsByTagAndId( |
185 | string|array|null $tag = null, |
186 | int|array|null $listId = null, |
187 | bool $publicOnly = true, |
188 | bool $andTags = true, |
189 | bool $caseSensitiveTags = false |
190 | ): array { |
191 | $lists = $this->getDbTable('ResourceTags') |
192 | ->getListsForTag($tag, $listId, $publicOnly, $andTags, $caseSensitiveTags); |
193 | $listIds = array_column(iterator_to_array($lists), 'list_id'); |
194 | $callback = function ($select) use ($listIds) { |
195 | $select->where->in('id', $listIds); |
196 | }; |
197 | return iterator_to_array($this->getDbTable('UserList')->select($callback)); |
198 | } |
199 | |
200 | /** |
201 | * Get list objects belonging to the specified user. |
202 | * |
203 | * @param UserEntityInterface|int $userOrId User entity object or ID |
204 | * |
205 | * @return UserListEntityInterface[] |
206 | */ |
207 | public function getUserListsByUser(UserEntityInterface|int $userOrId): array |
208 | { |
209 | $userId = $userOrId instanceof UserEntityInterface ? $userOrId->getId() : $userOrId; |
210 | $callback = function ($select) use ($userId) { |
211 | $select->where->equalTo('user_id', $userId); |
212 | $select->order(['title']); |
213 | }; |
214 | return iterator_to_array($this->getDbTable('UserList')->select($callback)); |
215 | } |
216 | |
217 | /** |
218 | * Get lists containing a specific record. |
219 | * |
220 | * @param string $recordId ID of record being checked. |
221 | * @param string $source Source of record to look up |
222 | * @param UserEntityInterface|int|null $userOrId Optional user ID or entity object (to limit results |
223 | * to a particular user). |
224 | * |
225 | * @return UserListEntityInterface[] |
226 | */ |
227 | public function getListsContainingRecord( |
228 | string $recordId, |
229 | string $source = DEFAULT_SEARCH_BACKEND, |
230 | UserEntityInterface|int|null $userOrId = null |
231 | ): array { |
232 | return iterator_to_array( |
233 | $this->getDbTable('UserList')->getListsContainingResource( |
234 | $recordId, |
235 | $source, |
236 | is_int($userOrId) ? $userOrId : $userOrId->getId() |
237 | ) |
238 | ); |
239 | } |
240 | } |