1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Blacklight; |
4
|
|
|
|
5
|
|
|
use App\Models\Release; |
6
|
|
|
use App\Models\Category; |
7
|
|
|
use App\Models\Settings; |
8
|
|
|
use Chumper\Zipper\Zipper; |
9
|
|
|
use App\Models\UsenetGroup; |
10
|
|
|
use Illuminate\Database\Eloquent\Collection; |
11
|
|
|
use Illuminate\Support\Arr; |
12
|
|
|
use Blacklight\utility\Utility; |
13
|
|
|
use Illuminate\Support\Facades\DB; |
14
|
|
|
use Illuminate\Support\Facades\File; |
15
|
|
|
use Illuminate\Support\Facades\Cache; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Class Releases. |
19
|
|
|
*/ |
20
|
|
|
class Releases extends Release |
21
|
|
|
{ |
22
|
|
|
// RAR/ZIP Passworded indicator. |
23
|
|
|
public const PASSWD_NONE = 0; // No password. |
24
|
|
|
public const PASSWD_POTENTIAL = 1; // Might have a password. |
25
|
|
|
public const BAD_FILE = 2; // Possibly broken RAR/ZIP. |
26
|
|
|
public const PASSWD_RAR = 10; // Definitely passworded. |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* @var \Blacklight\SphinxSearch |
30
|
|
|
*/ |
31
|
|
|
public $sphinxSearch; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* @var int |
35
|
|
|
*/ |
36
|
|
|
public $passwordStatus; |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* @var array Class instances. |
40
|
|
|
* @throws \Exception |
41
|
|
|
*/ |
42
|
|
|
public function __construct() |
43
|
|
|
{ |
44
|
|
|
parent::__construct(); |
45
|
|
|
$this->sphinxSearch = new SphinxSearch(); |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* Used for Browse results. |
50
|
|
|
* |
51
|
|
|
* |
52
|
|
|
* @param $page |
53
|
|
|
* @param $cat |
54
|
|
|
* @param $start |
55
|
|
|
* @param $num |
56
|
|
|
* @param $orderBy |
57
|
|
|
* @param int $maxAge |
58
|
|
|
* @param array $excludedCats |
59
|
|
|
* @param array $tags |
60
|
|
|
* @param int $groupName |
61
|
|
|
* @param int $minSize |
62
|
|
|
* |
63
|
|
|
* @return Collection|mixed |
64
|
|
|
*/ |
65
|
|
|
public function getBrowseRange($page, $cat, $start, $num, $orderBy, $maxAge = -1, array $excludedCats = [], $groupName = -1, $minSize = 0, array $tags = []) |
66
|
|
|
{ |
67
|
|
|
$orderBy = $this->getBrowseOrder($orderBy); |
68
|
|
|
|
69
|
|
|
$qry = sprintf( |
70
|
|
|
"SELECT r.id, r.searchname, r.groups_id, r.guid, r.postdate, r.categories_id, r.size, r.totalpart, r.fromname, r.passwordstatus, r.grabs, r.comments, r.adddate, r.videos_id, r.tv_episodes_id, r.haspreview, r.jpgstatus, cp.title AS parent_category, c.title AS sub_category, r.group_name, |
71
|
|
|
CONCAT(cp.title, ' > ', c.title) AS category_name, |
72
|
|
|
CONCAT(cp.id, ',', c.id) AS category_ids, |
73
|
|
|
df.failed AS failed, |
74
|
|
|
rn.releases_id AS nfoid, |
75
|
|
|
re.releases_id AS reid, |
76
|
|
|
v.tvdb, v.trakt, v.tvrage, v.tvmaze, v.imdb, v.tmdb, |
77
|
|
|
tve.title, tve.firstaired |
78
|
|
|
FROM |
79
|
|
|
( |
80
|
|
|
SELECT r.id, r.searchname, r.guid, r.postdate, r.groups_id, r.categories_id, r.size, r.totalpart, r.fromname, r.passwordstatus, r.grabs, r.comments, r.adddate, r.videos_id, r.tv_episodes_id, r.haspreview, r.jpgstatus, g.name AS group_name |
81
|
|
|
FROM releases r |
82
|
|
|
LEFT JOIN usenet_groups g ON g.id = r.groups_id |
83
|
|
|
%s |
84
|
|
|
WHERE r.nzbstatus = %d |
85
|
|
|
AND r.passwordstatus %s |
86
|
|
|
%s %s %s %s %s %s |
87
|
|
|
ORDER BY %s %s %s |
88
|
|
|
) r |
89
|
|
|
LEFT JOIN categories c ON c.id = r.categories_id |
90
|
|
|
LEFT JOIN root_categories cp ON cp.id = c.root_categories_id |
91
|
|
|
LEFT OUTER JOIN videos v ON r.videos_id = v.id |
92
|
|
|
LEFT OUTER JOIN tv_episodes tve ON r.tv_episodes_id = tve.id |
93
|
|
|
LEFT OUTER JOIN video_data re ON re.releases_id = r.id |
94
|
|
|
LEFT OUTER JOIN release_nfos rn ON rn.releases_id = r.id |
95
|
|
|
LEFT OUTER JOIN dnzb_failures df ON df.release_id = r.id |
96
|
|
|
GROUP BY r.id |
97
|
|
|
ORDER BY %10\$s %11\$s", |
98
|
|
|
! empty($tags) ? ' LEFT JOIN tagging_tagged tt ON tt.taggable_id = r.id' : '', |
99
|
|
|
NZB::NZB_ADDED, |
100
|
|
|
$this->showPasswords(), |
101
|
|
|
! empty($tags) ? " AND tt.tag_name IN ('".implode("','", $tags)."')" : '', |
102
|
|
|
Category::getCategorySearch($cat), |
103
|
|
|
($maxAge > 0 ? (' AND postdate > NOW() - INTERVAL '.$maxAge.' DAY ') : ''), |
104
|
|
|
(\count($excludedCats) ? (' AND r.categories_id NOT IN ('.implode(',', $excludedCats).')') : ''), |
105
|
|
|
((int) $groupName !== -1 ? sprintf(' AND g.name = %s ', escapeString($groupName)) : ''), |
106
|
|
|
($minSize > 0 ? sprintf('AND r.size >= %d', $minSize) : ''), |
107
|
|
|
$orderBy[0], |
108
|
|
|
$orderBy[1], |
109
|
|
|
($start === false ? '' : ' LIMIT '.$num.' OFFSET '.$start) |
110
|
|
|
); |
111
|
|
|
|
112
|
|
|
$releases = Cache::get(md5($qry.$page)); |
113
|
|
|
if ($releases !== null) { |
114
|
|
|
return $releases; |
115
|
|
|
} |
116
|
|
|
$sql = self::fromQuery($qry); |
117
|
|
|
if (\count($sql) > 0) { |
118
|
|
|
$possibleRows = $this->getBrowseCount($cat, $maxAge, $excludedCats, $groupName, $tags); |
119
|
|
|
$sql[0]->_totalcount = $sql[0]->_totalrows = $possibleRows; |
120
|
|
|
} |
121
|
|
|
$expiresAt = now()->addMinutes(config('nntmux.cache_expiry_medium')); |
122
|
|
|
Cache::put(md5($qry.$page), $sql, $expiresAt); |
123
|
|
|
|
124
|
|
|
return $sql; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* Used for pager on browse page. |
129
|
|
|
* |
130
|
|
|
* @param array $cat |
131
|
|
|
* @param int $maxAge |
132
|
|
|
* @param array $excludedCats |
133
|
|
|
* @param string|int $groupName |
134
|
|
|
* |
135
|
|
|
* @param array $tags |
136
|
|
|
* |
137
|
|
|
* @return int |
138
|
|
|
*/ |
139
|
|
|
public function getBrowseCount($cat, $maxAge = -1, array $excludedCats = [], $groupName = '', array $tags = []): int |
140
|
|
|
{ |
141
|
|
|
$sql = sprintf( |
142
|
|
|
'SELECT COUNT(r.id) AS count |
143
|
|
|
FROM releases r |
144
|
|
|
%s %s |
145
|
|
|
WHERE r.nzbstatus = %d |
146
|
|
|
AND r.passwordstatus %s |
147
|
|
|
%s |
148
|
|
|
%s %s %s %s ', |
149
|
|
|
($groupName !== -1 ? 'LEFT JOIN usenet_groups g ON g.id = r.groups_id' : ''), |
150
|
|
|
! empty($tags) ? ' LEFT JOIN tagging_tagged tt ON tt.taggable_id = r.id' : '', |
151
|
|
|
NZB::NZB_ADDED, |
152
|
|
|
$this->showPasswords(), |
153
|
|
|
($groupName !== -1 ? sprintf(' AND g.name = %s', escapeString($groupName)) : ''), |
154
|
|
|
! empty($tags) ? ' AND tt.tag_name IN ('.escapeString(implode(',', $tags)).')' : '', |
155
|
|
|
Category::getCategorySearch($cat), |
156
|
|
|
($maxAge > 0 ? (' AND r.postdate > NOW() - INTERVAL '.$maxAge.' DAY ') : ''), |
157
|
|
|
(\count($excludedCats) ? (' AND r.categories_id NOT IN ('.implode(',', $excludedCats).')') : '') |
158
|
|
|
); |
159
|
|
|
$count = Cache::get(md5($sql)); |
160
|
|
|
if ($count !== null) { |
161
|
|
|
return $count; |
162
|
|
|
} |
163
|
|
|
$count = self::fromQuery($sql); |
164
|
|
|
$expiresAt = now()->addMinutes(config('nntmux.cache_expiry_short')); |
165
|
|
|
Cache::put(md5($sql), $count[0]->count, $expiresAt); |
166
|
|
|
|
167
|
|
|
return $count[0]->count ?? 0; |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
/** |
171
|
|
|
* @return string |
172
|
|
|
*/ |
173
|
|
|
public function showPasswords(): ?string |
174
|
|
|
{ |
175
|
|
|
$setting = (int) Settings::settingValue('..showpasswordedrelease'); |
176
|
|
|
$setting = $setting ?? 10; |
177
|
|
|
switch ($setting) { |
178
|
|
|
case 0: // Hide releases with a password or a potential password (Hide unprocessed releases). |
|
|
|
|
179
|
|
|
|
180
|
|
|
return '= '.self::PASSWD_NONE; |
181
|
|
|
case 1: // Show releases with no password or a potential password (Show unprocessed releases). |
|
|
|
|
182
|
|
|
|
183
|
|
|
return '<= '.self::PASSWD_POTENTIAL; |
184
|
|
|
case 2: // Hide releases with a password or a potential password (Show unprocessed releases). |
|
|
|
|
185
|
|
|
return '<= '.self::PASSWD_NONE; |
186
|
|
|
case 10: // Shows everything. |
|
|
|
|
187
|
|
|
default: |
188
|
|
|
return '<= '.self::PASSWD_RAR; |
189
|
|
|
} |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
/** |
193
|
|
|
* Use to order releases on site. |
194
|
|
|
* |
195
|
|
|
* @param string|array $orderBy |
196
|
|
|
* |
197
|
|
|
* @return array |
198
|
|
|
*/ |
199
|
|
|
public function getBrowseOrder($orderBy): array |
200
|
|
|
{ |
201
|
|
|
$orderArr = explode('_', ($orderBy === '' ? 'posted_desc' : $orderBy)); |
|
|
|
|
202
|
|
|
switch ($orderArr[0]) { |
203
|
|
|
case 'cat': |
204
|
|
|
$orderField = 'categories_id'; |
205
|
|
|
break; |
206
|
|
|
case 'name': |
207
|
|
|
$orderField = 'searchname'; |
208
|
|
|
break; |
209
|
|
|
case 'size': |
210
|
|
|
$orderField = 'size'; |
211
|
|
|
break; |
212
|
|
|
case 'files': |
213
|
|
|
$orderField = 'totalpart'; |
214
|
|
|
break; |
215
|
|
|
case 'stats': |
216
|
|
|
$orderField = 'grabs'; |
217
|
|
|
break; |
218
|
|
|
case 'posted': |
219
|
|
|
default: |
220
|
|
|
$orderField = 'postdate'; |
221
|
|
|
break; |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
return [$orderField, isset($orderArr[1]) && preg_match('/^(asc|desc)$/i', $orderArr[1]) ? $orderArr[1] : 'desc']; |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
/** |
228
|
|
|
* Return ordering types usable on site. |
229
|
|
|
* |
230
|
|
|
* @return string[] |
231
|
|
|
*/ |
232
|
|
|
public function getBrowseOrdering(): array |
233
|
|
|
{ |
234
|
|
|
return [ |
235
|
|
|
'name_asc', |
236
|
|
|
'name_desc', |
237
|
|
|
'cat_asc', |
238
|
|
|
'cat_desc', |
239
|
|
|
'posted_asc', |
240
|
|
|
'posted_desc', |
241
|
|
|
'size_asc', |
242
|
|
|
'size_desc', |
243
|
|
|
'files_asc', |
244
|
|
|
'files_desc', |
245
|
|
|
'stats_asc', |
246
|
|
|
'stats_desc', |
247
|
|
|
]; |
248
|
|
|
} |
249
|
|
|
|
250
|
|
|
/** |
251
|
|
|
* Get list of releases available for export. |
252
|
|
|
* |
253
|
|
|
* |
254
|
|
|
* @param string $postFrom |
255
|
|
|
* @param string $postTo |
256
|
|
|
* @param string $groupID |
257
|
|
|
* |
258
|
|
|
* @return Collection|\Illuminate\Support\Collection|static[] |
259
|
|
|
*/ |
260
|
|
|
public function getForExport($postFrom = '', $postTo = '', $groupID = '') |
261
|
|
|
{ |
262
|
|
|
$query = self::query() |
263
|
|
|
->where('r.nzbstatus', NZB::NZB_ADDED) |
264
|
|
|
->select(['r.searchname', 'r.guid', 'g.name as gname', DB::raw("CONCAT(cp.title,'_',c.title) AS catName")]) |
265
|
|
|
->from('releases as r') |
266
|
|
|
->leftJoin('categories as c', 'c.id', '=', 'r.categories_id') |
267
|
|
|
->leftJoin('root_categories as cp', 'cp.id', '=', 'c.root_categories_id') |
268
|
|
|
->leftJoin('usenet_groups as g', 'g.id', '=', 'r.groups_id'); |
269
|
|
|
|
270
|
|
|
if ($groupID !== '') { |
271
|
|
|
$query->where('r.groups_id', $groupID); |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
if ($postFrom !== '') { |
275
|
|
|
$dateParts = explode('/', $postFrom); |
276
|
|
|
if (\count($dateParts) === 3) { |
277
|
|
|
$query->where('r.postdate', '>', $dateParts[2].'-'.$dateParts[1].'-'.$dateParts[0].'00:00:00'); |
278
|
|
|
} |
279
|
|
|
} |
280
|
|
|
|
281
|
|
|
if ($postTo !== '') { |
282
|
|
|
$dateParts = explode('/', $postTo); |
283
|
|
|
if (\count($dateParts) === 3) { |
284
|
|
|
$query->where('r.postdate', '<', $dateParts[2].'-'.$dateParts[1].'-'.$dateParts[0].'23:59:59'); |
285
|
|
|
} |
286
|
|
|
} |
287
|
|
|
|
288
|
|
|
return $query->get(); |
289
|
|
|
} |
290
|
|
|
|
291
|
|
|
/** |
292
|
|
|
* Get date in this format : 01/01/2014 of the oldest release. |
293
|
|
|
* |
294
|
|
|
* @note Used for exporting NZBs. |
295
|
|
|
* @return mixed |
296
|
|
|
*/ |
297
|
|
|
public function getEarliestUsenetPostDate() |
298
|
|
|
{ |
299
|
|
|
$row = self::query()->selectRaw("DATE_FORMAT(min(postdate), '%d/%m/%Y') AS postdate")->first(); |
300
|
|
|
|
301
|
|
|
return $row === null ? '01/01/2014' : $row['postdate']; |
302
|
|
|
} |
303
|
|
|
|
304
|
|
|
/** |
305
|
|
|
* Get date in this format : 01/01/2014 of the newest release. |
306
|
|
|
* |
307
|
|
|
* @note Used for exporting NZBs. |
308
|
|
|
* @return mixed |
309
|
|
|
*/ |
310
|
|
|
public function getLatestUsenetPostDate() |
311
|
|
|
{ |
312
|
|
|
$row = self::query()->selectRaw("DATE_FORMAT(max(postdate), '%d/%m/%Y') AS postdate")->first(); |
313
|
|
|
|
314
|
|
|
return $row === null ? '01/01/2014' : $row['postdate']; |
315
|
|
|
} |
316
|
|
|
|
317
|
|
|
/** |
318
|
|
|
* Gets all groups for drop down selection on NZB-Export web page. |
319
|
|
|
* |
320
|
|
|
* @param bool $blnIncludeAll |
321
|
|
|
* |
322
|
|
|
* @note Used for exporting NZBs. |
323
|
|
|
* @return array |
324
|
|
|
*/ |
325
|
|
|
public function getReleasedGroupsForSelect($blnIncludeAll = true): array |
326
|
|
|
{ |
327
|
|
|
$groups = self::query() |
328
|
|
|
->selectRaw('DISTINCT g.id, g.name') |
329
|
|
|
->leftJoin('usenet_groups as g', 'g.id', '=', 'releases.groups_id') |
330
|
|
|
->get(); |
331
|
|
|
$temp_array = []; |
332
|
|
|
|
333
|
|
|
if ($blnIncludeAll) { |
334
|
|
|
$temp_array[-1] = '--All Groups--'; |
335
|
|
|
} |
336
|
|
|
|
337
|
|
|
foreach ($groups as $group) { |
338
|
|
|
$temp_array[$group['id']] = $group['name']; |
339
|
|
|
} |
340
|
|
|
|
341
|
|
|
return $temp_array; |
342
|
|
|
} |
343
|
|
|
|
344
|
|
|
/** |
345
|
|
|
* Cache of concatenated category ID's used in queries. |
346
|
|
|
* @var null|array |
347
|
|
|
*/ |
348
|
|
|
private $concatenatedCategoryIDsCache = null; |
349
|
|
|
|
350
|
|
|
/** |
351
|
|
|
* Gets / sets a string of concatenated category ID's used in queries. |
352
|
|
|
* |
353
|
|
|
* @return array|null|string |
354
|
|
|
*/ |
355
|
|
|
public function getConcatenatedCategoryIDs() |
356
|
|
|
{ |
357
|
|
|
if ($this->concatenatedCategoryIDsCache === null) { |
358
|
|
|
$result = Category::query() |
359
|
|
|
->remember(config('nntmux.cache_expiry_long')) |
360
|
|
|
->whereNotNull('categories.root_categories_id') |
361
|
|
|
->whereNotNull('cp.id') |
362
|
|
|
->selectRaw('CONCAT(cp.id, ", ", categories.id) AS category_ids') |
363
|
|
|
->leftJoin('root_categories as cp', 'cp.id', '=', 'categories.root_categories_id') |
364
|
|
|
->get(); |
365
|
|
|
if (isset($result[0]['category_ids'])) { |
366
|
|
|
$this->concatenatedCategoryIDsCache = $result[0]['category_ids']; |
367
|
|
|
} |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
return $this->concatenatedCategoryIDsCache; |
371
|
|
|
} |
372
|
|
|
|
373
|
|
|
/** |
374
|
|
|
* Get TV for My Shows page. |
375
|
|
|
* |
376
|
|
|
* |
377
|
|
|
* @param $userShows |
378
|
|
|
* @param $offset |
379
|
|
|
* @param $limit |
380
|
|
|
* @param $orderBy |
381
|
|
|
* @param int $maxAge |
382
|
|
|
* @param array $excludedCats |
383
|
|
|
* @return Collection|mixed |
384
|
|
|
*/ |
385
|
|
|
public function getShowsRange($userShows, $offset, $limit, $orderBy, $maxAge = -1, array $excludedCats = []) |
386
|
|
|
{ |
387
|
|
|
$orderBy = $this->getBrowseOrder($orderBy); |
388
|
|
|
$sql = sprintf( |
389
|
|
|
"SELECT r.id, r.searchname, r.guid, r.postdate, r.groups_id, r.categories_id, r.size, r.totalpart, r.fromname, r.passwordstatus, r.grabs, r.comments, r.adddate, r.videos_id, r.tv_episodes_id, r.haspreview, r.jpgstatus, cp.title AS parent_category, c.title AS sub_category, |
390
|
|
|
CONCAT(cp.title, '-', c.title) AS category_name, |
391
|
|
|
%s AS category_ids, |
392
|
|
|
g.name AS group_name, |
393
|
|
|
rn.releases_id AS nfoid, re.releases_id AS reid, |
394
|
|
|
tve.firstaired, |
395
|
|
|
df.failed AS failed |
396
|
|
|
FROM releases r |
397
|
|
|
LEFT OUTER JOIN video_data re ON re.releases_id = r.id |
398
|
|
|
LEFT JOIN usenet_groups g ON g.id = r.groups_id |
399
|
|
|
LEFT OUTER JOIN release_nfos rn ON rn.releases_id = r.id |
400
|
|
|
LEFT OUTER JOIN tv_episodes tve ON tve.videos_id = r.videos_id |
401
|
|
|
LEFT JOIN categories c ON c.id = r.categories_id |
402
|
|
|
LEFT JOIN root_categories cp ON cp.id = c.root_categories_id |
403
|
|
|
LEFT OUTER JOIN dnzb_failures df ON df.release_id = r.id |
404
|
|
|
WHERE %s %s |
405
|
|
|
AND r.nzbstatus = %d |
406
|
|
|
AND r.categories_id BETWEEN %d AND %d |
407
|
|
|
AND r.passwordstatus %s |
408
|
|
|
%s |
409
|
|
|
GROUP BY r.id |
410
|
|
|
ORDER BY %s %s %s", |
411
|
|
|
$this->getConcatenatedCategoryIDs(), |
|
|
|
|
412
|
|
|
$this->uSQL($userShows, 'videos_id'), |
413
|
|
|
(\count($excludedCats) ? ' AND r.categories_id NOT IN ('.implode(',', $excludedCats).')' : ''), |
414
|
|
|
NZB::NZB_ADDED, |
415
|
|
|
Category::TV_ROOT, |
416
|
|
|
Category::TV_OTHER, |
417
|
|
|
$this->showPasswords(), |
418
|
|
|
($maxAge > 0 ? sprintf(' AND r.postdate > NOW() - INTERVAL %d DAY ', $maxAge) : ''), |
419
|
|
|
$orderBy[0], |
420
|
|
|
$orderBy[1], |
421
|
|
|
($offset === false ? '' : (' LIMIT '.$limit.' OFFSET '.$offset)) |
422
|
|
|
); |
423
|
|
|
|
424
|
|
|
$expiresAt = now()->addMinutes(config('nntmux.cache_expiry_medium')); |
425
|
|
|
$result = Cache::get(md5($sql)); |
426
|
|
|
if ($result !== null) { |
427
|
|
|
return $result; |
428
|
|
|
} |
429
|
|
|
|
430
|
|
|
$result = self::fromQuery($sql); |
431
|
|
|
Cache::put(md5($sql), $result, $expiresAt); |
432
|
|
|
|
433
|
|
|
return $result; |
434
|
|
|
} |
435
|
|
|
|
436
|
|
|
/** |
437
|
|
|
* Get count for my shows page pagination. |
438
|
|
|
* |
439
|
|
|
* @param $userShows |
440
|
|
|
* @param int $maxAge |
441
|
|
|
* @param array $excludedCats |
442
|
|
|
* |
443
|
|
|
* @return int |
444
|
|
|
*/ |
445
|
|
|
public function getShowsCount($userShows, $maxAge = -1, array $excludedCats = []): int |
446
|
|
|
{ |
447
|
|
|
return $this->getPagerCount( |
448
|
|
|
sprintf( |
449
|
|
|
'SELECT r.id |
450
|
|
|
FROM releases r |
451
|
|
|
WHERE %s %s |
452
|
|
|
AND r.nzbstatus = %d |
453
|
|
|
AND r.categories_id BETWEEN %d AND %d |
454
|
|
|
AND r.passwordstatus %s |
455
|
|
|
%s', |
456
|
|
|
$this->uSQL($userShows, 'videos_id'), |
457
|
|
|
(\count($excludedCats) ? ' AND r.categories_id NOT IN ('.implode(',', $excludedCats).')' : ''), |
458
|
|
|
NZB::NZB_ADDED, |
459
|
|
|
Category::TV_ROOT, |
460
|
|
|
Category::TV_OTHER, |
461
|
|
|
$this->showPasswords(), |
462
|
|
|
($maxAge > 0 ? sprintf(' AND r.postdate > NOW() - INTERVAL %d DAY ', $maxAge) : '') |
463
|
|
|
) |
464
|
|
|
); |
465
|
|
|
} |
466
|
|
|
|
467
|
|
|
/** |
468
|
|
|
* Delete multiple releases, or a single by ID. |
469
|
|
|
* |
470
|
|
|
* @param array|int|string $list Array of GUID or ID of releases to delete. |
471
|
|
|
* @throws \Exception |
472
|
|
|
*/ |
473
|
|
|
public function deleteMultiple($list): void |
474
|
|
|
{ |
475
|
|
|
$list = (array) $list; |
476
|
|
|
|
477
|
|
|
$nzb = new NZB(); |
478
|
|
|
$releaseImage = new ReleaseImage(); |
479
|
|
|
|
480
|
|
|
foreach ($list as $identifier) { |
481
|
|
|
$this->deleteSingle(['g' => $identifier, 'i' => false], $nzb, $releaseImage); |
482
|
|
|
} |
483
|
|
|
} |
484
|
|
|
|
485
|
|
|
/** |
486
|
|
|
* Deletes a single release by GUID, and all the corresponding files. |
487
|
|
|
* |
488
|
|
|
* @param array $identifiers ['g' => Release GUID(mandatory), 'id => ReleaseID(optional, pass |
489
|
|
|
* false)] |
490
|
|
|
* @param \Blacklight\NZB $nzb |
491
|
|
|
* @param \Blacklight\ReleaseImage $releaseImage |
492
|
|
|
* |
493
|
|
|
* @throws \Exception |
494
|
|
|
*/ |
495
|
|
|
public function deleteSingle($identifiers, NZB $nzb, ReleaseImage $releaseImage): void |
496
|
|
|
{ |
497
|
|
|
// Delete NZB from disk. |
498
|
|
|
$nzbPath = $nzb->NZBPath($identifiers['g']); |
499
|
|
|
if (! empty($nzbPath)) { |
500
|
|
|
File::delete($nzbPath); |
501
|
|
|
} |
502
|
|
|
|
503
|
|
|
// Delete images. |
504
|
|
|
$releaseImage->delete($identifiers['g']); |
505
|
|
|
|
506
|
|
|
// Delete from sphinx. |
507
|
|
|
$this->sphinxSearch->deleteRelease($identifiers); |
508
|
|
|
|
509
|
|
|
// Delete from DB. |
510
|
|
|
self::whereGuid($identifiers['g'])->delete(); |
511
|
|
|
} |
512
|
|
|
|
513
|
|
|
/** |
514
|
|
|
* @param $guids |
515
|
|
|
* @param $category |
516
|
|
|
* @param $grabs |
517
|
|
|
* @param $videoId |
518
|
|
|
* @param $episodeId |
519
|
|
|
* @param $anidbId |
520
|
|
|
* @param $imdbId |
521
|
|
|
* @return bool|int |
522
|
|
|
*/ |
523
|
|
|
public function updateMulti($guids, $category, $grabs, $videoId, $episodeId, $anidbId, $imdbId) |
524
|
|
|
{ |
525
|
|
|
if (! \is_array($guids) || \count($guids) < 1) { |
526
|
|
|
return false; |
527
|
|
|
} |
528
|
|
|
|
529
|
|
|
$update = [ |
530
|
|
|
'categories_id' => $category === -1 ? 'categories_id' : $category, |
531
|
|
|
'grabs' => $grabs, |
532
|
|
|
'videos_id' => $videoId, |
533
|
|
|
'tv_episodes_id' => $episodeId, |
534
|
|
|
'anidbid' => $anidbId, |
535
|
|
|
'imdbid' => $imdbId, |
536
|
|
|
]; |
537
|
|
|
|
538
|
|
|
return self::query()->whereIn('guid', $guids)->update($update); |
539
|
|
|
} |
540
|
|
|
|
541
|
|
|
/** |
542
|
|
|
* Creates part of a query for some functions. |
543
|
|
|
* |
544
|
|
|
* @param array|Collection $userQuery |
545
|
|
|
* @param string $type |
546
|
|
|
* |
547
|
|
|
* @return string |
548
|
|
|
*/ |
549
|
|
|
public function uSQL($userQuery, $type): string |
550
|
|
|
{ |
551
|
|
|
$sql = '(1=2 '; |
552
|
|
|
foreach ($userQuery as $query) { |
553
|
|
|
$sql .= sprintf('OR (r.%s = %d', $type, $query->$type); |
554
|
|
|
if (! empty($query->categories)) { |
555
|
|
|
$catsArr = explode('|', $query->categories); |
556
|
|
|
if (\count($catsArr) > 1) { |
557
|
|
|
$sql .= sprintf(' AND r.categories_id IN (%s)', implode(',', $catsArr)); |
558
|
|
|
} else { |
559
|
|
|
$sql .= sprintf(' AND r.categories_id = %d', $catsArr[0]); |
560
|
|
|
} |
561
|
|
|
} |
562
|
|
|
$sql .= ') '; |
563
|
|
|
} |
564
|
|
|
$sql .= ') '; |
565
|
|
|
|
566
|
|
|
return $sql; |
567
|
|
|
} |
568
|
|
|
|
569
|
|
|
/** |
570
|
|
|
* Function for searching on the site (by subject, searchname or advanced). |
571
|
|
|
* |
572
|
|
|
* |
573
|
|
|
* @param array $searchArr |
574
|
|
|
* @param $groupName |
575
|
|
|
* @param $sizeFrom |
576
|
|
|
* @param $sizeTo |
577
|
|
|
* @param $daysNew |
578
|
|
|
* @param $daysOld |
579
|
|
|
* @param int $offset |
580
|
|
|
* @param int $limit |
581
|
|
|
* @param string|array $orderBy |
582
|
|
|
* @param int $maxAge |
583
|
|
|
* @param array $excludedCats |
584
|
|
|
* @param string $type |
585
|
|
|
* @param array $cat |
586
|
|
|
* @param int $minSize |
587
|
|
|
* @param array $tags |
588
|
|
|
* |
589
|
|
|
* @return array|Collection|mixed |
590
|
|
|
*/ |
591
|
|
|
public function search($searchArr, $groupName, $sizeFrom, $sizeTo, $daysNew, $daysOld, $offset = 0, $limit = 1000, $orderBy = '', $maxAge = -1, array $excludedCats = [], $type = 'basic', array $cat = [-1], $minSize = 0, array $tags = []) |
592
|
|
|
{ |
593
|
|
|
$sizeRange = [ |
594
|
|
|
1 => 1, |
595
|
|
|
2 => 2.5, |
596
|
|
|
3 => 5, |
597
|
|
|
4 => 10, |
598
|
|
|
5 => 20, |
599
|
|
|
6 => 30, |
600
|
|
|
7 => 40, |
601
|
|
|
8 => 80, |
602
|
|
|
9 => 160, |
603
|
|
|
10 => 320, |
604
|
|
|
11 => 640, |
605
|
|
|
]; |
606
|
|
|
if ($orderBy === '') { |
607
|
|
|
$orderBy = []; |
608
|
|
|
$orderBy[0] = 'postdate '; |
609
|
|
|
$orderBy[1] = 'desc '; |
610
|
|
|
} else { |
611
|
|
|
$orderBy = $this->getBrowseOrder($orderBy); |
612
|
|
|
} |
613
|
|
|
|
614
|
|
|
$searchFields = Arr::where($searchArr, function ($value) { |
615
|
|
|
return $value !== -1; |
616
|
|
|
}); |
617
|
|
|
|
618
|
|
|
$results = $this->sphinxSearch->searchIndexes('releases_rt', '', [], $searchFields); |
619
|
|
|
|
620
|
|
|
$searchResult = Arr::pluck($results, 'id'); |
621
|
|
|
|
622
|
|
|
$catQuery = ''; |
623
|
|
|
if ($type === 'basic') { |
624
|
|
|
$catQuery = Category::getCategorySearch($cat); |
625
|
|
|
} elseif ($type === 'advanced' && (int) $cat[0] !== -1) { |
626
|
|
|
$catQuery = sprintf('AND r.categories_id = %d', $cat[0]); |
627
|
|
|
} |
628
|
|
|
$whereSql = sprintf( |
629
|
|
|
'WHERE r.passwordstatus %s AND r.nzbstatus = %d %s %s %s %s %s %s %s %s %s %s %s', |
630
|
|
|
$this->showPasswords(), |
631
|
|
|
NZB::NZB_ADDED, |
632
|
|
|
! empty($tags) ? " AND tt.tag_name IN ('".implode("','", $tags)."')" : '', |
633
|
|
|
($maxAge > 0 ? sprintf(' AND r.postdate > (NOW() - INTERVAL %d DAY) ', $maxAge) : ''), |
634
|
|
|
((int) $groupName !== -1 ? sprintf(' AND r.groups_id = %d ', UsenetGroup::getIDByName($groupName)) : ''), |
|
|
|
|
635
|
|
|
(array_key_exists($sizeFrom, $sizeRange) ? ' AND r.size > '.(104857600 * (int) $sizeRange[$sizeFrom]).' ' : ''), |
636
|
|
|
(array_key_exists($sizeTo, $sizeRange) ? ' AND r.size < '.(104857600 * (int) $sizeRange[$sizeTo]).' ' : ''), |
637
|
|
|
$catQuery, |
638
|
|
|
((int) $daysNew !== -1 ? sprintf(' AND r.postdate < (NOW() - INTERVAL %d DAY) ', $daysNew) : ''), |
639
|
|
|
((int) $daysOld !== -1 ? sprintf(' AND r.postdate > (NOW() - INTERVAL %d DAY) ', $daysOld) : ''), |
640
|
|
|
(\count($excludedCats) > 0 ? ' AND r.categories_id NOT IN ('.implode(',', $excludedCats).')' : ''), |
641
|
|
|
(! empty($searchResult) ? 'AND r.id IN ('.implode(',', $searchResult).')' : ''), |
642
|
|
|
($minSize > 0 ? sprintf('AND r.size >= %d', $minSize) : '') |
643
|
|
|
); |
644
|
|
|
$baseSql = sprintf( |
645
|
|
|
"SELECT r.searchname, r.guid, r.postdate, r.groups_id, r.categories_id, r.size, r.totalpart, r.fromname, r.passwordstatus, r.grabs, r.comments, r.adddate, r.videos_id, r.tv_episodes_id, r.haspreview, r.jpgstatus, cp.title AS parent_category, c.title AS sub_category, |
646
|
|
|
CONCAT(cp.title, ' > ', c.title) AS category_name, |
647
|
|
|
%s AS category_ids, |
648
|
|
|
df.failed AS failed, |
649
|
|
|
g.name AS group_name, |
650
|
|
|
rn.releases_id AS nfoid, |
651
|
|
|
re.releases_id AS reid, |
652
|
|
|
cp.id AS categoryparentid, |
653
|
|
|
v.tvdb, v.trakt, v.tvrage, v.tvmaze, v.imdb, v.tmdb, |
654
|
|
|
tve.firstaired |
655
|
|
|
FROM releases r |
656
|
|
|
LEFT OUTER JOIN video_data re ON re.releases_id = r.id |
657
|
|
|
LEFT OUTER JOIN videos v ON r.videos_id = v.id |
658
|
|
|
LEFT OUTER JOIN tv_episodes tve ON r.tv_episodes_id = tve.id |
659
|
|
|
LEFT OUTER JOIN release_nfos rn ON rn.releases_id = r.id |
660
|
|
|
LEFT JOIN usenet_groups g ON g.id = r.groups_id |
661
|
|
|
LEFT JOIN categories c ON c.id = r.categories_id |
662
|
|
|
LEFT JOIN root_categories cp ON cp.id = c.root_categories_id |
663
|
|
|
LEFT OUTER JOIN dnzb_failures df ON df.release_id = r.id |
664
|
|
|
%s %s", |
665
|
|
|
$this->getConcatenatedCategoryIDs(), |
|
|
|
|
666
|
|
|
! empty($tags) ? ' LEFT JOIN tagging_tagged tt ON tt.taggable_id = r.id' : '', |
667
|
|
|
$whereSql |
668
|
|
|
); |
669
|
|
|
$sql = sprintf( |
670
|
|
|
'SELECT * FROM ( |
671
|
|
|
%s |
672
|
|
|
) r |
673
|
|
|
ORDER BY r.%s %s |
674
|
|
|
LIMIT %d OFFSET %d', |
675
|
|
|
$baseSql, |
676
|
|
|
$orderBy[0], |
677
|
|
|
$orderBy[1], |
678
|
|
|
$limit, |
679
|
|
|
$offset |
680
|
|
|
); |
681
|
|
|
$releases = Cache::get(md5($sql)); |
682
|
|
|
if ($releases !== null) { |
683
|
|
|
return $releases; |
684
|
|
|
} |
685
|
|
|
$releases = ! empty($searchResult) ? self::fromQuery($sql) : collect(); |
686
|
|
|
if ($releases->isNotEmpty()) { |
687
|
|
|
$releases[0]->_totalrows = $this->getPagerCount($baseSql); |
688
|
|
|
} |
689
|
|
|
$expiresAt = now()->addMinutes(config('nntmux.cache_expiry_medium')); |
690
|
|
|
Cache::put(md5($sql), $releases, $expiresAt); |
691
|
|
|
|
692
|
|
|
return $releases; |
693
|
|
|
} |
694
|
|
|
|
695
|
|
|
/** |
696
|
|
|
* Search function for API. |
697
|
|
|
* |
698
|
|
|
* |
699
|
|
|
* @param $searchName |
700
|
|
|
* @param $groupName |
701
|
|
|
* @param int $offset |
702
|
|
|
* @param int $limit |
703
|
|
|
* @param int $maxAge |
704
|
|
|
* @param array $excludedCats |
705
|
|
|
* @param array $cat |
706
|
|
|
* @param int $minSize |
707
|
|
|
* @param array $tags |
708
|
|
|
* |
709
|
|
|
* @return Collection|mixed |
710
|
|
|
*/ |
711
|
|
|
public function apiSearch($searchName, $groupName, $offset = 0, $limit = 1000, $maxAge = -1, array $excludedCats = [], array $cat = [-1], $minSize = 0, array $tags = []) |
712
|
|
|
{ |
713
|
|
|
if ($searchName !== -1) { |
714
|
|
|
$searchResult = Arr::pluck($this->sphinxSearch->searchIndexes('releases_rt', $searchName, ['searchname']), 'id'); |
715
|
|
|
} |
716
|
|
|
|
717
|
|
|
$catQuery = Category::getCategorySearch($cat); |
718
|
|
|
|
719
|
|
|
$whereSql = sprintf( |
720
|
|
|
'WHERE r.passwordstatus %s AND r.nzbstatus = %d %s %s %s %s %s %s %s', |
721
|
|
|
$this->showPasswords(), |
722
|
|
|
NZB::NZB_ADDED, |
723
|
|
|
! empty($tags) ? " AND tt.tag_name IN ('".implode("','", $tags)."')" : '', |
724
|
|
|
($maxAge > 0 ? sprintf(' AND r.postdate > (NOW() - INTERVAL %d DAY) ', $maxAge) : ''), |
725
|
|
|
((int) $groupName !== -1 ? sprintf(' AND r.groups_id = %d ', UsenetGroup::getIDByName($groupName)) : ''), |
|
|
|
|
726
|
|
|
$catQuery, |
727
|
|
|
(\count($excludedCats) > 0 ? ' AND r.categories_id NOT IN ('.implode(',', $excludedCats).')' : ''), |
728
|
|
|
(! empty($searchResult) ? 'AND r.id IN ('.implode(',', $searchResult).')' : ''), |
729
|
|
|
($minSize > 0 ? sprintf('AND r.size >= %d', $minSize) : '') |
730
|
|
|
); |
731
|
|
|
$baseSql = sprintf( |
732
|
|
|
"SELECT r.searchname, r.guid, r.postdate, r.groups_id, r.categories_id, r.size, r.totalpart, r.fromname, r.passwordstatus, r.grabs, r.comments, r.adddate, r.videos_id, r.tv_episodes_id, r.haspreview, r.jpgstatus, m.imdbid, m.tmdbid, m.traktid, cp.title AS parent_category, c.title AS sub_category, |
733
|
|
|
CONCAT(cp.title, ' > ', c.title) AS category_name, |
734
|
|
|
%s AS category_ids, |
735
|
|
|
g.name AS group_name, |
736
|
|
|
cp.id AS categoryparentid, |
737
|
|
|
v.tvdb, v.trakt, v.tvrage, v.tvmaze, v.imdb, v.tmdb, |
738
|
|
|
tve.firstaired, tve.title, tve.series, tve.episode |
739
|
|
|
FROM releases r |
740
|
|
|
LEFT OUTER JOIN videos v ON r.videos_id = v.id |
741
|
|
|
LEFT OUTER JOIN tv_episodes tve ON r.tv_episodes_id = tve.id |
742
|
|
|
LEFT JOIN movieinfo m ON m.id = r.movieinfo_id |
743
|
|
|
LEFT JOIN usenet_groups g ON g.id = r.groups_id |
744
|
|
|
LEFT JOIN categories c ON c.id = r.categories_id |
745
|
|
|
LEFT JOIN root_categories cp ON cp.id = c.root_categories_id |
746
|
|
|
%s %s", |
747
|
|
|
$this->getConcatenatedCategoryIDs(), |
|
|
|
|
748
|
|
|
! empty($tags) ? ' LEFT JOIN tagging_tagged tt ON tt.taggable_id = r.id' : '', |
749
|
|
|
$whereSql |
750
|
|
|
); |
751
|
|
|
$sql = sprintf( |
752
|
|
|
'SELECT * FROM ( |
753
|
|
|
%s |
754
|
|
|
) r |
755
|
|
|
ORDER BY r.postdate DESC |
756
|
|
|
LIMIT %d OFFSET %d', |
757
|
|
|
$baseSql, |
758
|
|
|
$limit, |
759
|
|
|
$offset |
760
|
|
|
); |
761
|
|
|
$releases = Cache::get(md5($sql)); |
762
|
|
|
if ($releases !== null) { |
763
|
|
|
return $releases; |
764
|
|
|
} |
765
|
|
|
if ($searchName !== -1 && ! empty($searchResult)) { |
766
|
|
|
$releases = self::fromQuery($sql); |
767
|
|
|
} elseif ($searchName !== -1 && empty($searchResult)) { |
768
|
|
|
$releases = collect(); |
769
|
|
|
} else { |
770
|
|
|
$releases = self::fromQuery($sql); |
771
|
|
|
} |
772
|
|
|
if ($releases->isNotEmpty()) { |
773
|
|
|
$releases[0]->_totalrows = $this->getPagerCount($baseSql); |
774
|
|
|
} |
775
|
|
|
$expiresAt = now()->addMinutes(config('nntmux.cache_expiry_medium')); |
776
|
|
|
Cache::put(md5($sql), $releases, $expiresAt); |
777
|
|
|
|
778
|
|
|
return $releases; |
779
|
|
|
} |
780
|
|
|
|
781
|
|
|
/** |
782
|
|
|
* Search TV Shows via API. |
783
|
|
|
* |
784
|
|
|
* |
785
|
|
|
* @param array $siteIdArr |
786
|
|
|
* @param string $series |
787
|
|
|
* @param string $episode |
788
|
|
|
* @param string $airdate |
789
|
|
|
* @param int $offset |
790
|
|
|
* @param int $limit |
791
|
|
|
* @param string $name |
792
|
|
|
* @param array $cat |
793
|
|
|
* @param int $maxAge |
794
|
|
|
* @param int $minSize |
795
|
|
|
* @param array $excludedCategories |
796
|
|
|
* @param array $tags |
797
|
|
|
* @return Collection|mixed |
798
|
|
|
*/ |
799
|
|
|
public function tvSearch(array $siteIdArr = [], $series = '', $episode = '', $airdate = '', $offset = 0, $limit = 100, $name = '', array $cat = [-1], $maxAge = -1, $minSize = 0, array $excludedCategories = [], array $tags = []) |
800
|
|
|
{ |
801
|
|
|
$siteSQL = []; |
802
|
|
|
$showSql = ''; |
803
|
|
|
|
804
|
|
|
foreach ($siteIdArr as $column => $Id) { |
805
|
|
|
if ($Id > 0) { |
806
|
|
|
$siteSQL[] = sprintf('v.%s = %d', $column, $Id); |
807
|
|
|
} |
808
|
|
|
} |
809
|
|
|
|
810
|
|
|
if (\count($siteSQL) > 0) { |
811
|
|
|
// If we have show info, find the Episode ID/Video ID first to avoid table scans |
812
|
|
|
$showQry = sprintf( |
813
|
|
|
" |
814
|
|
|
SELECT |
815
|
|
|
v.id AS video, |
816
|
|
|
GROUP_CONCAT(tve.id SEPARATOR ',') AS episodes |
817
|
|
|
FROM videos v |
818
|
|
|
LEFT JOIN tv_episodes tve ON v.id = tve.videos_id |
819
|
|
|
WHERE (%s) %s %s %s |
820
|
|
|
GROUP BY v.id |
821
|
|
|
LIMIT 1", |
822
|
|
|
implode(' OR ', $siteSQL), |
823
|
|
|
($series !== '' ? sprintf('AND tve.series = %d', (int) preg_replace('/^s0*/i', '', $series)) : ''), |
824
|
|
|
($episode !== '' ? sprintf('AND tve.episode = %d', (int) preg_replace('/^e0*/i', '', $episode)) : ''), |
825
|
|
|
($airdate !== '' ? sprintf('AND DATE(tve.firstaired) = %s', escapeString($airdate)) : '') |
826
|
|
|
); |
827
|
|
|
$show = self::fromQuery($showQry); |
828
|
|
|
|
829
|
|
|
if (! empty($show[0])) { |
830
|
|
|
if ((! empty($series) || ! empty($episode) || ! empty($airdate)) && $show[0]->episodes !== '') { |
831
|
|
|
$showSql = sprintf('AND r.tv_episodes_id IN (%s)', $show[0]->episodes); |
832
|
|
|
} elseif ((int) $show[0]->video > 0) { |
833
|
|
|
$showSql = 'AND r.videos_id = '.$show[0]->video; |
834
|
|
|
// If $series is set but episode is not, return Season Packs only |
835
|
|
|
if (! empty($series) && empty($episode)) { |
836
|
|
|
$showSql .= ' AND r.tv_episodes_id = 0'; |
837
|
|
|
} |
838
|
|
|
} else { |
839
|
|
|
// If we were passed Episode Info and no match was found, do not run the query |
840
|
|
|
return []; |
841
|
|
|
} |
842
|
|
|
} else { |
843
|
|
|
// If we were passed Site ID Info and no match was found, do not run the query |
844
|
|
|
return []; |
845
|
|
|
} |
846
|
|
|
} |
847
|
|
|
// If $name is set it is a fallback search, add available SxxExx/airdate info to the query |
848
|
|
|
if (! empty($name) && $showSql === '') { |
849
|
|
|
if (! empty($series) && (int) $series < 1900) { |
850
|
|
|
$name .= sprintf(' S%s', str_pad($series, 2, '0', STR_PAD_LEFT)); |
851
|
|
|
if (! empty($episode) && strpos($episode, '/') === false) { |
852
|
|
|
$name .= sprintf('E%s', str_pad($episode, 2, '0', STR_PAD_LEFT)); |
853
|
|
|
} |
854
|
|
|
} elseif (! empty($airdate)) { |
855
|
|
|
$name .= sprintf(' %s', str_replace(['/', '-', '.', '_'], ' ', $airdate)); |
856
|
|
|
} |
857
|
|
|
} |
858
|
|
|
|
859
|
|
|
if (! empty($name)) { |
860
|
|
|
$searchResult = Arr::pluck($this->sphinxSearch->searchIndexes('releases_rt', $name, ['searchname']), 'id'); |
861
|
|
|
} |
862
|
|
|
|
863
|
|
|
$whereSql = sprintf( |
864
|
|
|
'WHERE r.nzbstatus = %d |
865
|
|
|
AND r.passwordstatus %s |
866
|
|
|
%s %s %s %s %s %s %s', |
867
|
|
|
NZB::NZB_ADDED, |
868
|
|
|
$this->showPasswords(), |
869
|
|
|
! empty($tags) ? " AND tt.tag_name IN ('".implode("','", $tags)."')" : '', |
870
|
|
|
$showSql, |
871
|
|
|
((! empty($name) && ! empty($searchResult)) ? 'AND r.id IN ('.implode(',', $searchResult).')' : ''), |
872
|
|
|
Category::getCategorySearch($cat), |
873
|
|
|
($maxAge > 0 ? sprintf('AND r.postdate > NOW() - INTERVAL %d DAY', $maxAge) : ''), |
874
|
|
|
($minSize > 0 ? sprintf('AND r.size >= %d', $minSize) : ''), |
875
|
|
|
! empty($excludedCategories) ? sprintf('AND r.categories_id NOT IN('.implode(',', $excludedCategories).')') : '' |
876
|
|
|
); |
877
|
|
|
$baseSql = sprintf( |
878
|
|
|
"SELECT r.searchname, r.guid, r.postdate, r.groups_id, r.categories_id, r.size, r.totalpart, r.fromname, r.passwordstatus, r.grabs, r.comments, r.adddate, r.videos_id, r.tv_episodes_id, r.haspreview, r.jpgstatus, |
879
|
|
|
v.title, v.countries_id, v.started, v.tvdb, v.trakt, |
880
|
|
|
v.imdb, v.tmdb, v.tvmaze, v.tvrage, v.source, |
881
|
|
|
tvi.summary, tvi.publisher, tvi.image, |
882
|
|
|
tve.series, tve.episode, tve.se_complete, tve.title, tve.firstaired, tve.summary, cp.title AS parent_category, c.title AS sub_category, |
883
|
|
|
CONCAT(cp.title, ' > ', c.title) AS category_name, |
884
|
|
|
%s AS category_ids, |
885
|
|
|
g.name AS group_name, |
886
|
|
|
rn.releases_id AS nfoid, |
887
|
|
|
re.releases_id AS reid |
888
|
|
|
FROM releases r |
889
|
|
|
LEFT OUTER JOIN videos v ON r.videos_id = v.id AND v.type = 0 |
890
|
|
|
LEFT OUTER JOIN tv_info tvi ON v.id = tvi.videos_id |
891
|
|
|
LEFT OUTER JOIN tv_episodes tve ON r.tv_episodes_id = tve.id |
892
|
|
|
LEFT JOIN categories c ON c.id = r.categories_id |
893
|
|
|
LEFT JOIN root_categories cp ON cp.id = c.root_categories_id |
894
|
|
|
LEFT JOIN usenet_groups g ON g.id = r.groups_id |
895
|
|
|
LEFT OUTER JOIN video_data re ON re.releases_id = r.id |
896
|
|
|
LEFT OUTER JOIN release_nfos rn ON rn.releases_id = r.id |
897
|
|
|
%s %s", |
898
|
|
|
$this->getConcatenatedCategoryIDs(), |
|
|
|
|
899
|
|
|
! empty($tags) ? ' LEFT JOIN tagging_tagged tt ON tt.taggable_id = r.id' : '', |
900
|
|
|
$whereSql |
901
|
|
|
); |
902
|
|
|
$sql = sprintf( |
903
|
|
|
'%s |
904
|
|
|
ORDER BY postdate DESC |
905
|
|
|
LIMIT %d OFFSET %d', |
906
|
|
|
$baseSql, |
907
|
|
|
$limit, |
908
|
|
|
$offset |
909
|
|
|
); |
910
|
|
|
$releases = Cache::get(md5($sql)); |
911
|
|
|
if ($releases !== null) { |
912
|
|
|
return $releases; |
913
|
|
|
} |
914
|
|
|
((! empty($name) && ! empty($searchResult)) || empty($name)) ? $releases = self::fromQuery($sql) : []; |
915
|
|
|
if (! empty($releases) && $releases->isNotEmpty()) { |
916
|
|
|
$releases[0]->_totalrows = $this->getPagerCount( |
917
|
|
|
preg_replace('#LEFT(\s+OUTER)?\s+JOIN\s+(?!tv_episodes)\s+.*ON.*=.*\n#i', ' ', $baseSql) |
918
|
|
|
); |
919
|
|
|
} |
920
|
|
|
|
921
|
|
|
$expiresAt = now()->addMinutes(config('nntmux.cache_expiry_medium')); |
922
|
|
|
Cache::put(md5($sql), $releases, $expiresAt); |
923
|
|
|
|
924
|
|
|
return $releases; |
925
|
|
|
} |
926
|
|
|
|
927
|
|
|
/** |
928
|
|
|
* Search TV Shows via APIv2. |
929
|
|
|
* |
930
|
|
|
* |
931
|
|
|
* @param array $siteIdArr |
932
|
|
|
* @param string $series |
933
|
|
|
* @param string $episode |
934
|
|
|
* @param string $airdate |
935
|
|
|
* @param int $offset |
936
|
|
|
* @param int $limit |
937
|
|
|
* @param string $name |
938
|
|
|
* @param array $cat |
939
|
|
|
* @param int $maxAge |
940
|
|
|
* @param int $minSize |
941
|
|
|
* @param array $excludedCategories |
942
|
|
|
* @param array $tags |
943
|
|
|
* @return Collection|mixed |
944
|
|
|
*/ |
945
|
|
|
public function apiTvSearch(array $siteIdArr = [], $series = '', $episode = '', $airdate = '', $offset = 0, $limit = 100, $name = '', array $cat = [-1], $maxAge = -1, $minSize = 0, array $excludedCategories = [], array $tags = []) |
946
|
|
|
{ |
947
|
|
|
$siteSQL = []; |
948
|
|
|
$showSql = ''; |
949
|
|
|
foreach ($siteIdArr as $column => $Id) { |
950
|
|
|
if ($Id > 0) { |
951
|
|
|
$siteSQL[] = sprintf('v.%s = %d', $column, $Id); |
952
|
|
|
} |
953
|
|
|
} |
954
|
|
|
|
955
|
|
|
if (\count($siteSQL) > 0) { |
956
|
|
|
// If we have show info, find the Episode ID/Video ID first to avoid table scans |
957
|
|
|
$showQry = sprintf( |
958
|
|
|
" |
959
|
|
|
SELECT |
960
|
|
|
v.id AS video, |
961
|
|
|
GROUP_CONCAT(tve.id SEPARATOR ',') AS episodes |
962
|
|
|
FROM videos v |
963
|
|
|
LEFT JOIN tv_episodes tve ON v.id = tve.videos_id |
964
|
|
|
WHERE (%s) %s %s %s |
965
|
|
|
GROUP BY v.id |
966
|
|
|
LIMIT 1", |
967
|
|
|
implode(' OR ', $siteSQL), |
968
|
|
|
($series !== '' ? sprintf('AND tve.series = %d', (int) preg_replace('/^s0*/i', '', $series)) : ''), |
969
|
|
|
($episode !== '' ? sprintf('AND tve.episode = %d', (int) preg_replace('/^e0*/i', '', $episode)) : ''), |
970
|
|
|
($airdate !== '' ? sprintf('AND DATE(tve.firstaired) = %s', escapeString($airdate)) : '') |
971
|
|
|
); |
972
|
|
|
$show = self::fromQuery($showQry); |
973
|
|
|
|
974
|
|
|
if ($show->isNotEmpty()) { |
975
|
|
|
if ((! empty($series) || ! empty($episode) || ! empty($airdate)) && $show[0]->episodes != '') { |
976
|
|
|
$showSql = sprintf('AND r.tv_episodes_id IN (%s)', $show[0]->episodes); |
977
|
|
|
} elseif ((int) $show[0]->video > 0) { |
978
|
|
|
$showSql = 'AND r.videos_id = '.$show[0]->video; |
979
|
|
|
// If $series is set but episode is not, return Season Packs only |
980
|
|
|
if (! empty($series) && empty($episode)) { |
981
|
|
|
$showSql .= ' AND r.tv_episodes_id = 0'; |
982
|
|
|
} |
983
|
|
|
} else { |
984
|
|
|
// If we were passed Episode Info and no match was found, do not run the query |
985
|
|
|
return []; |
986
|
|
|
} |
987
|
|
|
} else { |
988
|
|
|
// If we were passed Site ID Info and no match was found, do not run the query |
989
|
|
|
return []; |
990
|
|
|
} |
991
|
|
|
} |
992
|
|
|
// If $name is set it is a fallback search, add available SxxExx/airdate info to the query |
993
|
|
|
if (! empty($name) && $showSql === '') { |
994
|
|
|
if (! empty($series) && (int) $series < 1900) { |
995
|
|
|
$name .= sprintf(' S%s', str_pad($series, 2, '0', STR_PAD_LEFT)); |
996
|
|
|
if (! empty($episode) && strpos($episode, '/') === false) { |
997
|
|
|
$name .= sprintf('E%s', str_pad($episode, 2, '0', STR_PAD_LEFT)); |
998
|
|
|
} |
999
|
|
|
} elseif (! empty($airdate)) { |
1000
|
|
|
$name .= sprintf(' %s', str_replace(['/', '-', '.', '_'], ' ', $airdate)); |
1001
|
|
|
} |
1002
|
|
|
} |
1003
|
|
|
|
1004
|
|
|
if (! empty($name)) { |
1005
|
|
|
$searchResult = Arr::pluck($this->sphinxSearch->searchIndexes('releases_rt', $name, ['searchname']), 'id'); |
1006
|
|
|
} |
1007
|
|
|
|
1008
|
|
|
$whereSql = sprintf( |
1009
|
|
|
'WHERE r.nzbstatus = %d |
1010
|
|
|
AND r.passwordstatus %s |
1011
|
|
|
%s %s %s %s %s %s %s', |
1012
|
|
|
NZB::NZB_ADDED, |
1013
|
|
|
$this->showPasswords(), |
1014
|
|
|
! empty($tags) ? " AND tt.tag_name IN ('".implode("','", $tags)."')" : '', |
1015
|
|
|
$showSql, |
1016
|
|
|
(! empty($searchResult) ? 'AND r.id IN ('.implode(',', $searchResult).')' : ''), |
1017
|
|
|
Category::getCategorySearch($cat), |
1018
|
|
|
($maxAge > 0 ? sprintf('AND r.postdate > NOW() - INTERVAL %d DAY', $maxAge) : ''), |
1019
|
|
|
($minSize > 0 ? sprintf('AND r.size >= %d', $minSize) : ''), |
1020
|
|
|
! empty($excludedCategories) ? sprintf('AND r.categories_id NOT IN('.implode(',', $excludedCategories).')') : '' |
1021
|
|
|
); |
1022
|
|
|
$baseSql = sprintf( |
1023
|
|
|
"SELECT r.searchname, r.guid, r.postdate, r.groups_id, r.categories_id, r.size, r.totalpart, r.fromname, r.passwordstatus, r.grabs, r.comments, r.adddate, r.tv_episodes_id, r.haspreview, r.jpgstatus, |
1024
|
|
|
v.title, v.type, v.tvdb, v.trakt,v.imdb, v.tmdb, v.tvmaze, v.tvrage, |
1025
|
|
|
tve.series, tve.episode, tve.se_complete, tve.title, tve.firstaired, cp.title AS parent_category, c.title AS sub_category, |
1026
|
|
|
CONCAT(cp.title, ' > ', c.title) AS category_name, |
1027
|
|
|
%s AS category_ids, |
1028
|
|
|
g.name AS group_name |
1029
|
|
|
FROM releases r |
1030
|
|
|
LEFT OUTER JOIN videos v ON r.videos_id = v.id AND v.type = 0 |
1031
|
|
|
LEFT OUTER JOIN tv_info tvi ON v.id = tvi.videos_id |
1032
|
|
|
LEFT OUTER JOIN tv_episodes tve ON r.tv_episodes_id = tve.id |
1033
|
|
|
LEFT JOIN categories c ON c.id = r.categories_id |
1034
|
|
|
LEFT JOIN root_categories cp ON cp.id = c.root_categories_id |
1035
|
|
|
LEFT JOIN usenet_groups g ON g.id = r.groups_id |
1036
|
|
|
%s %s", |
1037
|
|
|
$this->getConcatenatedCategoryIDs(), |
|
|
|
|
1038
|
|
|
! empty($tags) ? ' LEFT JOIN tagging_tagged tt ON tt.taggable_id = r.id' : '', |
1039
|
|
|
$whereSql |
1040
|
|
|
); |
1041
|
|
|
$sql = sprintf( |
1042
|
|
|
'%s |
1043
|
|
|
ORDER BY postdate DESC |
1044
|
|
|
LIMIT %d OFFSET %d', |
1045
|
|
|
$baseSql, |
1046
|
|
|
$limit, |
1047
|
|
|
$offset |
1048
|
|
|
); |
1049
|
|
|
$releases = Cache::get(md5($sql)); |
1050
|
|
|
if ($releases !== null) { |
1051
|
|
|
return $releases; |
1052
|
|
|
} |
1053
|
|
|
$releases = self::fromQuery($sql); |
1054
|
|
|
if ($releases->isNotEmpty()) { |
1055
|
|
|
$releases[0]->_totalrows = $this->getPagerCount( |
1056
|
|
|
preg_replace('#LEFT(\s+OUTER)?\s+JOIN\s+(?!tv_episodes)\s+.*ON.*=.*\n#i', ' ', $baseSql) |
1057
|
|
|
); |
1058
|
|
|
} |
1059
|
|
|
|
1060
|
|
|
$expiresAt = now()->addMinutes(config('nntmux.cache_expiry_medium')); |
1061
|
|
|
Cache::put(md5($sql), $releases, $expiresAt); |
1062
|
|
|
|
1063
|
|
|
return $releases; |
1064
|
|
|
} |
1065
|
|
|
|
1066
|
|
|
/** |
1067
|
|
|
* Search anime releases. |
1068
|
|
|
* |
1069
|
|
|
* |
1070
|
|
|
* @param $aniDbID |
1071
|
|
|
* @param int $offset |
1072
|
|
|
* @param int $limit |
1073
|
|
|
* @param string $name |
1074
|
|
|
* @param array $cat |
1075
|
|
|
* @param int $maxAge |
1076
|
|
|
* @param array $excludedCategories |
1077
|
|
|
* @return Collection|mixed |
1078
|
|
|
*/ |
1079
|
|
|
public function animeSearch($aniDbID, $offset = 0, $limit = 100, $name = '', array $cat = [-1], $maxAge = -1, array $excludedCategories = []) |
1080
|
|
|
{ |
1081
|
|
|
if (! empty($name)) { |
1082
|
|
|
$searchResult = Arr::pluck($this->sphinxSearch->searchIndexes('releases_rt', $name, ['searchname']), 'id'); |
1083
|
|
|
} |
1084
|
|
|
|
1085
|
|
|
$whereSql = sprintf( |
1086
|
|
|
'WHERE r.passwordstatus %s |
1087
|
|
|
AND r.nzbstatus = %d |
1088
|
|
|
%s %s %s %s %s', |
1089
|
|
|
$this->showPasswords(), |
1090
|
|
|
NZB::NZB_ADDED, |
1091
|
|
|
($aniDbID > -1 ? sprintf(' AND r.anidbid = %d ', $aniDbID) : ''), |
1092
|
|
|
(! empty($searchResult) ? 'AND r.id IN ('.implode(',', $searchResult).')' : ''), |
1093
|
|
|
! empty($excludedCategories) ? sprintf('AND r.categories_id NOT IN('.implode(',', $excludedCategories).')') : '', |
1094
|
|
|
Category::getCategorySearch($cat), |
1095
|
|
|
($maxAge > 0 ? sprintf(' AND r.postdate > NOW() - INTERVAL %d DAY ', $maxAge) : '') |
1096
|
|
|
); |
1097
|
|
|
$baseSql = sprintf( |
1098
|
|
|
"SELECT r.id, r.searchname, r.guid, r.postdate, r.groups_id, r.categories_id, r.size, r.totalpart, r.fromname, r.passwordstatus, r.grabs, r.comments, r.adddate, r.haspreview, r.jpgstatus, cp.title AS parent_category, c.title AS sub_category, |
1099
|
|
|
CONCAT(cp.title, ' > ', c.title) AS category_name, |
1100
|
|
|
%s AS category_ids, |
1101
|
|
|
g.name AS group_name, |
1102
|
|
|
rn.releases_id AS nfoid, |
1103
|
|
|
re.releases_id AS reid |
1104
|
|
|
FROM releases r |
1105
|
|
|
LEFT JOIN categories c ON c.id = r.categories_id |
1106
|
|
|
LEFT JOIN root_categories cp ON cp.id = c.root_categories_id |
1107
|
|
|
LEFT JOIN usenet_groups g ON g.id = r.groups_id |
1108
|
|
|
LEFT OUTER JOIN release_nfos rn ON rn.releases_id = r.id |
1109
|
|
|
LEFT OUTER JOIN releaseextrafull re ON re.releases_id = r.id |
1110
|
|
|
%s", |
1111
|
|
|
$this->getConcatenatedCategoryIDs(), |
|
|
|
|
1112
|
|
|
$whereSql |
1113
|
|
|
); |
1114
|
|
|
$sql = sprintf( |
1115
|
|
|
'%s |
1116
|
|
|
ORDER BY postdate DESC |
1117
|
|
|
LIMIT %d OFFSET %d', |
1118
|
|
|
$baseSql, |
1119
|
|
|
$limit, |
1120
|
|
|
$offset |
1121
|
|
|
); |
1122
|
|
|
$releases = Cache::get(md5($sql)); |
1123
|
|
|
if ($releases !== null) { |
1124
|
|
|
return $releases; |
1125
|
|
|
} |
1126
|
|
|
$releases = self::fromQuery($sql); |
1127
|
|
|
if ($releases->isNotEmpty()) { |
1128
|
|
|
$releases[0]->_totalrows = $this->getPagerCount($baseSql); |
1129
|
|
|
} |
1130
|
|
|
$expiresAt = now()->addMinutes(config('nntmux.cache_expiry_medium')); |
1131
|
|
|
Cache::put(md5($sql), $releases, $expiresAt); |
1132
|
|
|
|
1133
|
|
|
return $releases; |
1134
|
|
|
} |
1135
|
|
|
|
1136
|
|
|
/** |
1137
|
|
|
* Movies search through API and site. |
1138
|
|
|
* |
1139
|
|
|
* |
1140
|
|
|
* @param int $imDbId |
1141
|
|
|
* @param int $tmDbId |
1142
|
|
|
* @param int $traktId |
1143
|
|
|
* @param int $offset |
1144
|
|
|
* @param int $limit |
1145
|
|
|
* @param string $name |
1146
|
|
|
* @param array $cat |
1147
|
|
|
* @param int $maxAge |
1148
|
|
|
* @param int $minSize |
1149
|
|
|
* @param array $excludedCategories |
1150
|
|
|
* @param array $tags |
1151
|
|
|
* @return Collection|mixed |
1152
|
|
|
*/ |
1153
|
|
|
public function moviesSearch($imDbId = -1, $tmDbId = -1, $traktId = -1, $offset = 0, $limit = 100, $name = '', array $cat = [-1], $maxAge = -1, $minSize = 0, array $excludedCategories = [], array $tags = []) |
1154
|
|
|
{ |
1155
|
|
|
if (! empty($name)) { |
1156
|
|
|
$searchResult = Arr::pluck($this->sphinxSearch->searchIndexes('releases_rt', $name, ['searchname']), 'id'); |
1157
|
|
|
} |
1158
|
|
|
|
1159
|
|
|
$whereSql = sprintf( |
1160
|
|
|
'WHERE r.categories_id BETWEEN '.Category::MOVIE_ROOT.' AND '.Category::MOVIE_OTHER.' |
1161
|
|
|
AND r.nzbstatus = %d |
1162
|
|
|
AND r.passwordstatus %s |
1163
|
|
|
%s %s %s %s %s %s %s %s', |
1164
|
|
|
NZB::NZB_ADDED, |
1165
|
|
|
$this->showPasswords(), |
1166
|
|
|
(! empty($searchResult) ? 'AND r.id IN ('.implode(',', $searchResult).')' : ''), |
1167
|
|
|
! empty($tags) ? " AND tt.tag_name IN ('".implode("','", $tags)."')" : '', |
1168
|
|
|
($imDbId !== -1 && is_numeric($imDbId)) ? sprintf(' AND m.imdbid = %d ', $imDbId) : '', |
1169
|
|
|
($tmDbId !== -1 && is_numeric($tmDbId)) ? sprintf(' AND m.tmdbid = %d ', $tmDbId) : '', |
1170
|
|
|
($traktId !== -1 && is_numeric($traktId)) ? sprintf(' AND m.traktid = %d ', $traktId) : '', |
1171
|
|
|
! empty($excludedCategories) ? sprintf('AND r.categories_id NOT IN('.implode(',', $excludedCategories).')') : '', |
1172
|
|
|
Category::getCategorySearch($cat), |
1173
|
|
|
$maxAge > 0 ? sprintf(' AND r.postdate > NOW() - INTERVAL %d DAY ', $maxAge) : '', |
1174
|
|
|
$minSize > 0 ? sprintf('AND r.size >= %d', $minSize) : '' |
1175
|
|
|
); |
1176
|
|
|
$baseSql = sprintf( |
1177
|
|
|
"SELECT r.id, r.searchname, r.guid, r.postdate, r.groups_id, r.categories_id, r.size, r.totalpart, r.fromname, r.passwordstatus, r.grabs, r.comments, r.adddate, r.imdbid, r.videos_id, r.tv_episodes_id, r.haspreview, r.jpgstatus, m.imdbid, m.tmdbid, m.traktid, cp.title AS parent_category, c.title AS sub_category, |
1178
|
|
|
concat(cp.title, ' > ', c.title) AS category_name, |
1179
|
|
|
%s AS category_ids, |
1180
|
|
|
g.name AS group_name, |
1181
|
|
|
rn.releases_id AS nfoid |
1182
|
|
|
FROM releases r |
1183
|
|
|
LEFT JOIN movieinfo m ON m.id = r.movieinfo_id |
1184
|
|
|
LEFT JOIN usenet_groups g ON g.id = r.groups_id |
1185
|
|
|
LEFT JOIN categories c ON c.id = r.categories_id |
1186
|
|
|
LEFT JOIN root_categories cp ON cp.id = c.root_categories_id |
1187
|
|
|
LEFT OUTER JOIN release_nfos rn ON rn.releases_id = r.id |
1188
|
|
|
%s %s", |
1189
|
|
|
$this->getConcatenatedCategoryIDs(), |
|
|
|
|
1190
|
|
|
! empty($tags) ? ' LEFT JOIN tagging_tagged tt ON tt.taggable_id = r.id' : '', |
1191
|
|
|
$whereSql |
1192
|
|
|
); |
1193
|
|
|
$sql = sprintf( |
1194
|
|
|
'%s |
1195
|
|
|
ORDER BY postdate DESC |
1196
|
|
|
LIMIT %d OFFSET %d', |
1197
|
|
|
$baseSql, |
1198
|
|
|
$limit, |
1199
|
|
|
$offset |
1200
|
|
|
); |
1201
|
|
|
|
1202
|
|
|
$releases = Cache::get(md5($sql)); |
1203
|
|
|
if ($releases !== null) { |
1204
|
|
|
return $releases; |
1205
|
|
|
} |
1206
|
|
|
$releases = self::fromQuery($sql); |
1207
|
|
|
if ($releases->isNotEmpty()) { |
1208
|
|
|
$releases[0]->_totalrows = $this->getPagerCount($baseSql); |
1209
|
|
|
} |
1210
|
|
|
$expiresAt = now()->addMinutes(config('nntmux.cache_expiry_medium')); |
1211
|
|
|
Cache::put(md5($sql), $releases, $expiresAt); |
1212
|
|
|
|
1213
|
|
|
return $releases; |
1214
|
|
|
} |
1215
|
|
|
|
1216
|
|
|
/** |
1217
|
|
|
* @param $currentID |
1218
|
|
|
* @param $name |
1219
|
|
|
* @param array $excludedCats |
1220
|
|
|
* @return array|Collection |
1221
|
|
|
*/ |
1222
|
|
|
public function searchSimilar($currentID, $name, array $excludedCats = []) |
1223
|
|
|
{ |
1224
|
|
|
// Get the category for the parent of this release. |
1225
|
|
|
$ret = false; |
1226
|
|
|
$currRow = self::getCatByRelId($currentID); |
1227
|
|
|
if ($currRow !== null) { |
1228
|
|
|
$catRow = Category::find($currRow['categories_id']); |
1229
|
|
|
$parentCat = $catRow['root_categories_id']; |
1230
|
|
|
|
1231
|
|
|
$results = $this->search(['searchname' => getSimilarName($name)], -1, '', '', -1, -1, 0, config('nntmux.items_per_page'), '', -1, $excludedCats, [$parentCat]); |
1232
|
|
|
if (! $results) { |
1233
|
|
|
return $results; |
1234
|
|
|
} |
1235
|
|
|
|
1236
|
|
|
$ret = []; |
1237
|
|
|
foreach ($results as $res) { |
1238
|
|
|
if ($res['id'] !== $currentID && $res['categoryparentid'] === $parentCat) { |
1239
|
|
|
$ret[] = $res; |
1240
|
|
|
} |
1241
|
|
|
} |
1242
|
|
|
} |
1243
|
|
|
|
1244
|
|
|
return $ret; |
|
|
|
|
1245
|
|
|
} |
1246
|
|
|
|
1247
|
|
|
/** |
1248
|
|
|
* Get count of releases for pager. |
1249
|
|
|
* |
1250
|
|
|
* |
1251
|
|
|
* @param string $query The query to get the count from. |
1252
|
|
|
* |
1253
|
|
|
* @return int |
1254
|
|
|
*/ |
1255
|
|
|
private function getPagerCount($query): int |
1256
|
|
|
{ |
1257
|
|
|
$sql = sprintf( |
1258
|
|
|
'SELECT COUNT(z.id) AS count FROM (%s LIMIT %s) z', |
1259
|
|
|
preg_replace('/SELECT.+?FROM\s+releases/is', 'SELECT r.id FROM releases', $query), |
1260
|
|
|
config('nntmux.max_pager_results') |
1261
|
|
|
); |
1262
|
|
|
$count = Cache::get(md5($sql)); |
1263
|
|
|
if ($count !== null) { |
1264
|
|
|
return $count; |
1265
|
|
|
} |
1266
|
|
|
$count = self::fromQuery($sql); |
1267
|
|
|
$expiresAt = now()->addMinutes(config('nntmux.cache_expiry_short')); |
1268
|
|
|
Cache::put(md5($sql), $count[0]->count, $expiresAt); |
1269
|
|
|
|
1270
|
|
|
return $count[0]->count ?? 0; |
1271
|
|
|
} |
1272
|
|
|
} |
1273
|
|
|
|
As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next
break
.There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.