Completed
Push — master ( a06a95...a1d542 )
by dan
15s
created

StyleManager::getMediaQuerySourceMappings()   B

Complexity

Conditions 4
Paths 2

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 25
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 14
nc 2
nop 2

1 Method

Rating   Name   Duplication   Size   Complexity  
A StyleManager::findMultiplierStyles() 0 15 3
1
<?php
2
/**
3
 * This file is part of the IrishDan\ResponsiveImageBundle package.
4
 *
5
 * (c) Daniel Byrne <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE file that was distributed with this source
8
 * code.
9
 */
10
11
namespace IrishDan\ResponsiveImageBundle;
12
13
use IrishDan\ResponsiveImageBundle\ImageProcessing\CoordinateGeometry;
14
15
/**
16
 * Class StyleManager
17
 * This class is responsible for image style information,
18
 * and translating styles into relative style paths.
19
 *
20
 * @package ResponsiveImageBundle
21
 */
22
class StyleManager
23
{
24
    private $breakpoints = [];
25
    private $pictureSets = [];
26
    private $sizeSets = [];
27
    private $styles = [];
28
    private $styleDirectory = 'styles';
29
30
    /**
31
     * StyleManager constructor.
32
     *
33
     * @param array $configuration
34
     */
35
    public function __construct(array $configuration)
36
    {
37
        // Set the styles directory;
38
        if (!empty($configuration['image_styles_directory'])) {
39
            $this->styleDirectory = $configuration['image_styles_directory'];
40
        }
41
42
        // Set the styles array.
43
        if (!empty($configuration['image_styles'])) {
44
            $this->styles = $configuration['image_styles'];
45
        }
46
47
        // Set the picture sets array.
48
        if (!empty($configuration['picture_sets'])) {
49
            $this->pictureSets = $configuration['picture_sets'];
50
        }
51
52
        // Set the size sets array.
53
        if (!empty($configuration['size_sets'])) {
54
            $this->sizeSets = $configuration['size_sets'];
55
        }
56
57
        // Set the breakpoints array.
58
        if (!empty($configuration['breakpoints'])) {
59
            $this->breakpoints = $configuration['breakpoints'];
60
        }
61
    }
62
63
    public function setImageAttributes(ResponsiveImageInterface $image, $styleName = null, $src = null)
64
    {
65
        // Use the style data to figure out the width and height for this image
66
        // and then set hose attributes on the image.
67
        if (!empty($styleName)) {
68
            $styleData = $this->getStyleData($styleName);
69
            if (!empty($styleData) && !empty($styleData['effect'])) {
70
                switch ($styleData['effect']) {
71
                    case 'crop':
72
                        $image->setWidth($styleData['width']);
73
                        $image->setHeight($styleData['height']);
74
                        break;
75
76
                    case 'scale':
77
                        $scaledDimensions = $this->getScaledDimensions($image, $styleData);
78
79
                        $image->setWidth($scaledDimensions['width']);
80
                        $image->setHeight($scaledDimensions['height']);
81
82
                        break;
83
                }
84
            }
85
        }
86
87
        // Set the src if value is provided
88
        if (!empty($src)) {
89
            $image->setSrc($src);
90
        }
91
92
        return $image;
93
    }
94
95
    protected function getScaledDimensions(ResponsiveImageInterface $image, array $styleData)
96
    {
97
        $coordinates = $image->getCropCoordinates();
98
99
        if (empty($coordinates)) {
100
            $geometry = new CoordinateGeometry(0, 0, $image->getWidth(), $image->getHeight());
101
        }
102
        else {
103
            $cropCoordinates = explode(':', $coordinates)[0];
104
            $points          = explode(',', $cropCoordinates);
105
            $geometry        = new CoordinateGeometry(
106
                trim($points[0]),
107
                trim($points[1]),
108
                trim($points[2]),
109
                trim($points[3])
110
            );
111
        }
112
113
        return $geometry->scaleSize($styleData['width'], $styleData['height']);
114
    }
115
116
    public function styleExists($styleName)
117
    {
118
        // If its's a custom style, grab the data and add the styles array.
119
        if (0 === strpos($styleName, 'custom_')) {
120
            $styleData = $this->styleDataFromCustomStyleString($styleName);
121
            $this->addStyle($styleName, $styleData);
122
        }
123
124
        $style = $this->getStyleData($styleName);
125
126
        return !empty($style);
127
    }
128
129
    public function getAllStyles()
130
    {
131
        return $this->styles;
132
    }
133
134
    public function getAllStylesNames()
135
    {
136
        $styles = $this->getAllStyles();
137
138
        return array_keys($styles);
139
    }
140
141
    public function getStyleData($styleName)
142
    {
143
        if (!in_array($styleName, array_keys($this->styles))) {
144
            // If is custom style string.
145
            if (strpos($styleName, 'custom_') === 0) {
146
                return $this->styleDataFromCustomStyleString($styleName);
147
            }
148
        }
149
        else {
150
            return $this->styles[$styleName];
151
        }
152
153
        return false;
154
    }
155
156
    public function getPictureData(ResponsiveImageInterface $image, $pictureSetName)
157
    {
158
        $mappings = [
159
            'fallback' => '',
160
            'sources'  => [],
161
        ];
162
        $filename = $image->getPath();
163
164
        if (!empty($this->pictureSets[$pictureSetName])) {
165
            $set = $this->pictureSets[$pictureSetName];
166
167
            foreach ($set['sources'] as $break => $styleName) {
168
                $paths   = [];
169
                $paths[] = $this->buildStylePath($styleName, $filename);
170
171
                // Check to for multiplier styles
172
                $multiplierStyles = $this->findMultiplierStyles($styleName);
173
                if (!empty($multiplierStyles)) {
174
                    foreach ($multiplierStyles as $multiplier => $style) {
175
                        $paths[] = $this->buildStylePath($style, $filename) . ' ' . $multiplier;
176
                    }
177
                }
178
179
                // Mappings should be in 'media_query' => '/path/to/image'
180
                if ($this->breakpoints[$break]) {
181
                    $mediaQuery                       = $this->breakpoints[$break]['media_query'];
182
                    $mappings['sources'][$mediaQuery] = implode(', ', $paths);
183
                }
184
            }
185
186
            // Set the fallback image path.
187
            if (isset($set['fallback'])) {
188
                $mappings['fallback'] = $this->getStylePath($image, $set['fallback']);
189
            }
190
        }
191
192
        return $mappings;
193
    }
194
195
    protected function findMultiplierStyles($styleName)
196
    {
197
        $multiplierStyles = [];
198
        foreach ($this->styles as $style => $styleData) {
199
            // ^thumb_[0-9]+([.][0-9])?x$
0 ignored issues
show
Unused Code Comprehensibility introduced by
69% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
200
            $regex = '/^' . $styleName . '_([0-9]+([.][0-9])?x$)/';
201
            preg_match($regex, $style, $matches);
202
203
            if ($matches) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $matches of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
204
                $multiplierStyles[$matches[1]] = $style;
205
            }
206
        }
207
208
        return $multiplierStyles;
209
    }
