Passed
Push — master ( 641929...562012 )
by Alexey
06:04 queued 12s
created

AppInfo::equals()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 30
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 6.0073

Importance

Changes 0
Metric Value
eloc 16
c 0
b 0
f 0
dl 0
loc 30
ccs 16
cts 17
cp 0.9412
rs 9.1111
cc 6
nc 6
nop 1
crap 6.0073
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * Copyright (c) Ne-Lexa
7
 *
8
 * For the full copyright and license information, please view
9
 * the LICENSE file that was distributed with this source code.
10
 *
11
 * @see https://github.com/Ne-Lexa/google-play-scraper
12
 */
13
14
namespace Nelexa\GPlay\Model;
15
16
use Nelexa\GPlay\GPlayApps;
17
use Nelexa\GPlay\Model\Builder\AppBuilder;
18
19
/**
20
 * Contains detailed information about the application from the Google Play store.
21
 *
22
 * @see App Basic information about the application from the Google Play store.
23
 * @see GPlayApps::getAppInfo() Returns detailed information about the Android
24
 *     application from the Google Play store.
25
 * @see GPlayApps::getAppsInfo() Returns detailed information about many android packages.
26
 * @see GPlayApps::getAppInLocales() Returns detailed information about an application
27
 *     from the Google Play store for an array of locales.
28
 * @see GPlayApps::getAppInfoForAvailableLocales() Returns detailed information about the
29
 *     application in all available locales.
30
 */
