Completed
Pull Request — master (#55)
by Márk
17:40 queued 07:36
created

HttplugFactory::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace Http\HttplugBundle\Util;
4
5
use Puli\Discovery\Api\Discovery;
6
use Puli\Discovery\Binding\ClassBinding;
7
use Webmozart\Expression\Expr;
8
9
/**
10
 * This class is a wrapper around Puli discovery.
11
 *
12
 * @author Márk Sági-Kazár <[email protected]>
13
 */
14
final class HttplugFactory
15
{
16
    /**
17
     * @var Discovery
18
     */
19
    private $discovery;
20
21
    /**
22
     * @param Discovery $discovery
23
     */
24
    public function __construct(Discovery $discovery)
25
    {
26
        $this->discovery = $discovery;
27
    }
28
29
    /**
30
     * Creates a class of type.
31
     *
32
     * @param string $type
33
     *
34
     * @return object
35
     */
36
    public function find($type)
37
    {
38
        $class = $this->findOneByType($type);
39
40
        // TODO: use doctrine instantiator?
41
        return new $class();
42
    }
43
44
    /**
45
     * Finds a class of type and resolves optional dependency conditions.
46
     *
47
     * @param string $type
48
     *
49
     * @return string
50
     *
51
     * @throws \RuntimeException if no class is found.
52
     */
53
    private function findOneByType($type)
54
    {
55
        /** @var ClassBinding[] $bindings */
56
        $bindings = $this->discovery->findBindings(
57
            $type,
58
            Expr::isInstanceOf('Puli\Discovery\Binding\ClassBinding')
59
        );
60
61
        foreach ($bindings as $binding) {
62
            if ($binding->hasParameterValue('depends')) {
63
                $dependency = $binding->getParameterValue('depends');
64
65
                if (false === $this->evaluateCondition($dependency)) {
66
                    continue;
67
                }
68
            }
69
70
            return $binding->getClassName();
71
        }
72
73
        throw new \RuntimeException(sprintf('Class binding of type "%s" is not found', $type));
74
    }
75
76
    /**
77
     * Evaulates conditions to boolean.
78
     *
79
     * @param mixed $condition
80
     *
81
     * @return bool
82
     *
83
     * TODO: review this method
84
     */
85
    protected function evaluateCondition($condition)
86
    {
87
        if (is_string($condition)) {
88
            // Should be extended for functions, extensions???
89
            return class_exists($condition);
90
        } elseif (is_callable($condition)) {
91
            return $condition();
92
        } elseif (is_bool($condition)) {
93
            return $condition;
94
        } elseif (is_array($condition)) {
95
            $evaluatedCondition = true;
96
97
            // Immediately stop execution if the condition is false
98
            for ($i = 0; $i < count($condition) && false !== $evaluatedCondition; ++$i) {
99
                $evaluatedCondition &= $this->evaluateCondition($condition[$i]);
100
            }
101
102
            return $evaluatedCondition;
103
        }
104
105
        return false;
106
    }
107
}
108