210
211
    public function getImageSizesData(ResponsiveImageInterface $image, $imageSizesSetName)
212
    {
213
        $mappings = [
214
            'fallback' => '',
215
            'sizes'    => [],
216
            'srcsets'  => [],
217
        ];
218
        $sizeData = $this->getSizesSet($imageSizesSetName);
219
220
        if ($sizeData) {
221
            // Sort out the sizes data.
222
            $mappings['sizes'] = [];
223
            foreach ($sizeData['sizes'] as $vw => $mediaQuery) {
224
                // Get the media query from the breakpoint data.
225
                $breakpoint = $this->breakpoints[$mediaQuery['breakpoint']];
226
227
                if ($breakpoint) {
228
                    // $mappings['sizes'][$vw] = $breakpoint['media_query'];
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
229
                    $mappings['sizes'][] = '(' . $breakpoint['media_query'] . ') ' . $vw;
230
                }
231
            }
232
233
            // Get the image paths and widths.
234
            // In most case the width will be apart of the style (crop or scale)
235
            // If it's not we can need to derive it.
236
            foreach ($sizeData['srcsets'] as $styleName) {
237
                $styleData = $this->getStyleData($styleName);
238
                if ($styleData) {
239
                    if (empty($styleData['width'])) {
240
                        // We need to derive the width.
241
                        $scaledDimensions = $this->getScaledDimensions($image, $styleData);
242
                        $width            = $scaledDimensions['width'];
243
                    }
244
                    else {
245
                        $width = $styleData['width'];
246
                    }
247
248
                    $path = $this->getStylePath($image, $styleName);
249
                    // Stick it into that array there.
250
                    $mappings['srcsets'][$path] = $width;
251
                }
252
            }
253
        }
254
255
        return $mappings;
256
    }
257
258
    protected function buildStylePath($styleName, $fileName)
259
    {
260
        $path = $this->styleDirectory . '/' . $styleName . '/' . $fileName;
261
262
        return $path;
263
    }
264
265
    public function getStylePath(ResponsiveImageInterface $image, $styleName = null)
266
    {
267
        $filename = $image->getPath();
268
269
        if (!empty($styleName)) {
270
            $stylePath = $this->buildStylePath($styleName, $filename);
271
        }
272
        else {
273
            $stylePath = $filename;
274
        }
275
276
        return $stylePath;
277
    }
278
279
    public function addStyle($key, $styleData)
280
    {
281
        $this->styles[$key] = $styleData;
282
    }
283
284
    public function styleDataFromCustomStyleString($customStyleString)
285
    {
286
        $styleData = explode('_', $customStyleString);
287
288
        list($custom, $effect, $width, $height) = $styleData;
0 ignored issues
show
Unused Code introduced by
The assignment to $custom is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
289
290
        return [
291
            'effect' => $effect,
292
            'width'  => $width,
293
            'height' => $height,
294
        ];
295
    }
296
297
    public function getSizesSet($setName)
298
    {
299
        return isset($this->sizeSets[$setName]) ? $this->sizeSets[$setName] : false;
300
    }
301
}