31
final class AppInfo extends App
32
{
33
    /** @var string Default currency. */
34
    private const DEFAULT_CURRENCY = 'USD';
35
36
    /** @var string Application description. */
37
    private $description;
38
39
    /**
40
     * Locale (language) of the original description. Google automatically translates
41
     * the description of the application if the developer has not added it to the
42
     * Play Console in the "Add your own translation text" section. If a translation
43
     * is added, the value will be null.
44
     *
45
     * @var string|null locale of the original description or null
46
     *
47
     * @see https://support.google.com/googleplay/android-developer/answer/3125566
48
     */
49
    private $translatedFromLocale;
50
51
    /** @var GoogleImage|null Cover image. */
52
    private $cover;
53
54
    /** @var GoogleImage[] Screenshots of the application. */
55
    private $screenshots;
56
57
    /** @var Category|null Application category. */
58
    private $category;
59
60
    /** @var Category|null Family category or null/ */
61
    private $categoryFamily;
62
63
    /** @var Video|null Promo video or null. */
64
    private $video;
65
66
    /** @var string|null Recent changes. */
67
    private $recentChanges;
68
69
    /** @var bool Editors' choice. */
70
    private $editorsChoice;
71
72
    /** @var int Number of application installations. */
73
    private $installs;
74
75
    /** @var HistogramRating Histogram rating. */
76
    private $histogramRating;
77
78
    /** @var float Price of the application in the Google Play store. */
79
    private $price;
80
81
    /** @var string Currency price of the application. */
82
    private $currency;
83
84
    /** @var string|null In-App Purchase price. */
85
    private $offersIAPCost;
86
87
    /** @var bool Application contains ads. */
88
    private $containsAds;
89
90
    /** @var string|null Application size, null if the size depends on the device. */
91
    private $size;
92
93
    /** @var string|null Application version, null if the application version depends on the device. */
94
    private $appVersion;
95
96
    /** @var string|null Android version, null if android version depends on the device. */
97
    private $androidVersion;
98
99
    /** @var string|null Minimum android version, null if android version depends on the device. */
100
    private $minAndroidVersion;
101
102
    /** @var string|null Content rating. */
103
    private $contentRating;
104
105
    /** @var string|null Privacy policy URL. */
106
    private $privacyPoliceUrl;
107
108
    /** @var \DateTimeInterface|null Release date if known. */
109
    private $released;
110
111
    /** @var \DateTimeInterface|null Update date or null. */
112
    private $updated;
113
114
    /** @var int Number of voters. */
115
    private $numberVoters;
116
117
    /** @var int Number of reviews. */
118
    private $numberReviews;
119
120
    /** @var Review[] Some useful reviews. */
121
    private $reviews;
122
123
    /**
124
     * Returns an object with detailed information about the application.
125
     *
126
     * @param AppBuilder $builder application builder
127
     *
128
     * @ignore
129
     */
130 21
    public function __construct(AppBuilder $builder)
131
    {
132 21
        parent::__construct($builder);
133
134 21
        if (empty($builder->getDescription())) {
135 1
            throw new \InvalidArgumentException(
136
                'Application description cannot be null or empty. Solution: $appBuilder->setDescription(...);'
137
            );
138
        }
139
140 21
        if (empty($builder->getScreenshots())) {
141 1
            throw new \InvalidArgumentException(
142
                'Screenshots of the application must contain at least one screenshot. Solution: $appBuilder->setScreenshots(...); or $appBuilder->addScreenshot(...);'
143
            );
144
        }
145
146 21
        $this->description = $builder->getDescription();
147 21
        $this->translatedFromLocale = $builder->getTranslatedFromLocale();
148 21
        $this->cover = $builder->getCover();
149 21
        $this->screenshots = $builder->getScreenshots();
150 21
        $this->category = $builder->getCategory();
151 21
        $this->categoryFamily = $builder->getCategoryFamily();
152 21
        $this->privacyPoliceUrl = $builder->getPrivacyPoliceUrl();
153 21
        $this->video = $builder->getVideo();
154 21
        $this->recentChanges = $builder->getRecentChanges();
155 21
        $this->editorsChoice = $builder->isEditorsChoice();
156 21
        $this->installs = $builder->getInstalls();
157 21
        $this->histogramRating = $builder->getHistogramRating()
158 2
            ?? new HistogramRating(0, 0, 0, 0, 0);
159 21
        $this->price = $builder->getPrice();
160 21
        $this->currency = $builder->getCurrency() ?? self::DEFAULT_CURRENCY;
161 21
        $this->offersIAPCost = $builder->getOffersIAPCost();
162 21
        $this->containsAds = $builder->isContainsAds();
163 21
        $this->size = $builder->getSize();
164 21
        $this->appVersion = $builder->getAppVersion();
165 21
        $this->androidVersion = $builder->getAndroidVersion();
166 21
        $this->minAndroidVersion = $builder->getMinAndroidVersion();
167 21
        $this->contentRating = $builder->getContentRating();
168 21
        $this->released = $builder->getReleased();
169 21
        $this->updated = $builder->getUpdated();
170 21
        $this->numberVoters = $builder->getNumberVoters();
171 21
        $this->numberReviews = $builder->getNumberReviews();
172 21
        $this->reviews = $builder->getReviews();
173
    }
174
175
    /**
176
     * Returns a description of the application.
177
     *
178
     * @return string description of the application
179
     */
180 1
    public function getDescription(): string
181
    {
182 1
        return $this->description;
183
    }
184
185
    /**
186
     * Checks if the class description is automatically translated via Google Translate.
187
     *
188
     * @return bool `true` if the description was automatically translated using Google Translate and
189
     *              `false` if the developer added a description for the locale in the Google Play Console
190
     */
191 13
    public function isAutoTranslatedDescription(): bool
192
    {
193 13
        return $this->translatedFromLocale !== null;
194
    }
195
196
    /**
197
     * Returns locale (language) of the original description.
198
     *
199
     * Google automatically translates the description of the application if the developer
200
     * has not added it to the Play Console in the "Add your own translation text" section.
201
     * If a translation is added, the value will be null.
202
     *
203
     * @return string|null if the developer added a translation of the description, then the
204
     *                     value will be `null`, otherwise the original language of the application description
205
     */
206 13
    public function getTranslatedFromLocale(): ?string
207
    {
208 13
        return $this->translatedFromLocale;
209
    }
210
211
    /**
212
     * Returns cover image.
213
     *
214
     * **Where it's displayed**
215
     * The feature graphic is displayed in front of screenshots of the application and in
216
     * the list of developer applications. If a promo video is added, a **Play** button
217
     * will overlay on the feature graphic so users can watch the promo video.
218
     *
219
     * Google Play requirements:
220
     * * JPEG or 24-bit PNG (no alpha)
221
     * * Dimensions: 1024px by 500px
222
     *
223
     * @return GoogleImage|null cover image or `null`
224
     *
225
     * @see https://support.google.com/googleplay/android-developer/answer/1078870?hl=en Graphic assets,
226
     *     screenshots, & video. Section **Feature graphic**.
227
     */
228 1
    public function getCover(): ?GoogleImage
229
    {
230 1
        return $this->cover;
231
    }
232
233
    /**
234
     * Returns screenshots of the application.
235
     *
236
     * The array must contain at least 2 screenshots.
237
     *
238
     * Google Play screenshots requirements:
239
     * * JPEG or 24-bit PNG (no alpha)
240
     * * Minimum dimension: 320px
241
     * * Maximum dimension: 3840px
242
     * * The maximum dimension of the screenshot can't be more than twice as long as the minimum dimension.
243
     *
244
     * @return GoogleImage[] array of screenshots
245
     */
246 2
    public function getScreenshots(): array
247
    {
248 2
        return $this->screenshots;
249
    }
250
251
    /**
252
     * Returns the category of the application.
253
     *
254
     * @return Category|null category of application or `null`
255
     */
256 1
    public function getCategory(): ?Category
257
    {
258 1
        return $this->category;
259
    }
260
261
    /**
262
     * Returns family category.
263
     *
264
     * @return Category|null family category or `null`
265
     */
266 1
    public function getCategoryFamily(): ?Category
267
    {
268 1
        return $this->categoryFamily;
269
    }
270
271
    /**
272
     * Returns a video about the application.
273
     *
274
     * @return Video|null promo video or `null`
275
     */
276 1
    public function getVideo(): ?Video
277
    {
278 1
        return $this->video;
279
    }
280
281
    /**
282
     * Returns recent changes.
283
     *
284
     * @return string|null recent changes or null if not provided
285
     */
286 1
    public function getRecentChanges(): ?string
287
    {
288 1
        return $this->recentChanges;
289
    }
290
291
    /**
292
     * Checks if the application is an editors' choice.
293
     *
294
     * @return bool `true` if the application is selected by Google Play editor, otherwise `false`
295
     */
296 1
    public function isEditorsChoice(): bool
297
    {
298 1
        return $this->editorsChoice;
299
    }
300
301
    /**
302
     * Returns the number of installations of the application.
303
     *
304
     * @return int the number of installations of the application
305
     */
306 1
    public function getInstalls(): int
307
    {
308 1
        return $this->installs;
309
    }
310
311
    /**
312
     * Returns histogram rating.
313
     *
314
     * @return HistogramRating histogram rating
315
     */
316 1
    public function getHistogramRating(): HistogramRating
317
    {
318 1
        return $this->histogramRating;
319
    }
320
321
    /**
322
     * Returns the price of the app in the Google Play store.
323
     *
324
     * @return float price or 0.00 if the app is free
325
     *
326
     * @see AppInfo::getCurrency() Returns the price currency
327
     *     of the app in the Google Play store.
328
     */
329 1
    public function getPrice(): float
330
    {
331 1
        return $this->price;
332
    }
333
334
    /**
335
     * Returns the price currency of the app in the Google Play store.
336
     *
337
     * @return string currency price of the application, default USD
338
     */
339 1
    public function getCurrency(): string
340
    {
341 1
        return $this->currency;
342
    }
343
344
    /**
345
     * Checks if the app contains In-App Purchases (IAP).
346
     *
347
     * @return bool `true` if the application contains AIP, and `false` if not contains
348
     */
349 1
    public function isContainsIAP(): bool
350
    {
351 1
        return $this->offersIAPCost !== null;
352
    }
353
354
    /**
355
     * Returns the cost of In-App Purchases (IAP).
356
     *
357
     * @return string|null in-App Purchase price
358
     */
359 1
    public function getOffersIAPCost(): ?string
360
    {
361 1
        return $this->offersIAPCost;
362
    }
363
364
    /**
365
     * Checks if the app contains ads.
366
     *
367
     * @return bool `true` if the application contains ads, and `false` if not contains
368
     */
369 1
    public function isContainsAds(): bool
370
    {
371 1
        return $this->containsAds;
372
    }
373
374
    /**
375
     * Returns the size of the application.
376
     *
377
     * @return string|null application size, `null` if the size depends on the device
378
     */
379 1
    public function getSize(): ?string
380
    {
381 1
        return $this->size;
382
    }
383
384
    /**
385
     * Returns the version of the application.
386
     *
387
     * @return string|null application version, `null` if the application version depends on the device
388
     */
389 1
    public function getAppVersion(): ?string
390
    {
391 1
        return $this->appVersion;
392
    }
393
394
    /**
395
     * Returns the supported version of Android.
396
     *
397
     * @return string|null android version, `null` if android version depends on the device
398
     */
399 1
    public function getAndroidVersion(): ?string
400
    {
401 1
        return $this->androidVersion;
402
    }
403
404
    /**
405
     * Returns the minimum supported version of Android.
406
     *
407
     * @return string|null minimum android version, `null` if android version depends on the device
408
     */
409 1
    public function getMinAndroidVersion(): ?string
410
    {
411 1
        return $this->minAndroidVersion;
412
    }
413
414
    /**
415
     * Returns the age limit.
416
     *
417
     * @return string|null Content rating or `null` if not provided
418
     */
419 1
    public function getContentRating(): ?string
420
    {
421 1
        return $this->contentRating;
422
    }
423
424
    /**
425
     * Returns privacy policy URL.
426
     *
427
     * @return string|null privacy policy URL
428
     */
429 1
    public function getPrivacyPoliceUrl(): ?string
430
    {
431 1
        return $this->privacyPoliceUrl;
432
    }
433
434
    /**
435
     * Returns the release date.
436
     *
437
     * @return \DateTimeInterface|null release date or `null` if not provided
438
     */
439 13
    public function getReleased(): ?\DateTimeInterface
440
    {
441 13
        return $this->released;
442
    }
443
444
    /**
445
     * Returns the date of the update.
446
     *
447
     * @return \DateTimeInterface|null update date or `null` if not provided
448
     */
449 1
    public function getUpdated(): ?\DateTimeInterface
450
    {
451 1
        return $this->updated;
452
    }
453
454
    /**
455
     * Returns the number of voters.
456
     *
457
     * @return int number of voters
458
     */
459 1
    public function getNumberVoters(): int
460
    {
461 1
        return $this->numberVoters;
462
    }
463
464
    /**
465
     * Returns the number of reviews.
466
     *
467
     * @return int number of reviews
468
     */
469 1
    public function getNumberReviews(): int
470
    {
471 1
        return $this->numberReviews;
472
    }
473
474
    /**
475
     * Returns some useful reviews.
476
     *
477
     * @return Review[] some useful reviews
478
     */
479 1
    public function getReviews(): array
480
    {
481 1
        return $this->reviews;
482
    }
483
484
    /**
485
     * Checks for equality of applications.
486
     *
487
     * @param AppInfo $otherApp application with which is compared
488
     *
489
     * @return bool `true` if the contents of the objects being changed are the same
490
     *              and `false` if the objects contain different data
491
     *
492
     * @internal
493
     */
494 14
    public function equals(self $otherApp): bool
495
    {
496 14
        if ($otherApp->getId() !== $this->getId()) {
497
            return false;
498
        }
499
500 14
        if ($otherApp->getName() !== $this->getName()) {
501 9
            return false;
502
        }
503
504 14
        if ($otherApp->description !== $this->description) {
505 12
            return false;
506
        }
507
508 12
        if ($otherApp->recentChanges !== $this->recentChanges) {
509 1
            return false;
510
        }
511
512 12
        if ($otherApp->getIcon()->getOriginalSizeUrl() !== $this->getIcon()->getOriginalSizeUrl()) {
513 1
            return false;
514
        }
515 12
        $diff = array_udiff(
516 12
            $otherApp->screenshots,
517 12
            $this->screenshots,
518 12
            static function (GoogleImage $a, GoogleImage $b) {
519 12
                return strcmp($a->getOriginalSizeUrl(), $b->getOriginalSizeUrl());
520
            }
521
        );
522
523 12
        return empty($diff);
524
    }
525
526
    /**
527
     * Returns class properties as an array.
528
     *
529
     * @return array class properties as an array
530
     */
531
    public function asArray(): array
532
    {
533
        $array = parent::asArray();
534
        $array['description'] = $this->description;
535
        $array['translatedFromLocale'] = $this->translatedFromLocale;
536
        $array['cover'] = $this->cover !== null ? $this->cover->getUrl() : null;
537
        $array['screenshots'] = array_map(
538
            static function (GoogleImage $googleImage) {
539
                return $googleImage->getUrl();
540
            },
541
            $this->screenshots
542
        );
543
        $array['category'] = $this->category->asArray();
0 ignored issues
show
Bug introduced by
The method asArray() does not exist on null. ( Ignorable by Annotation )

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

543
        /** @scrutinizer ignore-call */ 
544
        $array['category'] = $this->category->asArray();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
544
        $array['categoryFamily'] = $this->categoryFamily !== null ? $this->categoryFamily->asArray() : null;
545
        $array['video'] = $this->video !== null ? $this->video->asArray() : null;
546
        $array['privacyPoliceUrl'] = $this->privacyPoliceUrl;
547
        $array['recentChange'] = $this->recentChanges;
548
        $array['editorsChoice'] = $this->editorsChoice;
549
        $array['installs'] = $this->installs;
550
        $array['numberVoters'] = $this->numberVoters;
551
        $array['histogramRating'] = $this->histogramRating;
552
        $array['price'] = $this->price;
553
        $array['currency'] = $this->currency;
554
        $array['offersIAP'] = $this->isContainsIAP();
555
        $array['offersIAPCost'] = $this->offersIAPCost;
556
        $array['containsAds'] = $this->containsAds;
557
        $array['size'] = $this->size;
558
        $array['appVersion'] = $this->appVersion;
559
        $array['androidVersion'] = $this->androidVersion;
560
        $array['minAndroidVersion'] = $this->minAndroidVersion;
561
        $array['contentRating'] = $this->contentRating;
562
        $array['released'] = $this->released !== null ? $this->released->format(\DateTime::RFC3339) : null;
563
        $array['releasedTimestamp'] = $this->released !== null ? $this->released->getTimestamp() : 0;
564
        $array['updated'] = $this->updated !== null ? $this->updated->format(\DateTime::RFC3339) : null;
565
        $array['updatedTimestamp'] = $this->updated !== null ? $this->updated->getTimestamp() : 0;
566
        $array['numberReviews'] = $this->numberReviews;
567
        $array['reviews'] = array_map(
568
            static function (Review $review) {
569
                return $review->asArray();
570
            },
571
            $this->reviews
572
        );
573
574
        return $array;
575
    }
576
}
577