Completed
Pull Request — master (#59)
by Tobias
10:02
created

ClassDiscovery::getFromCache()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 3

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 13
ccs 2
cts 2
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
                $candidates = call_user_func($strategy.'::getCandidates', $type);
56
            } catch (StrategyUnavailableException $e) {
57
                $exceptions[] = $e;
58 21
                continue;
59 21
            }
60 21
61
            foreach ($candidates as $candidate) {
62
                if ($candidate['condition']) {
63
                    if (!self::evaluateCondition($candidate['condition'])) {
64
                        continue;
65 21
                    }
66
                }
67 21
68 21
                // save the result for later use
69 21
                self::storeInCache($type, $candidate);
70
71
                return $candidate['class'];
72
            }
73
        }
74
75
        throw new DiscoveryFailedException('Could not find resource using any discovery strategy', $exceptions);
76 9
    }
77
78 9
    /**
79 9
     * Get a value from cache.
80 9
     *
81
     * @param string $type
82 9
     *
83 9
     * @return string|null
84
     */
85 9
    private static function getFromCache($type)
86
    {
87
        if (!isset(self::$cache[$type])) {
88
            return;
89
        }
90
91
        $candidate = self::$cache[$type];
92
        if (!self::evaluateCondition($candidate['condition'])) {
93
            return;
94
        }
95
96
        return $candidate['class'];
97 8
    }
98
99 8
    /**
100
     * Store a value in cache.
101 8
     *
102 7
     * @param string $type
103 1
     * @param string $class
104
     */
105 1
    private static function storeInCache($type, $class)
106 1
    {
107
        self::$cache[$type] = $class;
108
    }
109
110
    /**
111 7
     * Evaulates conditions to boolean.
112 1
     *
113
     * @param mixed $condition
114 1
     *
115
     * @return bool
116
     */
117
    protected static function evaluateCondition($condition)
118
    {
119
        if (is_string($condition)) {
120
            // Should be extended for functions, extensions???
121
            return class_exists($condition);
122
        } elseif (is_callable($condition)) {
123
            return $condition();
124
        } elseif (is_bool($condition)) {
125
            return $condition;
126
        } elseif (is_array($condition)) {
127
            $evaluatedCondition = true;
128
129
            // Immediately stop execution if the condition is false
130
            for ($i = 0; $i < count($condition) && false !== $evaluatedCondition; ++$i) {
131
                $evaluatedCondition &= static::evaluateCondition($condition[$i]);
132
            }
133
134 1
            return $evaluatedCondition;
135
        }
136 1
137
        return false;
138
    }
139
}
140