Skip to content

Commit 26aa71d

Browse files
authoredApr 24, 2024··
Merge pull request #45 from andreaswolf/add-better-fractor-configuration
[FEATURE] Add better DX for configuring fractor
2 parents 859ca20 + a929b43 commit 26aa71d

File tree

19 files changed

+230
-46
lines changed

19 files changed

+230
-46
lines changed
 

‎.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
.phpunit.result.cache
2-
./run-test.sh
2+
./run-test.sh
3+
.run-test.sh

‎README.md

+9-8
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,15 @@ To utilize Fractor effectively, follow these steps:
3737
- At minimum, a configuration file must specify the paths to process:
3838
```php
3939
<?php
40-
41-
use a9f\Fractor\Configuration\Option;
42-
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
43-
44-
return static function (ContainerConfigurator $containerConfigurator) {
45-
$parameters = $containerConfigurator->parameters();
46-
$parameters->set(Option::PATHS, [__DIR__ . '/output/']);
47-
};
40+
41+
use a9f\Fractor\DependencyInjection\FractorConfiguration;
42+
43+
return FractorConfiguration::configure()
44+
->withPaths([__DIR__ . '/packages/'])
45+
->withSets([
46+
Typo3LevelSetList::UP_TO_TYPO3_13
47+
]);
48+
4849
```
4950

5051
3. **Running Fractor**:

‎e2e/typo3-flexform/fractor.php

+7-8
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
<?php
22

3-
use a9f\Fractor\Configuration\Option;
4-
use a9f\Typo3Fractor\Set\Typo3LevelSetList;
5-
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
63

7-
return static function (ContainerConfigurator $containerConfigurator): void {
8-
$parameters = $containerConfigurator->parameters();
9-
$parameters->set(Option::PATHS, [__DIR__ . '/output/']);
4+
use a9f\Fractor\Configuration\FractorConfiguration;
5+
use a9f\Typo3Fractor\Set\Typo3LevelSetList;
106

11-
$containerConfigurator->import(Typo3LevelSetList::UP_TO_TYPO3_13);
12-
};
7+
return FractorConfiguration::configure()
8+
->withPaths([__DIR__ . '/output/'])
9+
->withSets([
10+
Typo3LevelSetList::UP_TO_TYPO3_13
11+
]);

‎fractor/bin/fractor.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
$configFile = ConfigResolver::resolveConfigsFromInput(new ArgvInput());
2828

29-
$container = (new ContainerContainerBuilder())->createDependencyInjectionContainer([$configFile]);
29+
$container = (new ContainerContainerBuilder())->createDependencyInjectionContainer($configFile);
3030

3131
/** @var FractorApplication $application */
3232
$application = $container->get(FractorApplication::class);

‎fractor/config/application.php

-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
use a9f\Fractor\Application\FractorRunner;
55
use a9f\Fractor\Configuration\AllowedFileExtensionsResolver;
66
use a9f\Fractor\Configuration\ConfigurationFactory;
7-
use a9f\Fractor\Configuration\Option;
87
use a9f\Fractor\Configuration\ValueObject\Configuration;
98
use a9f\Fractor\Differ\ConsoleDiffer;
109
use a9f\Fractor\Differ\Contract\Differ;
@@ -21,9 +20,6 @@
2120
use function Symfony\Component\DependencyInjection\Loader\Configurator\tagged_iterator;
2221

