Syndesi/neo4j-sync-bundle

View on GitHub
src/Statement/BatchCreateRelationStatementBuilder.php

Summary

Maintainability
A
25 mins
Test Coverage
A
100%
<?php

declare(strict_types=1);

namespace Syndesi\Neo4jSyncBundle\Statement;

use Laudis\Neo4j\Databags\Statement;
use Syndesi\Neo4jSyncBundle\Contract\BatchRelationStatementBuilderInterface;
use Syndesi\Neo4jSyncBundle\Exception\InvalidArgumentException;
use Syndesi\Neo4jSyncBundle\ValueObject\Relation;

class BatchCreateRelationStatementBuilder implements BatchRelationStatementBuilderInterface
{
    /**
     * @param Relation[] $relations
     *
     * @return Statement[]
     *
     * @throws InvalidArgumentException
     */
    public static function build(array $relations): array
    {
        if (empty($relations)) {
            return [];
        }
        foreach ($relations as $relation) {
            if (!($relation instanceof Relation)) {
                throw new InvalidArgumentException('All relations need to be of type relation.');
            }
            if (!$relation->getLabel()->isEqualTo($relations[0]->getLabel())) {
                throw new InvalidArgumentException('All relations need to be for the same relation label');
            }
        }

        return self::createReturnStatements($relations);
    }

    /**
     * @param Relation[] $relations
     *
     * @return Statement[]
     */
    private static function createReturnStatements(array $relations): array
    {
        return [new Statement(
            sprintf(
                "UNWIND \$batch as row\n".
                "MATCH\n".
                "  (child:%s {%s: row.childId}),\n".
                "  (parent:%s {%s: row.parentId})\n".
                "CREATE (child)-[relation:%s]->(parent)\n".
                "SET relation += row.properties",
                (string) $relations[0]->getRelatesFromLabel(),
                $relations[0]->getRelatesFromIdentifier()->getName(),
                (string) $relations[0]->getRelatesToLabel(),
                $relations[0]->getRelatesToIdentifier()->getName(),
                (string) $relations[0]->getLabel()
            ),
            [
                'batch' => self::createBatchArray($relations),
            ]
        )];
    }

    /**
     * @param Relation[] $relations
     *
     * @return array<array<string, mixed>>
     */
    private static function createBatchArray(array $relations): array
    {
        $batch = [];
        foreach ($relations as $relation) {
            $batch[] = [
                'childId' => $relation->getRelatesFromIdentifier()->getValue(),
                'parentId' => $relation->getRelatesToIdentifier()->getValue(),
                'properties' => [
                    '_' => null,
                    ...$relation->getPropertiesAsAssociativeArray(),
                ],
            ];
        }

        return $batch;
    }
}