SvgRuntime::convertToSymbols()   B
last analyzed

Complexity

Conditions 8
Paths 12

Size

Total Lines 69
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 36
CRAP Score 8

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 34
c 2
b 0
f 0
dl 0
loc 69
ccs 36
cts 36
cp 1
rs 8.1315
cc 8
nc 12
nop 2
crap 8

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of ocubom/twig-svg-extension
5
 *
6
 * © Oscar Cubo Medina <https://ocubom.github.io>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Ocubom\Twig\Extension;
13
14
use Ocubom\Twig\Extension\Svg\Exception\LoaderException;
15
use Ocubom\Twig\Extension\Svg\Loader\LoaderInterface;
16
use Ocubom\Twig\Extension\Svg\Symbol;
17
use Ocubom\Twig\Extension\Svg\Util\DomUtil;
18
use Ocubom\Twig\Extension\Svg\Util\Html5Util;
19
use Psr\Log\LoggerInterface;
20
use Psr\Log\NullLogger;
21
use Twig\Environment;
22
use Twig\Extension\RuntimeExtensionInterface;
23
24
class SvgRuntime implements RuntimeExtensionInterface
25
{
26
    private LoaderInterface $loader;
27
28
    private LoggerInterface $logger;
29
30 11
    public function __construct(LoaderInterface $loader, LoggerInterface $logger = null)
31
    {
32 11
        $this->loader = $loader;
33 11
        $this->logger = $logger ?? new NullLogger();
34
    }
35
36 6
    public function convertToSymbols(Environment $twig, string $html): string
37
    {
38
        // Load HTML
39 6
        $doc = Html5Util::loadHtml($html);
40
41
        /** @var \DOMElement[] $elements */
42 5
        $elements = [];
43
44
        /** @var \DOMElement[] $symbols */
45 5
        $symbols = [];
46
47
        /** @var \DOMElement $svg */
48 5
        foreach ($doc->getElementsByTagName('svg') as $svg) {
49 4
            $symbol = new Symbol($svg, [
50 4
                'debug' => $twig->isDebug(),
51 4
            ]);
52
53
            // Replace the SVG with reference
54 4
            DomUtil::replaceNode($svg, $symbol->getReference());
55
56
            // Index symbol by id
57 4
            $symbols[$symbol->getId()] = $symbols[$symbol->getId()] ?? $symbol->getElement();
58 4
            $elements[] = $svg;
59
        }
60
61
        // Dump all symbols
62 5
        if (count($symbols) > 0) {
63
            // Create symbols container element before the end of body tag or DOM
64 4
            $node = DomUtil::createElement('svg', '', $doc
65 4
                ->getElementsByTagName('body')
66 4
                ->item(0) ?? $doc
67 4
            );
68 4
            $node->setAttribute('style', 'display:none');
69
70
            // Add format (duplicate previous node space) on debug mode
71 4
            if ($twig->isDebug()) {
72
                assert($node->previousSibling instanceof \DOMNode);
73 3
                DomUtil::appendChildNode($node->previousSibling, $node);
74
            }
75
76 4
            uksort($symbols, 'strnatcasecmp');
77 4
            foreach ($symbols as $symbol) {
78 4
                DomUtil::appendChildNode($symbol, $node);
79
80 4
                if ($twig->isDebug()) {
81
                    assert($node->previousSibling instanceof \DOMNode);
82 3
                    DomUtil::appendChildNode($node->previousSibling, $node);
83
                }
84
            }
85
86 4
            if ($twig->isDebug()) {
87
                assert($node->parentNode instanceof \DOMNode);
88
89 3
                DomUtil::appendChildNode(
90 3
                    $doc->createTextNode("\n"),
91 3
                    $node->parentNode
92 3
                );
93
94 3
                $this->logger->info('Converted {element_count} SVG elements into {symbol_count} SVG symbols', [
95 3
                    'element_count' => count($elements),
96 3
                    'symbol_count' => count($symbols),
97 3
                ]);
98
            }
99 1
        } elseif ($twig->isDebug()) {
100 1
            $this->logger->debug('No SVG found');
101
        }
102
103
        // Generate normalized HTML
104 5
        return Html5Util::toHtml($doc);
105
    }
106
107 5
    public function embedSvg(Environment $twig, string $ident, array $options = []): string
108
    {
109
        try {
110 5
            $svg = $this->loader->resolve($ident, $options);
111
112 3
            return $svg->toXml(!$twig->isDebug());
113 2
        } catch (LoaderException $err) {
114 1
            $this->logger->error($err->getMessage(), ['exception' => $err]);
115
116 1
            if ($twig->isDebug()) {
117 1
                return sprintf('<!--{{ svg("%s") }}-->', $ident);
118
            }
119
        }
120
121
        return '';
122
    }
123
}
124