Skip to content

Commit 2697f13

Browse files
committed
TASK: Refactoring and first unit tests
1 parent 991265a commit 2697f13

12 files changed

+555
-292
lines changed

Classes/Command/NodetypeObjectsCommandController.php

Lines changed: 70 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,16 @@
1313
use Neos\Flow\Package\PackageManager;
1414
use Neos\Utility\Files;
1515
use Neos\Utility\Unicode\Functions as UnicodeFunctions;
16+
use PackageFactory\NodeTypeObjects\Domain\NodeTypeObjectNameSpecification;
17+
use PackageFactory\NodeTypeObjects\Domain\NodeTypeObjectNameSpecificationCollection;
18+
use PackageFactory\NodeTypeObjects\Domain\NodeTypeObjectSpecification;
1619
use PackageFactory\NodeTypeObjects\Factory\NodeTypeObjectFileFactory;
17-
use PackageFactory\NodeTypeObjects\Factory\NodeTypeSpecificationFactory;
20+
use PackageFactory\NodeTypeObjects\Factory\NodeTypeObjectSpecificationFactory;
1821

1922
class NodetypeObjectsCommandController extends CommandController
2023
{
2124
private NodeTypeManager $nodeTypeManager;
2225
private PackageManager $packageManager;
23-
private NodeTypeSpecificationFactory $nodeTypeSpecificationFactory;
24-
private NodeTypeObjectFileFactory $nodeTypeObjectFileFactory;
25-
26-
2726

2827
public function injectNodeTypeManager(NodeTypeManager $nodeTypeManager): void
2928
{
@@ -35,18 +34,8 @@ public function injectPackageManager(PackageManager $packageManager): void
3534
$this->packageManager = $packageManager;
3635
}
3736

38-
public function injectNodeTypeSpecificationFactory(NodeTypeSpecificationFactory $nodeTypeSpecificationFactory): void
39-
{
40-
$this->nodeTypeSpecificationFactory = $nodeTypeSpecificationFactory;
41-
}
42-
43-
public function injectNodeTypeObjectFileFactory(NodeTypeObjectFileFactory $nodeTypeObjectFileFactory): void
44-
{
45-
$this->nodeTypeObjectFileFactory = $nodeTypeObjectFileFactory;
46-
}
47-
4837
/**
49-
* Remove all NodeTypeObjects from the selected package
38+
* Remove all *NodeObject.php and *NodeInterface.php from the NodeTypes folder of the specified package
5039
*
5140
* @param string $packageKey PackageKey to store the classes in
5241
* @return void
@@ -65,7 +54,16 @@ public function cleanCommand(string $packageKey): void
6554
}
6655

6756
$packagePath = $package->getPackagePath();
68-
$files = Files::readDirectoryRecursively($packagePath, 'NodeObject.php');
57+
$files = Files::readDirectoryRecursively($packagePath . DIRECTORY_SEPARATOR . 'NodeTypes', 'NodeObject.php');
58+
if (is_array($files)) {
59+
foreach ($files as $file) {
60+
if (is_file($file)) {
61+
unlink($file);
62+
}
63+
$this->outputLine(' - ' . $file);
64+
}
65+
}
66+
$files = Files::readDirectoryRecursively($packagePath . DIRECTORY_SEPARATOR . 'NodeTypes', 'NodeInterface.php');
6967
if (is_array($files)) {
7068
foreach ($files as $file) {
7169
if (is_file($file)) {
@@ -82,6 +80,55 @@ public function cleanCommand(string $packageKey): void
8280
* @param string $packageKey PackageKey
8381
*/
8482
public function buildCommand(string $packageKey): void
83+
{
84+
$package = $this->getPackage($packageKey);
85+
86+
$nodeTypes = $this->nodeTypeManager->getNodeTypes(true);
87+
$nameSpecifications = [];
88+
89+
foreach ($nodeTypes as $nodeType) {
90+
if (!str_starts_with($nodeType->getName(), $packageKey . ':')) {
91+
continue;
92+
}
93+
$nameSpecifications[$nodeType->getName()] = NodeTypeObjectNameSpecification::createFromPackageAndNodeType($package, $nodeType);
94+
}
95+
96+
$nameSpecificationsCollection = new NodeTypeObjectNameSpecificationCollection(...$nameSpecifications);
97+
98+
foreach ($nodeTypes as $nodeType) {
99+
if (!str_starts_with($nodeType->getName(), $packageKey . ':')) {
100+
continue;
101+
}
102+
103+
$specification = NodeTypeObjectSpecification::createFromPackageAndNodeType($package, $nodeType, $nameSpecificationsCollection);
104+
105+
Files::createDirectoryRecursively($specification->names->directory);
106+
107+
if ($specification->names->className) {
108+
file_put_contents(
109+
$specification->names->directory . DIRECTORY_SEPARATOR . $specification->names->className . '.php',
110+
$specification->toPhpClassString()
111+
);
112+
$this->outputLine(' - ' . $specification->names->nodeTypeName . ' -> ' . $specification->names->className);
113+
}
114+
115+
if ($specification->names->interfaceName) {
116+
file_put_contents(
117+
$specification->names->directory . DIRECTORY_SEPARATOR . $specification->names->interfaceName . '.php',
118+
$specification->toPhpInterfaceString()
119+
);
120+
$this->outputLine(' - ' . $specification->names->nodeTypeName . ' -> ' . $specification->names->interfaceName);
121+
}
122+
}
123+
}
124+
125+
/**
126+
* @param string $packageKey
127+
* @return mixed|FlowPackageInterface|GenericPackage|\Neos\Flow\Package\PackageInterface
128+
* @throws \Neos\Flow\Cli\Exception\StopCommandException
129+
* @throws \Neos\Flow\Package\Exception\UnknownPackageException
130+
*/
131+
protected function getPackage(string $packageKey): mixed
85132
{
86133
if ($this->packageManager->isPackageAvailable($packageKey)) {
87134
$package = $this->packageManager->getPackage($packageKey);
@@ -105,14 +152,14 @@ public function buildCommand(string $packageKey): void
105152
$namespace = null;
106153
foreach ($autoloadConfigurations as $autoloadConfiguration) {
107154
if (
108-
$autoloadConfiguration['mappingType'] === 'psr-4'
109-
&& str_ends_with($autoloadConfiguration['namespace'], '\\NodeTypes\\')
155+
$autoloadConfiguration[ 'mappingType' ] === 'psr-4'
156+
&& str_ends_with($autoloadConfiguration[ 'namespace' ], '\\NodeTypes\\')
110157
&& (
111-
$autoloadConfiguration['classPath'] === $package->getPackagePath() . 'NodeTypes'
112-
|| $autoloadConfiguration['classPath'] === $package->getPackagePath() . 'NodeTypes/'
158+
$autoloadConfiguration[ 'classPath' ] === $package->getPackagePath() . 'NodeTypes'
159+
|| $autoloadConfiguration[ 'classPath' ] === $package->getPackagePath() . 'NodeTypes/'
113160
)
114161
) {
115-
$namespace = $autoloadConfiguration['namespace'];
162+
$namespace = $autoloadConfiguration[ 'namespace' ];
116163
break;
117164
}
118165
}
@@ -121,28 +168,6 @@ public function buildCommand(string $packageKey): void
121168
$this->outputLine('<error>No PSR4-NodeTypes namespace for the NodeTypes folder is registered via composer</error>');
122169
$this->quit(1);
123170
}
124-
125-
$nodeTypes = $this->nodeTypeManager->getNodeTypes(false);
126-
foreach ($nodeTypes as $nodeType) {
127-
if (!str_starts_with($nodeType->getName(), $packageKey . ':')) {
128-
continue;
129-
}
130-
131-
$specification = $this->nodeTypeSpecificationFactory->createFromPackageKeyAndNodeType(
132-
$package,
133-
$nodeType
134-
);
135-
136-
$nodeTypeObjectFile = $this->nodeTypeObjectFileFactory->createNodeTypeObjectPhpCodeFromNode($specification);
137-
138-
Files::createDirectoryRecursively($nodeTypeObjectFile->pathName);
139-
140-
file_put_contents(
141-
$nodeTypeObjectFile->fileNameWithPath,
142-
$nodeTypeObjectFile->fileContent
143-
);
144-
145-
$this->outputLine(' - ' . $specification->nodeTypeName . ' -> ' . $specification->className);
146-
}
171+
return $package;
147172
}
148173
}

