Test Failed
Push — develop ( 425fc0...4f2be8 )
by Paul
13:11
created

Avatar::generateInitials()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 7
ccs 5
cts 5
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 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\Modules\Avatars\InitialsAvatar;
8
use GeminiLabs\SiteReviews\Modules\Avatars\PixelAvatar;
9
use GeminiLabs\SiteReviews\Modules\Html\Builder;
10
use GeminiLabs\SiteReviews\Review;
11
12
class Avatar
13
{
14
    public const FALLBACK_SIZE = 40;
15
    public const GRAVATAR_URL = 'https://secure.gravatar.com/avatar';
16
    public const MAX_SIZE = 240;
17
    public const MIN_SIZE = 16;
18
19
    /**
20
     * @var int
21
     */
22
    public $size;
23
24
    /**
25
     * @var string
26
     */
27
    public $type;
28
29 18
    public function __construct()
30
    {
31 18
        $this->size = glsr_get_option('reviews.avatars_size', static::FALLBACK_SIZE, 'int');
32 18
        $this->type = glsr_get_option('reviews.avatars_fallback', 'mystery', 'string');
33
    }
34
35 18
    public function fallbackUrl(Review $review, int $size = 0): string
36
    {
37 18
        $url = '';
38 18
        if (in_array($this->type, ['custom', 'initials', 'none', 'pixels'])) {
39 18
            $method = Helper::buildMethodName('generate', $this->type);
40 18
            if (method_exists($this, $method)) {
41 18
                $url = call_user_func([$this, $method], $review);
42
            }
43 18
            $this->type = 'mm'; // fallback to the mystery man avatar if the custom/initials/pixels URL is invalid
44
        }
45 18
        if ($this->isUrl($url)) {
46 18
            $this->type = '404'; // fallback to the custom/initials/pixels URL
47
        } else {
48
            $args = [
49
                'd' => $this->type,
50
                's' => $this->size($size, true),
51
            ];
52
            $url = add_query_arg($args, static::GRAVATAR_URL);
53
        }
54 18
        return glsr()->filterString('avatar/fallback', $url, $review, $this->size($size));
55
    }
56
57 18
    public function generate(Review $review, int $size = 0): string
58
    {
59 18
        $fallbackUrl = $this->fallbackUrl($review, $size);
60 18
        $avatarUrl = get_avatar_url($this->userField($review), [
61 18
            'default' => $this->type,
62 18
            'size' => $this->size($size, true),
63 18
        ]);
64 18
        $avatarUrl = glsr()->filterString('avatar/generate', $avatarUrl, $review, $this->size($size));
65 18
        if (!$this->isUrl($avatarUrl) || !$this->isUrlOnline($avatarUrl)) {
66 18
            return $fallbackUrl;
67
        }
68
        return $avatarUrl;
69
    }
70
71
    public function generateCustom(): string
72
    {
73
        return glsr_get_option('reviews.avatars_fallback_url', '', 'string');
74
    }
75
76 18
    public function generateInitials(Review $review): string
77
    {
78 18
        $name = $review->author;
79 18
        if (empty($review->author)) {
80 1
            $name = __('Anonymous', 'site-reviews');
81
        }
82 18
        return glsr(InitialsAvatar::class)->create($name);
83
    }
84
85
    public function generatePixels(Review $review): string
86
    {
87
        return glsr(PixelAvatar::class)->create($this->userField($review));
88
    }
89
90 1
    public function img(Review $review, int $size = 0): string
91
    {
92 1
        $attributes = [
93 1
            'alt' => sprintf(__('Avatar for %s', 'site-reviews'), $review->author()),
94 1
            'height' => $this->size($size, true),
95 1
            'loading' => 'lazy',
96 1
            'src' => $this->url($review, $size),
97 1
            'style' => sprintf('width:%1$spx; height:%1$spx;', $this->size($size)),
98 1
            'width' => $this->size($size, true),
99 1
        ];
100 1
        if (glsr()->isAdmin()) {
101
            $attributes['data-fallback'] = $this->fallbackUrl($review, $size);
102
        }
103 1
        $attributes = glsr()->filterArray('avatar/attributes', $attributes, $review);
104 1
        return glsr(Builder::class)->img($attributes);
105
    }
106
107 18
    public function url(Review $review, int $size = 0): string
108
    {
109 18
        if ($this->isUrl($review->avatar)) {
110 17
            return $review->avatar;
111
        }
112 1
        return $this->generate($review, $size);
113
    }
114
115 18
    protected function isUrl(string $url): bool
116
    {
117 18
        $path = parse_url($url, PHP_URL_PATH);
118 18
        $encodedPath = array_map('urlencode', explode('/', $path));
119 18
        $encodedPath = implode('/', $encodedPath);
120 18
        $url = str_replace($path, $encodedPath, $url);
121 18
        return !empty(filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED));
122
    }
123
124 18
    protected function isUrlOnline(string $url): bool
125
    {
126 18
        $key = md5(strtolower($url));
127 18
        $status = glsr(Cache::class)->get($key, 'avatar',
128 18
            fn () => Helper::remoteStatusCheck($url),
129 18
            HOUR_IN_SECONDS
130 18
        );
131 18
        return 200 === $status;
132
    }
133
134 18
    protected function size(int $size = 0, bool $double = false): int
135
    {
136 18
        if ($size < 1) {
137 18
            $size = $this->size;
138
        }
139 18
        $size = min(static::MAX_SIZE, max(static::MIN_SIZE, $size));
140 18
        if ($double) {
141 18
            return $size * 2;
142
        }
143 18
        return $size;
144
    }
145
146 18
    protected function userField(Review $review): string
147
    {
148 18
        if ($review->author_id) {
149
            $value = $review->author_id;
150
        }
151 18
        if (empty($value) || !is_numeric($value)) {
152 18
            $value = $review->email;
153
        }
154 18
        return glsr()->filterString('avatar/id_or_email', $value, $review->toArray());
155
    }
156
}
157