Completed
Push — feature/EVO-7964_fundInfo-exte... ( d593d5 )
by Bastian
08:56
created

MainController::decideApiAndEndpoint()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 0
cts 10
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 1
crap 6
1
<?php
2
/**
3
 * controller for start page
4
 */
5
6
namespace Graviton\CoreBundle\Controller;
7
8
use Graviton\ProxyBundle\Service\ApiDefinitionLoader;
9
use Graviton\RestBundle\HttpFoundation\LinkHeader;
10
use Graviton\RestBundle\HttpFoundation\LinkHeaderItem;
11
use Graviton\RestBundle\Service\RestUtilsInterface;
12
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
13
use Symfony\Component\HttpFoundation\Request;
14
use Symfony\Component\HttpFoundation\Response;
15
use Symfony\Component\Routing\Router;
16
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
17
18
/**
19
 * MainController
20
 *
21
 * @author   List of contributors <https://github.com/libgraviton/graviton/graphs/contributors>
22
 * @license  http://opensource.org/licenses/gpl-license.php GNU Public License
23
 * @link     http://swisscom.ch
24
 */
25
class MainController
26
{
27
    /**
28
     * @var Router
29
     */
30
    private $router;
31
32
    /**
33
     * @var Response
34
     */
35
    private $response;
36
37
    /**
38
     * @var RestUtilsInterface
39
     */
40
    private $restUtils;
41
42
    /**
43
     * @var EngineInterface
44
     */
45
    private $templating;
46
47
    /**
48
     * @var ApiDefinitionLoader
49
     */
50
    private $apiLoader;
51
52
    /**
53
     * @var array
54
     */
55
    private $addditionalRoutes;
56
57
    /**
58
     * @var array
59
     */
60
    private $pathWhitelist;
61
62
    /**
63
     * @var array
64
     */
65
    private $proxySourceConfiguration;
66
67
    /**
68
     * @param Router              $router                   router
69
     * @param Response            $response                 prepared response
70
     * @param RestUtilsInterface  $restUtils                rest-utils from GravitonRestBundle
71
     * @param EngineInterface     $templating               templating-engine
72
     * @param ApiDefinitionLoader $apiLoader                loader for third party api definition
73
     * @param array               $additionalRoutes         custom routes
74
     * @param array               $pathWhitelist            serviec path that always get aded to the main page
75
     * @param array               $proxySourceConfiguration Set of sources to be recognized by the controller
76
     */
77
    public function __construct(
78
        Router $router,
79
        Response $response,
80
        RestUtilsInterface $restUtils,
81
        EngineInterface $templating,
82
        ApiDefinitionLoader $apiLoader,
83
        $additionalRoutes = array(),
84
        $pathWhitelist = [],
85
        array $proxySourceConfiguration = array()
86
    ) {
87
        $this->router = $router;
88
        $this->response = $response;
89
        $this->restUtils = $restUtils;
90
        $this->templating = $templating;
91
        $this->apiLoader = $apiLoader;
92
        $this->addditionalRoutes = $additionalRoutes;
93
        $this->pathWhitelist = $pathWhitelist;
94
        $this->proxySourceConfiguration = $proxySourceConfiguration;
95
    }
96
97
    /**
98
     * create simple start page.
99
     *
100
     * @return Response $response Response with result or error
101
     */
102
    public function indexAction()
103
    {
104
        $response = $this->response;
105
106
        $mainPage = new \stdClass();
107
        $mainPage->services = $this->determineServices(
108
            $this->restUtils->getOptionRoutes()
109
        );
110
111
        $mainPage->thirdparty = $this->registerThirdPartyServices();
112
113
        $response->setContent(json_encode($mainPage));
114
        $response->setStatusCode(Response::HTTP_OK);
115
        $response->headers->set('Link', $this->prepareLinkHeader());
116
117
        // todo: make sure, that the correct content type is set.
118
        // todo: this should be covered by a kernel.response event listener?
119
        $response->headers->set('Content-Type', 'application/json');
120
121
        return $this->render(
122
            'GravitonCoreBundle:Main:index.json.twig',
123
            array('response' => $response->getContent()),
124
            $response
125
        );
126
    }
127
128
    /**
129
     * Renders a view.
130
     *
131
     * @param string   $view       The view name
132
     * @param array    $parameters An array of parameters to pass to the view
133
     * @param Response $response   A response instance
0 ignored issues
show
Documentation introduced by
Should the type for parameter $response not be null|Response?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
134
     *
135
     * @return Response A Response instance
136
     */
137
    public function render($view, array $parameters = array(), Response $response = null)
138
    {
139
        return $this->templating->renderResponse($view, $parameters, $response);
140
    }
141
142
    /**
143
     * Determines what service endpoints are available.
144
     *
145
     * @param array $optionRoutes List of routing options.
146
     *
147
     * @return array
148
     */
149
    protected function determineServices(array $optionRoutes)
150
    {
151
        $sortArr = array();
152
        $router = $this->router;
153
        foreach ($this->addditionalRoutes as $route) {
154
            // hack because only array keys are used
155
            $optionRoutes[$route] = null;
156
        }
157
158
        $services = array_map(
159
            function ($routeName) use ($router) {
160
                list($app, $bundle, $rest, $document) = explode('.', $routeName);
161
                $schemaRoute = implode('.', array($app, $bundle, $rest, $document, 'canonicalSchema'));
162
163
                return array(
164
                    '$ref' => $router->generate($routeName, array(), UrlGeneratorInterface::ABSOLUTE_URL),
165
                    'profile' => $router->generate($schemaRoute, array(), UrlGeneratorInterface::ABSOLUTE_URL),
166
                );
167
            },
168
            array_keys($optionRoutes)
169
        );
170
171
        foreach ($services as $key => $val) {
172
            if ($this->isRelevantForMainPage($val) && !in_array($val['$ref'], $sortArr)) {
173
                $sortArr[$key] = $val['$ref'];
174
            } else {
175
                unset($services[$key]);
176
            }
177
        }
178
        array_multisort($sortArr, SORT_ASC, $services);
179
180
        return $services;
181
    }
182
183
    /**
184
     * Prepares the header field containing information about pagination.
185
     *
186
     * @return string
187
     */
188
    protected function prepareLinkHeader()
189
    {
190
        $links = new LinkHeader(array());
191
        $links->add(
192
            new LinkHeaderItem(
193
                $this->router->generate('graviton.core.rest.app.all', array (), UrlGeneratorInterface::ABSOLUTE_URL),
194
                array ('rel' => 'apps', 'type' => 'application/json')
195
            )
196
        );
197
198
        return (string) $links;
199
    }
200
201
    /**
202
     * tells if a service is relevant for the mainpage
203
     *
204
     * @param array $val value of service spec
205
     *
206
     * @return boolean
207
     */
208
    private function isRelevantForMainPage($val)
209
    {
210
        return (substr($val['$ref'], -1) === '/')
211
            || in_array(parse_url($val['$ref'], PHP_URL_PATH), $this->pathWhitelist);
212
    }
213
214
    /**
215
     * Resolves all third party routes and add schema info
216
     *
217
     * @param array $thirdApiRoutes list of all routes from an API
218
     *
219
     * @return array
220
     */
221
    protected function determineThirdPartyServices(array $thirdApiRoutes)
222
    {
223
        $definition = $this->apiLoader;
224
        $mainRoute = $this->router->generate(
225
            'graviton.core.static.main.all',
226
            array(),
227
            UrlGeneratorInterface::ABSOLUTE_URL
228
        );
229
        $services = array_map(
230
            function ($apiRoute) use ($mainRoute, $definition) {
231
232
                return array (
233
                    '$ref' => $mainRoute.$apiRoute,
234
                    'profile' => $mainRoute."schema/".$apiRoute."/item",
235
                );
236
            },
237
            $thirdApiRoutes
238
        );
239
240
        return $services;
241
    }
242
243
    /**
244
     * Finds configured external apis to be exposed via G2.
245
     *
246
     * @return array
247
     */
248
    private function registerThirdPartyServices()
249
    {
250
        $services = [];
251
252
        // getenv()... it's a workaround for run all tests on travis! will be removed!
253
        if (getenv('USER') !== 'travis' && getenv('HAS_JOSH_K_SEAL_OF_APPROVAL') !== true) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
254
255
            foreach (array_keys($this->proxySourceConfiguration) as $source) {
256
                foreach ($this->proxySourceConfiguration[$source] as $thirdparty => $option) {
257
                    $this->apiLoader->resetDefinitionLoader();
258
                    $this->apiLoader->setOption($option);
259
                    $this->apiLoader->addOptions($this->decideApiAndEndpoint($option));
260
                    $services[$thirdparty] = $this->determineThirdPartyServices(
261
                        $this->apiLoader->getAllEndpoints(false, true)
262
                    );
263
                }
264
            }
265
        }
266
267
        return $services;
268
    }
269
270
    /**
271
     * get API name and endpoint from the url (third party API)
272
     *
273
     * @param string $url the url
0 ignored issues
show
Bug introduced by
There is no parameter named $url. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
274
     *
275
     * @return array
276
     */
277
    protected function decideApiAndEndpoint($config)
278
    {
279
        if (array_key_exists('serviceEndpoint', $config)) {
280
            return array (
281
                "apiName" => $config['prefix'],
282
                "endpoint" => $config['serviceEndpoint'],
283
            );
284
        }
285
286
        return [];
287
    }
288
}
289