Passed
Push — main ( 1a7f0e...7d39cf )
by Oscar
03:17
created

FontAwesomeRuntime   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 72
Duplicated Lines 0 %

Test Coverage

Coverage 86.11%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 10
eloc 31
c 1
b 0
f 0
dl 0
loc 72
ccs 31
cts 36
cp 0.8611
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 2
B replaceIcons() 0 56 7
A renderHtmlTag() 0 5 1
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\Svg\Library;
13
14
use function BenTools\IterableFunctions\iterable_to_array;
15
16
use Masterminds\HTML5;
17
use Ocubom\Twig\Extension\Svg\Exception\RuntimeException;
18
use Ocubom\Twig\Extension\Svg\FinderInterface;
19
use Ocubom\Twig\Extension\Svg\Library\FontAwesome\Finder;
20
use Ocubom\Twig\Extension\Svg\Library\FontAwesome\Icon;
21
use Ocubom\Twig\Extension\Svg\Util\DomHelper;
22
use Twig\Environment;
23
use Twig\Extension\RuntimeExtensionInterface;
24
25
class FontAwesomeRuntime implements RuntimeExtensionInterface
26
{
27
    private Finder $finder;
28
29 2
    public function __construct(FinderInterface $finder)
30
    {
31 2
        $this->finder = $finder instanceof Finder ? $finder : new Finder($finder);
32
    }
33
34 1
    public function replaceIcons(Environment $twig, string $html): string
35
    {
36 1
        $parser = new HTML5();
37
38
        // Load Document
39 1
        $doc = $parser->loadHTML($html);
40 1
        if ($parser->hasErrors()) {
41
            throw new RuntimeException(sprintf(
42
                'Unable to parse HTML: %s',
43
                implode("\n", $parser->getErrors())
44
            ));
45
        }
46
47 1
        $query = implode(' | ', array_map(
48 1
            function ($class) {
49 1
                return sprintf(
50 1
                    'descendant-or-self::*[@class and contains(concat(\' \', normalize-space(@class), \' \'), \' %s \')]',
51 1
                    $class
52 1
                );
53 1
            },
54 1
            array_keys(FontAwesome::PREFIXES)
55 1
        ));
56
57
        /** @var \DOMNode $node */
58 1
        foreach (DomHelper::query($query, $doc) as $node) {
59 1
            if ($node instanceof \DOMElement) {
60 1
                if ($node->hasAttribute('data-fa-transform')) {
61
                    continue; // Ignore icons with Power Transforms (use svg+js)
62
                }
63
64 1
                if ($twig->isDebug()) {
65 1
                    DomHelper::createComment(DomHelper::toHtml($node), $node, true);
66
                }
67
68 1
                $icon = new Icon(
69
                    // Resolve icon with class …
70 1
                    $this->finder->resolve($node->getAttribute('class')),
71
                    // … and clone all its attributes as options
72 1
                    iterable_to_array(DomHelper::getElementAttributes($node))
73 1
                );
74
75
                // Replace node
76 1
                DomHelper::replaceNode($node, $icon->getElement());
77
            }
78
        }
79
80
        // Normalize final doc
81 1
        $doc->normalize();
82
83
        // Fix EOL lines problem on Windows
84 1
        if ('Windows' === \PHP_OS_FAMILY) {
85
            return str_replace(\PHP_EOL, "\n", $parser->saveHTML($doc)); // @codeCoverageIgnore
86
        }
87
88
        // Generate output
89 1
        return $parser->saveHTML($doc);
90
    }
91
92 1
    public function renderHtmlTag(string $icon, array $options = []): string
93
    {
94 1
        $icon = new Icon($this->finder->resolve($icon), $options);
95
96 1
        return DomHelper::toHtml($icon->getHtmlTag($options));
97
    }
98
}
99