Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
3.28% |
2 / 61 |
|
40.00% |
2 / 5 |
CRAP | |
0.00% |
0 / 1 |
Ratings | |
3.28% |
2 / 61 |
|
40.00% |
2 / 5 |
218.59 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getForResource | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
12 | |||
getCountsForResource | |
0.00% |
0 / 26 |
|
0.00% |
0 / 1 |
90 | |||
deleteByUser | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getStatistics | |
0.00% |
0 / 19 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | /** |
4 | * Table Definition for ratings |
5 | * |
6 | * PHP version 8 |
7 | * |
8 | * Copyright (C) The National Library of Finland 2022. |
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 Db_Table |
25 | * @author Ere Maijala <ere.maijala@helsinki.fi> |
26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License |
27 | * @link https://vufind.org Main Site |
28 | */ |
29 | |
30 | namespace VuFind\Db\Table; |
31 | |
32 | use Laminas\Db\Adapter\Adapter; |
33 | use Laminas\Db\Sql\Expression; |
34 | use Laminas\Db\Sql\Select; |
35 | use VuFind\Db\Row\RowGateway; |
36 | use VuFind\Db\Service\DbServiceAwareInterface; |
37 | use VuFind\Db\Service\DbServiceAwareTrait; |
38 | use VuFind\Db\Service\ResourceServiceInterface; |
39 | |
40 | /** |
41 | * Table Definition for ratings |
42 | * |
43 | * @category VuFind |
44 | * @package Db_Table |
45 | * @author Ere Maijala <ere.maijala@helsinki.fi> |
46 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License |
47 | * @link https://vufind.org Main Site |
48 | */ |
49 | class Ratings extends Gateway implements DbServiceAwareInterface |
50 | { |
51 | use DbServiceAwareTrait; |
52 | |
53 | /** |
54 | * Constructor |
55 | * |
56 | * @param Adapter $adapter Database adapter |
57 | * @param PluginManager $tm Table manager |
58 | * @param array $cfg Laminas configuration |
59 | * @param RowGateway $rowObj Row prototype object (null for default) |
60 | * @param string $table Name of database table to interface with |
61 | */ |
62 | public function __construct( |
63 | Adapter $adapter, |
64 | PluginManager $tm, |
65 | $cfg, |
66 | ?RowGateway $rowObj = null, |
67 | $table = 'ratings' |
68 | ) { |
69 | parent::__construct($adapter, $tm, $cfg, $rowObj, $table); |
70 | } |
71 | |
72 | /** |
73 | * Get average rating and rating count associated with the specified resource. |
74 | * |
75 | * @param string $id Record ID to look up |
76 | * @param string $source Source of record to look up |
77 | * @param ?int $userId User ID, or null for all users |
78 | * |
79 | * @return array Array with keys count and rating (between 0 and 100) |
80 | */ |
81 | public function getForResource(string $id, string $source, ?int $userId): array |
82 | { |
83 | $resourceService = $this->getDbService(ResourceServiceInterface::class); |
84 | $resource = $resourceService->getResourceByRecordId($id, $source); |
85 | if (!$resource) { |
86 | return [ |
87 | 'count' => 0, |
88 | 'rating' => 0, |
89 | ]; |
90 | } |
91 | |
92 | $callback = function ($select) use ($resource, $userId) { |
93 | $select->columns( |
94 | [ |
95 | // RowGateway requires an id field: |
96 | 'id' => new Expression( |
97 | '1', |
98 | [], |
99 | [Expression::TYPE_IDENTIFIER] |
100 | ), |
101 | 'count' => new Expression( |
102 | 'COUNT(?)', |
103 | [Select::SQL_STAR], |
104 | [Expression::TYPE_IDENTIFIER] |
105 | ), |
106 | 'rating' => new Expression( |
107 | 'FLOOR(AVG(?))', |
108 | ['rating'], |
109 | [Expression::TYPE_IDENTIFIER] |
110 | ), |
111 | ] |
112 | ); |
113 | $select->where->equalTo('ratings.resource_id', $resource->id); |
114 | if (null !== $userId) { |
115 | $select->where->equalTo('ratings.user_id', $userId); |
116 | } |
117 | }; |
118 | |
119 | $result = $this->select($callback)->current(); |
120 | return [ |
121 | 'count' => $result->count ?? 0, |
122 | 'rating' => $result->rating ?? 0, |
123 | ]; |
124 | } |
125 | |
126 | /** |
127 | * Get rating breakdown for the specified resource. |
128 | * |
129 | * @param string $id Record ID to look up |
130 | * @param string $source Source of record to look up |
131 | * @param array $groups Group definition (key => [min, max]) |
132 | * |
133 | * @return array Array with keys count and rating (between 0 and 100) as well as |
134 | * an groups array with ratings from lowest to highest |
135 | */ |
136 | public function getCountsForResource( |
137 | string $id, |
138 | string $source, |
139 | array $groups |
140 | ): array { |
141 | $result = [ |
142 | 'count' => 0, |
143 | 'rating' => 0, |
144 | 'groups' => [], |
145 | ]; |
146 | foreach (array_keys($groups) as $key) { |
147 | $result['groups'][$key] = 0; |
148 | } |
149 | |
150 | $resourceService = $this->getDbService(ResourceServiceInterface::class); |
151 | $resource = $resourceService->getResourceByRecordId($id, $source); |
152 | if (!$resource) { |
153 | return $result; |
154 | } |
155 | |
156 | $callback = function ($select) use ($resource) { |
157 | $select->columns( |
158 | [ |
159 | // RowGateway requires an id field: |
160 | 'id' => new Expression( |
161 | '1', |
162 | [], |
163 | [Expression::TYPE_IDENTIFIER] |
164 | ), |
165 | 'count' => new Expression( |
166 | 'COUNT(?)', |
167 | [Select::SQL_STAR], |
168 | [Expression::TYPE_IDENTIFIER] |
169 | ), |
170 | 'rating' => 'rating', |
171 | ] |
172 | ); |
173 | $select->where->equalTo('ratings.resource_id', $resource->id); |
174 | $select->group('rating'); |
175 | }; |
176 | |
177 | $ratingTotal = 0; |
178 | $groupCount = 0; |
179 | foreach ($this->select($callback) as $rating) { |
180 | $result['count'] += $rating->count; |
181 | $ratingTotal += $rating->rating; |
182 | ++$groupCount; |
183 | if ($groups) { |
184 | foreach ($groups as $key => $range) { |
185 | if ( |
186 | $rating->rating >= $range[0] && $rating->rating <= $range[1] |
187 | ) { |
188 | $result['groups'][$key] = ($result['groups'][$key] ?? 0) |
189 | + $rating->count; |
190 | } |
191 | } |
192 | } |
193 | } |
194 | $result['rating'] = $groupCount ? floor($ratingTotal / $groupCount) : 0; |
195 | return $result; |
196 | } |
197 | |
198 | /** |
199 | * Deletes all ratings by a user. |
200 | * |
201 | * @param \VuFind\Db\Row\User $user User object |
202 | * |
203 | * @return void |
204 | */ |
205 | public function deleteByUser(\VuFind\Db\Row\User $user): void |
206 | { |
207 | $this->delete(['user_id' => $user->id]); |
208 | } |
209 | |
210 | /** |
211 | * Get statistics on use of ratings. |
212 | * |
213 | * @return array |
214 | */ |
215 | public function getStatistics(): array |
216 | { |
217 | $select = $this->sql->select(); |
218 | $select->columns( |
219 | [ |
220 | 'users' => new Expression( |
221 | 'COUNT(DISTINCT(?))', |
222 | ['user_id'], |
223 | [Expression::TYPE_IDENTIFIER] |
224 | ), |
225 | 'resources' => new Expression( |
226 | 'COUNT(DISTINCT(?))', |
227 | ['resource_id'], |
228 | [Expression::TYPE_IDENTIFIER] |
229 | ), |
230 | 'total' => new Expression('COUNT(*)'), |
231 | ] |
232 | ); |
233 | $statement = $this->sql->prepareStatementForSqlObject($select); |
234 | $result = $statement->execute(); |
235 | return (array)$result->current(); |
236 | } |
237 | } |