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
|
4 |
|
public function getSvgPlaceholder(int $width = 300, int $height = 150, array $options = []): string |
28
|
|
|
{ |
29
|
4 |
|
$options = array_replace(self::DEFAULT_OPTIONS, $options); |
30
|
|
|
$options += [ |
31
|
4 |
|
'fontSize' => $fontSize = floor(min($width, $height) * 0.2), |
32
|
4 |
|
'dy' => $fontSize * 0.35, |
33
|
4 |
|
'text' => sprintf('%dx%d', $width, $height), |
34
|
|
|
]; |
35
|
|
|
|
36
|
4 |
|
$doc = new \DOMDocument('1.0'); |
37
|
|
|
|
38
|
|
|
// svg element |
39
|
4 |
|
$svgElement = $doc->createElement('svg'); |
40
|
4 |
|
$svgElement->setAttribute('xmlns', 'http://www.w3.org/2000/svg'); |
41
|
4 |
|
$svgElement->setAttribute('width', (string) $width); |
42
|
4 |
|
$svgElement->setAttribute('height', (string) $height); |
43
|
4 |
|
$svgElement->setAttribute('viewBox', "0 0 $width $height"); |
44
|
4 |
|
if ($class = $options['class'] ?? null) { |
45
|
1 |
|
$svgElement->setAttribute('class', $class); |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
// rect element |
49
|
4 |
|
$rectElement = $doc->createElement('rect'); |
50
|
4 |
|
$rectElement->setAttribute('fill', $options['bgColor']); |
51
|
4 |
|
$rectElement->setAttribute('width', (string) $width); |
52
|
4 |
|
$rectElement->setAttribute('height', (string) $height); |
53
|
|
|
|
54
|
4 |
|
$svgElement->appendChild($rectElement); |
55
|
|
|
|
56
|
|
|
// text element |
57
|
4 |
|
if ($text = $options['text'] ?? null) { |
58
|
3 |
|
$textElement = $doc->createElement('text'); |
59
|
3 |
|
$textElement->setAttribute('fill', $options['textColor']); |
60
|
3 |
|
$textElement->setAttribute('font-family', $options['fontFamily']); |
61
|
3 |
|
$textElement->setAttribute('font-size', (string) $options['fontSize']); |
62
|
3 |
|
$textElement->setAttribute('font-weight', (string) $options['fontWeight']); |
63
|
3 |
|
$textElement->setAttribute('dy', (string) $options['dy']); |
64
|
3 |
|
$textElement->setAttribute('x', '50%'); |
65
|
3 |
|
$textElement->setAttribute('y', '50%'); |
66
|
3 |
|
$textElement->setAttribute('text-anchor', 'middle'); |
67
|
3 |
|
$textElement->appendChild($doc->createTextNode($text)); |
68
|
|
|
|
69
|
3 |
|
$svgElement->appendChild($textElement); |
70
|
|
|
} |
71
|
|
|
|
72
|
4 |
|
$doc->appendChild($svgElement); |
73
|
|
|
|
74
|
4 |
|
return trim($doc->saveHTML()); |
75
|
|
|
} |
76
|
|
|
|
77
|
1 |
|
public function getSvgPlaceholderUri(int $width = 300, int $height = 150, array $options = []): string |
78
|
|
|
{ |
79
|
1 |
|
return sprintf('data:image/svg+xml;charset=UTF-8,%s', rawurlencode($this->getSvgPlaceholder($width, $height, $options))); |
80
|
|
|
} |
81
|
|
|
} |
82
|
|
|
|