Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 54
0.00% covered (danger)
0.00%
0 / 28
CRAP
0.00% covered (danger)
0.00%
0 / 1
Search
0.00% covered (danger)
0.00%
0 / 54
0.00% covered (danger)
0.00%
0 / 28
1260
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 normalizeSearchObject
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 getSearchObject
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 getSearchObjectOrThrowException
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 save
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setLastExecuted
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setSchedule
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 getUnsubscribeSecret
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 getId
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getUser
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 setUser
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getSessionId
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setSessionId
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getCreated
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setCreated
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getTitle
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setTitle
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getSaved
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setSaved
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 setSearchObject
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 getChecksum
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setChecksum
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getNotificationFrequency
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setNotificationFrequency
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getLastNotificationSent
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setLastNotificationSent
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getNotificationBaseUrl
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setNotificationBaseUrl
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3/**
4 * Row Definition for search
5 *
6 * PHP version 8
7 *
8 * Copyright (C) Villanova University 2010.
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_Row
25 * @author   Demian Katz <demian.katz@villanova.edu>
26 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
27 * @link     https://vufind.org Main Site
28 */
29
30namespace VuFind\Db\Row;
31
32use DateTime;
33use VuFind\Crypt\HMAC;
34use VuFind\Db\Entity\SearchEntityInterface;
35use VuFind\Db\Entity\UserEntityInterface;
36use VuFind\Db\Service\DbServiceAwareInterface;
37use VuFind\Db\Service\DbServiceAwareTrait;
38use VuFind\Db\Service\UserServiceInterface;
39
40use function is_resource;
41
42/**
43 * Row Definition for search
44 *
45 * @category VuFind
46 * @package  Db_Row
47 * @author   Demian Katz <demian.katz@villanova.edu>
48 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
49 * @link     https://vufind.org Main Site
50 *
51 * @property int     $id
52 * @property int     $user_id
53 * @property ?string $session_id
54 * @property string  $created
55 * @property ?string $title
56 * @property int     $saved
57 * @property string  $search_object
58 * @property ?int    $checksum
59 * @property int     $notification_frequency
60 * @property string  $last_notification_sent
61 * @property string  $notification_base_url
62 */
63class Search extends RowGateway implements
64    \VuFind\Db\Entity\SearchEntityInterface,
65    \VuFind\Db\Table\DbTableAwareInterface,
66    DbServiceAwareInterface
67{
68    use \VuFind\Db\Table\DbTableAwareTrait;
69    use DbServiceAwareTrait;
70
71    /**
72     * Constructor
73     *
74     * @param \Laminas\Db\Adapter\Adapter $adapter Database adapter
75     */
76    public function __construct($adapter)
77    {
78        parent::__construct('id', 'search', $adapter);
79    }
80
81    /**
82     * Support method to make sure that the search_object field is formatted as a
83     * string, since PostgreSQL sometimes represents it as a resource.
84     *
85     * @return void
86     */
87    protected function normalizeSearchObject()
88    {
89        // Note that if we have a resource, we need to grab the contents before
90        // saving -- this is necessary for PostgreSQL compatibility although MySQL
91        // returns a plain string
92        if (is_resource($this->search_object)) {
93            $this->search_object = stream_get_contents($this->search_object);
94        }
95    }
96
97    /**
98     * Get the search object from the row.
99     *
100     * @return ?\VuFind\Search\Minified
101     */
102    public function getSearchObject(): ?\VuFind\Search\Minified
103    {
104        // We need to make sure the search object is a string before unserializing:
105        $this->normalizeSearchObject();
106        return $this->search_object ? unserialize($this->search_object) : null;
107    }
108
109    /**
110     * Get the search object from the row, and throw an exception if it is missing.
111     *
112     * @return \VuFind\Search\Minified
113     * @throws \Exception
114     *
115     * @deprecated
116     */
117    public function getSearchObjectOrThrowException(): \VuFind\Search\Minified
118    {
119        if (!($result = $this->getSearchObject())) {
120            throw new \Exception('Problem decoding saved search');
121        }
122        return $result;
123    }
124
125    /**
126     * Save
127     *
128     * @return int
129     */
130    public function save()
131    {
132        // We can't save if the search object is a resource; make sure it's a
133        // string first:
134        $this->normalizeSearchObject();
135        return parent::save();
136    }
137
138    /**
139     * Set last executed time for scheduled alert.
140     *
141     * @param string $time Time.
142     *
143     * @return mixed
144     *
145     * @deprecated
146     */
147    public function setLastExecuted($time)
148    {
149        $this->last_notification_sent = $time;
150        return $this->save();
151    }
152
153    /**
154     * Set schedule for scheduled alert.
155     *
156     * @param int    $schedule Schedule.
157     * @param string $url      Site base URL
158     *
159     * @return mixed
160     *
161     * @deprecated
162     */
163    public function setSchedule($schedule, $url = null)
164    {
165        $this->notification_frequency = $schedule;
166        if ($url) {
167            $this->notification_base_url = $url;
168        }
169        return $this->save();
170    }
171
172    /**
173     * Utility function for generating a token for unsubscribing a
174     * saved search.
175     *
176     * @param HMAC                $hmac HMAC hash generator
177     * @param UserEntityInterface $user User object
178     *
179     * @return string token
180     *
181     * @deprecated Use \VuFind\Crypt\SecretCalculator::getSearchUnsubscribeSecret()
182     */
183    public function getUnsubscribeSecret(HMAC $hmac, $user)
184    {
185        $data = [
186            'id' => $this->id,
187            'user_id' => $user->getId(),
188            'created' => $user->getCreated()->format('Y-m-d H:i:s'),
189        ];
190        return $hmac->generate(array_keys($data), $data);
191    }
192
193    /**
194     * Get identifier (returns null for an uninitialized or non-persisted object).
195     *
196     * @return ?int
197     */
198    public function getId(): ?int
199    {
200        return $this->id ?? null;
201    }
202
203    /**
204     * Get user.
205     *
206     * @return ?UserEntityInterface
207     */
208    public function getUser(): ?UserEntityInterface
209    {
210        return $this->user_id
211            ? $this->getDbServiceManager()->get(UserServiceInterface::class)->getUserById($this->user_id)
212            : null;
213    }
214
215    /**
216     * Set user.
217     *
218     * @param ?UserEntityInterface $user User
219     *
220     * @return SearchEntityInterface
221     */
222    public function setUser(?UserEntityInterface $user): SearchEntityInterface
223    {
224        $this->user_id = $user?->getId();
225        return $this;
226    }
227
228    /**
229     * Get session identifier.
230     *
231     * @return ?string
232     */
233    public function getSessionId(): ?string
234    {
235        return $this->session_id ?? null;
236    }
237
238    /**
239     * Set session identifier.
240     *
241     * @param ?string $sessionId Session id
242     *
243     * @return SearchEntityInterface
244     */
245    public function setSessionId(?string $sessionId): SearchEntityInterface
246    {
247        $this->session_id = $sessionId;
248        return $this;
249    }
250
251    /**
252     * Get created date.
253     *
254     * @return DateTime
255     */
256    public function getCreated(): DateTime
257    {
258        return DateTime::createFromFormat('Y-m-d H:i:s', $this->created);
259    }
260
261    /**
262     * Set created date.
263     *
264     * @param DateTime $dateTime Created date
265     *
266     * @return SearchEntityInterface
267     */
268    public function setCreated(DateTime $dateTime): SearchEntityInterface
269    {
270        $this->created = $dateTime->format('Y-m-d H:i:s');
271        return $this;
272    }
273
274    /**
275     * Get title.
276     *
277     * @return ?string
278     */
279    public function getTitle(): ?string
280    {
281        return $this->title ?? null;
282    }
283
284    /**
285     * Set title.
286     *
287     * @param ?string $title Title
288     *
289     * @return SearchEntityInterface
290     */
291    public function setTitle(?string $title): SearchEntityInterface
292    {
293        $this->title = $title;
294        return $this;
295    }
296
297    /**
298     * Get saved.
299     *
300     * @return bool
301     */
302    public function getSaved(): bool
303    {
304        return (bool)($this->saved ?? 0);
305    }
306
307    /**
308     * Set saved.
309     *
310     * @param bool $saved Saved
311     *
312     * @return SearchEntityInterface
313     */
314    public function setSaved(bool $saved): SearchEntityInterface
315    {
316        $this->saved = $saved ? 1 : 0;
317        return $this;
318    }
319
320    /**
321     * Set search object.
322     *
323     * @param ?\VuFind\Search\Minified $searchObject Search object
324     *
325     * @return SearchEntityInterface
326     */
327    public function setSearchObject(?\VuFind\Search\Minified $searchObject): SearchEntityInterface
328    {
329        $this->search_object = $searchObject ? serialize($searchObject) : null;
330        return $this;
331    }
332
333    /**
334     * Get checksum.
335     *
336     * @return ?int
337     */
338    public function getChecksum(): ?int
339    {
340        return $this->checksum ?? null;
341    }
342
343    /**
344     * Set checksum.
345     *
346     * @param ?int $checksum Checksum
347     *
348     * @return SearchEntityInterface
349     */
350    public function setChecksum(?int $checksum): SearchEntityInterface
351    {
352        $this->checksum = $checksum;
353        return $this;
354    }
355
356    /**
357     * Get notification frequency.
358     *
359     * @return int
360     */
361    public function getNotificationFrequency(): int
362    {
363        return $this->notification_frequency ?? 0;
364    }
365
366    /**
367     * Set notification frequency.
368     *
369     * @param int $notificationFrequency Notification frequency
370     *
371     * @return SearchEntityInterface
372     */
373    public function setNotificationFrequency(int $notificationFrequency): SearchEntityInterface
374    {
375        $this->notification_frequency = $notificationFrequency;
376        return $this;
377    }
378
379    /**
380     * When was the last notification sent?
381     *
382     * @return DateTime
383     */
384    public function getLastNotificationSent(): DateTime
385    {
386        return DateTime::createFromFormat('Y-m-d H:i:s', $this->last_notification_sent);
387    }
388
389    /**
390     * Set when last notification was sent.
391     *
392     * @param DateTime $lastNotificationSent Time when last notification was sent
393     *
394     * @return SearchEntityInterface
395     */
396    public function setLastNotificationSent(Datetime $lastNotificationSent): SearchEntityInterface
397    {
398        $this->last_notification_sent = $lastNotificationSent->format('Y-m-d H:i:s');
399        return $this;
400    }
401
402    /**
403     * Get notification base URL.
404     *
405     * @return string
406     */
407    public function getNotificationBaseUrl(): string
408    {
409        return $this->notification_base_url ?? '';
410    }
411
412    /**
413     * Set notification base URL.
414     *
415     * @param string $notificationBaseUrl Notification base URL
416     *
417     * @return SearchEntityInterface
418     */
419    public function setNotificationBaseUrl(string $notificationBaseUrl): SearchEntityInterface
420    {
421        $this->notification_base_url = $notificationBaseUrl;
422        return $this;
423    }
424}