tflori/dependency-injector

View on GitHub
src/Factory/Concern/CreatesClassInstances.php

Summary

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

namespace DependencyInjector\Factory\Concern;

use DependencyInjector\Factory\StringArgument;
use Psr\Container\ContainerInterface;

trait CreatesClassInstances
{
    /** @var ContainerInterface */
    protected $container;

    /** @var string */
    protected $class;

    /** @var array */
    protected $arguments = [];

    /** @var array */
    protected $methodCalls = [];

    /**
     * Add constructor arguments
     *
     * Strings will be resolved from container.
     *
     * @param mixed ...$args
     * @return $this
     */
    public function addArguments(...$args)
    {
        array_push($this->arguments, ...$args);
        return $this;
    }

    /**
     * Add call to $method with $args that get executed after initialization
     *
     * @param string $method
     * @param mixed ...$args
     * @return $this
     */
    public function addMethodCall(string $method, ...$args)
    {
        array_push($this->methodCalls, [$method, $args]);
        return $this;
    }

    /**
     * Build the product of this factory.
     *
     * @noinspection PhpDocSignatureInspection
     * @param mixed $additionalArgs...
     * @return mixed
     */
    protected function build()
    {
        $args = array_map([$this, 'resolveArg'], $this->arguments);

        $instance = new $this->class(...$args, ...func_get_args());

        foreach ($this->methodCalls as $methodCall) {
            call_user_func_array([$instance, $methodCall[0]], array_map([$this, 'resolveArg'], $methodCall[1]));
        }

        return $instance;
    }

    /**
     * Resolve $arg through container
     *
     * @param $arg
     * @return mixed|string
     */
    protected function resolveArg($arg)
    {
        if (is_string($arg) && $this->container->has($arg)) {
            return $this->container->get($arg);
        } elseif ($arg instanceof StringArgument) {
            return $arg->getString();
        } else {
            return $arg;
        }
    }
}