Skip to content

Commit 1bf2a64

Browse files
authored
Merge pull request #1 from andreaswolf/ci-pipeline
Add CI pipeline
2 parents 7ada7da + 99618b5 commit 1bf2a64

39 files changed

+260
-73
lines changed

.build/ecs.php

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use PhpCsFixer\Fixer\ArrayNotation\ArraySyntaxFixer;
6+
use PhpCsFixer\Fixer\Import\NoUnusedImportsFixer;
7+
use Symplify\EasyCodingStandard\Config\ECSConfig;
8+
9+
return ECSConfig::configure()
10+
// add a single rule
11+
->withRules([
12+
NoUnusedImportsFixer::class,
13+
ArraySyntaxFixer::class,
14+
])
15+
->withPreparedSets(psr12: true)
16+
;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: "Code style & tests"
2+
on:
3+
pull_request:
4+
# Run this workflow for all PRs against main
5+
branches:
6+
- main
7+
8+
jobs:
9+
php-check:
10+
runs-on: ubuntu-latest
11+
strategy:
12+
matrix:
13+
composer-command:
14+
- name: PHP Code Style
15+
command: 'style:php'
16+
- name: Composer normalize
17+
command: 'normalize --dry-run'
18+
- name: PHPStan
19+
command: analyze:php
20+
- name: PHPUnit
21+
command: test:php
22+
directory: ['extension-installer', 'fractor', 'fractor-xml', 'typo3-fractor']
23+
exclude:
24+
- directory: extension-installer
25+
composer-command: {name: 'PHPUnit', command: 'test:php'}
26+
27+
name: ${{ matrix.composer-command.name }}/${{ matrix.directory }}
28+
29+
defaults:
30+
run:
31+
working-directory: ${{ matrix.directory }}
32+
steps:
33+
- uses: actions/checkout@v4
34+
with:
35+
ref: ${{ github.event.pull_request.head.sha }}
36+
37+
- name: Install composer dependencies
38+
uses: php-actions/composer@v6
39+
with:
40+
container_workdir: /app/${{ matrix.directory }}
41+
memory_limit: 512M
42+
43+
- name: 'Run check "${{ matrix.composer-command.name }}"'
44+
uses: php-actions/composer@v6
45+
with:
46+
container_workdir: /app/${{ matrix.directory }}
47+
command: ${{ matrix.composer-command.command }}
48+
memory_limit: 512M

extension-installer/composer.json

+7-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
},
1717
"require-dev": {
1818
"composer/composer": "^2.7",
19-
"ergebnis/composer-normalize": "^2.42"
19+
"ergebnis/composer-normalize": "^2.42",
20+
"phpstan/phpstan": "^1.10",
21+
"symplify/easy-coding-standard": "^12.1"
2022
},
2123
"autoload": {
2224
"psr-4": {
@@ -31,5 +33,9 @@
3133
},
3234
"extra": {
3335
"class": "a9f\\FractorExtensionInstaller\\InstallerPlugin"
36+
},
37+
"scripts": {
38+
"analyze:php": "phpstan analyze",
39+
"style:php": "ecs"
3440
}
3541
}

extension-installer/ecs.php

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
return (include __DIR__ . '/../.build/ecs.php')
6+
->withPaths([
7+
__DIR__ . '/src',
8+
])
9+
;

extension-installer/phpstan.neon

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
parameters:
2+
level: 8
3+
4+
paths:
5+
- src/

extension-installer/src/InstallerPlugin.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,4 @@ public static function getSubscribedEvents(): array
5252
ScriptEvents::POST_UPDATE_CMD => 'processEvent',
5353
];
5454
}
55-
}
55+
}

extension-installer/src/PackagesFileGenerator.php

+2-3
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ public function __construct(
2323
private readonly InstalledRepositoryInterface $repository,
2424
private readonly InstallationManager $installationManager,
2525
private readonly string $fileToGenerate
26-
)
27-
{
26+
) {
2827
}
2928

3029
public function generate(): void
@@ -49,4 +48,4 @@ public function generate(): void
4948
sprintf(self::FILE_TEMPLATE, $installedPackagesCode)
5049
);
5150
}
52-
}
51+
}

fractor-xml/composer.json

