Passed
Push — main ( e85cc4...f68a23 )
by Paul
05:06
created

Avatar   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 140
Duplicated Lines 0 %

Test Coverage

Coverage 54.43%

Importance

Changes 3
Bugs 0 Features 1
Metric Value
wmc 28
eloc 69
c 3
b 0
f 1
dl 0
loc 140
ccs 43
cts 79
cp 0.5443
rs 10

12 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A fallbackUrl() 0 8 2
A url() 0 6 2
A userField() 0 9 4
A generatePixels() 0 3 1
A generate() 0 16 4
A fallbackDefault() 0 19 6
A isUrl() 0 3 1
A isUrlOnline() 0 7 1
A generateInitials() 0 7 2
A size() 0 8 2
A img() 0 16 2
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Modules;
4
5
use GeminiLabs\SiteReviews\Database\Cache;
6
use GeminiLabs\SiteReviews\Helper;
7
use GeminiLabs\SiteReviews\Helpers\Cast;
8
use GeminiLabs\SiteReviews\Modules\Avatars\InitialsAvatar;
9
use GeminiLabs\SiteReviews\Modules\Avatars\PixelAvatar;
10
use GeminiLabs\SiteReviews\Modules\Html\Builder;
11
use GeminiLabs\SiteReviews\Review;
12
13
class Avatar
14
{
15
    public const FALLBACK_SIZE = 40;
16
    public const GRAVATAR_URL = 'https://secure.gravatar.com/avatar';
17
18
    /**
19
     * @var string
20
     */
21
    public $type;
22
23 25
    public function __construct()
24
    {
25 25
        $this->type = glsr_get_option('reviews.avatars_fallback', 'mystery', 'string');
26
    }
27
28
    /**
29
     * @return string
30
     */
31 25
    public function fallbackDefault(Review $review)
32
    {
33 25
        if ('custom' === $this->type) {
34
            $customUrl = glsr_get_option('reviews.avatars_fallback_url');
35
            if ($this->isUrl($customUrl)) {
36
                return $customUrl;
37
            }
38
            $this->type = 'mystery'; // fallback to mystery if a custom url is not set
39
        }
40 25
        if ('initials' === $this->type) {
41
            return $this->generateInitials($review);
42
        }
43 25
        if ('none' === $this->type) {
44 25
            $this->type = '';
45
        }
46 25
        if ('pixels' === $this->type) {
47
            return $this->generatePixels($review);
48
        }
49 25
        return $this->type;
50
    }
51
52
    public function fallbackUrl(Review $review, int $size = 0): string
53
    {
54
        $fallbackUrl = $this->fallbackDefault($review);
55
        if ($fallbackUrl === $this->type) {
56
            $fallbackUrl = add_query_arg('d', $this->type, static::GRAVATAR_URL);
57
            $fallbackUrl = add_query_arg('s', $this->size($size), $fallbackUrl);
58
        }
59
        return glsr()->filterString('avatar/fallback', $fallbackUrl, $size, $review);
60
    }
61
62 25
    public function generate(Review $review, int $size = 0): string
63
    {
64 25
        $default = $this->fallbackDefault($review);
65 25
        if ($default !== $this->type) {
66
            $default = '404';
67
        }
68 25
        $size = $this->size($size);
69 25
        $avatarUrl = get_avatar_url($this->userField($review), [
70 25
            'default' => $default,
71 25
            'size' => $size,
72 25
        ]);
73 25
        $avatarUrl = glsr()->filterString('avatar/generate', $avatarUrl, $size, $review);
74 25
        if (!$this->isUrl($avatarUrl) || !$this->isUrlOnline($avatarUrl)) {
75
            return $this->fallbackUrl($review, $size);
76
        }
77 25
        return $avatarUrl;
78
    }
79
80
    public function generateInitials(Review $review): string
81
    {
82
        $name = $review->author;
83
        if (empty($review->author)) {
84
            $name = __('Anonymous', 'site-reviews');
85
        }
86
        return glsr(InitialsAvatar::class)->create($name);
87
    }
88
89
    public function generatePixels(Review $review): string
90
    {
91
        return glsr(PixelAvatar::class)->create($this->userField($review));
92
    }
93
94
    public function img(Review $review, int $size = 0): string
95
    {
96
        $size = $this->size($size);
97
        $attributes = [
98
            'alt' => sprintf(__('Avatar for %s', 'site-reviews'), $review->author()),
99
            'height' => $size, // @2x
100
            'loading' => 'lazy',
101
            'src' => $this->url($review, $size), // @2x
102
            'style' => sprintf('width:%1$spx; height:%1$spx;', $size / 2), // @1x
103
            'width' => $size, // @2x
104
        ];
105
        if (glsr()->isAdmin()) {
106
            $attributes['data-fallback'] = $this->fallbackUrl($review, $size);
107
        }
108
        $attributes = glsr()->filterArray('avatar/attributes', $attributes, $review);
109
        return glsr(Builder::class)->img($attributes);
110
    }
111
112 24
    public function url(Review $review, int $size = 0): string
113
    {
114 24
        if ($this->isUrl($review->avatar)) {
115 24
            return $review->avatar;
116
        }
117
        return $this->fallbackUrl($review, $size);
118
    }
119
120 25
    protected function isUrl(string $url): bool
121
    {
122 25
        return !empty(filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED));
123
    }
124
125 25
    protected function isUrlOnline(string $url): bool
126
    {
127 25
        $key = md5(strtolower($url));
128 25
        $status = glsr(Cache::class)->get($key, 'avatar', function () use ($url) {
129 25
            return Helper::remoteStatusCheck($url);
130 25
        }, HOUR_IN_SECONDS);
131 25
        return 200 === $status;
132
    }
133
134 25
    protected function size(int $size = 0): int
135
    {
136 25
        $size = Cast::toInt($size);
137 25
        if ($size < 1) {
138 25
            $size = glsr_get_option('reviews.avatars_size', static::FALLBACK_SIZE, 'int');
139 25
            $size = Helper::ifEmpty($size, static::FALLBACK_SIZE, $strict = true);
140
        }
141 25
        return $size * 2; // @2x
142
    }
143
144 25
    protected function userField(Review $review): string
145
    {
146 25
        if ($review->author_id) {
147 2
            $value = $review->author_id;
148
        }
149 25
        if (empty($value) || !is_numeric($value)) {
150 25
            $value = $review->email;
151
        }
152 25
        return glsr()->filterString('avatar/id_or_email', $value, $review->toArray());
153
    }
154
}
155