33
44namespace AdvancedJsonRpc ;
55
6+ use AdvancedJsonRpc \Reflection \NativeReflection ;
67use JsonMapper ;
78use JsonMapper_Exception ;
8- use phpDocumentor \Reflection \DocBlockFactory ;
9- use phpDocumentor \Reflection \Types ;
10- use ReflectionException ;
11- use ReflectionMethod ;
12- use ReflectionNamedType ;
139
1410class Dispatcher
1511{
@@ -24,21 +20,14 @@ class Dispatcher
2420 private $ delimiter ;
2521
2622 /**
27- * method => ReflectionMethod[]
28- *
29- * @var ReflectionMethod
30- */
31- private $ methods ;
32-
33- /**
34- * @var \phpDocumentor\Reflection\DocBlockFactory
23+ * @var Reflection\NativeReflection
3524 */
36- private $ docBlockFactory ;
25+ private $ reflection ;
3726
3827 /**
39- * @var \phpDocumentor\Reflection\Types\ContextFactory
28+ * @var JsonMapper
4029 */
41- private $ contextFactory ;
30+ private $ mapper ;
4231
4332 /**
4433 * @param object $target The target object that should receive the method calls
@@ -48,9 +37,8 @@ public function __construct($target, $delimiter = '->')
4837 {
4938 $ this ->target = $ target ;
5039 $ this ->delimiter = $ delimiter ;
51- $ this ->docBlockFactory = DocBlockFactory::createInstance ();
52- $ this ->contextFactory = new Types \ContextFactory ();
5340 $ this ->mapper = new JsonMapper ();
41+ $ this ->reflection = new NativeReflection ();
5442 }
5543
5644 /**
@@ -81,33 +69,19 @@ public function dispatch($msg)
8169 }
8270 $ obj = $ obj ->$ part ;
8371 }
84- if (!isset ($ this ->methods [$ msg ->method ])) {
85- try {
86- $ method = new ReflectionMethod ($ obj , $ fn );
87- $ this ->methods [$ msg ->method ] = $ method ;
88- } catch (ReflectionException $ e ) {
89- throw new Error ($ e ->getMessage (), ErrorCode::METHOD_NOT_FOUND , null , $ e );
90- }
91- }
92- $ method = $ this ->methods [$ msg ->method ];
93- $ parameters = $ method ->getParameters ();
94- if ($ method ->getDocComment ()) {
95- $ docBlock = $ this ->docBlockFactory ->create (
96- $ method ->getDocComment (),
97- $ this ->contextFactory ->createFromReflector ($ method ->getDeclaringClass ())
98- );
99- $ paramTags = $ docBlock ->getTagsByName ('param ' );
100- }
72+
73+ $ method = $ this ->reflection ->getMethodDetails ($ msg ->method , $ obj , $ fn );
74+
10175 $ args = [];
10276 if (isset ($ msg ->params )) {
10377 // Find out the position
10478 if (is_array ($ msg ->params )) {
10579 $ args = $ msg ->params ;
10680 } else if (is_object ($ msg ->params )) {
107- foreach ($ parameters as $ pos => $ parameter ) {
81+ foreach ($ method -> getParameters () as $ pos => $ parameter ) {
10882 $ value = null ;
10983 foreach (get_object_vars ($ msg ->params ) as $ key => $ val ) {
110- if ($ parameter ->name === $ key ) {
84+ if ($ parameter ->getName () === $ key ) {
11185 $ value = $ val ;
11286 break ;
11387 }
@@ -117,46 +91,25 @@ public function dispatch($msg)
11791 } else {
11892 throw new Error ('Params must be structured or omitted ' , ErrorCode::INVALID_REQUEST );
11993 }
94+
12095 foreach ($ args as $ position => $ value ) {
12196 try {
12297 // If the type is structured (array or object), map it with JsonMapper
12398 if (is_object ($ value )) {
12499 // Does the parameter have a type hint?
125- $ param = $ parameters [$ position ];
100+ $ param = $ method -> getParameters () [$ position ];
126101 if ($ param ->hasType ()) {
127- $ paramType = $ param ->getType ();
128- if ($ paramType instanceof ReflectionNamedType) {
129- // We have object data to map and want the class name.
130- // This should not include the `?` if the type was nullable.
131- $ class = $ paramType ->getName ();
132- } else {
133- // Fallback for php 7.0, which is still supported (and doesn't have nullable).
134- $ class = (string )$ paramType ;
135- }
102+ $ class = $ param ->getType ()->getName ();
136103 $ value = $ this ->mapper ->map ($ value , new $ class ());
137104 }
138- } else if (is_array ($ value ) && isset ($ docBlock )) {
139- // Get the array type from the DocBlock
140- $ type = $ paramTags [$ position ]->getType ();
141- // For union types, use the first one that is a class array (often it is SomeClass[]|null)
142- if ($ type instanceof Types \Compound) {
143- for ($ i = 0 ; $ t = $ type ->get ($ i ); $ i ++) {
144- if (
145- $ t instanceof Types \Array_
146- && $ t ->getValueType () instanceof Types \Object_
147- && (string )$ t ->getValueType () !== 'object '
148- ) {
149- $ class = (string )$ t ->getValueType ()->getFqsen ();
150- $ value = $ this ->mapper ->mapArray ($ value , [], $ class );
151- break ;
152- }
153- }
154- } else if ($ type instanceof Types \Array_) {
155- $ class = (string )$ type ->getValueType ()->getFqsen ();
156- $ value = $ this ->mapper ->mapArray ($ value , [], $ class );
157- } else {
105+ } else if (is_array ($ value ) && $ method ->getDocComment () !== '' ) {
106+ if (!array_key_exists ($ position , $ method ->getParamTags ())) {
158107 throw new Error ('Type is not matching @param tag ' , ErrorCode::INVALID_PARAMS );
159108 }
109+
110+ // Get the array type from the DocBlock
111+ $ class = $ method ->getParamTags ()[$ position ]->getType ()->getName ();
112+ $ value = $ this ->mapper ->mapArray ($ value , [], $ class );
160113 }
161114 } catch (JsonMapper_Exception $ e ) {
162115 throw new Error ($ e ->getMessage (), ErrorCode::INVALID_PARAMS , null , $ e );
0 commit comments