diff --git a/Classes/Controller/DummyImageController.php b/Classes/Controller/DummyImageController.php index c4bf333..2104f41 100644 --- a/Classes/Controller/DummyImageController.php +++ b/Classes/Controller/DummyImageController.php @@ -86,7 +86,7 @@ public function imageAction(int $w = 600, int $h = 400, string $bg = '#000', str } elseif (method_exists($this->response, 'setComponentParameter') && class_exists('\Neos\Flow\Http\Component\SetHeaderComponent')) { $this->response->setComponentParameter(\Neos\Flow\Http\Component\SetHeaderComponent::class, 'Cache-Control', 'max-age=883000000'); } - $this->response->setContentType('image/'.$f); + $this->response->setContentType('image/' . $f); return $result; } else { diff --git a/Classes/Domain/AbstractImageSource.php b/Classes/Domain/AbstractImageSource.php index ba85846..81d2b36 100644 --- a/Classes/Domain/AbstractImageSource.php +++ b/Classes/Domain/AbstractImageSource.php @@ -44,14 +44,14 @@ abstract class AbstractImageSource implements ImageSourceInterface, ProtectedCon protected $logger; /** - * @var array[] + * @var mixed[] * * @Flow\InjectConfiguration(path="thumbnailPresets", package="Neos.Media") */ protected $thumbnailPresets; /** - * @var array[] + * @var mixed[] * * @Flow\InjectConfiguration(path="variantPresets", package="Neos.Media") */ @@ -219,11 +219,11 @@ public function srcset($mediaDescriptors): string $width = (int) $matches['width']; $scaleFactor = $width / $this->width(); $scaled = $this->scale($scaleFactor); - $srcsetArray[] = $scaled->src().' '.$width.'w'; + $srcsetArray[] = $scaled->src() . ' ' . $width . 'w'; } elseif (preg_match('/^(?[0-9\\.]+)x$/u', $descriptor, $matches)) { $factor = (float) $matches['factor']; $scaled = $this->scale($factor); - $srcsetArray[] = $scaled->src().' '.$factor.'x'; + $srcsetArray[] = $scaled->src() . ' ' . $factor . 'x'; } } @@ -294,9 +294,10 @@ public function height(): ?int */ public function allowsCallOfMethod($methodName) { - if (in_array( - $methodName, - [ + if ( + in_array( + $methodName, + [ 'withAlt', 'withTitle', 'withDimensions', @@ -321,8 +322,8 @@ public function allowsCallOfMethod($methodName) 'alt', 'width', 'height', - ] - ) + ] + ) ) { return true; } diff --git a/Classes/Domain/AssetImageSource.php b/Classes/Domain/AssetImageSource.php index c5a4a54..ca3c244 100644 --- a/Classes/Domain/AssetImageSource.php +++ b/Classes/Domain/AssetImageSource.php @@ -174,7 +174,7 @@ public function dataSrc(): string if (is_resource($stream)) { if ($content = stream_get_contents($stream)) { if (is_string($content)) { - return 'data:image/png;base64,'.base64_encode($content); + return 'data:image/png;base64,' . base64_encode($content); } } } diff --git a/Classes/Domain/DummyImageGenerator.php b/Classes/Domain/DummyImageGenerator.php index 8a6be06..a48b9eb 100644 --- a/Classes/Domain/DummyImageGenerator.php +++ b/Classes/Domain/DummyImageGenerator.php @@ -45,8 +45,12 @@ class DummyImageGenerator public function initializeObject(): void { if (isset($this->settings['dummyImage']['overrideImagineDriver']) && $this->settings['dummyImage']['overrideImagineDriver'] !== false) { - $className = 'Imagine\\'.$this->settings['dummyImage']['overrideImagineDriver'].'\\Imagine'; - $this->imagineService = new $className(); + $className = 'Imagine\\' . $this->settings['dummyImage']['overrideImagineDriver'] . '\\Imagine'; + if (is_a($className, ImagineInterface::class, true)) { + $this->imagineService = new $className(); + } else { + throw new \Exception($className . ' does not implement the ImagineInterface'); + } } } @@ -246,7 +250,7 @@ protected function renderBorder(ImageInterface $image, ColorInterface $foregroun protected function renderText(ImageInterface $image, ColorInterface $textColor, int $width, int $height, string $text, bool $center = false): void { $initialFontSize = 10; - $fontFile = $this->packageManager->getPackage('Sitegeist.Kaleidoscope')->getPackagePath().'Resources/Private/Font/NotoSans-Regular.ttf'; + $fontFile = $this->packageManager->getPackage('Sitegeist.Kaleidoscope')->getPackagePath() . 'Resources/Private/Font/NotoSans-Regular.ttf'; $initialFont = $this->imagineService->font($fontFile, $initialFontSize, $textColor); // scale text to fit the image @@ -298,7 +302,6 @@ protected function renderPattern(ImageInterface $image, ColorInterface $patternC if ( $i === $k || ($i % 2 && $k % 2) - ) { $image->draw()->dot(new Point($borderWidth + $i, $borderWidth + $k), $patternColor); } diff --git a/Classes/Domain/DummyImageSource.php b/Classes/Domain/DummyImageSource.php index 8a14bbe..b19da61 100644 --- a/Classes/Domain/DummyImageSource.php +++ b/Classes/Domain/DummyImageSource.php @@ -104,7 +104,7 @@ public function src(): string $arguments['f'] = $this->targetFormat; } - return $this->baseUri.'?'.http_build_query($arguments); + return $this->baseUri . '?' . http_build_query($arguments); } public function dataSrc(): string @@ -119,7 +119,7 @@ public function dataSrc(): string $dummyImage = $this->dummyImageGenerator->createDummyImage($w, $h, $bg, $fg, $t, $f); if ($dummyImage) { - return 'data:image/'.$f.';base64,'.base64_encode($dummyImage->get($f)); + return 'data:image/' . $f . ';base64,' . base64_encode($dummyImage->get($f)); } return ''; diff --git a/Classes/Domain/ResourceImageSource.php b/Classes/Domain/ResourceImageSource.php index cfa000e..7b84744 100644 --- a/Classes/Domain/ResourceImageSource.php +++ b/Classes/Domain/ResourceImageSource.php @@ -51,7 +51,7 @@ public function src(): string public function dataSrc(): string { if ($this->package) { - $content = file_get_contents('resource://'.$this->package.'/'.$this->path); + $content = file_get_contents('resource://' . $this->package . '/' . $this->path); } else { $content = file_get_contents($this->path); } @@ -59,7 +59,7 @@ public function dataSrc(): string if ($content) { $extension = pathinfo($this->path, PATHINFO_EXTENSION); - return 'data:image/'.$extension.';base64,'.base64_encode($content); + return 'data:image/' . $extension . ';base64,' . base64_encode($content); } else { return ''; } diff --git a/Classes/Domain/UriImageSource.php b/Classes/Domain/UriImageSource.php index 5d669ee..db24fac 100644 --- a/Classes/Domain/UriImageSource.php +++ b/Classes/Domain/UriImageSource.php @@ -46,7 +46,7 @@ public function dataSrc(): string if ($content) { $extension = pathinfo($this->uri, PATHINFO_EXTENSION); - return 'data:image/'.$extension.';base64,'.base64_encode($content); + return 'data:image/' . $extension . ';base64,' . base64_encode($content); } else { return ''; } diff --git a/Resources/Private/Fusion/Prototypes/ImageBase64.fusion b/Resources/Private/Fusion/Prototypes/ImageBase64.fusion new file mode 100644 index 0000000..e74c563 --- /dev/null +++ b/Resources/Private/Fusion/Prototypes/ImageBase64.fusion @@ -0,0 +1,157 @@ +prototype(Sitegeist.Kaleidoscope:ImageBase64) < prototype(Neos.Fusion:Component) { + + @styleguide { + + title = "ImageBase64" + + props { + imageSource = Sitegeist.Kaleidoscope:DummyImageSource + width= 1000 + height = 500 + } + + propSets { + altAndTitleFromSource { + imageSource = Sitegeist.Kaleidoscope:DummyImageSource { + alt = 'Alternate assigned to source' + title = 'Title assigned to source' + } + } + + imageSourceWithWidth { + imageSource = Sitegeist.Kaleidoscope:DummyImageSource { + @process.adjust = ${value.withWidth(400)} + } + } + + imageSourceWithHeight { + imageSource = Sitegeist.Kaleidoscope:DummyImageSource { + @process.adjust = ${value.withHeight(400)} + } + } + + imageSourceWithDimensions { + imageSource = Sitegeist.Kaleidoscope:DummyImageSource { + @process.adjust = ${value.withDimensions(400, 400)} + } + } + + imageSourceWithTitleAndAlt { + imageSource = Sitegeist.Kaleidoscope:DummyImageSource { + @process.adjust = ${value.withAlt("Alternate assigned by eel").withTitle("Title assigned by eel")} + } + } + + imageSourceWithFormat { + imageSource = Sitegeist.Kaleidoscope:DummyImageSource { + @process.adjust = ${value.withFormat("png")} + } + } + + overrideAltAndTitleFromProp { + alt = 'Alternate assigned as prop' + title = 'Title assigned as prop' + } + + withResourceImageSource { + imageSource = Sitegeist.Kaleidoscope:ResourceImageSource { + path = "resource://Sitegeist.Kaleidoscope/Public/Images/imageError.png" + alt = 'Alternate assigned to source' + title = 'Title assigned to source' + } + } + + withUriImageSource { + imageSource = Sitegeist.Kaleidoscope:UriImageSource { + uri = "https://dummyimage.com/600x400/000/fff" + alt = 'Alternate assigned to source' + title = 'Title assigned to source' + } + } + + withAttributes { + attributes = Neos.Fusion:DataStructure { + data-foo="bar" + style="border: 5px solid pink;" + } + } + + multires_array { + srcset = ${['1x', '1.5x', '2x']} + } + + multires_string { + srcset = '1x, 1.5x, 2x' + } + + multisize_array { + srcset = ${['320w', '400w', '600w', '800w', '1000w', '1200w', '1600']} + } + + multisize_string { + srcset = '320w, 400ww, 600w, 800w, 1000w, 1200w, 1600' + } + + sizes_array { + srcset = ${['320w', '400w', '600w', '800w', '1000w', '1200w', '1600']} + sizes = ${['(max-width: 320px) 280px', '(max-width: 480px) 440px', '800px']} + } + + sizes_string { + srcset = '320w, 400ww, 600w, 800w, 1000w, 1200w, 1600' + sizes = '(max-width: 320px) 280px, (max-width: 480px) 440px, 800px' + } + } + } + + @propTypes { + imageSource = ${PropTypes.instanceOf('\\Sitegeist\\Kaleidoscope\\Domain\\ImageSourceInterface')} + } + + imageSource = null + srcset = null + sizes = null + alt = null + title = null + // class is deprecated in favor of attributes.class + class = null + loading = 'lazy' + width = null + height = null + format = null + attributes = Neos.Fusion:DataStructure + renderDimensionAttributes = true + + renderer = Neos.Fusion:Component { + @if.hasImageSource = ${props.imageSource && Type.instance(props.imageSource, '\\Sitegeist\\Kaleidoscope\\Domain\\ImageSourceInterface')} + + # apply format, width and height to the imageSource + imageSource = ${props.imageSource} + imageSource.@process.applyWidth = ${props.width ? value.withWidth(props.width) : value} + imageSource.@process.applyHeight = ${props.height ? value.withHeight(props.height) : value} + imageSource.@process.applyFormat = ${props.format ? value.withFormat(props.format) : value} + + srcset = ${props.srcset} + sizes = ${props.sizes} + loading = ${props.loading} + alt = ${props.alt} + title = ${props.title} + class = ${props.class} + attributes = ${props.attributes} + renderDimensionAttributes = ${props.renderDimensionAttributes} + + renderer = afx` + {props.alt + ` + } +} diff --git a/composer.json b/composer.json index 24703e2..9533e02 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,8 @@ "neos/imagine": "*" }, "require-dev": { - "phpstan/phpstan": "^0.12.78" + "phpstan/phpstan": "^1.8", + "squizlabs/php_codesniffer": "^3.7" }, "autoload": { "psr-4": { @@ -23,8 +24,11 @@ } }, "scripts": { - "test:stan": ["vendor/bin/phpstan analyse Classes"], - "test": ["composer install", "composer test:stan"] + "fix:style": "phpcbf --colors --standard=PSR12 Classes", + "test:style": "phpcs --colors -n --standard=PSR12 Classes", + "test:stan": "phpstan analyse Classes", + "cc": "phpstan clear cache", + "test": ["composer install", "composer test:style" , "composer test:stan"] }, "config": { "allow-plugins": {