soliantconsulting/SimpleFM

View on GitHub
src/Repository/LazyLoadedCollection.php

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
<?php
declare(strict_types = 1);

namespace Soliant\SimpleFM\Repository;

use ArrayIterator;
use IteratorAggregate;
use IteratorIterator;
use Soliant\SimpleFM\Collection\CollectionInterface;
use Soliant\SimpleFM\Repository\Query\FindQuery;
use Soliant\SimpleFM\Repository\Query\Query;
use Traversable;

final class LazyLoadedCollection implements IteratorAggregate, CollectionInterface
{
    /**
     * @var RepositoryInterface
     */
    private $repository;

    /**
     * @var string
     */
    private $idFieldName;

    /**
     * @var array
     */
    private $sparseRecords;

    /**
     * @var IteratorIterator
     */
    private $iterator;

    public function __construct(RepositoryInterface $repository, string $idFieldName, array $sparseRecords)
    {
        $this->repository = $repository;
        $this->idFieldName = $idFieldName;
        $this->sparseRecords = $sparseRecords;
    }

    public function getIterator() : Traversable
    {
        if (null !== $this->iterator) {
            return $this->iterator;
        }

        if (empty($this->sparseRecords)) {
            return $this->iterator = new ArrayIterator();
        }

        $findQuery = new FindQuery();
        $findQuery->addOrQueries(...array_map(function (array $sparseRecord) : Query {
            return new Query($this->idFieldName, (string) $sparseRecord[$this->idFieldName]);
        }, $this->sparseRecords));

        return $this->iterator = new IteratorIterator($this->repository->findByQuery($findQuery));
    }

    public function count() : int
    {
        return count($this->sparseRecords);
    }

    public function getTotalCount() : int
    {
        return count($this->sparseRecords);
    }

    public function isEmpty() : bool
    {
        return 0 === count($this->sparseRecords);
    }

    public function first()
    {
        if ($this->isEmpty()) {
            return null;
        }

        $iterator = $this->getIterator();
        $iterator->rewind();
        return $iterator->current();
    }
}