feffel/felfactory

View on GitHub
src/Statement/StatementExecutor.php

Summary

Maintainability
A
25 mins
Test Coverage
<?php
declare(strict_types=1);

namespace felfactory\Statement;

use Faker\Generator;
use InvalidArgumentException;

class StatementExecutor
{
    /** @var Generator */
    protected $generator;

    /** @var callable */
    protected $factoryCallback;

    public function __construct(Generator $generator, callable $factoryCallback)
    {
        $this->generator       = $generator;
        $this->factoryCallback = $factoryCallback;
    }

    protected function executeClassStatement(Statement $statement): callable
    {
        $factoryCall = $this->factoryCallback;
        $factoryArg  = $statement->value;

        return static function () use ($factoryCall, $factoryArg) {
            return $factoryCall($factoryArg);
        };
    }

    protected function executeGenerateStatement(Statement $statement): callable
    {
        $generator = $this->generator;
        $func      = $statement->value;

        return static function () use ($generator, $func) {
            return eval(sprintf('return $generator->%s;', $func));
        };
    }

    protected function executeValueStatement(Statement $statement): callable
    {
        $value = $statement->value;

        return static function () use ($value) {
            return eval(sprintf('return %s;', $value));
        };
    }

    protected function executeManyStatement(Statement $statement): callable
    {
        $statementCall = [$this, 'execute'];

        return static function () use ($statementCall, $statement) {
            $result             = [];
            $count              = random_int($statement->args['from'], $statement->args['to']);
            $statementGenerator = $statementCall($statement->value);
            for ($i = 0; $i < $count; $i++) {
                $result[] = $statementGenerator();
            }

            return $result;
        };
    }

    protected function executeNullStatement(): callable
    {
        return static function () {
            return null;
        };
    }

    public function execute(Statement $statement): callable
    {
        $call = null;
        switch ($statement->type) {
            case StatementType::CLASS_T:
                $call = $this->executeClassStatement($statement);
                break;
            case StatementType::GENERATE_T:
                $call = $this->executeGenerateStatement($statement);
                break;
            case StatementType::VALUE_T:
                $call = $this->executeValueStatement($statement);
                break;
            case StatementType::MANY_T:
                $call = $this->executeManyStatement($statement);
                break;
            case StatementType::NULL_T:
                $call = $this->executeNullStatement();
                break;
            default:
                throw new InvalidArgumentException(sprintf('%s is not a valid StatementType', $statement->type));
        }

        return $call;
    }
}