Skip to content

Commit

Permalink
[FEATURE] generate placeholder images internal
Browse files Browse the repository at this point in the history
  • Loading branch information
ulrichmathes committed Oct 24, 2024
1 parent a529e86 commit 2bee084
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 4 deletions.
14 changes: 10 additions & 4 deletions Classes/Domain/Model/PlaceholderImage.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

use SMS\FluidComponents\Interfaces\ImageWithDimensions;
use SMS\FluidComponents\Interfaces\ProcessableImage;
use SMS\FluidComponents\Service\PlaceholderImageService;
use TYPO3\CMS\Core\Imaging\ImageManipulation\Area;
use TYPO3\CMS\Core\Utility\GeneralUtility;

/**
* Data structure for a placeholder image to be passed to a component.
Expand All @@ -29,16 +31,16 @@ class PlaceholderImage extends Image implements ImageWithDimensions, Processable
/**
* Image format of the image
*/
protected string $format = 'gif';
protected string $format = 'svg';

/**
* Creates an image object for a placeholder image.
*/
public function __construct(int $width, int $height, string $format = 'gif')
public function __construct(int $width, int $height, ?string $format = null)
{
$this->width = $width;
$this->height = $height;
$this->format = $format;
$this->format = $format ?? $this->format;
}

public function getWidth(): int
Expand All @@ -58,7 +60,11 @@ public function getFormat(): string

public function getPublicUrl(): string
{
return 'https://via.placeholder.com/' . $this->width . 'x' . $this->height . '.' . $this->format;
return GeneralUtility::makeInstance(PlaceholderImageService::class)->generate(
$this->width,
$this->height,
$this->format,
);
}

public function process(int $width, int $height, ?string $format, Area $cropArea): ProcessableImage
Expand Down
89 changes: 89 additions & 0 deletions Classes/Service/PlaceholderImageService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php declare(strict_types=1);

namespace SMS\FluidComponents\Service;

use TYPO3\CMS\Core\Information\Typo3Version;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\View\ViewFactoryData;
use TYPO3\CMS\Core\View\ViewFactoryInterface;
use TYPO3\CMS\Fluid\View\StandaloneView;
use TYPO3\CMS\Frontend\Imaging\GifBuilder;

class PlaceholderImageService
{
const int STROKE_WIDTH = 18;
const int STROKE_HEIGHT = 3;
const string BACKGROUND_COLOR = '#C0C0C0';
const string COLOR = '#0B0B13';

public function __construct(
private readonly GifBuilder $gifBuilder,
private readonly ?ViewFactoryInterface $viewFactory = null,
) {
}

public function generate(int $width, int $height, string $format): string
{
$text = sprintf('%dx%d.%s', $width, $height, $format);
if ($format !== 'svg') {
return $this->generateBitmap($width, $height, $format, $text);
}

if (GeneralUtility::makeInstance(Typo3Version::class)->getMajorVersion() < 13) {
$view = new StandaloneView();
$view->setTemplatePathAndFilename('EXT:fluid_components/Resources/Private/Templates/Placeholder.svg');
} else {
$view = $this->viewFactory->create(new ViewFactoryData(
templatePathAndFilename: 'EXT:fluid_components/Resources/Private/Templates/Placeholder.svg',
));
}

$view->assignMultiple([
'width' => $width,
'height' => $height,
'backgroundColor' => self::BACKGROUND_COLOR,
'color' => self::COLOR,
'text' => $text,
]);
return 'data:image/svg+xml;base64,' . base64_encode($view->render());
}

private function generateBitmap(int $width, int $height, string $format, string $text): string
{
$configuration = [
'XY' => implode(',', [$width, $height]),
'backColor' => self::BACKGROUND_COLOR,
'format' => $format,
'10' => 'TEXT',
'10.' => [
'text' => $text,
'fontColor' => self::COLOR,
'fontSize' => round($width / 9),
'align' => 'center',
'offset' => implode(',', [0, $height / 1.75]),
],
];

$strokes = [
[0 ,0 , self::STROKE_WIDTH, self::STROKE_HEIGHT],
[0 ,0 , self::STROKE_HEIGHT, self::STROKE_WIDTH],
[($width - self::STROKE_WIDTH), 0, $width , self::STROKE_HEIGHT],
[($width - self::STROKE_HEIGHT), 0, $width, self::STROKE_WIDTH],
[0, ($height - self::STROKE_HEIGHT), self::STROKE_WIDTH, $height],
[0, ($height - self::STROKE_WIDTH), self::STROKE_HEIGHT, $height],
[($width - self::STROKE_WIDTH), ($height - self::STROKE_HEIGHT), $width, $height],
[($width - self::STROKE_HEIGHT), ($height - self::STROKE_WIDTH), $width, $height],
];

foreach ($strokes as $key => $dimensions) {
$configuration[10 * ($key + 2)] = 'BOX';
$configuration[10 * ($key + 2) . '.'] = [
'dimensions' => implode(',', $dimensions),
'color' => self::COLOR,
];
}

$this->gifBuilder->start($configuration, []);
return (string) $this->gifBuilder->gifBuild()->getPublicUrl();
}
}
3 changes: 3 additions & 0 deletions Configuration/Services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ services:
resource: '../Classes/*'
exclude: '../Classes/Domain/Model/*'

SMS\FluidComponents\Service\PlaceholderImageService:
public: true

SMS\FluidComponents\Command\GenerateXsdCommand:
tags:
- name: 'console.command'
Expand Down
24 changes: 24 additions & 0 deletions Resources/Private/Templates/Placeholder.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 2bee084

Please sign in to comment.