Classes/Domain/NodePropertySpecification.php

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace PackageFactory\NodeTypeObjects\Domain;
66

77
use Neos\Flow\Annotations as Flow;
8+
use Neos\Utility\Unicode\Functions as UnicodeFunctions;
89

910
#[Flow\Proxy(false)]
1011
readonly class NodePropertySpecification
@@ -15,4 +16,142 @@ public function __construct(
1516
public mixed $defaultValue,
1617
) {
1718
}
19+
20+
public function getPhpType(): string
21+
{
22+
$phpType = $this->propertyType;
23+
24+
if (str_ends_with($this->propertyType, '[]')) {
25+
$phpType = 'array';
26+
} elseif (str_starts_with($this->propertyType, 'array<') && str_ends_with($this->propertyType, '>')) {
27+
$phpType = 'array';
28+
} elseif ($this->propertyType === 'boolean') {
29+
$phpType = 'bool';
30+
} elseif ($this->propertyType === 'integer') {
31+
$phpType = 'int';
32+
} elseif ($this->propertyType === 'DateTime') {
33+
$phpType = '\DateTime';
34+
}
35+
36+
if (str_contains($phpType, '\\') && !str_starts_with($phpType, '\\')) {
37+
$phpType = '\\' . $phpType;
38+
}
39+
40+
return $phpType;
41+
}
42+
43+
public function getAnnotationType(): ?string
44+
{
45+
$annotationType = null;
46+
47+
if (str_ends_with($this->propertyType, '[]')) {
48+
$annotationType = $this->propertyType;
49+
} elseif (str_starts_with($this->propertyType, 'array<') && str_ends_with($this->propertyType, '>')) {
50+
$annotationType = substr($this->propertyType, 6, -1) . '[]';
51+
}
52+
53+
if (is_string($annotationType) && str_contains($annotationType, '\\') && !str_starts_with($annotationType, '\\')) {
54+
$annotationType = '\\' . $annotationType;
55+
}
56+
57+
return $annotationType;
58+
}
59+
60+
public function toPhpClassMethodString(): string
61+
{
62+
$propertyIsInternal = str_starts_with($this->propertyName, '_');
63+
if ($propertyIsInternal) {
64+
$methodName = 'getInternal' . UnicodeFunctions::ucfirst(substr($this->propertyName, 1));
65+
} else {
66+
$methodName = 'get' . UnicodeFunctions::ucfirst($this->propertyName);
67+
}
68+
69+
$annotationType = $this->getAnnotationType();
70+
$phpType = $this->getPhpType();
71+
72+
$returnType = ($this->defaultValue === null) ? '?' . $phpType : $phpType;
73+
74+
$defaultReturn = match (true) {
75+
($this->propertyType === 'DateTime' && is_string($this->defaultValue)) => 'new \DateTime(\'' . $this->defaultValue . '\')',
76+
default => var_export($this->defaultValue, true),
77+
};
78+
79+
$typeCheck = match ($phpType) {
80+
'null' => 'is_null($value)',
81+
'string' => 'is_string($value)',
82+
'int' => 'is_int($value)',
83+
'float' => 'is_float($value)',
84+
'bool' => 'is_bool($value)',
85+
'array' => 'is_array($value)',
86+
default => '$value instanceof ' . $phpType,
87+
};
88+
89+
if ($annotationType) {
90+
$propertyAccessor = <<<EOL
91+
92+
/**
93+
* @return ?$annotationType;
94+
*/
95+
public function $methodName(): $returnType
96+
{
97+
\$value = \$this->node->getProperty('$this->propertyName');
98+
if ($typeCheck) {
99+
return \$value;
100+
}
101+
return $defaultReturn;
102+
}
103+
104+
EOL;
105+
} else {
106+
$propertyAccessor = <<<EOL
107+
108+
public function $methodName(): $returnType
109+
{
110+
\$value = \$this->node->getProperty('$this->propertyName');
111+
if ($typeCheck) {
112+
return \$value;
113+
}
114+
return $defaultReturn;
115+
}
116+
117+
EOL;
118+
}
119+
120+
return $propertyAccessor;
121+
}
122+
123+
124+
public function toPhpInterfaceMethodString(): string
125+
{
126+
$propertyIsInternal = str_starts_with($this->propertyName, '_');
127+
if ($propertyIsInternal) {
128+
$methodName = 'getInternal' . UnicodeFunctions::ucfirst(substr($this->propertyName, 1));
129+
} else {
130+
$methodName = 'get' . UnicodeFunctions::ucfirst($this->propertyName);
131+
}
132+
133+
$annotationType = $this->getAnnotationType();
134+
$phpType = $this->getPhpType();
135+
$returnType = ($this->defaultValue === null) ? '?' . $phpType : $phpType;
136+
137+
138+
if ($annotationType) {
139+
$propertyAccessor = <<<EOL
140+
141+
/**
142+
* @return ?$annotationType;
143+
*/
144+
public function $methodName(): $returnType;
145+
146+
EOL;
147+
} else {
148+
$propertyAccessor = <<<EOL
149+
150+
public function $methodName(): $returnType;
151+
152+
EOL;
153+
}
154+
155+
return $propertyAccessor;
156+
}
18157
}

Classes/Domain/NodePropertySpecificationCollection.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace PackageFactory\NodeTypeObjects\Domain;
66

7+
use Neos\ContentRepository\Domain\Model\NodeType;
78
use Neos\Flow\Annotations as Flow;
89

910
/**
@@ -30,4 +31,20 @@ public function getIterator(): \Generator
3031
{
3132
yield from $this->items;
3233
}
34+
35+
public static function createFromNodeType(NodeType $nodeType): NodePropertySpecificationCollection
36+
{
37+
/**
38+
* @var NodePropertySpecification[] $propertySpecifications
39+
*/
40+
$propertySpecifications = [];
41+
foreach ($nodeType->getProperties() as $propertyName => $propertyConfiguration) {
42+
$propertySpecifications[] = new NodePropertySpecification(
43+
$propertyName,
44+
$nodeType->getPropertyType($propertyName),
45+
$propertyConfiguration['defaultValue'] ?? null
46+
);
47+
}
48+
return new NodePropertySpecificationCollection(...$propertySpecifications);
49+
}
3350
}

Classes/Domain/NodeTypeObjectFile.php

Lines changed: 0 additions & 25 deletions
This file was deleted.

0 commit comments

Comments
 (0)