Passed
Branch master (c471f8)
by Paul
09:53
created

Avatar::generateInitials()   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
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 0
cts 2
cp 0
rs 10
cc 1
nc 1
nop 1
crap 2
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Modules;
4
5
use GeminiLabs\SiteReviews\Helper;
6
use GeminiLabs\SiteReviews\Helpers\Arr;
7
use GeminiLabs\SiteReviews\Helpers\Cast;
8
use GeminiLabs\SiteReviews\Helpers\Str;
9
use GeminiLabs\SiteReviews\Modules\Avatars\InitialsAvatar;
10
use GeminiLabs\SiteReviews\Modules\Avatars\PixelAvatar;
11
use GeminiLabs\SiteReviews\Modules\Html\Builder;
12
use GeminiLabs\SiteReviews\Review;
13
14
class Avatar
15
{
16
    const FALLBACK_SIZE = 40;
17
    const GRAVATAR_URL = 'https://secure.gravatar.com/avatar';
18
19
    /**
20
     * @var string
21
     */
22
    public $type;
23
24 15
    public function __construct()
25
    {
26 15
        $this->type = glsr_get_option('reviews.avatars_fallback', 'mystery', 'string');
27 15
    }
28
29
    /**
30
     * @param \GeminiLabs\SiteReviews\Review $review
31
     * @return string
32
     */
33 15
    public function fallbackDefault($review)
34
    {
35 15
        if ('custom' === $this->type) {
36
            $customUrl = glsr_get_option('reviews.avatars_fallback_url');
37
            if ($this->isUrl($customUrl)) {
38
                return $customUrl;
39
            }
40
            $this->type = 'mystery'; // fallback to mystery if a custom url is not set
41
        }
42 15
        if ('pixels' === $this->type) {
43
            return $this->generatePixels($review);
44
        }
45 15
        if ('initials' === $this->type) {
46
            if (!empty($review->author)) {
47
                return $this->generateInitials($review);
48
            }
49
            $this->type = 'mystery'; // can't create initials without a name
50
        }
51 15
        return $this->type;
52
    }
53
54
    /**
55
     * @param \GeminiLabs\SiteReviews\Review $review
56
     * @param int $size
57
     * @return string
58
     */
59
    public function fallbackUrl($review, $size = 0)
60
    {
61
        $fallbackUrl = $this->fallbackDefault($review);
62
        if ($fallbackUrl === $this->type) {
63
            $fallbackUrl = add_query_arg('d', $this->type, static::GRAVATAR_URL);
64
            $fallbackUrl = add_query_arg('s', $this->size($size), $fallbackUrl);
65
        }
66
        return glsr()->filterString('avatar/fallback', $fallbackUrl, $size, $review);
67
    }
68
69
    /**
70
     * @param \GeminiLabs\SiteReviews\Review $review
71
     * @param int $size
72
     * @return string
73
     */
74 15
    public function generate($review, $size = 0)
75
    {
76 15
        $default = $this->fallbackDefault($review);
77 15
        if ($default !== $this->type) {
78
            $default = '404';
79
        }
80 15
        $size = $this->size($size);
81 15
        $avatarUrl = get_avatar_url($this->userField($review), [
82 15
            'default' => $default,
83 15
            'size' => $size,
84
        ]);
85 15
        if (!$this->isUrl($avatarUrl)) {
86
            return $this->fallbackUrl($review, $size);
87
        }
88 15
        if (404 === Helper::remoteStatusCheck($avatarUrl)) {
89
            // @todo generate the images with javascript on canvas to avoid this status check
90
            return $this->fallbackUrl($review, $size);
91
        }
92 15
        return $avatarUrl;
93
    }
94
95
    /**
96
     * @param \GeminiLabs\SiteReviews\Review $review
97
     * @return string
98
     */
99
    public function generateInitials($review)
100
    {
101
        return glsr(InitialsAvatar::class)->create($review->author);
102
    }
103
104
    /**
105
     * @param \GeminiLabs\SiteReviews\Review $review
106
     * @return string
107
     */
108
    public function generatePixels($review)
109
    {
110
        return glsr(PixelAvatar::class)->create($this->userField($review));
111
    }
112
113
    /**
114
     * @param \GeminiLabs\SiteReviews\Review $review
115
     * @param int $size
116
     * @return string
117
     */
118
    public function img($review, $size = 0)
119
    {
120
        $size = $this->size($size);
121
        $attributes = [
122
            'alt' => sprintf(__('Avatar for %s', 'site-reviews'), $review->author()),
123
            'height' => $size, // @2x
124
            'loading' => 'lazy',
125
            'src' => $this->url($review, $size), // @2x
126
            'style' => sprintf('width:%1$spx; height:%1$spx;', $size / 2), // @1x
127
            'width' => $size, // @2x
128
        ];
129
        if (glsr()->isAdmin()) {
130
            $attributes['data-fallback'] = $this->fallbackUrl($review, $size);
131
        }
132
        $attributes = glsr()->filterArray('avatar/attributes', $attributes, $review);
133
        return glsr(Builder::class)->img($attributes);
134
    }
135
136
    /**
137
     * @param \GeminiLabs\SiteReviews\Review $review
138
     * @param int $size
139
     * @return string
140
     */
141 14
    public function url($review, $size = 0)
142
    {
143 14
        if ($this->isUrl($review->avatar)) {
144 14
            return $review->avatar;
145
        }
146
        return $this->fallbackUrl($review, $size);
147
    }
148
149
    /**
150
     * @param mixed $url
151
     * @return bool
152
     */
153 15
    protected function isUrl($url)
154
    {
155 15
        return !empty(filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED));
156
    }
