Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
97.06% covered (success)
97.06%
33 / 34
0.00% covered (danger)
0.00%
0 / 1
CRAP
0.00% covered (danger)
0.00%
0 / 1
ItemListCodeGenerator
97.06% covered (success)
97.06%
33 / 34
0.00% covered (danger)
0.00%
0 / 1
13
0.00% covered (danger)
0.00%
0 / 1
 run
97.06% covered (success)
97.06%
33 / 34
0.00% covered (danger)
0.00%
0 / 1
13
1<?php
2namespace Apie\StorageMetadataBuilder\CodeGenerators;
3
4use Apie\Core\Context\ApieContext;
5use Apie\Core\Enums\ScalarType;
6use Apie\Core\Identifiers\KebabCaseSlug;
7use Apie\Core\Metadata\ItemHashmapMetadata;
8use Apie\Core\Metadata\ItemListMetadata;
9use Apie\Core\Metadata\MetadataFactory;
10use Apie\Core\Utils\ConverterUtils;
11use Apie\StorageMetadata\Attributes\OneToManyAttribute;
12use Apie\StorageMetadata\Attributes\OrderAttribute;
13use Apie\StorageMetadata\Attributes\ParentAttribute;
14use Apie\StorageMetadataBuilder\Factories\ClassTypeFactory;
15use Apie\StorageMetadataBuilder\Interfaces\RunGeneratedCodeContextInterface;
16use Apie\StorageMetadataBuilder\Mediators\GeneratedCodeContext;
17
18/**
19 * Creates the one to many relations for lists.
20 * - create a sub table for the list
21 * - the sub table references the entity with 'parent' property
22 * - an 'order' property is made for the index of the hashmap or the order of the list.
23 */
24final class ItemListCodeGenerator implements RunGeneratedCodeContextInterface
25{
26    public function run(GeneratedCodeContext $generatedCodeContext): void
27    {
28        $property = $generatedCodeContext->getCurrentProperty();
29        $class = $property ? ConverterUtils::toReflectionClass($property) : null;
30        $currentTable = $generatedCodeContext->getCurrentTable();
31        if (null === $class || null === $currentTable) {
32            return;
33        }
34        $metadata = MetadataFactory::getMetadataStrategyForType($property->getType())
35            ->getResultMetadata(new ApieContext());
36        $propertyName = 'apie_'
37            . str_replace('-', '_', (string) KebabCaseSlug::fromClass($property->getDeclaringClass()))
38            . '_'
39            . str_replace('-', '_', (string) KebabCaseSlug::fromClass($property));
40        if ($currentTable->hasProperty($propertyName)) {
41            return;
42        }
43        if ($metadata instanceof ItemListMetadata || $metadata instanceof ItemHashmapMetadata) {
44            $tableName = $generatedCodeContext->getPrefix('apie_resource_');
45            $arrayType = $class->getMethod('offsetGet')->getReturnType();
46            $scalar = MetadataFactory::getScalarForType($arrayType, $arrayType->allowsNull());
47            if (!$arrayType || 'mixed' === (string) $arrayType) {
48                return;
49            }
50            $arrayClass = $arrayType ? ConverterUtils::toReflectionClass($arrayType) : null;
51            $table = in_array($scalar, ScalarType::PRIMITIVES)
52                ? ClassTypeFactory::createPrimitiveTable($tableName, $scalar->toReflectionType())
53                : ClassTypeFactory::createStorageTable($tableName, $arrayClass);
54            $table->addProperty('parent')
55                ->setType($currentTable->getName())
56                ->addAttribute(ParentAttribute::class);
57            $table->addProperty('listOrder')
58                ->setType($metadata instanceof ItemListMetadata ? 'int' : 'string')
59                ->addAttribute(OrderAttribute::class);
60            if (in_array($scalar, ScalarType::PRIMITIVES)) {
61                $generatedCodeContext->generatedCode->generatedCodeHashmap[$tableName] = $table;
62            } else {
63                $generatedCodeContext->withCurrentObject($arrayClass)->iterateOverTable($table);
64            }
65            $currentTable->addProperty($propertyName)
66                ->addAttribute(OneToManyAttribute::class, [$property->name, $tableName, $property->getDeclaringClass()->name]);
67        }
68    }
69}