ThumbHelper::status()   B
last analyzed

Complexity

Conditions 9
Paths 29

Size

Total Lines 36
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 9
eloc 20
c 2
b 0
f 0
nc 29
nop 3
dl 0
loc 36
rs 8.0555
1
<?php
2
declare(strict_types=1);
3
4
/**
5
 * BEdita, API-first content management framework
6
 * Copyright 2019 ChannelWeb Srl, Chialab Srl
7
 *
8
 * This file is part of BEdita: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published
10
 * by the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * See LICENSE.LGPL or <http://gnu.org/licenses/lgpl-3.0.html> for more details.
14
 */
15
namespace BEdita\WebTools\View\Helper;
16
17
use BEdita\WebTools\ApiClientProvider;
18
use Cake\Cache\Cache;
19
use Cake\Log\LogTrait;
20
use Cake\Utility\Hash;
21
use Cake\View\Helper;
22
use Exception;
23
24
/**
25
 * Helper to obtain thumbnail url
26
 */
27
class ThumbHelper extends Helper
28
{
29
    use LogTrait;
30
31
    /**
32
     * Default config for this helper.
33
     *
34
     * @var array
35
     */
36
    protected array $_defaultConfig = [
37
        'cache' => '_thumbs_',
38
    ];
39
40
    /**
41
     * @var int Thumb not available
42
     */
43
    public const NOT_AVAILABLE = -10;
44
45
    /**
46
     * @var int Thumb not ready
47
     */
48
    public const NOT_READY = -20;
49
50
    /**
51
     * @var int Thumb not acceptable
52
     */
53
    public const NOT_ACCEPTABLE = -30;
54
55
    /**
56
     * @var int Thumb has no url
57
     */
58
    public const NO_URL = -40;
59
60
    /**
61
     * @var int Thumb is OK
62
     */
63
    public const OK = 1;
64
65
    /**
66
     * Use 'default' as fallback if no cache configuration is found.
67
     *
68
     * @param array $config The configuration settings provided to this helper.
69
     * @return void
70
     */
71
    public function initialize(array $config): void
72
    {
73
        parent::initialize($config);
74
        if (!empty($config['cache'])) {
75
            $this->setConfig('cache', $config['cache']);
76
        }
77
        $cacheCfg = $this->getConfig('cache');
78
        $cfg = Cache::getConfig($cacheCfg);
79
        if ($cfg === null) {
80
            $this->setConfig('cache', 'default');
81
        }
82
    }
83
84
    /**
85
     * Verify status of image thumb.
86
     * Return int representing status.
87
     * Possible values:
88
     *
89
     *   NOT_AVAILABLE: something went wrong during api call
90
     *   NOT_READY: thumb is available, but not ready
91
     *   NOT_ACCEPTABLE: image is not acceptable, api won't create thumb
92
     *   NO_URL: url not present in api response
93
     *   OK: thumb available, ready and with a proper url
94
     *
95
     * @param string|int|null $imageId The image ID
96
     * @param array|null $options The thumbs options
97
     * @param string|null $url The thumb url to populate when static::OK
98
     * @return int|null
99
     */
100
    public function status(
101
        int|string|null $imageId,
102
        ?array $options = ['preset' => 'default'],
103
        ?string &$url = '',
104
    ): ?int {
105
        if (empty($imageId) && empty($options['ids'])) {
106
            return static::NOT_ACCEPTABLE;
107
        }
108
        try {
109
            $id = !empty($imageId) ? intval($imageId) : null;
110
            $apiClient = ApiClientProvider::getApiClient();
111
            $response = $apiClient->thumbs($id, (array)$options);
112
            if (empty($response['meta']['thumbnails'][0])) {
113
                return static::NOT_AVAILABLE;
114
            }
115
            $thumb = $response['meta']['thumbnails'][0];
116
            // check thumb is acceptable
117
            if (!$this->isAcceptable($thumb)) {
118
                return static::NOT_ACCEPTABLE;
119
            }
120
            // check thumb is ready
121
            if (!$this->isReady($thumb)) {
122
                return static::NOT_READY;
123
            }
124
            // check thumb has url
125
            if (!$this->hasUrl($thumb)) {
126
                return static::NO_URL;
127
            }
128
            $url = $thumb['url'];
129
        } catch (Exception $e) {
130
            $this->log($e->getMessage(), 'error');
131
132
            return static::NOT_AVAILABLE;
133
        }
134
135
        return static::OK;
136
    }
137
138
    /**
139
     * Obtain thumbnail using API thumbs.
140
     *
141
     * @param string|int $imageId The image ID.
142
     * @param array|null $options The thumbs options.
143
     * @return string|int The url if available, the status code otherwise (see Thumb constants).
144
     */
145
    public function url(string|int $imageId, ?array $options): string|int
146
    {
147
        $url = '';
148
        $status = $this->status($imageId, $options, $url);
149
        if ($status === static::OK) {
150
            return $url;
151
        }
152
153
        return $status;
154
    }
155
156
    /**
157
     * Verify if thumb is acceptable
158
     *
159
     * @param array $thumb The thumbnail data
160
     * @return bool the acceptable flag
161
     */
162
    private function isAcceptable(array $thumb = []): bool
163
    {
164
        if (isset($thumb['acceptable']) && $thumb['acceptable'] === false) {
165
            return false;
166
        }
167
168
        return true;
169
    }
170
171
    /**
172
     * Verify if thumb is ready
173
     *
174
     * @param array $thumb The thumbnail data
175
     * @return bool the ready flag
176
     */
177
    private function isReady(array $thumb = []): bool
178
    {
179
        if (!empty($thumb['ready']) && $thumb['ready'] === true) {
180
            return true;
181
        }
182
183
        return false;
184
    }
185
186
    /**
187
     * Verify if thumb has url
188
     *
189
     * @param array $thumb The thumbnail data
190
     * @return bool the url availability
191
     */
192
    private function hasUrl(array $thumb = []): bool
193
    {
194
        if (!empty($thumb['url'])) {
195
            return true;
196
        }
197
198
        return false;
199
    }
200
201
    /**
202
     * Retrieve thumb URL using cache.
203
     * Silently fail with log if no image 'id' is found in array.
204
     *
205
     * @param array|null $image Image object array containing at least `id`
206
     * @param string $options Thumb options
207
     * @return string
208
     */
209
    public function getUrl(?array $image, array $options = []): string
210
    {
211
        if (empty($image) || empty($image['id'])) {
212
            $this->log(sprintf('Missing image ID - %s', json_encode($image)), 'warning');
213
214
            return '';
215
        }
216
        $imageId = intval($image['id']);
217
        $thumbHash = md5((string)Hash::get($image, 'meta.media_url') . json_encode($options));
218
        $key = sprintf('%d_%s', $imageId, $thumbHash);
219
220
        return (string)Cache::remember(
221
            $key,
222
            function () use ($imageId, $options) {
223
                return $this->url($imageId, $options);
224
            },
225
            $this->getConfig('cache'),
226
        );
227
    }
228
}
229