Skip to content

Commit a30579c

Browse files
Merge pull request #52 from andreaswolf/issue-5
[FEATURE] Fractor for Yaml files
2 parents e95b0f4 + 5c86182 commit a30579c

20 files changed

+445
-29
lines changed

.github/workflows/lint_test_pull_requests.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
command: test:php
2222
- name: Rector
2323
command: 'rector --dry-run'
24-
directory: [ 'extension-installer', 'fractor', 'fractor-xml', 'typo3-fractor', 'fractor-doc-generator' ]
24+
directory: [ 'extension-installer', 'fractor', 'fractor-xml', 'typo3-fractor', 'fractor-doc-generator', 'fractor-yaml']
2525
exclude:
2626
- directory: extension-installer
2727
composer-command: {name: 'PHPUnit', command: 'test:php'}

README.md

+28-28
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Fractor is a generic tool for changing all kinds of files via defined rules—si
66

77
The main package `a9f/fractor` provides infrastructure for configuring and running Fractor,
88
but no rules for changing any files.
9-
These are provided by packages specific for filetypes (like `a9f/fractor-xml`)
9+
These are provided by packages specific for filetypes (like `a9f/fractor-xml`)
1010
or ecosystems (like `a9f/typo3-fractor`).
1111

1212
For different file types, different operation modes are possible.
@@ -24,17 +24,17 @@ there is no advanced support available right now.
2424
To utilize Fractor effectively, follow these steps:
2525

2626
1. **Installation**:
27-
- Install Fractor via Composer by running the following command in your terminal:
28-
```
29-
composer require a9f/fractor a9f/fractor-xml
27+
Install Fractor via Composer by running the following command in your terminal:
28+
```
29+
composer require a9f/fractor a9f/fractor-xml
3030
31-
# if you want to use Fractor with TYPO3, use this instead:
32-
composer require a9f/typo3-fractor
33-
```
31+
# if you want to use Fractor with TYPO3, use this instead:
32+
composer require a9f/typo3-fractor
33+
```
3434

3535
2. **Configuration**:
36-
- Create a PHP configuration file (e.g., `fractor.php`) where you define the paths to your files.
37-
- At minimum, a configuration file must specify the paths to process:
36+
Create a PHP configuration file (e.g., `fractor.php`) where you define the paths to your files.
37+
At minimum, a configuration file must specify the paths to process:
3838
```php
3939
<?php
4040

@@ -49,18 +49,18 @@ return FractorConfiguration::configure()
4949
```
5050

5151
3. **Running Fractor**:
52-
- Execute Fractor from the command line, passing the path to your configuration file as an argument:
53-
```
54-
./vendor/bin/fractor process -f fractor.php
55-
```
52+
Execute Fractor from the command line, passing the path to your configuration file as an argument:
53+
```
54+
./vendor/bin/fractor process -f fractor.php
55+
```
5656

5757
4. **Review Changes**:
58-
- Fractor will apply the rules specified in the configuration file to the targeted files.
59-
- Review the changes made by Fractor to ensure they meet your expectations.
58+
Fractor will apply the rules specified in the configuration file to the targeted files.
59+
Review the changes made by Fractor to ensure they meet your expectations.
6060

6161
5. **Customization**:
62-
- You can modify existing rules or create new ones to tailor Fractor's behavior to your specific needs.
63-
- See the "Extending Fractor" section for guidance on creating custom rules.
62+
You can modify existing rules or create new ones to tailor Fractor's behavior to your specific needs.
63+
See the "Extending Fractor" section for guidance on creating custom rules.
6464

6565
## Extending Fractor
6666

@@ -71,27 +71,27 @@ Fractor can be extended with additional transformation rules and support for new
7171
Here's how you can extend Fractor with a custom rule:
7272

7373
1. **Creating New Rules**:
74-
- Create a new rule by subclassing the appropriate rule class for the file type,
75-
e.g. `\a9f\FractorXml\XmlFractor` for XML files.
76-
- Each rule should specify the conditions under which it should be applied and the corresponding changes to be made.
77-
- Ideally, new rules also have a test case that validates that they work correctly.
74+
- Create a new rule by subclassing the appropriate rule class for the file type,
75+
e.g. `\a9f\FractorXml\XmlFractor` for XML files.
76+
- Each rule should specify the conditions under which it should be applied and the corresponding changes to be made.
77+
- Ideally, new rules also have a test case that validates that they work correctly.
7878

