irishdan /
ResponsiveImageBundle
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 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$ |
||
| 200 | $regex = '/^' . $styleName . '_([0-9]+([.][0-9])?x$)/'; |
||
| 201 | preg_match($regex, $style, $matches); |
||
| 202 | |||
| 203 | if ($matches) { |
||
|
0 ignored issues
–
show
|
|||
| 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']; |
||
| 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; |
||
| 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 | } |
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.