+14-7
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,14 @@
2020
"require-dev": {
2121
"ergebnis/composer-normalize": "^2.42",
2222
"phpstan/phpstan": "^1.10",
23-
"phpunit/phpunit": "^10.5"
23+
"phpunit/phpunit": "^10.5",
24+
"symplify/easy-coding-standard": "^12.1"
25+
},
26+
"repositories": {
27+
"fractor": {
28+
"type": "path",
29+
"url": "../*"
30+
}
2431
},
2532
"autoload": {
2633
"psr-4": {
@@ -32,16 +39,16 @@
3239
"a9f\\FractorXml\\Tests\\": "tests/"
3340
}
3441
},
35-
"repositories": {
36-
"fractor": {
37-
"type": "path",
38-
"url": "../*"
39-
}
40-
},
4142
"config": {
4243
"allow-plugins": {
44+
"a9f/fractor-extension-installer": true,
4345
"ergebnis/composer-normalize": true
4446
},
4547
"sort-packages": true
48+
},
49+
"scripts": {
50+
"analyze:php": "phpstan analyze",
51+
"style:php": "ecs",
52+
"test:php": "phpunit tests/"
4653
}
4754
}

fractor-xml/config/application.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@
99
->autoconfigure();
1010

1111
$services->load('a9f\\FractorXml\\', __DIR__ . '/../src/');
12-
};
12+
};

fractor-xml/config/fractor.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
use a9f\Fractor\Configuration\FractorConfig;
44
use a9f\FractorXml\DependencyInjection\XmlFractorCompilerPass;
55

6-
return static function(FractorConfig $config) {
6+
return static function (FractorConfig $config) {
77
$config->addCompilerPass(new XmlFractorCompilerPass());
8-
};
8+
};

fractor-xml/ecs.php

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
return (include __DIR__ . '/../.build/ecs.php')
6+
->withPaths([
7+
__DIR__ . '/config',
8+
__DIR__ . '/src',
9+
__DIR__ . '/tests',
10+
])
11+
;

fractor-xml/phpstan.neon

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
parameters:
2+
level: 8
3+
4+
paths:
5+
- src/
6+
- tests/

fractor-xml/src/AbstractXmlFractor.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ public function afterTraversal(\DOMNode $rootNode): void
2929
{
3030
// no-op for now
3131
}
32-
}
32+
}

fractor-xml/src/DependencyInjection/XmlFractorCompilerPass.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,4 @@ public function process(ContainerBuilder $container): void
3131
$definition = $container->findDefinition(XmlFileProcessor::class);
3232
$definition->setArgument('$rules', $references);
3333
}
34-
}
34+
}

fractor-xml/src/DomDocumentIterator.php

+8-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ public function traverseDocument(\DOMDocument $document): void
2020
$visitor->beforeTraversal($document);
2121
}
2222

23-
$this->traverseNode($document->firstChild);
23+
if ($document->firstChild instanceof \DOMNode) {
24+
$this->traverseNode($document->firstChild);
25+
}
2426

2527
foreach ($this->visitors as $visitor) {
2628
$visitor->afterTraversal($document);
@@ -33,6 +35,11 @@ private function traverseNode(\DOMNode $node): void
3335
foreach ($this->visitors as $visitor) {
3436
$result = $visitor->enterNode($node);
3537

38+
if ($node->parentNode === null) {
39+
// TODO convert into a custom ShouldNotHappenException
40+
throw new \RuntimeException('Node has no parent node');
41+
}
42+
3643
if ($result === DomDocumentIterator::REMOVE_NODE) {
3744
$node->parentNode->removeChild($node);
3845
$nodeRemoved = true;

fractor-xml/src/DomNodeVisitor.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ public function enterNode(\DOMNode $node): \DOMNode|int;
1717
public function leaveNode(\DOMNode $node): void;
1818

1919
public function afterTraversal(\DOMNode $rootNode): void;
20-
}
20+
}

fractor-xml/src/XmlFileProcessor.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,4 @@ public function handle(\SplFileInfo $file): void
3232
// TODO only update file if changed
3333
file_put_contents($file->getPathname(), $doc->saveXML());
3434
}
35-
}
35+
}

fractor-xml/src/XmlFractor.php

+5-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
namespace a9f\FractorXml;
44

5-
interface XmlFractor
5+
interface XmlFractor extends DomNodeVisitor
66
{
77
public function canHandle(\DOMNode $node): bool;
88

9+
/**
10+
* @return \DOMNode|DomDocumentIterator::*|null
11+
*/
912
public function refactor(\DOMNode $node): \DOMNode|int|null;
10-
}
13+
}

fractor-xml/tests/DomDocumentIteratorTest.php