157
158
    /**
159
     * @param int $size
160
     * @return int
161
     */
162 15
    protected function size($size = 0)
163
    {
164 15
        $size = Cast::toInt($size);
165 15
        if ($size < 1) {
166 15
            $size = glsr_get_option('reviews.avatars_size', static::FALLBACK_SIZE, 'int');
167 15
            $size = Helper::ifEmpty($size, static::FALLBACK_SIZE, $strict = true);
168
        }
169 15
        return $size * 2; // @2x
170
    }
171
172
    /**
173
     * @param string $contents
174
     * @param string $name
175
     * @return string
176
     */
177
    protected function svg($contents, $name)
178
    {
179
        $uploadsDir = wp_upload_dir();
180
        $baseDir = trailingslashit($uploadsDir['basedir']);
181
        $baseUrl = trailingslashit($uploadsDir['baseurl']);
182
        $pathDir = trailingslashit(glsr()->id).trailingslashit('avatars');
183
        $filename = sprintf('%s.svg', $name);
184
        $filepath = $baseDir.$pathDir.$filename;
185
        if (!file_exists($filepath)) {
186
            wp_mkdir_p($baseDir.$pathDir);
187
            $fp = @fopen($filepath, 'wb');
188
            if (false === $fp) {
189
                return '';
190
            }
191
            mbstring_binary_safe_encoding();
192
            $dataLength = strlen($contents);
193
            $bytesWritten = fwrite($fp, $contents);
194
            reset_mbstring_encoding();
195
            fclose($fp);
196
            if ($dataLength !== $bytesWritten) {
197
                return '';
198
            }
199
            chmod($filepath, (fileperms(ABSPATH.'index.php') & 0777 | 0644));
200
        }
201
        return set_url_scheme($baseUrl.$pathDir.$filename);
202
    }
203
204
    /**
205
     * @param string $initials
206
     * @return string
207
     */
208
    protected function svgContent($initials)
209
    {
210
        $colors = [
211
            ['background' => '#e3effb', 'color' => '#134d92'], // blue
212
            ['background' => '#e1f0ee', 'color' => '#125960'], // green
213
            ['background' => '#ffeff7', 'color' => '#ba3a80'], // pink
214
            ['background' => '#fcece3', 'color' => '#a14326'], // red
215
            ['background' => '#faf7d9', 'color' => '#da9640'], // yellow
216
        ];
217
        $colors = glsr()->filterArray('avatar/colors', $colors);
218
        shuffle($colors);
219
        $color = Cast::toArray(Arr::get($colors, 0));
220
        $data = wp_parse_args($color, [
221
            'background' => '#dcdce6',
222
            'color' => '#6f6f87',
223
            'text' => $initials,
224
        ]);
225
        return trim(glsr()->build('avatar', $data));
226
    }
227
228
    /**
229
     * @param \GeminiLabs\SiteReviews\Review $review
230
     * @return int|string
231
     */
232 15
    protected function userField($review)
233
    {
234 15
        if ($review->author_id) {
235
            $value = get_the_author_meta('user_email', $review->author_id);
236
        }
237 15
        if (empty($value)) {
238 15
            $value = $review->email;
239
        }
240 15
        return glsr()->filterString('avatar/id_or_email', $value, $review->toArray());
241
    }
242
}
243