2322
return static function (ContainerConfigurator $containerConfigurator, ContainerBuilder $containerBuilder): void {
24-
$parameters = $containerConfigurator->parameters();
25-
$parameters->set(Option::PATHS, [__DIR__]);
26-
$parameters->set(Option::SKIP, []);
2723
$services = $containerConfigurator->services();
2824
$services->defaults()
2925
->autowire()

‎fractor/config/fractor.php

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
3+
use a9f\Fractor\Configuration\FractorConfiguration;
4+
5+
return FractorConfiguration::configure();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace a9f\Fractor\Configuration;
6+
7+
final class FractorConfiguration
8+
{
9+
public static function configure(): FractorConfigurationBuilder
10+
{
11+
return new FractorConfigurationBuilder();
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace a9f\Fractor\Configuration;
6+
7+
use a9f\Fractor\Application\Contract\ConfigurableFractorRule;
8+
use a9f\Fractor\Application\Contract\FractorRule;
9+
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
10+
use Webmozart\Assert\Assert;
11+
12+
final class FractorConfigurationBuilder
13+
{
14+
/**
15+
* @var string[]
16+
*/
17+
private array $sets = [];
18+
19+
/**
20+
* @var string[]
21+
*/
22+
private array $paths = [];
23+
24+
/**
25+
* @var array<mixed>
26+
*/
27+
private array $skip = [];
28+
29+
/**
30+
* @var array<class-string<FractorRule>>
31+
*/
32+
private array $rules = [];
33+
34+
/**
35+
* @var array<class-string<ConfigurableFractorRule>, array<int|string, mixed>>
36+
*/
37+
private array $rulesWithConfigurations = [];
38+
39+
/**
40+
* @param string[] $paths
41+
*/
42+
public function withPaths(array $paths): self
43+
{
44+
$this->paths = $paths;
45+
46+
return $this;
47+
}
48+
49+
/**
50+
* @param array<mixed> $skip
51+
*/
52+
public function withSkip(array $skip): self
53+
{
54+
$this->skip = array_merge($this->skip, $skip);
55+
56+
return $this;
57+
}
58+
59+
/**
60+
* @param string[] $sets
61+
*/
62+
public function withSets(array $sets): self
63+
{
64+
$this->sets = array_merge($this->sets, $sets);
65+
66+
return $this;
67+
}
68+
69+
/**
70+
* @param class-string<ConfigurableFractorRule> $fractorClass
71+
* @param array<int|string, mixed> $configuration
72+
*/
73+
public function withConfiguredRule(string $fractorClass, array $configuration): self
74+
{
75+
$this->rulesWithConfigurations[$fractorClass][] = $configuration;
76+
77+
return $this;
78+
}
79+
80+
/**
81+
* @param array<class-string<FractorRule>> $rules
82+
*/
83+
public function withRules(array $rules): self
84+
{
85+
$this->rules = array_merge($this->rules, $rules);
86+
87+
return $this;
88+
}
89+
90+
public function __invoke(ContainerConfigurator $containerConfigurator): void
91+
{
92+
Assert::allString($this->paths);
93+
94+
$parameters = $containerConfigurator->parameters();
95+
$parameters->set(Option::PATHS, $this->paths);
96+
$parameters->set(Option::SKIP, $this->skip);
97+
98+
$services = $containerConfigurator->services();
99+
100+
foreach ($this->rules as $rule) {
101+
Assert::classExists($rule);
102+
Assert::isAOf($rule, FractorRule::class);
103+
$services->set($rule)
104+
->autoconfigure()
105+
->autowire();
106+
}
107+
108+
Assert::allString($this->sets);
109+
foreach ($this->sets as $set) {
110+
Assert::fileExists($set);
111+
$containerConfigurator->import($set);
112+
}
113+
114+
foreach ($this->rulesWithConfigurations as $configuredRule => $configuration) {
115+
Assert::classExists($configuredRule);
116+
Assert::isAOf($configuredRule, ConfigurableFractorRule::class);
117+
118+
$services->set($configuredRule)
119+
->call('configure', $configuration)
120+
->autoconfigure()
121+
->autowire();
122+
}
123+
}
124+
}

‎fractor/src/DependencyInjection/ContainerContainerBuilder.php

+21-1
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@
77
use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass;
88
use Symfony\Component\DependencyInjection\ContainerBuilder;
99
use Symfony\Component\DependencyInjection\ContainerInterface;
10+
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
1011
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
12+
use Webmozart\Assert\Assert;
1113

1214
class ContainerContainerBuilder
1315
{
1416
/**
1517
* @param string[] $additionalConfigFiles
1618
*/
17-
public function createDependencyInjectionContainer(array $additionalConfigFiles = []): ContainerInterface
19+
public function createDependencyInjectionContainer(?string $fractorConfigFile, array $additionalConfigFiles = []): ContainerInterface
1820
{
1921
$containerBuilder = new ContainerBuilder();
2022

@@ -23,6 +25,11 @@ public function createDependencyInjectionContainer(array $additionalConfigFiles
2325
$configFiles = [
2426
__DIR__ . '/../../config/application.php'
2527
];
28+
29+
$fractorConfigFile ??= __DIR__ . '/../../config/fractor.php';
30+
31+
$this->loadFractorConfigFile($fractorConfigFile, $containerBuilder);
32+
2633
$configFiles = array_merge($configFiles, $additionalConfigFiles);
2734
$configFiles = array_merge($configFiles, $this->collectConfigFilesFromExtensions());
2835

@@ -56,4 +63,17 @@ private function collectConfigFilesFromExtensions(): array
5663

5764
return $collectedConfigFiles;
5865
}
66+
67+
private function loadFractorConfigFile(string $fractorConfigFile, ContainerBuilder $containerBuilder): void
68+
{
69+
Assert::fileExists($fractorConfigFile);
70+
71+
$self = $this;
72+
$callable = (require $fractorConfigFile);
73+
74+
Assert::isCallable($callable);
75+
$instanceOf = [];
76+
/** @var callable(ContainerConfigurator $container): void $callable */
77+
$callable(new ContainerConfigurator($containerBuilder, new PhpFileLoader($containerBuilder, new FileLocator(dirname($fractorConfigFile))), $instanceOf, dirname($fractorConfigFile), basename($fractorConfigFile)));
78+
}
5979
}

‎fractor/src/Testing/PHPUnit/AbstractFractorTestCase.php

+6-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ protected function additionalConfigurationFiles(): array
2626
return [];
2727
}
2828

29+
protected function provideFractorConfigFile(): ?string
30+
{
31+
return null;
32+
}
33+
2934
protected function setUp(): void
3035
{
3136
$this->bootFromConfigFile();
@@ -35,7 +40,7 @@ protected function setUp(): void
3540

3641
protected function bootFromConfigFile(): void
3742
{
38-
$this->currentContainer = (new ContainerContainerBuilder())->createDependencyInjectionContainer($this->additionalConfigurationFiles());
43+
$this->currentContainer = (new ContainerContainerBuilder())->createDependencyInjectionContainer($this->provideFractorConfigFile(), $this->additionalConfigurationFiles());
3944
}
4045

4146
protected function doTest(): void

‎fractor/tests/Application/FractorRunner/FractorRunnerTest.php

+5
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,9 @@ protected function additionalConfigurationFiles(): array
1919
__DIR__ . '/config/config.php'
2020
];
2121
}
22+
23+
protected function provideFractorConfigFile(): ?string
24+
{
25+
return __DIR__ . '/config/fractor.php';
26+
}
2227
}
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,17 @@
11
<?php
22

3-
use a9f\Fractor\Configuration\Option;
43
use a9f\Fractor\Tests\Fixture\DummyProcessor\Contract\TextRule;
54
use a9f\Fractor\Tests\Fixture\DummyProcessor\FileProcessor\TextFileProcessor;
6-
use a9f\Fractor\Tests\Fixture\DummyProcessor\Rules\ReplaceXXXTextRule;
75
use Symfony\Component\DependencyInjection\ContainerBuilder;
86
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
97
use function Symfony\Component\DependencyInjection\Loader\Configurator\tagged_iterator;
108

119
return static function (ContainerConfigurator $containerConfigurator, ContainerBuilder $containerBuilder): void {
12-
$parameters = $containerConfigurator->parameters();
13-
$parameters->set(Option::PATHS, [__DIR__ . '/../Fixtures/']);
1410
$services = $containerConfigurator->services();
1511
$services->defaults()
1612
->autowire()
1713
->autoconfigure();
1814

19-
$services->set(ReplaceXXXTextRule::class);
2015
$services->set(TextFileProcessor::class)->arg('$rules', tagged_iterator('fractor.text_rules'));
2116
$containerBuilder->registerForAutoconfiguration(TextRule::class)->addTag('fractor.text_rules');
2217
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
use a9f\Fractor\Configuration\FractorConfiguration;
4+
use a9f\Fractor\Tests\Fixture\DummyProcessor\Rules\ReplaceXXXTextRule;
5+
6+
return FractorConfiguration::configure()
7+
->withRules([
8+
ReplaceXXXTextRule::class
9+
])
10+
->withPaths(
11+
[
12+
__DIR__ . '/../Fixtures/'
13+
]
14+
);

‎fractor/tests/FileSystem/FilesFinder/FilesFinderTest.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ private function getFileBasename(string $foundFile): string
6262
return pathinfo($foundFile, PATHINFO_BASENAME);
6363
}
6464

65-
protected function additionalConfigurationFiles(): array
65+
protected function provideFractorConfigFile(): ?string
6666
{
67-
return [__DIR__ . '/config/config.php'];
67+
return __DIR__ . '/config/fractor.php';
6868
}
6969
}