+14-9
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ public function traversalEntersAndLeavesGrandChildrenBeforeLeavingChildren(): vo
141141
#[Test]
142142
public function nodeIsRemovedFromDomIfVisitorReturnsRemoveNode(): void
143143
{
144-
$nodeRemovingVisitor = new class extends CollectingDomNodeVisitor {
144+
$nodeRemovingVisitor = new class() extends CollectingDomNodeVisitor {
145145
public function enterNode(\DOMNode $node): \DOMNode|int
146146
{
147147
parent::enterNode($node);
@@ -150,7 +150,6 @@ public function enterNode(\DOMNode $node): \DOMNode|int
150150
}
151151
return $node;
152152
}
153-
154153
};
155154
$document = new \DOMDocument();
156155
$document->loadXML(<<<XML
@@ -169,22 +168,25 @@ public function enterNode(\DOMNode $node): \DOMNode|int
169168
'afterTraversal:#document',
170169
], $nodeRemovingVisitor->calls);
171170

172-
self::assertXmlStringEqualsXmlString('<Root></Root>', $document->saveXML());
171+
self::assertXmlStringEqualsXmlString('<Root></Root>', $document->saveXML() ?: '');
173172
}
174173

175174
#[Test]
176175
public function nodeIsReplacedIfVisitorReturnsNewDomNode(): void
177176
{
178-
$nodeRemovingVisitor = new class extends CollectingDomNodeVisitor {
177+
$nodeRemovingVisitor = new class() extends CollectingDomNodeVisitor {
179178
public function enterNode(\DOMNode $node): \DOMNode|int
180179
{
181180
parent::enterNode($node);
182181
if ($node->nodeName === 'Child') {
182+
if ($node->ownerDocument === null) {
183+
throw new \RuntimeException('Node does not have an ownerDocument, cannot create element');
184+
}
185+
183186
return $node->ownerDocument->createElement('NewChild');
184187
}
185188
return $node;
186189
}
187-
188190
};
189191
$document = new \DOMDocument();
190192
$document->loadXML(<<<XML
@@ -203,14 +205,17 @@ public function enterNode(\DOMNode $node): \DOMNode|int
203205
'afterTraversal:#document',
204206
], $nodeRemovingVisitor->calls);
205207

206-
self::assertXmlStringEqualsXmlString('<Root><NewChild></NewChild></Root>', $document->saveXML());
208+
self::assertXmlStringEqualsXmlString('<Root><NewChild></NewChild></Root>', $document->saveXML() ?: '');
207209
}
208210

209-
private function getCollectingDomNodeVisitor(): DomNodeVisitor
211+
private function getCollectingDomNodeVisitor(): CollectingDomNodeVisitor
210212
{
211213
return new CollectingDomNodeVisitor();
212214
}
213215

216+
/**
217+
* @param list<string> $recorder
218+
*/
214219
private function getCallRecordingDomNodeVisitor(string $visitorName, array &$recorder): DomNodeVisitor
215220
{
216221
return new class($visitorName, $recorder) implements DomNodeVisitor {
@@ -219,7 +224,7 @@ private function getCallRecordingDomNodeVisitor(string $visitorName, array &$rec
219224
*/
220225
public function __construct(
221226
private readonly string $visitorName,
222-
private array &$calls
227+
public array &$calls // only public to please PHPStan
223228
) {
224229
}
225230

@@ -245,4 +250,4 @@ public function afterTraversal(\DOMNode $rootNode): void
245250
}
246251
};
247252
}
248-
}
253+
}

fractor-xml/tests/Fixtures/CollectingDomNodeVisitor.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
use a9f\FractorXml\DomNodeVisitor;
66

7-
class CollectingDomNodeVisitor implements DomNodeVisitor {
7+
class CollectingDomNodeVisitor implements DomNodeVisitor
8+
{
89
/** @var list<non-empty-string> */
910
public array $calls = [];
1011

@@ -28,4 +29,4 @@ public function afterTraversal(\DOMNode $rootNode): void
2829
{
2930
$this->calls[] = sprintf('afterTraversal:%s', $rootNode->nodeName);
3031
}
31-
}
32+
}

fractor/composer.json

+8-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@
2020
},
2121
"require-dev": {
2222
"ergebnis/composer-normalize": "^2.42",
23-
"phpstan/phpstan": "1.10",
24-
"phpunit/phpunit": "^10.5"
23+
"phpstan/phpstan": "^1.10",
24+
"phpunit/phpunit": "^10.5",
25+
"symplify/easy-coding-standard": "^12.1"
2526
},
2627
"autoload": {
2728
"psr-4": {
@@ -41,5 +42,10 @@
4142
"ergebnis/composer-normalize": true
4243
},
4344
"sort-packages": true
45+
},
46+
"scripts": {
47+
"analyze:php": "phpstan analyze",
48+
"style:php": "ecs",
49+
"test:php": "phpunit tests/"
4450
}
4551
}

fractor/config/application.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@
2323

2424
$services->set(FractorConfig::class)
2525
->lazy(true);
26-
};
26+
};

0 commit comments

Comments
 (0)