1 | <?php |
||
26 | class MainController |
||
27 | { |
||
28 | /** |
||
29 | * @var Router |
||
30 | */ |
||
31 | private $router; |
||
32 | |||
33 | /** |
||
34 | * @var Response |
||
35 | */ |
||
36 | private $response; |
||
37 | |||
38 | /** |
||
39 | * @var RestUtilsInterface |
||
40 | */ |
||
41 | private $restUtils; |
||
42 | |||
43 | /** |
||
44 | * @var EventDispatcherInterface |
||
45 | */ |
||
46 | private $eventDispatcher; |
||
47 | |||
48 | /** |
||
49 | * @var ApiDefinitionLoader |
||
50 | */ |
||
51 | private $apiLoader; |
||
52 | |||
53 | /** |
||
54 | * @var array |
||
55 | */ |
||
56 | private $addditionalRoutes; |
||
57 | |||
58 | /** |
||
59 | * @var array |
||
60 | */ |
||
61 | private $pathWhitelist; |
||
62 | |||
63 | /** |
||
64 | * @var array |
||
65 | */ |
||
66 | private $proxySourceConfiguration; |
||
67 | |||
68 | /** |
||
69 | * @param Router $router router |
||
70 | * @param Response $response prepared response |
||
71 | * @param RestUtilsInterface $restUtils rest-utils from GravitonRestBundle |
||
72 | * @param EventDispatcherInterface $eventDispatcher event dispatcher |
||
73 | * @param ApiDefinitionLoader $apiLoader loader for third party api definition |
||
74 | * @param array $additionalRoutes custom routes |
||
75 | * @param array $pathWhitelist serviec path that always get aded to the main page |
||
76 | * @param array $proxySourceConfiguration Set of sources to be recognized by the controller |
||
77 | */ |
||
78 | public function __construct( |
||
79 | Router $router, |
||
80 | Response $response, |
||
81 | RestUtilsInterface $restUtils, |
||
82 | EventDispatcherInterface $eventDispatcher, |
||
83 | ApiDefinitionLoader $apiLoader, |
||
84 | $additionalRoutes = [], |
||
85 | $pathWhitelist = [], |
||
86 | array $proxySourceConfiguration = [] |
||
87 | ) { |
||
88 | $this->router = $router; |
||
89 | $this->response = $response; |
||
90 | $this->restUtils = $restUtils; |
||
91 | $this->eventDispatcher = $eventDispatcher; |
||
92 | $this->apiLoader = $apiLoader; |
||
93 | $this->addditionalRoutes = $additionalRoutes; |
||
94 | $this->pathWhitelist = $pathWhitelist; |
||
95 | $this->proxySourceConfiguration = $proxySourceConfiguration; |
||
96 | } |
||
97 | |||
98 | /** |
||
99 | * create simple start page. |
||
100 | * |
||
101 | * @return Response $response Response with result or error |
||
102 | */ |
||
103 | public function indexAction() |
||
104 | { |
||
105 | $response = $this->response; |
||
106 | |||
107 | $mainPage = new \stdClass(); |
||
108 | $mainPage->services = $this->determineServices( |
||
109 | $this->restUtils->getOptionRoutes() |
||
110 | ); |
||
111 | |||
112 | $mainPage->thirdparty = $this->registerThirdPartyServices(); |
||
113 | |||
114 | $response->setContent(json_encode($mainPage)); |
||
115 | $response->setStatusCode(Response::HTTP_OK); |
||
116 | $response->headers->set('Link', $this->prepareLinkHeader()); |
||
117 | |||
118 | // todo: make sure, that the correct content type is set. |
||
119 | // todo: this should be covered by a kernel.response event listener? |
||
120 | $response->headers->set('Content-Type', 'application/json'); |
||
121 | |||
122 | return $response; |
||
123 | } |
||
124 | |||
125 | /** |
||
126 | * Determines what service endpoints are available. |
||
127 | * |
||
128 | * @param array $optionRoutes List of routing options. |
||
129 | * |
||
130 | * @return array |
||
131 | */ |
||
132 | protected function determineServices(array $optionRoutes) |
||
133 | { |
||
134 | $router = $this->router; |
||
135 | foreach ($this->addditionalRoutes as $route) { |
||
136 | $optionRoutes[$route] = null; |
||
137 | } |
||
138 | |||
139 | $services = array_map( |
||
140 | function ($routeName) use ($router) { |
||
141 | $routeParts = explode('.', $routeName); |
||
142 | if (count($routeParts) > 3) { |
||
143 | list($app, $bundle, $rest, $document) = $routeParts; |
||
144 | |||
145 | $schemaRoute = implode('.', [$app, $bundle, $rest, $document, 'canonicalSchema']); |
||
146 | |||
147 | return [ |
||
148 | '$ref' => $router->generate($routeName, [], UrlGeneratorInterface::ABSOLUTE_URL), |
||
149 | 'profile' => $router->generate($schemaRoute, [], UrlGeneratorInterface::ABSOLUTE_URL), |
||
150 | ]; |
||
151 | } |
||
152 | }, |
||
153 | array_keys($optionRoutes) |
||
154 | ); |
||
155 | |||
156 | $sortArr = []; |
||
157 | foreach ($services as $key => $val) { |
||
158 | if ($this->isRelevantForMainPage($val) && !in_array($val['$ref'], $sortArr)) { |
||
159 | $sortArr[$key] = $val['$ref']; |
||
160 | } else { |
||
161 | unset($services[$key]); |
||
162 | } |
||
163 | } |
||
164 | |||
165 | // get additional routes |
||
166 | $additionalRoutes = $this->getAdditionalRoutes($sortArr); |
||
167 | |||
168 | $services = array_merge($services, $additionalRoutes); |
||
169 | |||
170 | array_multisort($sortArr, SORT_ASC, $services); |
||
171 | return $services; |
||
172 | } |
||
173 | |||
174 | /** |
||
175 | * gets the additional routes that can be injected by listeners/subscribers |
||
176 | * |
||
177 | * @param array $sortArr array needed for sorting |
||
178 | * |
||
179 | * @return array additional routes |
||
180 | */ |
||
181 | private function getAdditionalRoutes(array &$sortArr) |
||
182 | { |
||
183 | $additionalRoutes = []; |
||
184 | $event = new HomepageRenderEvent(); |
||
185 | $routes = $this->eventDispatcher->dispatch(HomepageRenderEvent::EVENT_NAME, $event)->getRoutes(); |
||
|
|||
186 | |||
187 | if (!empty($routes)) { |
||
188 | $baseRoute = $this->router->match("/"); |
||
189 | $baseUrl = $this->router->generate($baseRoute['_route'], [], UrlGeneratorInterface::ABSOLUTE_URL); |
||
190 | foreach ($routes as $route) { |
||
191 | $thisUrl = $baseUrl.$route['$ref']; |
||
192 | $additionalRoutes[] = [ |
||
193 | '$ref' => $thisUrl, |
||
194 | 'profile' => $baseUrl.$route['profile'] |
||
195 | ]; |
||
196 | $sortArr[$thisUrl] = $thisUrl; |
||
197 | } |
||
198 | } |
||
199 | |||
200 | return $additionalRoutes; |
||
201 | } |
||
202 | |||
203 | /** |
||
204 | * Prepares the header field containing information about pagination. |
||
205 | * |
||
206 | * @return string |
||
207 | */ |
||
208 | protected function prepareLinkHeader() |
||
220 | |||
221 | /** |
||
222 | * tells if a service is relevant for the mainpage |
||
223 | * |
||
224 | * @param array $val value of service spec |
||
225 | * |
||
226 | * @return boolean |
||
227 | */ |
||
228 | private function isRelevantForMainPage($val) |
||
233 | |||
234 | /** |
||
235 | * Resolves all third party routes and add schema info |
||
236 | * |
||
237 | * @param array $thirdApiRoutes list of all routes from an API |
||
238 | * |
||
239 | * @return array |
||
240 | */ |
||
241 | protected function determineThirdPartyServices(array $thirdApiRoutes) |
||
262 | |||
263 | /** |
||
264 | * Finds configured external apis to be exposed via G2. |
||
265 | * |
||
266 | * @return array |
||
267 | */ |
||
268 | private function registerThirdPartyServices() |
||
288 | |||
289 | /** |
||
290 | * get API name and endpoint from the url (third party API) |
||
291 | * |
||
292 | * @param array $config Configuration information ['prefix', 'serviceEndpoint'] |
||
293 | * |
||
294 | * @return array |
||
295 | */ |
||
296 | protected function decideApiAndEndpoint(array $config) |
||
307 | |||
308 | /** |
||
309 | * Return OPTIONS results. |
||
310 | * |
||
311 | * @param Request $request Current http request |
||
312 | * |
||
313 | * @return Response $response Result of the action |
||
314 | */ |
||
315 | public function optionsAction(Request $request) |
||
323 | } |
||
324 |
Let’s take a look at an example:
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.
Available Fixes
Change the type-hint for the parameter:
Add an additional type-check:
Add the method to the parent class: