1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace Kerox\TwigImagePlaceholder; |
6
|
|
|
|
7
|
|
|
use Twig\Extension\AbstractExtension; |
8
|
|
|
use Twig\TwigFunction; |
9
|
|
|
|
10
|
|
|
final class SvgPlaceholderExtension extends AbstractExtension |
11
|
|
|
{ |
12
|
|
|
private const DEFAULT_OPTIONS = [ |
13
|
|
|
'fontFamily' => 'sans-serif', |
14
|
|
|
'fontWeight' => 'bold', |
15
|
|
|
'bgColor' => '#ddd', |
16
|
|
|
'textColor' => 'rgba(0,0,0,0.5)', |
17
|
|
|
]; |
18
|
|
|
|
19
|
1 |
|
public function getFunctions(): array |
20
|
|
|
{ |
21
|
|
|
return [ |
22
|
1 |
|
new TwigFunction('svg_placeholder', [$this, 'getSvgPlaceholder'], ['is_safe' => ['html']]), |
23
|
1 |
|
new TwigFunction('svg_placeholder_uri', [$this, 'getSvgPlaceholderUri']), |
24
|
|
|
]; |
25
|
|
|
} |
26
|
|
|
|
27
|
3 |
|
public function getSvgPlaceholder(int $width = 300, int $height = 150, array $options = []): string |
28
|
|
|
{ |
29
|
3 |
|
$options = array_replace(self::DEFAULT_OPTIONS, $options); |
30
|
|
|
$options += [ |
31
|
3 |
|
'fontSize' => $fontSize = floor(min($width, $height) * 0.2), |
32
|
3 |
|
'dy' => $fontSize * 0.35, |
33
|
3 |
|
'text' => sprintf('%dx%d', $width, $height), |
34
|
|
|
]; |
35
|
|
|
|
36
|
3 |
|
$doc = new \DOMDocument('1.0'); |
37
|
|
|
|
38
|
3 |
|
$rectElement = $doc->createElement('rect'); |
39
|
3 |
|
$rectElement->setAttribute('fill', $options['bgColor']); |
40
|
3 |
|
$rectElement->setAttribute('width', (string) $width); |
41
|
3 |
|
$rectElement->setAttribute('height', (string) $height); |
42
|
|
|
|
43
|
3 |
|
$textElement = $doc->createElement('text'); |
44
|
3 |
|
$textElement->setAttribute('fill', $options['textColor']); |
45
|
3 |
|
$textElement->setAttribute('font-family', $options['fontFamily']); |
46
|
3 |
|
$textElement->setAttribute('font-size', (string) $options['fontSize']); |
47
|
3 |
|
$textElement->setAttribute('font-weight', (string)$options['fontWeight']); |
48
|
3 |
|
$textElement->setAttribute('dy', (string) $options['dy']); |
49
|
3 |
|
$textElement->setAttribute('x', '50%'); |
50
|
3 |
|
$textElement->setAttribute('y', '50%'); |
51
|
3 |
|
$textElement->setAttribute('text-anchor', 'middle'); |
52
|
3 |
|
$textElement->appendChild($doc->createTextNode($options['text'])); |
53
|
|
|
|
54
|
3 |
|
$svgElement = $doc->createElement('svg'); |
55
|
3 |
|
$svgElement->setAttribute('xmlns', 'http://www.w3.org/2000/svg'); |
56
|
3 |
|
$svgElement->setAttribute('width', (string) $width); |
57
|
3 |
|
$svgElement->setAttribute('height', (string) $height); |
58
|
3 |
|
$svgElement->setAttribute('viewBox', "0 0 $width $height"); |
59
|
3 |
|
$svgElement->appendChild($rectElement); |
60
|
3 |
|
$svgElement->appendChild($textElement); |
61
|
|
|
|
62
|
3 |
|
$doc->appendChild($svgElement); |
63
|
|
|
|
64
|
3 |
|
return trim($doc->saveHTML()); |
65
|
|
|
} |
66
|
|
|
|
67
|
1 |
|
public function getSvgPlaceholderUri(int $width = 300, int $height = 150, array $options = []): string |
68
|
|
|
{ |
69
|
1 |
|
return sprintf('data:image/svg+xml;charset=UTF-8,%s', rawurlencode($this->getSvgPlaceholder($width, $height, $options))); |
70
|
|
|
} |
71
|
|
|
} |
72
|
|
|
|