• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

eliashaeussler / cache-warmup / 12401324735

18 Dec 2024 09:06PM UTC coverage: 89.057% (-1.4%) from 90.444%
12401324735

Pull #421

github

web-flow
Merge 4e24c8e38 into d133b8e46
Pull Request #421: [FEATURE] Use simpler XML parsing to reduce high memory load

128 of 164 new or added lines in 9 files covered. (78.05%)

1 existing line in 1 file now uncovered.

1652 of 1855 relevant lines covered (89.06%)

9.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/Xml/Node/SitemapNodeProcessor.php
1
<?php
2

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of the Composer package "eliashaeussler/cache-warmup".
7
 *
8
 * Copyright (C) 2020-2024 Elias Häußler <elias@haeussler.dev>
9
 *
10
 * This program is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation, either version 3 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22
 */
23

24
namespace EliasHaeussler\CacheWarmup\Xml\Node;
25

26
use EliasHaeussler\CacheWarmup\Exception;
27
use Netlogix\XmlProcessor;
28
use XMLReader;
29

30
use function array_map;
31
use function in_array;
32

33
/**
34
 * SitemapNodeProcessor.
35
 *
36
 * @author Elias Häußler <elias@haeussler.dev>
37
 * @license GPL-3.0-or-later
38
 *
39
 * @internal
40
 */
41
final class SitemapNodeProcessor implements XmlProcessor\NodeProcessor\NodeProcessorInterface, XmlProcessor\NodeProcessor\TextNodeProcessorInterface, XmlProcessor\NodeProcessor\CloseNodeProcessorInterface
42
{
43
    /**
44
     * @var list<array<string, string>>
45
     */
46
    private array $processedNodes = [];
47

48
    /**
49
     * @var array<string, string>
50
     */
51
    private array $currentNode = [];
52

53
    /**
54
     * @param list<SitemapNode> $supportedNodes
55
     */
NEW
56
    public function __construct(
×
57
        private readonly SitemapNodePath $baseNodePath,
58
        private readonly array $supportedNodes,
NEW
59
    ) {}
×
60

61
    /**
62
     * @return iterable<string, callable>
63
     */
NEW
64
    public function getSubscribedEvents(string $nodePath, XmlProcessor\XmlProcessorContext $context): iterable
×
65
    {
NEW
66
        if ($this->isSupportedNodePath($nodePath)) {
×
NEW
67
            yield XmlProcessor\XmlProcessor::EVENT_OPEN_FILE => $this->reset(...);
×
NEW
68
            yield 'NodeType_'.XMLReader::TEXT => $this->textElement(...);
×
NEW
69
            yield 'NodeType_'.XMLReader::END_ELEMENT => $this->closeElement(...);
×
70
        }
71

NEW
72
        yield from [];
×
73
    }
74

NEW
75
    public function textElement(XmlProcessor\NodeProcessor\Context\TextContext $context): void
×
76
    {
NEW
77
        $node = SitemapNode::tryFromPath($context->getNodePath(), $this->baseNodePath);
×
78

NEW
79
        if (null !== $node && in_array($node, $this->supportedNodes, true)) {
×
NEW
80
            $this->currentNode[$node->value] = $context->getText();
×
81
        }
82
    }
83

84
    /**
85
     * @throws Exception\XmlNodeIsEmpty
86
     */
NEW
87
    public function closeElement(XmlProcessor\NodeProcessor\Context\CloseContext $context): void
×
88
    {
89
        // Early return if unsupported node is processed
NEW
90
        if ($context->getNodePath() !== $this->baseNodePath->value) {
×
NEW
91
            return;
×
92
        }
93

94
        // Throw exception if processed node is empty
NEW
95
        if ([] === $this->currentNode) {
×
NEW
96
            throw new Exception\XmlNodeIsEmpty($this->baseNodePath->value);
×
97
        }
98

NEW
99
        $this->processedNodes[] = $this->currentNode;
×
NEW
100
        $this->currentNode = [];
×
101
    }
102

NEW
103
    public function reset(): void
×
104
    {
NEW
105
        $this->processedNodes = [];
×
NEW
106
        $this->currentNode = [];
×
107
    }
108

109
    /**
110
     * @return list<array<string, string>>
111
     */
NEW
112
    public function getProcessedNodes(): array
×
113
    {
NEW
114
        return $this->processedNodes;
×
115
    }
116

NEW
117
    private function isSupportedNodePath(string $nodePath): bool
×
118
    {
NEW
119
        $supportedNodePaths = [
×
NEW
120
            $this->baseNodePath->value,
×
NEW
121
            ...array_map(fn (SitemapNode $node) => $node->asPath($this->baseNodePath), $this->supportedNodes),
×
NEW
122
        ];
×
123

NEW
124
        foreach ($supportedNodePaths as $expected) {
×
NEW
125
            if (XmlProcessor\XmlProcessor::checkNodePath($nodePath, $expected)) {
×
NEW
126
                return true;
×
127
            }
128
        }
129

NEW
130
        return false;
×
131
    }
132
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc