Syndesi/neo4j-sync-bundle

View on GitHub
src/Provider/DatabaseSyncNodeRelationProvider.php

Summary

Maintainability
A
1 hr
Test Coverage
F
0%
<?php

declare(strict_types=1);

namespace Syndesi\Neo4jSyncBundle\Provider;

use Doctrine\ORM\EntityManagerInterface;
use Syndesi\Neo4jSyncBundle\Contract\NodeAttributeInterface;
use Syndesi\Neo4jSyncBundle\Contract\PaginatedStatementProviderInterface;
use Syndesi\Neo4jSyncBundle\Statement\BatchCreateRelationStatementBuilder;
use Syndesi\Neo4jSyncBundle\Statement\BatchDeleteRelationsFromNodeStatementBuilder;

class DatabaseSyncNodeRelationProvider implements PaginatedStatementProviderInterface
{
    private int $page = 0;
    private int $size;

    /**
     * @param class-string $className
     */
    public function __construct(
        private string $className,
        private EntityManagerInterface $em,
        private NodeAttributeInterface $nodeAttribute
    ) {
        $this->size = $this->em->getRepository($this->className)->count([]);
    }

    public function next(): void
    {
        ++$this->page;
    }

    public function key(): mixed
    {
        return $this->page;
    }

    public function valid(): bool
    {
        return ($this->page * self::PAGE_SIZE) < $this->size;
    }

    public function rewind(): void
    {
        $this->page = 0;
    }

    public function current(): array
    {
        /** @var class-string $className */
        $className = $this->className;
        $elements = $this->em->getRepository($this->className)
            ->createQueryBuilder('n')
            ->setFirstResult($this->page * self::PAGE_SIZE)
            ->setMaxResults(($this->page + 1) * self::PAGE_SIZE)
            ->getQuery()
            ->execute();

        $nodes = [];
        $relationTypes = []; // contains one array per relationship type
        foreach ($elements as $element) {
            $node = $this->nodeAttribute->getNode($element);
            $nodes[] = $node;
            foreach ($node->getRelations() as $relation) {
                $key = $relation->getLabel()->getLabel();
                if (!array_key_exists($key, $relationTypes)) {
                    $relationTypes[$key] = [];
                }
                $relationTypes[$key][] = $relation;
            }
        }
        $relationStatements = [];
        foreach ($relationTypes as $relations) {
            $relationStatements = [
                ...$relationStatements,
                ...BatchCreateRelationStatementBuilder::build($relations),
            ];
        }

        return [
            ...BatchDeleteRelationsFromNodeStatementBuilder::build($nodes),
            ...$relationStatements,
        ];
    }

    public function countPages(): int
    {
        return (int) ceil((float) $this->size / (float) self::PAGE_SIZE);
    }

    public function countElements(): int
    {
        return $this->size;
    }

    public function getName(): string
    {
        return $this->className;
    }
}