FinderCommon::getOptionValue()   B
last analyzed

Complexity

Conditions 8
Paths 5

Size

Total Lines 31
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 15
dl 0
loc 31
rs 8.4444
c 0
b 0
f 0
cc 8
nc 5
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace WebThumbnailer\Finder;
6
7
use WebThumbnailer\Exception\BadRulesException;
8
use WebThumbnailer\Utils\SizeUtils;
9
use WebThumbnailer\WebThumbnailer;
10
11
/**
12
 * Define multiple attributes and methods which can be shared between finders.
13
 */
14
abstract class FinderCommon implements Finder
15
{
16
    /** Key which represent the size. */
17
    protected const SIZE_KEY = 'size';
18
19
    /** @var string Current domain used by this finder. */
20
    protected $domain;
21
22
    /** @var string URL provided by the user. */
23
    protected $url;
24
25
    /** @var mixed[] List of options from this Finder rules. */
26
    protected $finderOptions;
27
28
    /** @var mixed[] List of options provided by the user. */
29
    protected $userOptions;
30
31
    /**
32
     * Replace a part of the thumbnail URL from an option provided by the user, and known by this Finder.
33
     * URL options must be defined between `${}`.
34
     * Example:
35
     *      if ${size} is provided with the regex Finder rule `thumbnail_url`,
36
     *      it will be replaced by the proper size from $finderOptions, depending of size options in $userOptions.
37
     *
38
     * @param string $thumbnailUrl Thumbnail resolved URL.
39
     * @param string $option Option to replace.
40
     *
41
     * @return string Thumbnail URL updated with the proper option placeholder replacement.
42
     *
43
     * @throws BadRulesException
44
     */
45
    protected function replaceOption(string $thumbnailUrl, string $option): string
46
    {
47
        $chosenOption = $this->getOptionValue($option);
48
49
        return str_replace('${' . $option . '}', $chosenOption, $thumbnailUrl);
50
    }
51
52
    /**
53
     * @param string $option to retrieve
54
     *
55
     * @return mixed Found option value
56
     *
57
     * @throws BadRulesException
58
     */
59
    protected function getOptionValue(string $option)
60
    {
61
        // If the provided option is not defined in the Finder rules.
62
        if (empty($this->finderOptions) || ! in_array($option, array_keys($this->finderOptions))) {
63
            throw new BadRulesException('Unknown option "' . $option . '" for the finder "' . $this->getName() . '"');
64
        }
65
66
        // User option is defined.
67
        // Any defined option must provide a replacement value in rules under the `param` key.
68
        if (
69
            ! empty($this->userOptions[$option])
70
            && is_string($this->userOptions[$option])
71
            && isset($this->finderOptions[$option][$this->userOptions[$option]]['param'])
72
        ) {
73
            return $this->finderOptions[$option][$this->userOptions[$option]]['param'];
74
        }
75
76
        // If no user option has been found, and no default value is provided: error.
77
        if (! isset($this->finderOptions[$option]['default'])) {
78
            $error = 'No default set for option "' . $option . '" for the finder "' . $this->getName() . '"';
79
            throw new BadRulesException($error);
80
        }
81
82
        // Use default option replacement.
83
        $default = $this->finderOptions[$option]['default'];
84
        if (!isset($this->finderOptions[$option][$default]['param'])) {
85
            $error = 'No default parameter set for option "' . $option . '" for the finder "' . $this->getName() . '"';
86
            throw new BadRulesException($error);
87
        }
88
89
        return $this->finderOptions[$option][$default]['param'];
90
    }
91
92
    /** @inheritdoc */
93
    public function isHotlinkAllowed(): bool
94
    {
95
        if (! isset($this->finderOptions['hotlink_allowed']) ||  $this->finderOptions['hotlink_allowed'] === true) {
96
            return true;
97
        }
98
99
        return false;
100
    }
101
102
    /** @inheritdoc */
103
    public function setUserOptions(?array $userOptions): void
104
    {
105
        $this->userOptions = $userOptions;
106
107
        $this->setSizeOption();
108
    }
109
110
    /**
111
     * Set size parameter properly.
112
     *
113
     * If something goes wrong, we just ignore it.
114
     * The size user setting can be set to small, medium, etc. or a pixel value (int).
115
     *
116
     * We retrieve the thumbnail size bigger than the minimal size asked.
117
     */
118
    protected function setSizeOption(): void
119
    {
120
        // If no option has been provided, we'll use default values.
121
        if (
122
            empty($this->userOptions[WebThumbnailer::MAX_HEIGHT])
123
            && empty($this->userOptions[WebThumbnailer::MAX_WIDTH])
124
        ) {
125
            return;
126
        }
127
128
        // If the rules doesn't specify anything about size, abort.
129
        if (empty($this->finderOptions[static::SIZE_KEY])) {
130
            return;
131
        }
132
133
        // Load height user option.
134
        if (!empty($this->userOptions[WebThumbnailer::MAX_HEIGHT])) {
135
            $height = $this->userOptions[WebThumbnailer::MAX_HEIGHT];
136
            if (SizeUtils::isMetaSize((string) $height)) {
137
                $height = SizeUtils::getMetaSize((string) $height);
138
            }
139
        }
140
141
        // Load width user option.
142
        if (!empty($this->userOptions[WebThumbnailer::MAX_WIDTH])) {
143
            $width = $this->userOptions[WebThumbnailer::MAX_WIDTH];
144
            if (SizeUtils::isMetaSize((string) $width)) {
145
                $width = SizeUtils::getMetaSize((string) $width);
146
            }
147
        }
148
149
        // Trying to find a resolution higher than the one asked.
150
        foreach ($this->finderOptions[static::SIZE_KEY] as $sizeOption => $value) {
151
            if ($sizeOption == 'default') {
152
                continue;
153
            }
154
155
            if (
156
                (empty($value['maxwidth']) || empty($width) || $value['maxwidth'] >= $width)
157
                && (empty($value['maxheight']) || empty($height) || $value['maxheight'] >= $height)
158
            ) {
159
                $this->userOptions[static::SIZE_KEY] = $sizeOption;
160
                break;
161
            }
162
        }
163
164
        // If the resolution asked hasn't been reached, take the highest resolution we have.
165
        if ((!empty($width) || !empty($height)) && empty($this->userOptions[static::SIZE_KEY])) {
166
            $ref = array_keys($this->finderOptions[static::SIZE_KEY]);
167
            $this->userOptions[static::SIZE_KEY] = end($ref);
168
        }
169
    }
170
171
    /** @inheritdoc */
172
    public function getDomain(): string
173
    {
174
        return $this->domain;
175
    }
176
}
177