Completed
Pull Request — master (#59)
by Tobias
08:55
created

ClassDiscovery::storeInCache()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1.037

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 2
cts 3
cp 0.6667
rs 10
cc 1
eloc 2
nc 1
nop 2
crap 1.037
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 (isset($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
     * Clear the cache.
112 1
     */
113
    public static function clearCache()
114 1
    {
115
        self::$cache = [];
116
    }
117
118
    /**
119
     * Evaulates conditions to boolean.
120
     *
121
     * @param mixed $condition
122
     *
123
     * @return bool
124
     */
125
    protected static function evaluateCondition($condition)
126
    {
127
        if (is_string($condition)) {
128
            // Should be extended for functions, extensions???
129
            return class_exists($condition);
130
        } elseif (is_callable($condition)) {
131
            return $condition();
132
        } elseif (is_bool($condition)) {
133
            return $condition;
134 1
        } elseif (is_array($condition)) {
135
            $evaluatedCondition = true;
136 1
137
            // Immediately stop execution if the condition is false
138
            for ($i = 0; $i < count($condition) && false !== $evaluatedCondition; ++$i) {
139 1
                $evaluatedCondition &= static::evaluateCondition($condition[$i]);
140
            }
141 1
142 1
            return $evaluatedCondition;
143
        }
144
145
        return false;
146
    }
147
}
148