‎fractor/tests/FileSystem/FilesFinder/config/config.php

-9
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?php
2+
3+
use a9f\Fractor\Configuration\FractorConfiguration;
4+
5+
return FractorConfiguration::configure()
6+
->withSkip([__DIR__ . '/../Fixtures/SourceWithBrokenSymlinks/folder2']);

‎typo3-fractor/tests/Rules/TYPO37/FlexForm/AddRenderTypeToFlexFormFractor/AddRenderTypeToFlexFormFractorTest.php

+5
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,9 @@ protected function additionalConfigurationFiles(): array
1717
__DIR__ . '/config/config.php',
1818
];
1919
}
20+
21+
protected function provideFractorConfigFile(): ?string
22+
{
23+
return __DIR__ . '/config/fractor.php';
24+
}
2025
}
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
11
<?php
22

3-
use a9f\Fractor\Configuration\Option;
4-
use a9f\Typo3Fractor\Set\Typo3SetList;
53
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
64

75
return static function (ContainerConfigurator $containerConfigurator): void {
86
$containerConfigurator->import(__DIR__ . '/../../../../../../config/application.php');
97
$containerConfigurator->import(__DIR__ . '/../../../../../../../fractor-xml/config/application.php');
10-
$containerConfigurator->import(Typo3SetList::TYPO3_7);
11-
12-
$parameters = $containerConfigurator->parameters();
13-
$parameters->set(Option::PATHS, [__DIR__ . '/../Fixtures/']);
148
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
use a9f\Fractor\Configuration\FractorConfiguration;
4+
use a9f\Typo3Fractor\Set\Typo3SetList;
5+
6+
return FractorConfiguration::configure()
7+
->withSets([Typo3SetList::TYPO3_7])
8+
->withPaths(
9+
[__DIR__ . '/../Fixtures/']
10+
);

0 commit comments

Comments
 (0)
Please sign in to comment.