Completed
Push — dev ( 8486bf...fdc38b )
by Darko
08:23
created

Books::getBrowseByOptions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
ccs 0
cts 1
cp 0
crap 2
1
<?php
2
3
namespace Blacklight;
4
5
use App\Models\Release;
6
use App\Models\BookInfo;
7
use App\Models\Category;
8
use App\Models\Settings;
9
use DariusIII\ItunesApi\iTunes;
10
use Illuminate\Support\Facades\DB;
11
use Illuminate\Support\Facades\Cache;
12
use DariusIII\ItunesApi\Exceptions\EbookNotFoundException;
13
use DariusIII\ItunesApi\Exceptions\SearchNoResultsException;
14
15
/**
16
 * Class Books.
17
 */
18
class Books
19
{
20
    /**
21
     * @var bool
22
     */
23
    public $echooutput;
24
25
    /**
26
     * @var null|string
27
     */
28
    public $pubkey;
29
30
    /**
31
     * @var null|string
32
     */
33
    public $privkey;
34
35
    /**
36
     * @var null|string
37
     */
38
    public $asstag;
39
40
    /**
41
     * @var int|null|string
42
     */
43
    public $bookqty;
44
45
    /**
46
     * @var int|null|string
47
     */
48
    public $sleeptime;
49
50
    /**
51
     * @var string
52
     */
53
    public $imgSavePath;
54
55
    /**
56
     * @var null|string
57
     */
58
    public $bookreqids;
59
60
    /**
61
     * @var string
62
     */
63
    public $renamed;
64
65
    /**
66
     * @var array
67
     */
68
    public $failCache;
69
70
    /**
71
     * @var \Blacklight\ColorCLI
72
     */
73
    protected $colorCli;
74
75
    /**
76
     * @param array $options Class instances / Echo to cli.
77
     *
78
     * @throws \Exception
79
     */
80
    public function __construct(array $options = [])
81
    {
82
        $defaults = [
83
            'Echo'     => false,
84
            'Settings' => null,
85
        ];
86
        $options += $defaults;
87
88
        $this->echooutput = ($options['Echo'] && config('nntmux.echocli'));
89
90
        $this->colorCli = new ColorCLI();
91
92
        $this->pubkey = Settings::settingValue('APIs..amazonpubkey');
93
        $this->privkey = Settings::settingValue('APIs..amazonprivkey');
94
        $this->asstag = Settings::settingValue('APIs..amazonassociatetag');
95
        $this->bookqty = Settings::settingValue('..maxbooksprocessed') !== '' ? (int) Settings::settingValue('..maxbooksprocessed') : 300;
0 ignored issues
show
introduced by
The condition App\Models\Settings::set...booksprocessed') !== '' is always true.
Loading history...
96
        $this->sleeptime = Settings::settingValue('..amazonsleep') !== '' ? (int) Settings::settingValue('..amazonsleep') : 1000;
0 ignored issues
show
introduced by
The condition App\Models\Settings::set...'..amazonsleep') !== '' is always true.
Loading history...
97
        $this->imgSavePath = NN_COVERS.'book'.DS;
98
        $result = Settings::settingValue('..book_reqids');
99
        $this->bookreqids = $result ?? Category::BOOKS_EBOOK;
100
        $this->renamed = (int) Settings::settingValue('..lookupbooks') === 2 ? 'AND isrenamed = 1' : '';
101
102
        $this->failCache = [];
103
    }
104
105
    /**
106
     * @param $id
107
     *
108
     * @return \Illuminate\Database\Eloquent\Model|null|static
109
     */
110
    public function getBookInfo($id)
111
    {
112
        return BookInfo::query()->where('id', $id)->first();
113
    }
114
115
    /**
116
     * @param $title
117
     *
118
     * @return \Illuminate\Database\Eloquent\Model
119
     */
120
    public function getBookInfoByName($title)
