@@ -39,24 +39,34 @@ public function __construct($instance, $method, $source) {
3939 $ this ->method = $ method instanceof Method ? $ method : Reflection::type ($ instance )->method ($ method );
4040 foreach ($ this ->method ->parameters () as $ param ) {
4141
42- // Source explicitely set by annotation
42+ // Check for source being explicitely set by annotation
43+ $ accessor = null ;
44+ $ conversions = [];
4345 foreach ($ param ->annotations () as $ annotation ) {
44- if ($ accessor = self ::$ SOURCES [$ annotation ->name ()] ?? null ) {
45- $ this ->param ($ param , $ annotation ->argument (0 ) ?? $ param ->name (), $ accessor );
46- continue 2 ;
46+ if (null === $ accessor && $ accessor = self ::$ SOURCES [$ annotation ->name ()] ?? null ) {
47+ $ name = $ annotation ->argument (0 ) ?? $ param ->name ();
48+ } else if ($ annotation ->is (Conversion::class)) {
49+ $ conversions []= $ annotation ->newInstance ();
4750 }
4851 }
4952
50- // Source derived from parameter type
51- $ type = $ param ->constraint ()->type ();
52- if (Type::$ VAR === $ type ) {
53- // NOOP
54- } else if ($ type ->isAssignableFrom (InputStream::class)) {
55- $ source = 'stream ' ;
56- } else if ($ type ->isAssignableFrom (Request::class)) {
57- $ source = 'request ' ;
53+ // Otherwise try to derive source from parameter type, falling
54+ // back to the one supplied via constructor parameter.
55+ if (null === $ accessor ) {
56+ $ name = $ param ->name ();
57+ $ type = $ param ->constraint ()->type ();
58+ if (Type::$ VAR === $ type ) {
59+ goto supplied;
60+ } else if ($ type ->isAssignableFrom (InputStream::class)) {
61+ $ accessor = self ::$ SOURCES ['stream ' ];
62+ } else if ($ type ->isAssignableFrom (Request::class)) {
63+ $ accessor = self ::$ SOURCES ['request ' ];
64+ } else {
65+ supplied: $ accessor = self ::$ SOURCES [$ source ];
66+ }
5867 }
59- $ this ->param ($ param , $ param ->name (), self ::$ SOURCES [$ source ]);
68+
69+ $ this ->param ($ param , $ name , $ accessor , $ conversions );
6070 }
6171 }
6272
@@ -66,10 +76,11 @@ public function __construct($instance, $method, $source) {
6676 * @param lang.reflection.Parameter $param
6777 * @param string $name
6878 * @param function(web.Request, web.rest.format.EntityFormat, string): var $accessor
79+ * @param web.rest.Conversion[] $conversions
6980 * @return void
7081 * @throws lang.IllegalArgumentException
7182 */
72- private function param ($ param , $ name , $ accessor ) {
83+ private function param ($ param , $ name , $ accessor, $ conversions = [] ) {
7384 if ($ param ->optional ()) {
7485 $ default = $ param ->default ();
7586 $ read = function ($ req , $ format ) use ($ accessor , $ name , $ default ) {
@@ -83,7 +94,7 @@ private function param($param, $name, $accessor) {
8394 return $ value ;
8495 };
8596 }
86- $ this ->params [$ name ]= ['type ' => $ param ->constraint ()->type (), 'read ' => $ read ];
97+ $ this ->params [$ name ]= ['type ' => $ param ->constraint ()->type (), 'read ' => $ read, ' conv ' => $ conversions ];
8798 }
8899
89100 /** @return string */
0 commit comments