Passed
Push — master ( 1b988a...8cef26 )
by Darko
11:12
created

ReleaseCreationService::createReleases()   F

Complexity

Conditions 25
Paths 2912

Size

Total Lines 163
Code Lines 115

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 115
c 1
b 0
f 0
dl 0
loc 163
rs 0
cc 25
nc 2912
nop 3

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace App\Services;
4
5
use App\Models\Category;
6
use App\Models\Collection;
7
use App\Models\Predb;
8
use App\Models\Release;
9
use App\Models\ReleaseRegex;
10
use App\Models\ReleasesGroups;
11
use App\Models\UsenetGroup;
12
use Blacklight\Categorize;
13
use Blacklight\ColorCLI;
14
use Blacklight\NZB;
15
use Blacklight\processing\ProcessReleases;
16
use Blacklight\ReleaseCleaning;
17
use Illuminate\Support\Facades\DB;
18
use Illuminate\Support\Str; // for constants
19
20
class ReleaseCreationService
21
{
22
    public function __construct(
23
        private readonly ColorCLI $colorCLI,
24
        private readonly ReleaseCleaning $releaseCleaning
25
    ) {}
26
27
    /**
28
     * Create releases from complete collections.
29
     *
30
     * @return array{added:int,dupes:int}
31
     */
32
    public function createReleases(int|string|null $groupID, int $limit, bool $echoCLI): array
33
    {
34
        $startTime = now()->toImmutable();
35
        $categorize = new Categorize;
36
        $returnCount = 0;
37
        $duplicate = 0;
38
39
        if ($echoCLI) {
40
            $this->colorCLI->header('Process Releases -> Create releases from complete collections.');
41
        }
42
43
        $collectionsQuery = Collection::query()
44
            ->where('collections.filecheck', ProcessReleases::COLLFC_SIZED)
45
            ->where('collections.filesize', '>', 0);
46
        if (! empty($groupID)) {
47
            $collectionsQuery->where('collections.groups_id', $groupID);
48
        }
49
        $collectionsQuery->select(['collections.*', 'usenet_groups.name as gname'])
50
            ->join('usenet_groups', 'usenet_groups.id', '=', 'collections.groups_id')
51
            ->limit($limit);
52
        $collections = $collectionsQuery->get();
53
54
        if ($echoCLI && $collections->count() > 0) {
55
            $this->colorCLI->primary(\count($collections).' Collections ready to be converted to releases.', true);
56
        }
57
58
        foreach ($collections as $collection) {
59
            $cleanRelName = mb_convert_encoding(str_replace(['#', '@', '$', '%', '^', '§', '¨', '©', 'Ö'], '', $collection->subject), 'UTF-8', mb_list_encodings());
60
            $fromName = mb_convert_encoding(trim($collection->fromname, "'"), 'UTF-8', mb_list_encodings());
61
62
            // Deduplicate by name, from, and ~size
63
            $dupeCheck = Release::query()
64
                ->where(['name' => $cleanRelName, 'fromname' => $fromName])
65
                ->whereBetween('size', [$collection->filesize * .99, $collection->filesize * 1.01])
66
                ->first(['id']);
67
68
            if ($dupeCheck === null) {
69
                $cleanedMeta = $this->releaseCleaning->releaseCleaner(
70
                    $collection->subject,
71
                    $collection->fromname,
72
                    $collection->gname
0 ignored issues
show
Bug introduced by
The property gname does not seem to exist on App\Models\Collection. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
73
                );
74
75
                $namingRegexId = 0;
76
                if (\is_array($cleanedMeta)) {
77
                    $namingRegexId = isset($cleanedMeta['id']) ? (int) $cleanedMeta['id'] : 0;
78
                }
79
80
                if (\is_array($cleanedMeta)) {
81
                    $properName = $cleanedMeta['properlynamed'] ?? false;
82
                    $preID = $cleanedMeta['predb'] ?? false;
83
                    $cleanedName = $cleanedMeta['cleansubject'] ?? $cleanRelName;
84
                } else {
85
                    $properName = true;
86
                    $preID = false;
87
                    $cleanedName = $cleanRelName;
88
                }
89
90
                if ($preID === false && $cleanedName !== '') {
91
                    $preMatch = Predb::matchPre($cleanedName);
92
                    if ($preMatch !== false) {
93
                        $cleanedName = $preMatch['title'];
94
                        $preID = $preMatch['predb_id'];
95
                        $properName = true;
96
                    }
97
                }
98
99
                $determinedCategory = $categorize->determineCategory($collection->groups_id, $cleanedName);
100
101
                $searchName = ! empty($cleanedName) ? mb_convert_encoding($cleanedName, 'UTF-8', mb_list_encodings()) : $cleanRelName;
102
103
                $releaseID = Release::insertRelease([
104
                    'name' => $cleanRelName,
105
                    'searchname' => $searchName,
106
                    'totalpart' => $collection->totalfiles,
107
                    'groups_id' => $collection->groups_id,
108
                    'guid' => Str::uuid()->toString(),
109
                    'postdate' => $collection->date,
110
                    'fromname' => $fromName,
111
                    'size' => $collection->filesize,
112
                    'categories_id' => $determinedCategory['categories_id'] ?? Category::OTHER_MISC,
113
                    'isrenamed' => $properName === true ? 1 : 0,
114
                    'predb_id' => $preID === false ? 0 : $preID,
115
                    'nzbstatus' => NZB::NZB_NONE,
116
                    'ishashed' => preg_match('/^[a-fA-F0-9]{32}\b|^[a-fA-F0-9]{40}\b|^[a-fA-F0-9]{64}\b|^[a-fA-F0-9]{96}\b|^[a-fA-F0-9]{128}\b/i', $searchName) ? 1 : 0,
0 ignored issues
show
Bug introduced by
It seems like $searchName can also be of type array; however, parameter $subject of preg_match() does only seem to accept 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 ignore-type  annotation

116
                    'ishashed' => preg_match('/^[a-fA-F0-9]{32}\b|^[a-fA-F0-9]{40}\b|^[a-fA-F0-9]{64}\b|^[a-fA-F0-9]{96}\b|^[a-fA-F0-9]{128}\b/i', /** @scrutinizer ignore-type */ $searchName) ? 1 : 0,
Loading history...
117
                ]);
118
119
                if ($releaseID !== null) {
120
                    DB::transaction(static function () use ($collection, $releaseID) {
121
                        Collection::query()->where('id', $collection->id)->update([
122
                            'filecheck' => ProcessReleases::COLLFC_INSERTED,
123
                            'releases_id' => $releaseID,
124
                        ]);
125
                    }, 10);
126
127
                    ReleaseRegex::insertOrIgnore([
128
                        'releases_id' => $releaseID,
129
                        'collection_regex_id' => $collection->collection_regexes_id,
130
                        'naming_regex_id' => $namingRegexId,
131
                    ]);
132
133
                    if (preg_match_all('#(\S+):\S+#', $collection->xref, $hits)) {
134
                        foreach ($hits[1] as $grp) {
135
                            $grpTmp = UsenetGroup::isValidGroup($grp);
136
                            if ($grpTmp !== false) {
137
                                $xrefGrpID = UsenetGroup::getIDByName($grpTmp);
138
                                if ($xrefGrpID === '') {
139
                                    $xrefGrpID = UsenetGroup::addGroup([
140
                                        'name' => $grpTmp,
141
                                        'description' => 'Added by Release processing',
142
                                        'backfill_target' => 1,
143
                                        'first_record' => 0,
144
                                        'last_record' => 0,
145
                                        'active' => 0,
146
                                        'backfill' => 0,
147
                                        'minfilestoformrelease' => '',
148
                                        'minsizetoformrelease' => '',
149
                                    ]);
150
                                }
151
152
                                $relGroupsChk = ReleasesGroups::query()->where([
153
                                    ['releases_id', '=', $releaseID],
154
                                    ['groups_id', '=', $xrefGrpID],
155
                                ])->first();
156
157
                                if ($relGroupsChk === null) {
158
                                    ReleasesGroups::query()->insert([
159
                                        'releases_id' => $releaseID,
160
                                        'groups_id' => $xrefGrpID,
161
                                    ]);
162
                                }
163
                            }
164
                        }
165
                    }
166
167
                    $returnCount++;
168
                    if ($echoCLI) {
169
                        echo "Added $returnCount releases.\r";
170
                    }
171
                }
172
            } else {
173
                DB::transaction(static function () use ($collection) {
174
                    Collection::query()->where('collectionhash', $collection->collectionhash)->delete();
175
                }, 10);
176
177
                $duplicate++;
178
            }
179
        }
180
181
        $totalTime = now()->diffInSeconds($startTime, true);
182
        if ($echoCLI) {
183
            $this->colorCLI->primary(
184
                PHP_EOL.
185
                number_format($returnCount).
186
                ' Releases added and '.
187
                number_format($duplicate).
188
                ' duplicate collections deleted in '.
189
                $totalTime.\Illuminate\Support\Str::plural(' second', $totalTime),
190
                true
191
            );
192
        }
193
194
        return ['added' => $returnCount, 'dupes' => $duplicate];
195
    }
196
}
197