Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
2.78% covered (danger)
2.78%
1 / 36
7.69% covered (danger)
7.69%
1 / 13
CRAP
0.00% covered (danger)
0.00%
0 / 1
ResourceService
2.78% covered (danger)
2.78%
1 / 36
7.69% covered (danger)
7.69%
1 / 13
315.74
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 beginTransaction
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 commitTransaction
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 rollBackTransaction
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getResourceById
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 createEntity
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 findMissingMetadata
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getResourceByRecordId
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getResourcesByRecordIds
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getFavorites
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
12
 deleteResourceByRecordId
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 renameSource
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 deleteResource
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3/**
4 * Database service for resource.
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   Demian Katz <demian.katz@villanova.edu>
26 * @author   Sudharma Kellampalli <skellamp@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
31namespace VuFind\Db\Service;
32
33use Exception;
34use VuFind\Db\Entity\ResourceEntityInterface;
35use VuFind\Db\Entity\UserEntityInterface;
36use VuFind\Db\Entity\UserListEntityInterface;
37use VuFind\Db\Table\Resource;
38
39use function count;
40
41/**
42 * Database service for resource.
43 *
44 * @category VuFind
45 * @package  Database
46 * @author   Demian Katz <demian.katz@villanova.edu>
47 * @author   Sudharma Kellampalli <skellamp@villanova.edu>
48 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
49 * @link     https://vufind.org/wiki/development:plugins:database_gateways Wiki
50 */
51class ResourceService extends AbstractDbService implements ResourceServiceInterface, Feature\TransactionInterface
52{
53    /**
54     * Constructor.
55     *
56     * @param Resource $resourceTable Resource table
57     */
58    public function __construct(protected Resource $resourceTable)
59    {
60    }
61
62    /**
63     * Begin a database transaction.
64     *
65     * @return void
66     * @throws Exception
67     */
68    public function beginTransaction(): void
69    {
70        $this->resourceTable->beginTransaction();
71    }
72
73    /**
74     * Commit a database transaction.
75     *
76     * @return void
77     * @throws Exception
78     */
79    public function commitTransaction(): void
80    {
81        $this->resourceTable->commitTransaction();
82    }
83
84    /**
85     * Roll back a database transaction.
86     *
87     * @return void
88     * @throws Exception
89     */
90    public function rollBackTransaction(): void
91    {
92        $this->resourceTable->rollbackTransaction();
93    }
94
95    /**
96     * Lookup and return a resource.
97     *
98     * @param int $id Identifier value
99     *
100     * @return ?ResourceEntityInterface
101     */
102    public function getResourceById(int $id): ?ResourceEntityInterface
103    {
104        return $this->resourceTable->select(['id' => $id])->current();
105    }
106
107    /**
108     * Create a resource entity object.
109     *
110     * @return ResourceEntityInterface
111     */
112    public function createEntity(): ResourceEntityInterface
113    {
114        return $this->resourceTable->createRow();
115    }
116
117    /**
118     * Get a set of records that do not have metadata stored in the resource
119     * table.
120     *
121     * @return ResourceEntityInterface[]
122     */
123    public function findMissingMetadata(): array
124    {
125        $callback = function ($select) {
126            $select->where->equalTo('title', '')
127                ->OR->isNull('author')
128                ->OR->isNull('year');
129        };
130        return iterator_to_array($this->resourceTable->select($callback));
131    }
132
133    /**
134     * Retrieve a single resource row by record ID/source. Return null if it does not exist.
135     *
136     * @param string $id     Record ID
137     * @param string $source Record source
138     *
139     * @return ?ResourceEntityInterface
140     */
141    public function getResourceByRecordId(string $id, string $source = DEFAULT_SEARCH_BACKEND): ?ResourceEntityInterface
142    {
143        return $this->resourceTable->select(['record_id' => $id, 'source' => $source])->current();
144    }
145
146    /**
147     * Retrieve resource entities matching a set of specified records.
148     *
149     * @param string[] $ids    Array of IDs
150     * @param string   $source Source of records to look up
151     *
152     * @return ResourceEntityInterface[]
153     */
154    public function getResourcesByRecordIds(array $ids, string $source = DEFAULT_SEARCH_BACKEND): array
155    {
156        $callback = function ($select) use ($ids, $source) {
157            $select->where->in('record_id', $ids);
158            $select->where->equalTo('source', $source);
159        };
160        return iterator_to_array($this->resourceTable->select($callback));
161    }
162
163    /**
164     * Get a set of resources from the requested favorite list.
165     *
166     * @param UserEntityInterface|int          $userOrId          ID of user owning favorite list
167     * @param UserListEntityInterface|int|null $listOrId          ID of list to retrieve (null for all favorites)
168     * @param string[]                         $tags              Tags to use for limiting results
169     * @param ?string                          $sort              Resource table field to use for sorting (null for no
170     * particular sort).
171     * @param int                              $offset            Offset for results
172     * @param ?int                             $limit             Limit for results (null for none)
173     * @param bool                             $caseSensitiveTags Treat tags as case-sensitive?
174     *
175     * @return ResourceEntityInterface[]
176     */
177    public function getFavorites(
178        UserEntityInterface|int $userOrId,
179        UserListEntityInterface|int|null $listOrId = null,
180        array $tags = [],
181        ?string $sort = null,
182        int $offset = 0,
183        ?int $limit = null,
184        bool $caseSensitiveTags = false
185    ): array {
186        return iterator_to_array(
187            $this->resourceTable->getFavorites(
188                $userOrId instanceof UserEntityInterface ? $userOrId->getId() : $userOrId,
189                $listOrId instanceof UserListEntityInterface ? $listOrId->getId() : $listOrId,
190                $tags,
191                $sort,
192                $offset,
193                $limit,
194                $caseSensitiveTags
195            )
196        );
197    }
198
199    /**
200     * Delete a resource by record id and source. Return true if found and deleted, false if not found.
201     * Throws exception if something goes wrong.
202     *
203     * @param string $id     Resource ID
204     * @param string $source Resource source
205     *
206     * @return bool
207     * @throws Exception
208     */
209    public function deleteResourceByRecordId(string $id, string $source): bool
210    {
211        $row = $this->resourceTable->select(['source' => $source, 'record_id' => $id])->current();
212        if (!$row) {
213            return false;
214        }
215        $row->delete();
216        return true;
217    }
218
219    /**
220     * Globally change the name of a source value in the database; return the number of rows affected.
221     *
222     * @param string $old Old source value
223     * @param string $new New source value
224     *
225     * @return int
226     */
227    public function renameSource(string $old, string $new): int
228    {
229        $resourceWhere = ['source' => $old];
230        $resourceRows = $this->resourceTable->select($resourceWhere);
231        if ($count = count($resourceRows)) {
232            $this->resourceTable->update(['source' => $new], $resourceWhere);
233        }
234        return $count;
235    }
236
237    /**
238     * Delete a resource entity.
239     *
240     * @param ResourceEntityInterface|int $resourceOrId Resource entity or ID value.
241     *
242     * @return void
243     */
244    public function deleteResource(ResourceEntityInterface|int $resourceOrId): void
245    {
246        $id = $resourceOrId instanceof ResourceEntityInterface ? $resourceOrId->getId() : $resourceOrId;
247        $this->resourceTable->delete(['id' => $id]);
248    }
249}