Skip to content

Commit

Permalink
Replace annotations to attributes for custom index metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
Nikolay Parshakov authored and underground20 committed Aug 26, 2024
1 parent 00d4b65 commit a536fe8
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 124 deletions.
123 changes: 0 additions & 123 deletions Metadata/Annotation/Reader.php

This file was deleted.

17 changes: 17 additions & 0 deletions Metadata/Attribute/CustomIndex.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Intaro\CustomIndexBundle\Metadata\Attribute;

#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)]
class CustomIndex
{
/** @param array<string> $columns */
public function __construct(
public ?string $name = null,
public array $columns = [],
public ?string $where = null,
public ?string $using = null,
public bool $unique = false,
) {
}
}
127 changes: 127 additions & 0 deletions Metadata/Reader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
<?php

namespace Intaro\CustomIndexBundle\Metadata;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Intaro\CustomIndexBundle\DTO\CustomIndex;

final class Reader implements ReaderInterface
{
public function __construct(private readonly EntityManagerInterface $em)
{
}

public function getIndexes(string $currentSchema, bool $searchInAllSchemas): array
{
$metadata = $this->em->getMetadataFactory()->getAllMetadata();
$indexNamesToCustomIndexes = [];
$abstractClassesInfo = $this->getAbstractClassesInfo($metadata);
foreach ($metadata as $meta) {
if ($this->isAbstract($meta)) {
continue;
}

$this->collect($indexNamesToCustomIndexes, $meta, $meta->getTableName(), $currentSchema, $searchInAllSchemas);
$parentsMeta = $this->searchParentsWithIndex($meta, $abstractClassesInfo);
foreach ($parentsMeta as $parentMeta) {
$tableName = $this->getTableNameFromMetadata($meta, $parentMeta);
$this->collect($indexNamesToCustomIndexes, $parentMeta, $tableName, $currentSchema, $searchInAllSchemas, true);
}
}

return $indexNamesToCustomIndexes;
}

private function collect(
array &$indexNamesToCustomIndexes,
ClassMetadata $metadata,
string $tableName,
string $currentSchema,
bool $searchInAllSchemas,
bool $tablePostfix = false
): void {
$reflectionAttributes = $this->getCustomIndexesAttributes($metadata);
if (empty($reflectionAttributes)) {
return;
}

foreach ($reflectionAttributes as $attribute) {
$schema = $metadata->getSchemaName() ?: $currentSchema;
// skip index from side schema in single schema mode
if (!$searchInAllSchemas && $schema !== $currentSchema) {
continue;
}

$attributeArguments = $attribute->getArguments();
$name = $attributeArguments['name'] ?? '';
$index = new CustomIndex(
$tableName,
$schema,
$attributeArguments['columns'] ?? [],
$name . ($name && $tablePostfix ? '_' . $tableName : ''),
$attributeArguments['unique'] ?? false,
$attributeArguments['using'] ?? null,
$attributeArguments['where'] ?? null,
);

$key = $schema . '.' . $index->getName();
$indexNamesToCustomIndexes[$key] = $index;
}
}

private function getTableNameFromMetadata(ClassMetadata $metadata, ClassMetadata $parentMetadata): string
{
if ($metadata->inheritanceType === ClassMetadataInfo::INHERITANCE_TYPE_JOINED) {
return $parentMetadata->getTableName();
}

return $metadata->getTableName();
}

/** @return array<\ReflectionAttribute> */
private function getCustomIndexesAttributes(ClassMetadata $meta): array
{
return $meta->getReflectionClass()->getAttributes(\Intaro\CustomIndexBundle\Metadata\Attribute\CustomIndex::class);
}

private function isAbstract(ClassMetadata $meta): bool
{
return $meta->getReflectionClass()->isAbstract();
}


/**
* @param array $metadata
* @return array<string, mixed>
*/
private function getAbstractClassesInfo(array $metadata): array
{
$abstractClasses = [];
foreach ($metadata as $meta) {
if ($this->isAbstract($meta)) {
$abstractClasses[$meta->getName()] = $meta;
}
}

return $abstractClasses;
}

/**
* @param array<string, mixed> $abstractClasses
* @return array<string, mixed>
*/
private function searchParentsWithIndex(ClassMetadata $meta, array $abstractClasses): array
{
$reflectionClass = $meta->getReflectionClass();
$parentMeta = [];
foreach ($abstractClasses as $entityName => $entityMeta) {
if ($reflectionClass->isSubclassOf($entityName)) {
$parentMeta[$entityName] = $entityMeta;
}
}

return $parentMeta;
}
}
2 changes: 1 addition & 1 deletion config/di.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?php

use Intaro\CustomIndexBundle\Command\IndexUpdateCommand;
use Intaro\CustomIndexBundle\Metadata\Annotation\Reader;
use Intaro\CustomIndexBundle\DBAL\QueryExecutor;
use Intaro\CustomIndexBundle\Metadata\Reader;
use Intaro\CustomIndexBundle\Validator\Constraints\AllowedIndexTypeValidator;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;
Expand Down

0 comments on commit a536fe8

Please sign in to comment.