Code Coverage  | 
      ||||||||||
Lines  | 
       Functions and Methods  | 
       Classes and Traits  | 
      ||||||||
| Total |         | 
       73.68%  | 
       42 / 57  | 
               | 
       33.33%  | 
       1 / 3  | 
       CRAP |         | 
       0.00%  | 
       0 / 1  | 
      
| FileTableGenerator |         | 
       73.68%  | 
       42 / 57  | 
               | 
       33.33%  | 
       1 / 3  | 
       14.62 |         | 
       0.00%  | 
       0 / 1  | 
      
| createFileProperties |         | 
       100.00%  | 
       9 / 9  | 
               | 
       100.00%  | 
       1 / 1  | 
       1 | |||
| applyProperty |         | 
       0.00%  | 
       0 / 14  | 
               | 
       0.00%  | 
       0 / 1  | 
       12 | |||
| run |         | 
       97.06%  | 
       33 / 34  | 
               | 
       0.00%  | 
       0 / 1  | 
       8 | |||
| 1 | <?php | 
| 2 | namespace Apie\StorageMetadataBuilder\CodeGenerators; | 
| 3 | |
| 4 | use Apie\Core\FileStorage\FileStorageInterface; | 
| 5 | use Apie\Core\FileStorage\StoredFile; | 
| 6 | use Apie\Core\Identifiers\KebabCaseSlug; | 
| 7 | use Apie\Core\Lists\IntegerHashmap; | 
| 8 | use Apie\Core\Utils\ConverterUtils; | 
| 9 | use Apie\StorageMetadata\Attributes\GetMethodOrPropertyAttribute; | 
| 10 | use Apie\StorageMetadata\Attributes\OneToOneAttribute; | 
| 11 | use Apie\StorageMetadata\Attributes\StorageMappingAttribute; | 
| 12 | use Apie\StorageMetadataBuilder\Factories\ClassTypeFactory; | 
| 13 | use Apie\StorageMetadataBuilder\Interfaces\RunGeneratedCodeContextInterface; | 
| 14 | use Apie\StorageMetadataBuilder\Mediators\GeneratedCodeContext; | 
| 15 | use Nette\PhpGenerator\ClassType; | 
| 16 | use Psr\Http\Message\UploadedFileInterface; | 
| 17 | use ReflectionClass; | 
| 18 | use ReflectionProperty; | 
| 19 | |
| 20 | final class FileTableGenerator implements RunGeneratedCodeContextInterface | 
| 21 | { | 
| 22 | private const ALT_TYPES = [ | 
| 23 | 'fileSize' => '?int', | 
| 24 | 'indexing' => '?' . IntegerHashmap::class, | 
| 25 | 'storagePath' => 'string' | 
| 26 | ]; | 
| 27 | |
| 28 | private function createFileProperties(ReflectionClass $class): array | 
| 29 | { | 
| 30 | return [ | 
| 31 | 'storagePath' => ['getStoragePath', 'storagePath', $class->name, 'allowLargeStrings' => true], | 
| 32 | 'clientMimeType' => ['getClientMediaType', 'clientMimeType', $class->name], | 
| 33 | 'clientOriginalFile' => ['getClientFilename', 'clientOriginalFile', $class->name], | 
| 34 | 'fileSize' => ['getSize', 'fileSize', $class->name], | 
| 35 | 'serverMimeType' => ['getServerMimeType', 'serverMimeType', $class->name], | 
| 36 | 'serverPath' => ['getServerPath', 'serverPath', $class->name], | 
| 37 | 'indexing' => ['getIndexing', 'indexing', $class->name], | 
| 38 | ]; | 
| 39 | } | 
| 40 | |
| 41 | private function applyProperty(ClassType $table, ReflectionProperty $property, ReflectionClass $class): void | 
| 42 | { | 
| 43 | if (!$table->hasProperty('storage')) { | 
| 44 | $table->addProperty('storage') | 
| 45 | ->setType('?' . FileStorageInterface::class) | 
| 46 | ->addAttribute(StorageMappingAttribute::class); | 
| 47 | } | 
| 48 | |
| 49 | $properties = $this->createFileProperties($class); | 
| 50 | $propertyName = $property->name; | 
| 51 | $type = self::ALT_TYPES[$propertyName] ?? '?string'; | 
| 52 | if (isset($properties[$propertyName])) { | 
| 53 | $table->addProperty($propertyName) | 
| 54 | ->setType($type) | 
| 55 | ->addAttribute( | 
| 56 | GetMethodOrPropertyAttribute::class, | 
| 57 | $properties[$propertyName] | 
| 58 | ); | 
| 59 | } | 
| 60 | } | 
| 61 | |
| 62 | public function run(GeneratedCodeContext $generatedCodeContext): void | 
| 63 | { | 
| 64 | $property = $generatedCodeContext->getCurrentProperty(); | 
| 65 | $currentTable = $generatedCodeContext->getCurrentTable(); | 
| 66 | if ($property === null || $currentTable === null) { | 
| 67 | return; | 
| 68 | } | 
| 69 | $class = ConverterUtils::toReflectionClass($property); | 
| 70 | if (!$class) { | 
| 71 | if ($property->getDeclaringClass()->name === StoredFile::class) { | 
| 72 | $this->applyProperty($currentTable, $property, new ReflectionClass(StoredFile::class)); | 
| 73 | } | 
| 74 | return; | 
| 75 | } | 
| 76 | if ($class->name === UploadedFileInterface::class) { | 
| 77 | $class = new ReflectionClass(StoredFile::class); | 
| 78 | } | 
| 79 | if (in_array(UploadedFileInterface::class, $class->getInterfaceNames())) { | 
| 80 | // TODO: is this still needed? | 
| 81 | $tableName = $generatedCodeContext->getPrefix('apie_resource_'); | 
| 82 | $table = ClassTypeFactory::createStorageTable($tableName, new ReflectionClass(StoredFile::class)); | 
| 83 | $table->addProperty('storage') | 
| 84 | ->setType('?' . FileStorageInterface::class) | 
| 85 | ->addAttribute(StorageMappingAttribute::class); | 
| 86 | $properties = $this->createFileProperties($class); | 
| 87 | foreach ($properties as $propertyName => $attributeArguments) { | 
| 88 | $type = self::ALT_TYPES[$propertyName] ?? '?string'; | 
| 89 | $table->addProperty($propertyName) | 
| 90 | ->setType($type) | 
| 91 | ->addAttribute( | 
| 92 | GetMethodOrPropertyAttribute::class, | 
| 93 | $attributeArguments | 
| 94 | ); | 
| 95 | } | 
| 96 | $generatedCodeContext->generatedCode->generatedCodeHashmap[$tableName] = $table; | 
| 97 | //$generatedCodeContext->withCurrentObject($class)->iterateOverTable($table); | 
| 98 | $propertyName = 'apie_' | 
| 99 | . str_replace('-', '_', (string) KebabCaseSlug::fromClass($property->getDeclaringClass())) | 
| 100 | . '_' | 
| 101 | . str_replace('-', '_', (string) KebabCaseSlug::fromClass($property)); | 
| 102 | $currentTable->addProperty($propertyName) | 
| 103 | ->setType('?' . $tableName) | 
| 104 | ->addAttribute(OneToOneAttribute::class, [$property->name, null, $property->getDeclaringClass()->name]); | 
| 105 | } | 
| 106 | } | 
| 107 | } |