Skip to content

Commit b47175d

Browse files
theseersebastianbergmann
authored andcommitted
Enhance Exclude Migration to support multiple occurrences
Closes #4419 This also introduces a SnapshotNodeList helper since we can't use live lists as we are modifying the DOM tree while iterating
1 parent 32ff2c8 commit b47175d

File tree

4 files changed

+67
-4
lines changed

4 files changed

+67
-4
lines changed

src/TextUI/XmlConfiguration/Migration/Migrations/MoveWhitelistExcludesToCoverage.php

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
use DOMDocument;
1313
use DOMElement;
14+
use TextUI\XmlConfiguration\Migration\SnapshotNodeList;
1415

1516
/**
1617
* @internal This class is not covered by the backward compatibility promise for PHPUnit
@@ -28,9 +29,8 @@ public function migrate(DOMDocument $document): void
2829
return;
2930
}
3031

31-
$exclude = $whitelist->getElementsByTagName('exclude')->item(0);
32-
33-
if ($exclude === null) {
32+
$excludeNodes = SnapshotNodeList::fromNodeList($whitelist->getElementsByTagName('exclude'));
33+
if ($excludeNodes->count() === 0) {
3434
return;
3535
}
3636

@@ -40,6 +40,31 @@ public function migrate(DOMDocument $document): void
4040
throw new MigrationException('Unexpected state - No coverage element');
4141
}
4242

43-
$coverage->appendChild($exclude);
43+
$targetExclude = $coverage->getElementsByTagName('exclude')->item(0);
44+
45+
if ($targetExclude === null) {
46+
$targetExclude = $coverage->appendChild(
47+
$document->createElement('exclude')
48+
);
49+
}
50+
51+
foreach ($excludeNodes as $excludeNode) {
52+
assert($excludeNode instanceof DOMElement);
53+
54+
55+
foreach (SnapshotNodeList::fromNodeList($excludeNode->childNodes) as $child) {
56+
if (!$child instanceof DOMElement || !in_array($child->nodeName, ['directory', 'file'], true)) {
57+
continue;
58+
}
59+
60+
$targetExclude->appendChild($child);
61+
}
62+
63+
if ($excludeNode->getElementsByTagName('*')->count() !== 0) {
64+
throw new MigrationException('Dangling child elements in exclude found.');
65+
}
66+
67+
$whitelist->removeChild($excludeNode);
68+
}
4469
}
4570
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php declare(strict_types = 1);
2+
namespace TextUI\XmlConfiguration\Migration;
3+
4+
use ArrayIterator;
5+
use Countable;
6+
use DOMNode;
7+
use DOMNodeList;
8+
use IteratorAggregate;
9+
10+
class SnapshotNodeList implements IteratorAggregate, Countable {
11+
12+
/** @var DOMNode[] */
13+
private $nodes = [];
14+
15+
public static function fromNodeList(DOMNodeList $list): SnapshotNodeList {
16+
$snapshot = new self();
17+
foreach($list as $node) {
18+
$snapshot->nodes[] = $node;
19+
}
20+
21+
return $snapshot;
22+
}
23+
24+
public function count(): int {
25+
return count($this->nodes);
26+
}
27+
28+
public function getIterator() {
29+
return new ArrayIterator($this->nodes);
30+
}
31+
32+
}

tests/_files/XmlConfigurationMigration/input-9.2.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
<directory suffix=".php">src/generated</directory>
1515
<file>src/autoload.php</file>
1616
</exclude>
17+
<exclude>
18+
<directory suffix=".php">src/other</directory>
19+
<file>src/some.php</file>
20+
</exclude>
1721
</whitelist>
1822
</filter>
1923

tests/_files/XmlConfigurationMigration/output-9.3.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
<exclude>
1414
<directory suffix=".php">src/generated</directory>
1515
<file>src/autoload.php</file>
16+
<directory suffix=".php">src/other</directory>
17+
<file>src/some.php</file>
1618
</exclude>
1719

1820
<report>

0 commit comments

Comments
 (0)