2
2
3
3
namespace Http \Discovery ;
4
4
5
+ use Http \Discovery \Exception \DiscoveryFailedException ;
6
+ use Http \Discovery \Exception \StrategyUnavailableException ;
5
7
use Http \Discovery \Exception \NotFoundException ;
6
- use Http \Discovery \Exception \PuliNotAvailableException ;
7
- use Http \Discovery \FallbackStrategy \HttpClients ;
8
- use Http \Discovery \FallbackStrategy \DiactorosFactory ;
9
- use Http \Discovery \FallbackStrategy \GuzzleFactory ;
10
- use Puli \Discovery \Api \Discovery ;
8
+ use Http \Discovery \Strategy \DiactorosFactory ;
9
+ use Http \Discovery \Strategy \GuzzleFactory ;
10
+ use Http \Discovery \Strategy \HttpClients ;
11
+ use Http \Discovery \Strategy \Puli ;
11
12
12
13
/**
13
14
* Registry that based find results on class existence.
14
15
*
15
16
* @author David de Boer <[email protected] >
16
17
* @author Márk Sági-Kazár <[email protected] >
18
+ * @author Tobias Nyholm <[email protected] >
17
19
*/
18
20
abstract class ClassDiscovery
19
21
{
20
22
/**
21
- * @var GeneratedPuliFactory
22
- */
23
- private static $ puliFactory ;
24
-
25
- /**
26
- * @var Discovery
27
- */
28
- private static $ puliDiscovery ;
29
-
30
- /**
31
- * @return GeneratedPuliFactory
32
- */
33
- public static function getPuliFactory ()
34
- {
35
- if (null === self ::$ puliFactory ) {
36
- if (!defined ('PULI_FACTORY_CLASS ' )) {
37
- throw new PuliNotAvailableException ('Puli Factory is not available ' );
38
- }
39
-
40
- $ puliFactoryClass = PULI_FACTORY_CLASS ;
41
-
42
- if (!class_exists ($ puliFactoryClass )) {
43
- throw new PuliNotAvailableException ('Puli Factory class does not exist ' );
44
- }
45
-
46
- self ::$ puliFactory = new $ puliFactoryClass ();
47
- }
48
-
49
- return self ::$ puliFactory ;
50
- }
51
-
52
- /**
53
- * Sets the Puli factory.
23
+ * A list of strategies to find classes.
54
24
*
55
- * @param object $puliFactory
25
+ * @var array
56
26
*/
57
- public static function setPuliFactory ($ puliFactory )
58
- {
59
- if (!is_callable ([$ puliFactory , 'createRepository ' ]) || !is_callable ([$ puliFactory , 'createDiscovery ' ])) {
60
- throw new \InvalidArgumentException ('The Puli Factory must expose a repository and a discovery ' );
61
- }
62
-
63
- self ::$ puliFactory = $ puliFactory ;
64
- self ::$ puliDiscovery = null ;
65
- }
27
+ public static $ strategies = [
28
+ Puli::class,
29
+ HttpClients::class,
30
+ GuzzleFactory::class,
31
+ DiactorosFactory::class,
32
+ ];
66
33
67
34
/**
68
- * Resets the factory.
35
+ * Discovery cache to make the second time we use discovery faster.
36
+ * @var array
69
37
*/
70
- public static function resetPuliFactory ()
71
- {
72
- self ::$ puliFactory = null ;
73
- self ::$ puliDiscovery = null ;
74
- }
75
-
76
- /**
77
- * Returns the Puli discovery layer.
78
- *
79
- * @return Discovery
80
- */
81
- public static function getPuliDiscovery ()
82
- {
83
- if (!isset (self ::$ puliDiscovery )) {
84
- $ factory = self ::getPuliFactory ();
85
- $ repository = $ factory ->createRepository ();
86
-
87
- self ::$ puliDiscovery = $ factory ->createDiscovery ($ repository );
88
- }
89
-
90
- return self ::$ puliDiscovery ;
91
- }
38
+ private static $ cache = [];
92
39
93
40
/**
94
41
* Finds a class.
@@ -101,58 +48,62 @@ public static function getPuliDiscovery()
101
48
*/
102
49
public static function findOneByType ($ type )
103
50
{
104
- try {
105
- return self ::puliFindOneByType ($ type );
106
- } catch (PuliNotAvailableException $ e ) {
107
- if (false !== $ class = HttpClients::findOneByType ($ type )) {
108
- return $ class ;
109
- } elseif (false !== $ class = GuzzleFactory::findOneByType ($ type )) {
110
- return $ class ;
111
- } elseif (false !== $ class = DiactorosFactory::findOneByType ($ type )) {
112
- return $ class ;
51
+ $ exceptions = [];
52
+
53
+ if (null !== $ class = self ::getFromCache ($ type )) {
54
+ return $ class ;
55
+ }
56
+
57
+ foreach (self ::$ strategies as $ strategy ) {
58
+ try {
59
+ $ bindings = call_user_func ($ strategy .'::find ' , $ type );
60
+ } catch (StrategyUnavailableException $ e ) {
61
+ $ exceptions [] = $ e ;
62
+ continue ;
63
+ }
64
+
65
+ foreach ($ bindings as $ binding ) {
66
+ if ($ binding ['condition ' ]) {
67
+ if (!self ::evaluateCondition ($ binding ['condition ' ])) {
68
+ continue ;
69
+ }
70
+ }
71
+
72
+ // save the result for later use
73
+ self ::storeInCache ($ type , $ binding ['class ' ]);
74
+
75
+ return $ binding ['class ' ];
113
76
}
114
- throw new NotFoundException ('Could not find resource using Puli nor common Guzzle/Diactoros classes ' , 0 , $ e );
115
77
}
78
+
79
+ throw new DiscoveryFailedException ('Could not find resource using any discovery strategy ' , $ exceptions );
116
80
}
117
81
118
82
/**
119
- * Finds a class using Puli.
83
+ * Get a value from cache
120
84
*
121
- * @param $type
122
- *
123
- * @return string
85
+ * @param string $type
124
86
*
125
- * @throws NotFoundException
126
- * @throws PuliNotAvailableException
87
+ * @return string|null
127
88
*/
128
- private static function puliFindOneByType ($ type )
89
+ private static function getFromCache ($ type )
129
90
{
130
- $ bindings = self ::getPuliDiscovery ()->findBindings ($ type );
131
-
132
- foreach ($ bindings as $ binding ) {
133
- if ($ binding ->hasParameterValue ('depends ' )) {
134
- $ dependency = $ binding ->getParameterValue ('depends ' );
135
-
136
- if (!self ::evaluateCondition ($ dependency )) {
137
- continue ;
138
- }
139
- }
140
-
141
- // TODO: check class binding
142
- return $ binding ->getClassName ();
91
+ if (isset (self ::$ cache [$ type ])) {
92
+ return self ::$ cache [$ type ];
143
93
}
144
94
145
- throw new NotFoundException ( sprintf ( ' Resource of type "%s" not found ' , $ type )) ;
95
+ return null ;
146
96
}
147
97
148
98
/**
149
- * Finds a resource.
99
+ * Store a value in cache
150
100
*
151
- * @return object
101
+ * @param string $type
102
+ * @param string $class
152
103
*/
153
- public static function find ( )
104
+ private static function storeInCache ( $ type , $ class )
154
105
{
155
- throw new \ LogicException ( ' Not implemented ' ) ;
106
+ self :: $ cache [ $ type ] = $ class ;
156
107
}
157
108
158
109
/**
0 commit comments