Issues (26)

src/snippet/TempladoSnippet.php (2 issues)

Labels
Severity
1
<?php declare(strict_types = 1);
2
namespace Templado\Engine;
3
4
use DOMDocument;
5
use DOMElement;
6
use DOMNode;
7
8
class TempladoSnippet implements Snippet {
9
10
    /** @var string */
11
    private $targetId;
12
13
    /** @var DOMDocument */
14
    private $content;
15
16 21
    public function __construct(string $targetId, DOMDocument $dom) {
17 21
        $this->ensureNotEmpty($dom);
18 15
        $this->ensureTempladoNamespacedContainer($dom);
19 12
        $this->targetId = $targetId;
20 12
        $this->content  = $dom;
21 12
    }
22
23 3
    public function getTargetId(): string {
24 3
        return $this->targetId;
25
    }
26
27 9
    public function applyTo(DOMElement $node): DOMNode {
28 9
        if (!$this->shouldReplace($node)) {
29 6
            return $this->appendToNode($node);
30
        }
31
32 3
        return $this->replaceNode($node);
33
    }
34
35 15
    private function ensureTempladoNamespacedContainer(DOMDocument $dom): void {
36 15
        if ($dom->documentElement->namespaceURI !== 'https://templado.io/snippets/1.0') {
37 3
            throw new SnippetException('Document must be in templado namespace (https://templado.io/snippets/1.0).');
38
        }
39 12
    }
40
41 9
    private function shouldReplace(DOMElement $node): bool {
42 9
        $root = $this->content->documentElement;
43
44 9
        if (!$node->hasAttribute('id') || !$root->hasAttribute('id')) {
45 3
            return false;
46
        }
47
48 6
        return $node->getAttribute('id') === $root->getAttribute('id');
49
    }
50
51 6
    private function appendToNode(DOMElement $node): DOMNode {
52 6
        foreach ($this->content->documentElement->childNodes as $child) {
53 6
            $node->appendChild($node->ownerDocument->importNode($child, true));
0 ignored issues
show
The method importNode() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

53
            $node->appendChild($node->ownerDocument->/** @scrutinizer ignore-call */ importNode($child, true));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
54
        }
55
56 6
        return $node;
57
    }
58
59 3
    private function replaceNode(DOMElement $node): DOMNode {
60 3
        $root  = $this->content->documentElement;
61 3
        $first = $root->getElementsByTagName('*')->item(0);
62
63 3
        $parent = $node->parentNode;
64
65 3
        foreach ($root->childNodes as $child) {
66 3
            $parent->insertBefore($node->ownerDocument->importNode($child, true), $node);
0 ignored issues
show
The method insertBefore() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

66
            $parent->/** @scrutinizer ignore-call */ 
67
                     insertBefore($node->ownerDocument->importNode($child, true), $node);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
67
        }
68 3
        $parent->removeChild($node);
69
70 3
        return $first;
71
    }
72
73 21
    private function ensureNotEmpty(DOMDocument $dom): void {
74 21
        if ($dom->childNodes->length === 0) {
75 3
            throw new SnippetException('Document cannot be empty');
76
        }
77
78 18
        if ($dom->documentElement->childNodes->length === 0) {
79 3
            throw new SnippetException('Snippet content cannot be empty');
80
        }
81 15
    }
82
}
83