1 | <?php |
||||
2 | |||||
3 | namespace App\Models; |
||||
4 | |||||
5 | use Blacklight\ColorCLI; |
||||
6 | use Blacklight\NNTP; |
||||
7 | use Blacklight\NZB; |
||||
8 | use Blacklight\ReleaseImage; |
||||
9 | use Blacklight\Releases; |
||||
10 | use Illuminate\Contracts\Pagination\LengthAwarePaginator; |
||||
11 | use Illuminate\Database\Eloquent\Model; |
||||
12 | use Illuminate\Database\Eloquent\Relations\HasMany; |
||||
13 | use Illuminate\Support\Facades\DB; |
||||
14 | |||||
15 | /** |
||||
16 | * App\Models\Group. |
||||
17 | * |
||||
18 | * @property int $id |
||||
19 | * @property string $name |
||||
20 | * @property int $backfill_target |
||||
21 | * @property int $first_record |
||||
22 | * @property string|null $first_record_postdate |
||||
23 | * @property int $last_record |
||||
24 | * @property string|null $last_record_postdate |
||||
25 | * @property string|null $last_updated |
||||
26 | * @property int|null $minfilestoformrelease |
||||
27 | * @property int|null $minsizetoformrelease |
||||
28 | * @property bool $active |
||||
29 | * @property bool $backfill |
||||
30 | * @property string|null $description |
||||
31 | * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\Release[] $release |
||||
32 | * |
||||
33 | * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UsenetGroup whereActive($value) |
||||
34 | * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UsenetGroup whereBackfill($value) |
||||
35 | * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UsenetGroup whereBackfillTarget($value) |
||||
36 | * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UsenetGroup whereDescription($value) |
||||
37 | * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UsenetGroup whereFirstRecord($value) |
||||
38 | * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UsenetGroup whereFirstRecordPostdate($value) |
||||
39 | * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UsenetGroup whereId($value) |
||||
40 | * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UsenetGroup whereLastRecord($value) |
||||
41 | * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UsenetGroup whereLastRecordPostdate($value) |
||||
42 | * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UsenetGroup whereLastUpdated($value) |
||||
43 | * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UsenetGroup whereMinfilestoformrelease($value) |
||||
44 | * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UsenetGroup whereMinsizetoformrelease($value) |
||||
45 | * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UsenetGroup whereName($value) |
||||
46 | * |
||||
47 | * @mixin \Eloquent |
||||
48 | * |
||||
49 | * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UsenetGroup newModelQuery() |
||||
50 | * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UsenetGroup newQuery() |
||||
51 | * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UsenetGroup query() |
||||
52 | */ |
||||
53 | class UsenetGroup extends Model |
||||
54 | { |
||||
55 | /** |
||||
56 | * @var bool |
||||
57 | */ |
||||
58 | protected $dateFormat = false; |
||||
59 | |||||
60 | /** |
||||
61 | * @var bool |
||||
62 | */ |
||||
63 | public $timestamps = false; |
||||
64 | |||||
65 | /** |
||||
66 | * @var array |
||||
67 | */ |
||||
68 | protected $guarded = []; |
||||
69 | |||||
70 | /** |
||||
71 | * @var array |
||||
72 | */ |
||||
73 | protected static $cbpm = ['collections', 'binaries', 'parts', 'missed_parts']; |
||||
74 | |||||
75 | /** |
||||
76 | * @var array |
||||
77 | */ |
||||
78 | protected static $cbppTableNames; |
||||
79 | |||||
80 | /** |
||||
81 | * @var bool |
||||
82 | */ |
||||
83 | protected $allasmgr; |
||||
84 | |||||
85 | /** |
||||
86 | * Group constructor. |
||||
87 | * |
||||
88 | * @throws \Exception |
||||
89 | */ |
||||
90 | public function __construct() |
||||
91 | { |
||||
92 | parent::__construct(); |
||||
93 | } |
||||
94 | |||||
95 | public function release(): HasMany |
||||
96 | { |
||||
97 | return $this->hasMany(Release::class, 'groups_id'); |
||||
98 | } |
||||
99 | |||||
100 | /** |
||||
101 | * Returns an associative array of groups for list selection. |
||||
102 | */ |
||||
103 | public static function getGroupsForSelect(): array |
||||
104 | { |
||||
105 | $groups = self::getActive(); |
||||
106 | |||||
107 | $temp_array = []; |
||||
108 | $temp_array[-1] = '--Please Select--'; |
||||
109 | |||||
110 | foreach ($groups as $group) { |
||||
111 | $temp_array[$group['name']] = $group['name']; |
||||
112 | } |
||||
113 | |||||
114 | return $temp_array; |
||||
115 | } |
||||
116 | |||||
117 | /** |
||||
118 | * Get all properties of a single group by its ID. |
||||
119 | * |
||||
120 | * |
||||
121 | * @return Model|null|static |
||||
122 | */ |
||||
123 | public static function getGroupByID($id) |
||||
124 | { |
||||
125 | return self::query()->where('id', $id)->first(); |
||||
126 | } |
||||
127 | |||||
128 | /** |
||||
129 | * @return \Illuminate\Database\Eloquent\Collection|static[] |
||||
130 | */ |
||||
131 | public static function getActive() |
||||
132 | { |
||||
133 | return self::query()->where('active', '=', 1)->orderBy('name')->get(); |
||||
134 | } |
||||
135 | |||||
136 | /** |
||||
137 | * Get active backfill groups ordered by name ascending. |
||||
138 | * |
||||
139 | * |
||||
140 | * @return array|\Illuminate\Database\Eloquent\Collection|static[] |
||||
141 | */ |
||||
142 | public static function getActiveBackfill($order) |
||||
143 | { |
||||
144 | switch ($order) { |
||||
145 | case '': |
||||
146 | case 'normal': |
||||
147 | return self::query()->where('backfill', '=', 1)->where('last_record', '<>', 0)->orderBy('name')->get(); |
||||
148 | break; |
||||
0 ignored issues
–
show
|
|||||
149 | case 'date': |
||||
150 | return self::query()->where('backfill', '=', 1)->where('last_record', '<>', 0)->orderByDesc('first_record_postdate')->get(); |
||||
151 | break; |
||||
152 | default: |
||||
153 | return []; |
||||
154 | } |
||||
155 | } |
||||
156 | |||||
157 | /** |
||||
158 | * Get all active group IDs. |
||||
159 | * |
||||
160 | * |
||||
161 | * @return \Illuminate\Database\Eloquent\Collection|static[] |
||||
162 | */ |
||||
163 | public static function getActiveIDs() |
||||
164 | { |
||||
165 | return self::query()->where('active', '=', 1)->orderBy('name')->get(['id']); |
||||
166 | } |
||||
167 | |||||
168 | /** |
||||
169 | * Get all group columns by Name. |
||||
170 | * |
||||
171 | * |
||||
172 | * @return Model|null|static |
||||
173 | */ |
||||
174 | public static function getByName($grp) |
||||
175 | { |
||||
176 | return self::query()->where('name', $grp)->first(); |
||||
177 | } |
||||
178 | |||||
179 | /** |
||||
180 | * Get a group name using its ID. |
||||
181 | * |
||||
182 | * @param int|string $id The group ID. |
||||
183 | * @return string Empty string on failure, groupName on success. |
||||
184 | */ |
||||
185 | public static function getNameByID($id): string |
||||
186 | { |
||||
187 | $res = self::query()->where('id', $id)->first(['name']); |
||||
188 | |||||
189 | return $res !== null ? $res->name : ''; |
||||
190 | } |
||||
191 | |||||
192 | /** |
||||
193 | * Get a group ID using its name. |
||||
194 | * |
||||
195 | * @param string $name The group name. |
||||
196 | * @return false|int false on failure, groups_id on success. |
||||
197 | */ |
||||
198 | public static function getIDByName(string $name) |
||||
199 | { |
||||
200 | $res = self::query()->where('name', $name)->first(['id']); |
||||
201 | |||||
202 | return $res === null ? false : $res->id; |
||||
203 | } |
||||
204 | |||||
205 | /** |
||||
206 | * Gets a count of all groups in the table limited by parameters. |
||||
207 | * |
||||
208 | * @param string $groupname Constrain query to specific group name |
||||
209 | * @param int $active Constrain query to active status |
||||
210 | * @return mixed |
||||
211 | */ |
||||
212 | public static function getGroupsCount(string $groupname = '', int $active = -1) |
||||
213 | { |
||||
214 | $res = self::query(); |
||||
215 | |||||
216 | if ($groupname !== '') { |
||||
217 | $res->where('name', 'like', '%'.$groupname.'%'); |
||||
218 | } |
||||
219 | |||||
220 | if ($active > -1) { |
||||
221 | $res->where('active', $active); |
||||
222 | } |
||||
223 | |||||
224 | return $res === null ? 0 : $res->count(['id']); |
||||
225 | } |
||||
226 | |||||
227 | public static function getGroupsRange(string $groupname = '', $active = null): LengthAwarePaginator |
||||
228 | { |
||||
229 | $groups = self::query()->groupBy('id')->orderBy('name'); |
||||
0 ignored issues
–
show
'name' of type string is incompatible with the type Closure|Illuminate\Datab...\Database\Query\Builder expected by parameter $column of Illuminate\Database\Query\Builder::orderBy() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
230 | |||||
231 | if ($groupname !== '') { |
||||
232 | $groups->where('name', 'like', '%'.$groupname.'%'); |
||||
233 | } |
||||
234 | |||||
235 | if ($active === true) { |
||||
236 | $groups->where('active', '=', 1); |
||||
237 | } elseif ($active === false) { |
||||
238 | $groups->where('active', '=', 0); |
||||
239 | } |
||||
240 | |||||
241 | return $groups->paginate(config('nntmux.items_per_page')); |
||||
242 | } |
||||
243 | |||||
244 | /** |
||||
245 | * Update an existing group. |
||||
246 | */ |
||||
247 | public static function updateGroup($group): int |
||||
248 | { |
||||
249 | return self::query()->where('id', $group['id'])->update( |
||||
250 | [ |
||||
251 | 'name' => trim($group['name']), |
||||
252 | 'description' => trim($group['description']), |
||||
253 | 'backfill_target' => $group['backfill_target'], |
||||
254 | 'first_record' => $group['first_record'], |
||||
255 | 'last_record' => $group['last_record'], |
||||
256 | 'last_updated' => now(), |
||||
257 | 'active' => $group['active'], |
||||
258 | 'backfill' => $group['backfill'], |
||||
259 | 'minsizetoformrelease' => $group['minsizetoformrelease'] === '' ? null : $group['minsizetoformrelease'], |
||||
260 | 'minfilestoformrelease' => $group['minfilestoformrelease'] === '' ? null : $group['minfilestoformrelease'], |
||||
261 | ] |
||||
262 | ); |
||||
263 | } |
||||
264 | |||||
265 | /** |
||||
266 | * Checks group name is standard and replaces any shorthand prefixes. |
||||
267 | * |
||||
268 | * @param string $groupName The full name of the usenet group being evaluated |
||||
269 | * @return string|bool The name of the group replacing shorthand prefix or false if groupname was malformed |
||||
270 | */ |
||||
271 | public static function isValidGroup(string $groupName) |
||||
272 | { |
||||
273 | if (preg_match('/^([\w\-]+\.)+[\w\-]+$/i', $groupName)) { |
||||
274 | return preg_replace('/^a\.b\./i', 'alt.binaries.', $groupName, 1); |
||||
275 | } |
||||
276 | |||||
277 | return false; |
||||
278 | } |
||||
279 | |||||
280 | /** |
||||
281 | * Add a new group. |
||||
282 | * |
||||
283 | * |
||||
284 | * @return int|mixed |
||||
285 | */ |
||||
286 | public static function addGroup($group) |
||||
287 | { |
||||
288 | $checkOld = UsenetGroup::query()->where('name', trim($group['name']))->first(); |
||||
289 | if (empty($checkOld)) { |
||||
290 | return self::query()->insertGetId([ |
||||
291 | 'name' => trim($group['name']), |
||||
292 | 'description' => isset($group['description']) ? trim($group['description']) : '', |
||||
293 | 'backfill_target' => $group['backfill_target'] ?? 1, |
||||
294 | 'first_record' => $group['first_record'] ?? 0, |
||||
295 | 'last_record' => $group['last_record'] ?? 0, |
||||
296 | 'active' => $group['active'] ?? 0, |
||||
297 | 'backfill' => $group['backfill'] ?? 0, |
||||
298 | 'minsizetoformrelease' => $group['minsizetoformrelease'] ?? null, |
||||
299 | 'minfilestoformrelease' => $group['minfilestoformrelease'] ?? null, |
||||
300 | ]); |
||||
301 | } |
||||
302 | |||||
303 | return $checkOld->id; |
||||
304 | } |
||||
305 | |||||
306 | /** |
||||
307 | * Delete a group. |
||||
308 | * |
||||
309 | * @param int|string $id ID of the group. |
||||
310 | * |
||||
311 | * @throws \Exception |
||||
312 | */ |
||||
313 | public static function deleteGroup($id): bool |
||||
314 | { |
||||
315 | self::purge($id); |
||||
316 | |||||
317 | return self::query()->where('id', $id)->delete(); |
||||
0 ignored issues
–
show
|
|||||
318 | } |
||||
319 | |||||
320 | /** |
||||
321 | * Reset a group. |
||||
322 | * |
||||
323 | * @param string|int $id The group ID. |
||||
324 | * |
||||
325 | * @throws \Exception |
||||
326 | */ |
||||
327 | public static function reset($id): bool |
||||
328 | { |
||||
329 | // Remove rows from part repair. |
||||
330 | MissedPart::query()->where('groups_id', $id)->delete(); |
||||
331 | |||||
332 | // Reset the group stats. |
||||
333 | return self::query()->where('id', $id)->update( |
||||
0 ignored issues
–
show
|
|||||
334 | [ |
||||
335 | 'backfill_target' => 1, |
||||
336 | 'first_record' => 0, |
||||
337 | 'first_record_postdate' => null, |
||||
338 | 'last_record' => 0, |
||||
339 | 'last_record_postdate' => null, |
||||
340 | 'last_updated' => null, |
||||
341 | 'active' => 0, |
||||
342 | ] |
||||
343 | ); |
||||
344 | } |
||||
345 | |||||
346 | /** |
||||
347 | * Reset all groups. |
||||
348 | */ |
||||
349 | public static function resetall(): bool |
||||
350 | { |
||||
351 | foreach (self::$cbpm as $tablePrefix) { |
||||
352 | DB::statement("TRUNCATE TABLE {$tablePrefix}"); |
||||
353 | } |
||||
354 | |||||
355 | // Reset the group stats. |
||||
356 | |||||
357 | return self::query()->update( |
||||
0 ignored issues
–
show
|
|||||
358 | [ |
||||
359 | 'backfill_target' => 1, |
||||
360 | 'first_record' => 0, |
||||
361 | 'first_record_postdate' => null, |
||||
362 | 'last_record' => 0, |
||||
363 | 'last_record_postdate' => null, |
||||
364 | 'last_updated' => null, |
||||
365 | 'active' => 0, |
||||
366 | ] |
||||
367 | ); |
||||
368 | } |
||||
369 | |||||
370 | /** |
||||
371 | * Purge a single group or all groups. |
||||
372 | * |
||||
373 | * @param int|string|bool $id The group ID. If false, purge all groups. |
||||
374 | * |
||||
375 | * @throws \Exception |
||||
376 | */ |
||||
377 | public static function purge($id = false) |
||||
378 | { |
||||
379 | if ($id === false) { |
||||
380 | self::resetall(); |
||||
381 | } else { |
||||
382 | self::reset($id); |
||||
0 ignored issues
–
show
It seems like
$id can also be of type true ; however, parameter $id of App\Models\UsenetGroup::reset() does only seem to accept integer|string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
383 | } |
||||
384 | |||||
385 | $res = Release::query()->select(['id', 'guid']); |
||||
386 | |||||
387 | if ($id !== false) { |
||||
388 | $res->where('groups_id', $id); |
||||
389 | } |
||||
390 | |||||
391 | $res->get(); |
||||
392 | |||||
393 | $releases = new Releases; |
||||
394 | $nzb = new NZB; |
||||
395 | $releaseImage = new ReleaseImage; |
||||
396 | foreach ($res as $row) { |
||||
397 | $releases->deleteSingle( |
||||
398 | [ |
||||
399 | 'g' => $row['guid'], |
||||
400 | 'i' => $row['id'], |
||||
401 | ], |
||||
402 | $nzb, |
||||
403 | $releaseImage |
||||
404 | ); |
||||
405 | } |
||||
406 | } |
||||
407 | |||||
408 | /** |
||||
409 | * Adds new newsgroups based on a regular expression match against USP available. |
||||
410 | * |
||||
411 | * @return array|string |
||||
412 | * |
||||
413 | * @throws \Exception |
||||
414 | */ |
||||
415 | public static function addBulk(string $groupList, int $active = 1, int $backfill = 1) |
||||
416 | { |
||||
417 | if (preg_match('/^\s*$/m', $groupList)) { |
||||
418 | $ret = 'No group list provided.'; |
||||
419 | } else { |
||||
420 | $nntp = new NNTP(['Echo' => false]); |
||||
0 ignored issues
–
show
The call to
Blacklight\NNTP::__construct() has too many arguments starting with array('Echo' => false) .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||
421 | if ($nntp->doConnect() !== true) { |
||||
422 | return 'Problem connecting to usenet.'; |
||||
423 | } |
||||
424 | $groups = $nntp->getGroups(); |
||||
425 | $nntp->doQuit(); |
||||
426 | |||||
427 | if ($nntp->isError($groups)) { |
||||
428 | return 'Problem fetching usenet_groups from usenet.'; |
||||
429 | } |
||||
430 | |||||
431 | $regFilter = '/'.$groupList.'/i'; |
||||
432 | |||||
433 | $ret = []; |
||||
434 | |||||
435 | foreach ($groups as $group) { |
||||
436 | if (preg_match($regFilter, $group['group']) > 0) { |
||||
437 | $res = self::getIDByName($group['group']); |
||||
438 | if ($res === false) { |
||||
439 | self::addGroup( |
||||
440 | [ |
||||
441 | 'name' => $group['group'], |
||||
442 | 'active' => $active, |
||||
443 | 'backfill' => $backfill, |
||||
444 | 'description' => 'Added by bulkAdd', |
||||
445 | ] |
||||
446 | ); |
||||
447 | $ret[] = ['group' => $group['group'], 'msg' => 'Created']; |
||||
448 | } |
||||
449 | } |
||||
450 | } |
||||
451 | |||||
452 | if (\count($ret) === 0) { |
||||
453 | $ret[] = ['group' => '', 'msg' => 'No groups found with your regex or groups already exist in database, try again!']; |
||||
454 | } |
||||
455 | } |
||||
456 | |||||
457 | return $ret; |
||||
458 | } |
||||
459 | |||||
460 | /** |
||||
461 | * Updates the group active/backfill status. |
||||
462 | * |
||||
463 | * @param int $id Which group ID |
||||
464 | * @param string $column Which column active/backfill |
||||
465 | * @param int $status Which status we are setting |
||||
466 | */ |
||||
467 | public static function updateGroupStatus(int $id, string $column, int $status = 0): string |
||||
468 | { |
||||
469 | self::query()->where('id', $id)->update( |
||||
470 | [ |
||||
471 | $column => $status, |
||||
472 | ] |
||||
473 | ); |
||||
474 | |||||
475 | return "Group {$id} has been ".(($status === 0) ? 'deactivated' : 'activated').'.'; |
||||
476 | } |
||||
477 | |||||
478 | /** |
||||
479 | * Disable group that does not exist on USP server. |
||||
480 | * |
||||
481 | * @param int $id The Group ID to disable |
||||
482 | */ |
||||
483 | public static function disableIfNotExist(int $id): void |
||||
484 | { |
||||
485 | self::updateGroupStatus($id, 'active'); |
||||
486 | (new ColorCLI)->error('Group does not exist on server, disabling'); |
||||
487 | } |
||||
488 | } |
||||
489 |
The
break
statement is not necessary if it is preceded for example by areturn
statement:If you would like to keep this construct to be consistent with other
case
statements, you can safely mark this issue as a false-positive.