7979
2. **Registering New Rules**:
80-
- Register your custom rules within the Fractor configuration file.
80+
- Register your custom rules within the Fractor configuration file.
8181

8282
### Supporting New File Types
8383

8484
1. **Supporting New File Types**:
85-
- To support a new file type, you will need to implement an instance of `\a9f\Fractor\Fractor\FileProcessor`.
86-
This processor must take care of decoding a file and then traversing the decoded file structure
87-
(e.g. the DOM tree of an XML file; see `\a9f\FractorXml\XmlFileProcessor` for an example)
85+
- To support a new file type, you will need to implement an instance of `\a9f\Fractor\Fractor\FileProcessor`.
86+
This processor must take care of decoding a file and then traversing the decoded file structure
87+
(e.g. the DOM tree of an XML file; see `\a9f\FractorXml\XmlFileProcessor` for an example)
8888

8989
2. **Testing**:
90-
- Thoroughly test your extensions to ensure they function as expected and do not introduce unintended side effects.
91-
- Write unit tests for your custom rules and parsers to maintain code quality and stability.
90+
- Thoroughly test your extensions to ensure they function as expected and do not introduce unintended side effects.
91+
- Write unit tests for your custom rules and parsers to maintain code quality and stability.
9292

9393
3. **Documentation**:
94-
- Document your custom rules and file type extensions to aid other users in understanding and utilizing your contributions.
94+
- Document your custom rules and file type extensions to aid other users in understanding and utilizing your contributions.
9595

9696
By extending Fractor in this manner, you can enhance its capabilities and adapt it to handle a wider range of file formats and transformation scenarios.
9797

fractor-yaml/.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/vendor/
2+
/composer.lock
3+
.phpunit.cache

fractor-yaml/composer.json

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{
2+
"name": "a9f/fractor-yaml",
3+
"description": "YAML extension for the File Read-Analyse-Change TOol. Allows modifying YAML files",
4+
"license": "MIT",
5+
"type": "fractor-extension",
6+
"authors": [
7+
{
8+
"name": "Andreas Wolf",
9+
"email": "[email protected]",
10+
"role": "Lead Developer"
11+
}
12+
],
13+
"require": {
14+
"php": "^8.2",
15+
"a9f/fractor": "@dev",
16+
"a9f/fractor-extension-installer": "@dev",
17+
"symfony/yaml": "^6.0",
18+
"webmozart/assert": "^1.11"
19+
},
20+
"require-dev": {
21+
"ergebnis/composer-normalize": "^2.42",
22+
"phpstan/phpstan": "^1.10",
23+
"phpunit/phpunit": "^10.5",
24+
"rector/rector": "^1.0",
25+
"symplify/easy-coding-standard": "^12.1"
26+
},
27+
"repositories": {
28+
"fractor": {
29+
"type": "path",
30+
"url": "../*"
31+
}
32+
},
33+
"autoload": {
34+
"psr-4": {
35+
"a9f\\FractorYaml\\": "src/"
36+
}
37+
},
38+
"autoload-dev": {
39+
"psr-4": {
40+
"a9f\\FractorYaml\\Tests\\": "tests/"
41+
}
42+
},
43+
"config": {
44+
"allow-plugins": {
45+
"a9f/fractor-extension-installer": true,
46+
"ergebnis/composer-normalize": true
47+
},
48+
"sort-packages": true
49+
},
50+
"scripts": {
51+
"analyze:php": "phpstan analyze",
52+
"rector": "rector",
53+
"style:php:check": "ecs",
54+
"style:php:fix": "ecs --fix",
55+
"test:php": "phpunit"
56+
}
57+
}

