Passed
Pull Request — master (#13)
by Alexey
03:59
created

AppInfo::equals()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 30
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 6.0061

Importance

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

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