121
    {
122
123
        //only used to get a count of words
124
        $searchWords = '';
125
        $title = preg_replace('/( - | -|\(.+\)|\(|\))/', ' ', $title);
126
        $title = preg_replace('/[^\w ]+/', '', $title);
127
        $title = trim(trim(preg_replace('/\s\s+/i', ' ', $title)));
128
        foreach (explode(' ', $title) as $word) {
129
            $word = trim(rtrim(trim($word), '-'));
130
            if ($word !== '' && $word !== '-') {
131
                $word = '+'.$word;
132
                $searchWords .= sprintf('%s ', $word);
133
            }
134
        }
135
        $searchWords = trim($searchWords);
136
137
        return BookInfo::search($searchWords)->first();
138
    }
139
140
    /**
141
     * @param       $page
142
     * @param       $cat
143
     * @param       $start
144
     * @param       $num
145
     * @param       $orderby
146
     * @param array $excludedcats
147
     *
148
     * @return array
149
     * @throws \Exception
150
     */
151
    public function getBookRange($page, $cat, $start, $num, $orderby, array $excludedcats = []): array
152
    {
153
        $browseby = $this->getBrowseBy();
154
        $catsrch = '';
155
        if (\count($cat) > 0 && $cat[0] !== -1) {
156
            $catsrch = Category::getCategorySearch($cat);
157
        }
158
        $exccatlist = '';
159
        if (\count($excludedcats) > 0) {
160
            $exccatlist = ' AND r.categories_id NOT IN ('.implode(',', $excludedcats).')';
161
        }
162
        $order = $this->getBookOrder($orderby);
163
        $booksql = sprintf(
164
            "
165
				SELECT SQL_CALC_FOUND_ROWS boo.id,
166
					GROUP_CONCAT(r.id ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_id
167
				FROM bookinfo boo
168
				LEFT JOIN releases r ON boo.id = r.bookinfo_id
169
				WHERE r.nzbstatus = 1
170
				AND boo.cover = 1
171
				AND boo.title != ''
172
				AND r.passwordstatus %s
173
				%s %s %s
174
				GROUP BY boo.id
175
				ORDER BY %s %s %s",
176
            (new Releases())->showPasswords(),
177
            $browseby,
178
            $catsrch,
179
            $exccatlist,
180
            $order[0],
181
            $order[1],
182
            ($start === false ? '' : ' LIMIT '.$num.' OFFSET '.$start)
183
        );
184
        $expiresAt = now()->addMinutes(config('nntmux.cache_expiry_medium'));
185
        $bookscache = Cache::get(md5($booksql.$page));
186
        if ($bookscache !== null) {
187
            $books = $bookscache;
188
        } else {
189
            $data = DB::select($booksql);
190
            $books = ['total' => DB::select('SELECT FOUND_ROWS() AS total'), 'result' => $data];
191
            Cache::put(md5($booksql.$page), $books, $expiresAt);
192
        }
193
        $bookIDs = $releaseIDs = false;
194
        if (\is_array($books['result'])) {
195
            foreach ($books['result'] as $book => $id) {
196
                $bookIDs[] = $id->id;
197
                $releaseIDs[] = $id->grp_release_id;
198
            }
199
        }
200
        $sql = sprintf(
201
            '
202
			SELECT
203
				r.id, r.rarinnerfilecount, r.grabs, r.comments, r.totalpart, r.size, r.postdate, r.searchname, r.haspreview, r.passwordstatus, r.guid, df.failed AS failed,
204
			boo.*,
205
			r.bookinfo_id,
206
			g.name AS group_name,
207
			rn.releases_id AS nfoid
208
			FROM releases r
209
			LEFT OUTER JOIN groups g ON g.id = r.groups_id
210
			LEFT OUTER JOIN release_nfos rn ON rn.releases_id = r.id
211
			LEFT OUTER JOIN dnzb_failures df ON df.release_id = r.id
212
			INNER JOIN bookinfo boo ON boo.id = r.bookinfo_id
213
			WHERE boo.id IN (%s)
214
			AND r.id IN (%s)
215
			%s
216
			GROUP BY boo.id
217
			ORDER BY %s %s',
218
            (\is_array($bookIDs) ? implode(',', $bookIDs) : -1),
0 ignored issues
show
introduced by
The condition is_array($bookIDs) is always false.
Loading history...
219
            (\is_array($releaseIDs) ? implode(',', $releaseIDs) : -1),
0 ignored issues
show
introduced by
The condition is_array($releaseIDs) is always false.
Loading history...
220
            $catsrch,
221
            $order[0],
222
            $order[1]
223
        );
224
        $return = Cache::get(md5($sql.$page));
225
        if ($return !== null) {
226
            return $return;
227
        }
228
        $return = DB::select($sql);
229
        if (\count($return) > 0) {
230
            $return[0]->_totalcount = $books['total'][0]->total ?? 0;
231
        }
232
        Cache::put(md5($sql.$page), $return, $expiresAt);
233
234
        return $return;
235
    }
236
237
    /**
238
     * @param $orderby
239
     *
240
     * @return array
241
     */
242
    public function getBookOrder($orderby): array
243
    {
244
        $order = $orderby === '' ? 'r.postdate' : $orderby;
245
        $orderArr = explode('_', $order);
246
        switch ($orderArr[0]) {
247
            case 'title':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

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.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
248
                $orderfield = 'boo.title';
249
                break;
250
            case 'author':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

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.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
251
                $orderfield = 'boo.author';
252
                break;
253
            case 'publishdate':
254
                $orderfield = 'boo.publishdate';
255
                break;
256
            case 'size':
257
                $orderfield = 'r.size';
258
                break;
259
            case 'files':
260
                $orderfield = 'r.totalpart';
261
                break;
262
            case 'stats':
263
                $orderfield = 'r.grabs';
264
                break;
265
            case 'posted':
266
            default:
267
                $orderfield = 'r.postdate';
268
                break;
269
        }
270
        $ordersort = (isset($orderArr[1]) && preg_match('/^asc|desc$/i', $orderArr[1])) ? $orderArr[1] : 'desc';
271
272
        return [$orderfield, $ordersort];
273
    }
274
275
    /**
276
     * @return array
277
     */
278
    public function getBookOrdering(): array
279
    {
280
        return [
281
            'title_asc',
282
            'title_desc',
283
            'posted_asc',
284
            'posted_desc',
285
            'size_asc',
286
            'size_desc',
287
            'files_asc',
288
            'files_desc',
289
            'stats_asc',
290
            'stats_desc',
291
            'releasedate_asc',
292
            'releasedate_desc',
293
            'author_asc',
294
            'author_desc',
295
        ];
296
    }
297
298
    /**
299
     * @return array
300
     */
301
    public function getBrowseByOptions(): array
302
    {
303
        return ['author' => 'author', 'title' => 'title'];
304
    }
305
306
    /**
307
     * @return string
308
     */
309
    public function getBrowseBy(): string
310
    {
311
        $browseby = ' ';
312
        foreach ($this->getBrowseByOptions() as $bbk => $bbv) {
313
            if (isset($_REQUEST[$bbk]) && ! empty($_REQUEST[$bbk])) {
314
                $bbs = stripslashes($_REQUEST[$bbk]);
315
                $browseby .= 'AND boo.'.$bbv.' '.'LIKE '.escapeString('%'.$bbs.'%');
316
            }
317
        }
318
319
        return $browseby;
320
    }
321
322
    /**
323
     * Process book releases, 1 category at a time.
324
     *
325
     * @throws \Exception
326
     */
327
    public function processBookReleases(): void
328
    {
329
        $bookids = [];
330
        if (ctype_digit((string) $this->bookreqids)) {
331
            $bookids[] = $this->bookreqids;
332
        } else {
333
            $bookids = explode(', ', $this->bookreqids);
334
        }
335
336
        $total = \count($bookids);
337
        if ($total > 0) {
338
            foreach ($bookids as $i => $iValue) {
339
                $this->processBookReleasesHelper(
340
                    Release::query()->where('nzbstatus', '=', NZB::NZB_ADDED)
341
                        ->whereNull('bookinfo_id')
342
                        ->whereIn('categories_id', [$bookids[$i]])
343
                    ->orderBy('postdate', 'desc')
344
                    ->limit($this->bookqty)
0 ignored issues
show
Bug introduced by
It seems like $this->bookqty can also be of type string; however, parameter $value of Illuminate\Database\Query\Builder::limit() does only seem to accept integer, 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

344
                    ->limit(/** @scrutinizer ignore-type */ $this->bookqty)
Loading history...
345
                    ->get(['searchname', 'id', 'categories_id']),
346
                    $bookids[$i]
347
                );
348
            }
349
        }
350
    }
351
352
    /**
353
     * @param $res
354
     * @param $categoryID
355
     *
356
     * @throws \Exception
357
     */
358
    protected function processBookReleasesHelper($res, $categoryID): void
359
    {
360
        if ($res->count() > 0) {
361
            if ($this->echooutput) {
362
                $this->colorCli->header('Processing '.$res->count().' book release(s) for categories id '.$categoryID);
363
            }
364
365
            $bookId = -2;
366
            foreach ($res as $arr) {
367
                $startTime = now()->timestamp;
368
                $usedAmazon = false;
369
                // audiobooks are also books and should be handled in an identical manor, even though it falls under a music category
370
                if ($arr['categories_id'] === '3030') {
371
                    // audiobook
372
                    $bookInfo = $this->parseTitle($arr['searchname'], $arr['id'], 'audiobook');
373
                } else {
374
                    // ebook
375
                    $bookInfo = $this->parseTitle($arr['searchname'], $arr['id'], 'ebook');
376
                }
377
378
                if ($bookInfo !== false) {
379
                    if ($this->echooutput) {
380
                        $this->colorCli->headerOver('Looking up: ').$this->colorCli->primary($bookInfo);
0 ignored issues
show
Bug introduced by
Are you sure $this->colorCli->headerOver('Looking up: ') of type void can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

380
                        /** @scrutinizer ignore-type */ $this->colorCli->headerOver('Looking up: ').$this->colorCli->primary($bookInfo);
Loading history...
Bug introduced by
Are you sure the usage of $this->colorCli->headerOver('Looking up: ') targeting Blacklight\ColorCLI::headerOver() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug introduced by
Are you sure the usage of $this->colorCli->primary($bookInfo) targeting Blacklight\ColorCLI::primary() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
381
                    }
382
383
                    // Do a local lookup first
384
                    $bookCheck = $this->getBookInfoByName($bookInfo);
385
386
                    if ($bookCheck === null && \in_array($bookInfo, $this->failCache, false)) {
387
                        // Lookup recently failed, no point trying again
388
                        if ($this->echooutput) {
389
                            $this->colorCli->headerOver('Cached previous failure. Skipping.');
390
                        }
391
                        $bookId = -2;
392
                    } elseif ($bookCheck === null) {
393
                        $bookId = $this->updateBookInfo($bookInfo);
394
                        $usedAmazon = true;
395
                        if ($bookId === -2) {
396
                            $this->failCache[] = $bookInfo;
397
                        }
398
                    } elseif ($bookCheck !== null) {
399
                        $bookId = $bookCheck['id'];
400
                    }
401
402
                    // Update release.
403
                    Release::query()->where('id', $arr['id'])->update(['bookinfo_id' => $bookId]);
404
                } else { // Could not parse release title.
405
                    Release::query()->where('id', $arr['id'])->update(['bookinfo_id' => $bookId]);
406
                    if ($this->echooutput) {
407
                        echo '.';
408
                    }
409
                }
410
                // Sleep to not flood amazon.
411
                $diff = floor((now()->timestamp - $startTime) * 1000000);
412
                if ($this->sleeptime * 1000 - $diff > 0 && $usedAmazon === true) {
413
                    usleep($this->sleeptime * 1000 - $diff);
0 ignored issues
show
Bug introduced by
$this->sleeptime * 1000 - $diff of type double is incompatible with the type integer expected by parameter $micro_seconds of usleep(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

413
                    usleep(/** @scrutinizer ignore-type */ $this->sleeptime * 1000 - $diff);
Loading history...
414
                }
415
            }
416
        } elseif ($this->echooutput) {
417
            $this->colorCli->header('No book releases to process for categories id '.$categoryID);
418
        }
419
    }
420
421
    /**
422
     * @param $release_name
423
     * @param $releaseID
424
     * @param $releasetype
425
     *
426
     * @return bool|string
427
     */
428
    public function parseTitle($release_name, $releaseID, $releasetype)
429
    {
430
        $a = preg_replace('/\d{1,2} \d{1,2} \d{2,4}|(19|20)\d\d|anybody got .+?[a-z]\? |[-._ ](Novel|TIA)([-._ ]|$)|([ \.])HQ([-\. ])|[\(\)\.\-_ ](AVI|AZW3?|DOC|EPUB|LIT|MOBI|NFO|RETAIL|(si)?PDF|RTF|TXT)[\)\]\.\-_ ](?![a-z0-9])|compleet|DAGSTiDNiNGEN|DiRFiX|\+ extra|r?e ?Books?([\.\-_ ]English|ers)?|azw3?|ePu([bp])s?|html|mobi|^NEW[\.\-_ ]|PDF([\.\-_ ]English)?|Please post more|Post description|Proper|Repack(fix)?|[\.\-_ ](Chinese|English|French|German|Italian|Retail|Scan|Swedish)|^R4 |Repost|Skytwohigh|TIA!+|TruePDF|V413HAV|(would someone )?please (re)?post.+? "|with the authors name right/i', '', $release_name);
431
        $b = preg_replace('/^(As Req |conversion |eq |Das neue Abenteuer \d+|Fixed version( ignore previous post)?|Full |Per Req As Found|(\s+)?R4 |REQ |revised |version |\d+(\s+)?$)|(COMPLETE|INTERNAL|RELOADED| (AZW3|eB|docx|ENG?|exe|FR|Fix|gnv64|MU|NIV|R\d\s+\d{1,2} \d{1,2}|R\d|Req|TTL|UC|v(\s+)?\d))(\s+)?$/i', '', $a);
432
433
        //remove book series from title as this gets more matches on amazon
434
        $c = preg_replace('/ - \[.+\]|\[.+\]/', '', $b);
435
436
        //remove any brackets left behind
437
        $d = preg_replace('/(\(\)|\[\])/', '', $c);
438
        $releasename = trim(preg_replace('/\s\s+/i', ' ', $d));
439
440
        // the default existing type was ebook, this handles that in the same manor as before
441
        if ($releasetype === 'ebook') {
442
            if (preg_match('/^([a-z0-9] )+$|ArtofUsenet|ekiosk|(ebook|mobi).+collection|erotica|Full Video|ImwithJamie|linkoff org|Mega.+pack|^[a-z0-9]+ (?!((January|February|March|April|May|June|July|August|September|O([ck])tober|November|De([cz])ember)))[a-z]+( (ebooks?|The))?$|NY Times|(Book|Massive) Dump|Sexual/i', $releasename)) {
443
                if ($this->echooutput) {
444
                    $this->colorCli->headerOver('Changing category to misc books: ').$this->colorCli->primary($releasename);
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->colorCli->primary($releasename) targeting Blacklight\ColorCLI::primary() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug introduced by
Are you sure $this->colorCli->headerO...egory to misc books: ') of type void can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

444
                    /** @scrutinizer ignore-type */ $this->colorCli->headerOver('Changing category to misc books: ').$this->colorCli->primary($releasename);
Loading history...
Bug introduced by
Are you sure the usage of $this->colorCli->headerO...egory to misc books: ') targeting Blacklight\ColorCLI::headerOver() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
445
                }
446
                Release::query()->where('id', $releaseID)->update(['categories_id' => Category::BOOKS_UNKNOWN]);
447
448
                return false;
449
            }
450
451
            if (preg_match('/^([a-z0-9ü!]+ ){1,2}(N|Vol)?\d{1,4}([abc])?$|^([a-z0-9]+ ){1,2}(Jan( |unar|$)|Feb( |ruary|$)|Mar( |ch|$)|Apr( |il|$)|May(?![a-z0-9])|Jun([ e$])|Jul([ y$])|Aug( |ust|$)|Sep( |tember|$)|O([ck])t( |ober|$)|Nov( |ember|$)|De([cz])( |ember|$))/ui', $releasename) && ! preg_match('/Part \d+/i', $releasename)) {
452
                if ($this->echooutput) {
453
                    $this->colorCli->headerOver('Changing category to magazines: ').$this->colorCli->primary($releasename);
0 ignored issues
show
Bug introduced by
Are you sure $this->colorCli->headerO...tegory to magazines: ') of type void can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

453
                    /** @scrutinizer ignore-type */ $this->colorCli->headerOver('Changing category to magazines: ').$this->colorCli->primary($releasename);
Loading history...
Bug introduced by
Are you sure the usage of $this->colorCli->primary($releasename) targeting Blacklight\ColorCLI::primary() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug introduced by
Are you sure the usage of $this->colorCli->headerO...tegory to magazines: ') targeting Blacklight\ColorCLI::headerOver() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
454
                }
455
                Release::query()->where('id', $releaseID)->update(['categories_id' => Category::BOOKS_MAGAZINES]);
456
457
                return false;
458
            }
459
            if (! empty($releasename) && ! preg_match('/^[a-z0-9]+$|^([0-9]+ ){1,}$|Part \d+/i', $releasename)) {
460
                return $releasename;
461
            }
462
463
            return false;
464
        }
465
        if ($releasetype === 'audiobook') {
466
            if (! empty($releasename) && ! preg_match('/^[a-z0-9]+$|^([0-9]+ ){1,}$|Part \d+/i', $releasename)) {
467
                // we can skip category for audiobooks, since we already know it, so as long as the release name is valid return it so that it is postprocessed by amazon.  In the future, determining the type of audiobook could be added (Lecture or book), since we can skip lookups on lectures, but for now handle them all the same way
468
                return $releasename;
469
            }
470
471
            return false;
472
        }
473
474
        return false;
475
    }
476
477
    /**
478
     * @param string $bookInfo
479
     * @param null   $amazdata
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $amazdata is correct as it would always require null to be passed?
Loading history...
480
     *
481
     * @return false|int|string
482
     * @throws \Exception
483
     */
484
    public function updateBookInfo($bookInfo = '', $amazdata = null)
485
    {
486
        $ri = new ReleaseImage();
487
488
        $bookId = -2;
489
490
        $book = false;
491
        if ($bookInfo !== '') {
492
            if (! $book) {
0 ignored issues
show
introduced by
The condition $book is always false.
Loading history...
493
                $this->colorCli->info('Fetching data from iTunes for '.$bookInfo);
494
                $book = $this->fetchItunesBookProperties($bookInfo);
495
            } elseif ($amazdata !== null) {
496
                $book = $amazdata;
497
            }
498
        }
499
500
        if (empty($book)) {
501
            return false;
502
        }
503
504
        $check = BookInfo::query()->where('asin', $book['asin'])->first();
505
        if ($check === null) {
506
            $bookId = BookInfo::query()->insertGetId(
507
                [
508
                    'title' => $book['title'],
509
                    'author' => $book['author'],
510
                    'asin' => $book['asin'],
511
                    'isbn' => $book['isbn'],
512
                    'ean' => $book['ean'],
513
                    'url' => $book['url'],
514
                    'salesrank' => $book['salesrank'],
515
                    'publisher' => $book['publisher'],
516
                    'publishdate' => $book['publishdate'],
517
                    'pages' => $book['pages'],
518
                    'overview' => $book['overview'],
519
                    'genre' => $book['genre'],
520
                    'cover' => $book['cover'],
521
                    'created_at' => now(),
522
                    'updated_at' => now(),
523
                ]
524
            );
525
        } else {
526
            if ($check !== null) {
527
                $bookId = $check['id'];
528
            }
529
            BookInfo::query()->where('id', $bookId)->update(
530
                [
531
                    'title' => $book['title'],
532
                    'author' => $book['author'],
533
                    'asin' => $book['asin'],
534
                    'isbn' => $book['isbn'],
535
                    'ean' => $book['ean'],
536
                    'url' => $book['url'],
537
                    'salesrank' => $book['salesrank'],
538
                    'publisher' => $book['publisher'],
539
                    'publishdate' => $book['publishdate'],
540
                    'pages' => $book['pages'],
541
                    'overview' => $book['overview'],
542
                    'genre' => $book['genre'],
543
                    'cover' => $book['cover'],
544
                ]
545
            );
546
        }
547
548
        if ($bookId && $bookId !== -2) {
549
            if ($this->echooutput) {
550
                $this->colorCli->header('Added/updated book: ');
551
                if ($book['author'] !== '') {
552
                    $this->colorCli->alternateOver('   Author: ').$this->colorCli->primary($book['author']);
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->colorCli->primary($book['author']) targeting Blacklight\ColorCLI::primary() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug introduced by
Are you sure the usage of $this->colorCli->alternateOver(' Author: ') targeting Blacklight\ColorCLI::alternateOver() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug introduced by
Are you sure $this->colorCli->alternateOver(' Author: ') of type void can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

552
                    /** @scrutinizer ignore-type */ $this->colorCli->alternateOver('   Author: ').$this->colorCli->primary($book['author']);
Loading history...
553
                }
554
                $this->colorCli->alternateOver('   Title: ').$this->colorCli->primary(' '.$book['title']);
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->colorCli->primary(' ' . $book['title']) targeting Blacklight\ColorCLI::primary() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug introduced by
Are you sure $this->colorCli->alternateOver(' Title: ') of type void can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

554
                /** @scrutinizer ignore-type */ $this->colorCli->alternateOver('   Title: ').$this->colorCli->primary(' '.$book['title']);
Loading history...
Bug introduced by
Are you sure the usage of $this->colorCli->alternateOver(' Title: ') targeting Blacklight\ColorCLI::alternateOver() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
555
                if ($book['genre'] !== 'null') {
556
                    $this->colorCli->alternateOver('   Genre: ').$this->colorCli->primary(' '.$book['genre']);
0 ignored issues
show
Bug introduced by
Are you sure $this->colorCli->alternateOver(' Genre: ') of type void can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

556
                    /** @scrutinizer ignore-type */ $this->colorCli->alternateOver('   Genre: ').$this->colorCli->primary(' '.$book['genre']);
Loading history...
Bug introduced by
Are you sure the usage of $this->colorCli->alternateOver(' Genre: ') targeting Blacklight\ColorCLI::alternateOver() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug introduced by
Are you sure the usage of $this->colorCli->primary(' ' . $book['genre']) targeting Blacklight\ColorCLI::primary() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
557
                }
558
            }
559
560
            $book['cover'] = $ri->saveImage($bookId, $book['coverurl'], $this->imgSavePath, 250, 250);
561
        } elseif ($this->echooutput) {
562
            $this->colorCli->header('Nothing to update: ').
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->colorCli->header('Nothing to update: ') targeting Blacklight\ColorCLI::header() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug introduced by
Are you sure $this->colorCli->header('Nothing to update: ') of type void can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

562
            /** @scrutinizer ignore-type */ $this->colorCli->header('Nothing to update: ').
Loading history...
563
                $this->colorCli->header($book['author'].
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->colorCli->header(...' - ' . $book['title']) targeting Blacklight\ColorCLI::header() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
564
                    ' - '.
565
                    $book['title']);
566
        }
567
568
        return $bookId;
569
    }
570
571
    /**
572
     * @param string $bookInfo
573
     * @return array|bool
574
     * @throws \DariusIII\ItunesApi\Exceptions\InvalidProviderException
575
     */
576
    public function fetchItunesBookProperties(string $bookInfo)
577
    {
578
        $book = true;
579
        try {
580
            $iTunesBook = iTunes::load('ebook')->fetchOneByName($bookInfo);
581
        } catch (EbookNotFoundException $e) {
582
            $book = false;
583
        } catch (SearchNoResultsException $e) {
584
            $book = false;
585
        }
586
587
        if ($book) {
588
            $this->colorCli->info('Found matching title: '.$iTunesBook->getName());
589
            $book = [
590
                'title' => $iTunesBook->getName(),
591
                'author' => $iTunesBook->getAuthor(),
0 ignored issues
show
Bug introduced by
The method getAuthor() does not exist on DariusIII\ItunesApi\Entities\EntityInterface. It seems like you code against a sub-type of DariusIII\ItunesApi\Entities\EntityInterface such as DariusIII\ItunesApi\Entities\Ebook. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

591
                'author' => $iTunesBook->/** @scrutinizer ignore-call */ getAuthor(),
Loading history...
592
                'asin' => $iTunesBook->getItunesId(),
593
                'isbn' => 'null',
594
                'ean' => 'null',
595
                'url' => $iTunesBook->getStoreUrl(),
0 ignored issues
show
Bug introduced by
The method getStoreUrl() does not exist on DariusIII\ItunesApi\Entities\EntityInterface. It seems like you code against a sub-type of said class. However, the method does not exist in DariusIII\ItunesApi\Entities\Track or DariusIII\ItunesApi\Entities\Artist. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

595
                'url' => $iTunesBook->/** @scrutinizer ignore-call */ getStoreUrl(),
Loading history...
596
                'salesrank' => '',
597
                'publisher' => '',
598
                'pages' => '',
599
                'coverurl' => ! empty($iTunesBook->getCover()) ? str_replace('100x100', '800x800', $iTunesBook->getCover()) : '',
0 ignored issues
show
Bug introduced by
The method getCover() does not exist on DariusIII\ItunesApi\Entities\EntityInterface. It seems like you code against a sub-type of said class. However, the method does not exist in DariusIII\ItunesApi\Entities\Track or DariusIII\ItunesApi\Entities\Artist. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

599
                'coverurl' => ! empty($iTunesBook->/** @scrutinizer ignore-call */ getCover()) ? str_replace('100x100', '800x800', $iTunesBook->getCover()) : '',
Loading history...
600
                'genre' => implode(', ', $iTunesBook->getGenre()),
0 ignored issues
show
Bug introduced by
The method getGenre() does not exist on DariusIII\ItunesApi\Entities\EntityInterface. It seems like you code against a sub-type of said class. However, the method does not exist in DariusIII\ItunesApi\Entities\Artist. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

600
                'genre' => implode(', ', $iTunesBook->/** @scrutinizer ignore-call */ getGenre()),
Loading history...
601
                'overview' => strip_tags($iTunesBook->getDescription()),
0 ignored issues
show
Bug introduced by
The method getDescription() does not exist on DariusIII\ItunesApi\Entities\EntityInterface. It seems like you code against a sub-type of DariusIII\ItunesApi\Entities\EntityInterface such as DariusIII\ItunesApi\Entities\Ebook or DariusIII\ItunesApi\Entities\Movie. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

601
                'overview' => strip_tags($iTunesBook->/** @scrutinizer ignore-call */ getDescription()),
Loading history...
602
                'publishdate' => $iTunesBook->getReleaseDate()->format('Y-m-d'),
0 ignored issues
show
Bug introduced by
The method getReleaseDate() does not exist on DariusIII\ItunesApi\Entities\EntityInterface. It seems like you code against a sub-type of said class. However, the method does not exist in DariusIII\ItunesApi\Entities\Track or DariusIII\ItunesApi\Entities\Artist. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

602
                'publishdate' => $iTunesBook->/** @scrutinizer ignore-call */ getReleaseDate()->format('Y-m-d'),
Loading history...
603
            ];
604
            if (! empty($book['coverurl'])) {
605
                $book['cover'] = 1;
606
            } else {
607
                $book['cover'] = 0;
608
            }
609
        } else {
610
            $this->colorCli->notice('Could not find a match on iTunes!');
611
        }
612
613
        return $book;
614
    }
615
}
616