1
+ <?php
2
+
3
+ namespace Saritasa \Laravel \Controllers \Api ;
4
+
5
+ use Saritasa \Exceptions \ConfigurationException ;
6
+ use Dingo \Api \Routing \Router ;
7
+
8
+ /**
9
+ * Wrapper for Dingo router, adds concise methods for API URLs registration.
10
+ * @method void get(string $resource, string $controller, string $action = null, string $route = null) Add POST route
11
+ * @method void post(string $resource, string $controller, string $action = null, string $route = null) Add POST route
12
+ * @method void patch(string $resource, string $controller, string $action = null, string $route = null) Add POST route
13
+ * @method void put(string $resource, string $controller, string $action = null, string $route = null) Add POST route
14
+ * @method void delete(string $resource, string $controller, string $action = null, string $route = null) Add POST route
15
+ */
16
+ class ApiResourceRegistrar
17
+ {
18
+ /**
19
+ * @var Router
20
+ */
21
+ private $ api ;
22
+
23
+ private $ default = [
24
+ 'index ' => ['verb ' => 'get ' , 'route ' => '' ],
25
+ 'create ' => ['verb ' => 'post ' , 'route ' => '' ],
26
+ 'show ' => ['verb ' => 'get ' , 'route ' => '/{id} ' ],
27
+ 'update ' => ['verb ' => 'put ' , 'route ' => '/{id} ' ],
28
+ 'destroy ' => ['verb ' => 'delete ' , 'route ' => '/{id} ' ]
29
+ ];
30
+
31
+ const VERBS = ['get ' , 'post ' , 'put ' , 'patch ' , 'delete ' ];
32
+
33
+ public function __construct (Router $ api )
34
+ {
35
+ $ this ->api = $ api ;
36
+ }
37
+
38
+ /**
39
+ * Registers controller methods
40
+ *
41
+ * index - as GET /resourceName
42
+ * create - as POST /resourceName
43
+ * show - as GET /resourceName/{id}
44
+ * update - as PUT /resourceName/{id}
45
+ * destroy - as DELETE /resourceName/{id}
46
+ *
47
+ * @param string $resourceName
48
+ * @param string $controller
49
+ * @param array $options
50
+ */
51
+ public function resource (string $ resourceName , string $ controller , array $ options = [])
52
+ {
53
+ $ routes = [];
54
+ if (!$ options || !count ($ options )) {
55
+ $ routes = $ this ->default ;
56
+ } else if (isset ($ options ['only ' ])) {
57
+ $ routes = array_intersect_key ($ this ->default , $ this ->asArray ($ options ['only ' ]));
58
+ } else if (isset ($ options ['except ' ])) {
59
+ $ routes = array_diff_key ($ this ->default , $ this ->asArray ($ options ['except ' ]));
60
+ }
61
+
62
+ foreach (static ::VERBS as $ verb ) {
63
+ if (isset ($ options [$ verb ])) {
64
+ $ actions = $ this ->asArray ($ options [$ verb ]);
65
+ if (!is_array ($ actions )) {
66
+ $ t = gettype ($ actions );
67
+ throw new \InvalidArgumentException ("\$options[' $ verb'] must contain string or array. $ t was given " );
68
+ }
69
+
70
+ foreach ($ actions as $ action => $ i ) {
71
+ $ routes [$ action ] = ['verb ' => $ verb , 'route ' => '/ ' .$ action ];
72
+ }
73
+ }
74
+ }
75
+
76
+ foreach ($ routes as $ action => $ opt ) {
77
+ $ verb = $ opt ['verb ' ];
78
+ $ this ->api ->$ verb ($ resourceName .$ opt ['route ' ], [
79
+ 'as ' => $ resourceName .'. ' .$ action ,
80
+ 'uses ' => $ controller .'@ ' .$ action
81
+ ]);
82
+ }
83
+ }
84
+
85
+ public function __call ($ name , $ arguments )
86
+ {
87
+ if (in_array ($ name , static ::VERBS )) {
88
+ array_splice ($ arguments , 0 , 0 , [$ name ]);
89
+ return call_user_func_array ([$ this , 'action ' ], $ arguments );
90
+ }
91
+ throw new ConfigurationException ("Unknown HTTP verb $ name used for route $ arguments [0 ]" );
92
+ }
93
+
94
+ /**
95
+ * @param string $verb - one of GET / POST / PUT / DELETE
96
+ * @param string $path - URL path
97
+ * @param string $controller Class, containing action method
98
+ * @param string|null $action method, which will be executed on route hit
99
+ * @param string|null $route - route name
100
+ * @return mixed
101
+ */
102
+ private function action (string $ verb , string $ path , string $ controller , string $ action = null , string $ route = null )
103
+ {
104
+ $ pos = strrpos ($ path , '/ ' , -1 );
105
+ $ pathLastSegment = $ pos ? substr ($ path , $ pos +1 ) : $ path ;
106
+
107
+ if (!$ action ) {
108
+ $ action = $ pathLastSegment ;
109
+ }
110
+ if (!$ route ) {
111
+ $ route = strtolower (str_replace ('/ ' , '. ' , $ path ));
112
+ // Small piece of magic: make auto-named routes look nicer
113
+ if ($ pathLastSegment != $ action ) {
114
+ if (strrpos ($ route , '. ' .$ pathLastSegment , -1 ) === false ) {
115
+ $ route = "$ route. $ action " ;
116
+ } else {
117
+ $ route = str_replace ('. ' . $ pathLastSegment , '. ' . $ action , $ route );
118
+ }
119
+ }
120
+ $ route = strtolower ($ route );
121
+ }
122
+ return $ this ->api ->$ verb ($ path ?: $ action , ['uses ' => $ controller .'@ ' .$ action , 'as ' => $ route ]);
123
+ }
124
+
125
+ private function asArray ($ value ): array
126
+ {
127
+ if (is_array ($ value )) {
128
+ return $ value ;
129
+ }
130
+ if (is_string ($ value )) {
131
+ $ keys = explode (', ' , $ value );
132
+ return array_flip ($ keys );
133
+ }
134
+ return null ;
135
+ }
136
+ }
0 commit comments