Completed
Pull Request — master (#59)
by Tobias
07:03
created

ClassDiscovery::getFromCache()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 3

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 13
ccs 3
cts 3
cp 1
rs 9.4285
cc 3
eloc 7
nc 3
nop 1
crap 3
1
<?php
2
3
namespace Http\Discovery;
4
5
use Http\Discovery\Exception\DiscoveryFailedException;
6
use Http\Discovery\Exception\StrategyUnavailableException;
7
8
/**
9
 * Registry that based find results on class existence.
10
 *
11
 * @author David de Boer <[email protected]>
12
 * @author Márk Sági-Kazár <[email protected]>
13
 * @author Tobias Nyholm <[email protected]>
14
 */
15
abstract class ClassDiscovery
16
{
17
    /**
18
     * A list of strategies to find classes.
19
     *
20
     * @var array
21
     */
22
    public static $strategies = [
23
        Strategy\Puli::class,
24
        Strategy\HttpClients::class,
25
        Strategy\GuzzleFactory::class,
26
        Strategy\DiactorosFactory::class,
27
    ];
28 10
29
    /**
30 10
     * Discovery cache to make the second time we use discovery faster.
31
     *
32
     * @var array
33
     */
34
    private static $cache = [];
35
36
    /**
37
     * Finds a class.
38
     *
39
     * @param string $type
40
     *
41
     * @return string
42
     *
43
     * @throws DiscoveryFailedException
44 10
     */
45
    protected static function findOneByType($type)
46
    {
47
        // Look in the cache
48
        if (null !== $class = self::getFromCache($type)) {
49
            return $class;
50
        }
51
52 21
        $exceptions = [];
53
        foreach (self::$strategies as $strategy) {
54 21
            try {
55
                if (is_string($strategy)) {
56
                    $candidates = call_user_func($strategy.'::getCandidates', $type);
57
                } else {
58 21
                    $candidates = $strategy->getCandidates($type);
59 21
                }
60 21
            } catch (StrategyUnavailableException $e) {
61
                $exceptions[] = $e;
62
                continue;
63
            }
64
65 21
            foreach ($candidates as $candidate) {
66
                if ($candidate['condition']) {
67 21
                    if (!self::evaluateCondition($candidate['condition'])) {
68 21
                        continue;
69 21
                    }
70
                }
71
72
                // save the result for later use
73
                self::storeInCache($type, $candidate);
74
75
                return $candidate['class'];
76 9
            }
77
        }
78 9
79 9
        throw new DiscoveryFailedException('Could not find resource using any discovery strategy', $exceptions);
80 9
    }
81
82 9
    /**
83 9
     * Get a value from cache.
84
     *
85 9
     * @param string $type
86
     *
87
     * @return string|null
88
     */
89
    private static function getFromCache($type)
90
    {
91
        if (!isset(self::$cache[$type])) {
92
            return;
93
        }
94
95
        $candidate = self::$cache[$type];
96
        if (!self::evaluateCondition($candidate['condition'])) {
97 8
            return;
98
        }
99 8
100
        return $candidate['class'];
101 8
    }
102 7
103 1
    /**
104
     * Store a value in cache.
105 1
     *
106 1
     * @param string $type
107
     * @param string $class
108
     */
109
    private static function storeInCache($type, $class)
110
    {
111 7
        self::$cache[$type] = $class;
112 1
    }
113
114 1
    /**
115
     * Evaulates conditions to boolean.
116
     *
117
     * @param mixed $condition
118
     *
119
     * @return bool
120
     */
121
    protected static function evaluateCondition($condition)
122
    {
123
        if (is_string($condition)) {
124
            // Should be extended for functions, extensions???
125
            return class_exists($condition);
126
        } elseif (is_callable($condition)) {
127
            return $condition();
128
        } elseif (is_bool($condition)) {
129
            return $condition;
130
        } elseif (is_array($condition)) {
131
            $evaluatedCondition = true;
132
133
            // Immediately stop execution if the condition is false
134 1
            for ($i = 0; $i < count($condition) && false !== $evaluatedCondition; ++$i) {
135
                $evaluatedCondition &= static::evaluateCondition($condition[$i]);
136 1
            }
137
138
            return $evaluatedCondition;
139 1
        }
140
141 1
        return false;
142 1
    }
143
}
144