fractor-yaml/config/application.php

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
use a9f\FractorYaml\Contract\YamlDumper;
4+
use a9f\FractorYaml\Contract\YamlFractorRule;
5+
use a9f\FractorYaml\Contract\YamlParser;
6+
use a9f\FractorYaml\SymfonyYamlDumper;
7+
use a9f\FractorYaml\SymfonyYamlParser;
8+
use a9f\FractorYaml\YamlFileProcessor;
9+
use Symfony\Component\DependencyInjection\ContainerBuilder;
10+
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
11+
use function Symfony\Component\DependencyInjection\Loader\Configurator\tagged_iterator;
12+
13+
return static function (ContainerConfigurator $containerConfigurator, ContainerBuilder $containerBuilder): void {
14+
$services = $containerConfigurator->services();
15+
$services->defaults()
16+
->autowire()
17+
->autoconfigure();
18+
19+
$services->load('a9f\\FractorYaml\\', __DIR__ . '/../src/');
20+
21+
$services->alias(YamlParser::class, SymfonyYamlParser::class);
22+
$services->alias(YamlDumper::class, SymfonyYamlDumper::class);
23+
24+
$services->set(YamlFileProcessor::class)->arg('$rules', tagged_iterator('fractor.yaml_rule'));
25+
26+
$containerBuilder->registerForAutoconfiguration(YamlFractorRule::class)->addTag('fractor.yaml_rule');
27+
};

fractor-yaml/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-yaml/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-yaml/phpunit.xml

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0"?>
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true" cacheDirectory=".phpunit.cache">
3+
<testsuites>
4+
<testsuite name="fractor-yaml">
5+
<directory>tests</directory>
6+
</testsuite>
7+
</testsuites>
8+
<source>
9+
<include>
10+
<directory>./src</directory>
11+
</include>
12+
</source>
13+
</phpunit>

fractor-yaml/rector.php

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
return (include __DIR__ . '/../.build/rector.php')
6+
->withPaths([
7+
__DIR__ . '/config',
8+
__DIR__ . '/src',
9+
__DIR__ . '/tests',
10+
]);
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace a9f\FractorYaml\Contract;
6+
7+
use a9f\Fractor\ValueObject\Indent;
8+
9+
interface YamlDumper
10+
{
11+
/**
12+
* @param mixed[] $input
13+
*/
14+
public function dump(array $input, Indent $indent): string;
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace a9f\FractorYaml\Contract;
6+
7+
use a9f\Fractor\Application\Contract\FractorRule;
8+
9+
interface YamlFractorRule extends FractorRule
10+
{
11+
/**
12+
* @param mixed[] $yaml
13+
* @return mixed[]
14+
*/
15+
public function refactor(array $yaml): array;
16+
}
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace a9f\FractorYaml\Contract;
6+
7+
use a9f\Fractor\Application\ValueObject\File;
8+
use a9f\FractorYaml\Exception\ParseException;
9+
10+
interface YamlParser
11+
{
12+
/**
13+
* @return mixed[]
14+
* @throws ParseException
15+
* /**
16+
*/
17+
public function parse(File $file): array;
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace a9f\FractorYaml\Exception;
6+
7+
final class ParseException extends \RuntimeException
8+
{
9+
}
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace a9f\FractorYaml;
6+
7+
use a9f\Fractor\ValueObject\Indent;
8+
use a9f\FractorYaml\Contract\YamlDumper;
9+
use Symfony\Component\Yaml\Yaml;
10+
11+
final class SymfonyYamlDumper implements YamlDumper
12+
{
13+
public function dump(array $input, Indent $indent): string
14+
{
15+
return Yaml::dump($input, 99, $indent->length());
16+
}
17+
}
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace a9f\FractorYaml;
6+
7+
use a9f\Fractor\Application\ValueObject\File;
8+
use a9f\FractorYaml\Contract\YamlParser;
9+
use a9f\FractorYaml\Exception\ParseException;
10+
use Symfony\Component\Yaml\Exception\ParseException as YamlParseException;
11+
use Symfony\Component\Yaml\Yaml;
12+
13+
final class SymfonyYamlParser implements YamlParser
14+
{
15+
public function parse(File $file): array
16+
{
17+
try {
18+
return Yaml::parse($file->getContent(), Yaml::PARSE_CUSTOM_TAGS) ?? [];
19+
} catch (YamlParseException $parseException) {
20+
$parseException->setParsedFile($file->getFilePath());
21+
22+
throw new ParseException($parseException->getMessage());
23+
}
24+
}
25+
}

0 commit comments

Comments
 (0)