diff --git a/src/Analyzer/YamlFileAnalyzer.php b/src/Analyzer/YamlFileAnalyzer.php new file mode 100644 index 0000000..c3d54a9 --- /dev/null +++ b/src/Analyzer/YamlFileAnalyzer.php @@ -0,0 +1,76 @@ +directory = rtrim($directory, '/\\'); + } + + public function save(object $data, string $class, string $attribute, array $scopes = []): void + { + $yaml = $this->serde->serialize($data, format: 'yaml'); + + $filename = $this->getFileName($class, $attribute, $scopes); + + $this->ensureDirectory($filename); + + file_put_contents($filename, $yaml); + } + + private function ensureDirectory(string $filename): void + { + $dir = dirname($filename); + if (!is_dir($dir)) { + if (!mkdir($dir, 0777, true) && !is_dir($dir)) { + throw new \RuntimeException(sprintf('Directory "%s" was not created', $dir)); + } + } + } + + private function getFileName(string $class, string $attribute, array $scopes): string + { + return $this->directory + . DIRECTORY_SEPARATOR + . str_replace('\\', '_', $attribute) + . DIRECTORY_SEPARATOR + . str_replace('\\', '_', $class) + . DIRECTORY_SEPARATOR + . (implode('_', $scopes) ?: 'all_scopes') + . '.yaml'; + } + + public function analyze(object|string $class, string $attribute, array $scopes = []): object + { + // Everything is easier if we normalize to a class first. + // Because anon classes have generated internal class names, they work, too. + $class = is_string($class) ? $class : $class::class; + + $classFile = $this->getFileName($class, $attribute, $scopes); + + $yaml = Yaml::parseFile($classFile); + + $result = $this->serde->deserialize($yaml, from: 'array', to: $attribute); + + return $result; + } +} diff --git a/tests/Analyzer/Attributes/Stuff.php b/tests/Analyzer/Attributes/Stuff.php new file mode 100644 index 0000000..d164127 --- /dev/null +++ b/tests/Analyzer/Attributes/Stuff.php @@ -0,0 +1,39 @@ +properties = $properties; + } + + public function includePropertiesByDefault(): bool + { + return true; + } + + public function __construct( + public readonly string $a, + public readonly string $b = '', + ) {} + + public function propertyAttribute(): string + { + return Thing::class; + } +} diff --git a/tests/Analyzer/Attributes/Thing.php b/tests/Analyzer/Attributes/Thing.php new file mode 100644 index 0000000..a584f58 --- /dev/null +++ b/tests/Analyzer/Attributes/Thing.php @@ -0,0 +1,14 @@ +analyze(Dummy::class, Stuff::class); + + $analyzer->save($classSettings, Dummy::class, Stuff::class); + + $result = $analyzer->analyze(Dummy::class, Stuff::class); + + self::assertEquals($classSettings, $result); + } +}