Completed
Push — feature/bigfix_proxy_httploade... ( 5efe01 )
by Bastian
43:53 queued 29:53
created

MainController   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 244
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 80.82%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 16
lcom 1
cbo 8
dl 0
loc 244
ccs 59
cts 73
cp 0.8082
rs 10
c 1
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 19 1
A render() 0 4 1
A isRelevantForMainPage() 0 5 2
A determineThirdPartyServices() 0 21 1
B indexAction() 0 26 1
B determineServices() 0 34 4
A prepareLinkHeader() 0 12 1
B registerThirdPartyServices() 0 18 5
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
17
/**
18
 * MainController
19
 *
20
 * @author   List of contributors <https://github.com/libgraviton/graviton/graphs/contributors>
21
 * @license  http://opensource.org/licenses/gpl-license.php GNU Public License
22
 * @link     http://swisscom.ch
23
 */
24
class MainController
25
{
26
    /**
27
     * @var Router
28
     */
29
    private $router;
30
31
    /**
32
     * @var Response
33
     */
34
    private $response;
35
36
    /**
37
     * @var RestUtilsInterface
38
     */
39
    private $restUtils;
40
41
    /**
42
     * @var EngineInterface
43
     */
44
    private $templating;
45
46
    /**
47
     * @var ApiDefinitionLoader
48
     */
49
    private $apiLoader;
50
    
51
    /**
52
     * @var array
53
     */
54
    private $addditionalRoutes;
55
56
    /**
57
     * @var array
58
     */
59
    private $pathWhitelist;
60
61
    /**
62
     * @var array
63
     */
64
    private $proxySourceConfiguration;
65
66
    /**
67
     * @param Router              $router                   router
68
     * @param Response            $response                 prepared response
69
     * @param RestUtilsInterface  $restUtils                rest-utils from GravitonRestBundle
70
     * @param EngineInterface     $templating               templating-engine
71
     * @param ApiDefinitionLoader $apiLoader                loader for third party api definition
72
     * @param array               $additionalRoutes         custom routes
73
     * @param array               $pathWhitelist            serviec path that always get aded to the main page
74
     * @param array               $proxySourceConfiguration Set of sources to be recognized by the controller
75
     */
76 7
    public function __construct(
77
        Router $router,
78
        Response $response,
79
        RestUtilsInterface $restUtils,
80
        EngineInterface $templating,
81
        ApiDefinitionLoader $apiLoader,
82
        $additionalRoutes = array(),
83
        $pathWhitelist = [],
84
        array $proxySourceConfiguration = array()
85
    ) {
86 7
        $this->router = $router;
87 7
        $this->response = $response;
88 7
        $this->restUtils = $restUtils;
89 7
        $this->templating = $templating;
90 7
        $this->apiLoader = $apiLoader;
91 7
        $this->addditionalRoutes = $additionalRoutes;
92 7
        $this->pathWhitelist = $pathWhitelist;
93 7
        $this->proxySourceConfiguration = $proxySourceConfiguration;
94 7
    }
95
96
    /**
97
     * create simple start page.
98
     *
99
     * @return Response $response Response with result or error
100
     */
101 4
    public function indexAction()
102
    {
103 4
        $response = $this->response;
104
105 4
        $mainPage = new \stdClass();
106 4
        $mainPage->message = 'Please look at the Link headers of this response for further information.';
107 4
        $mainPage->services = $this->determineServices(
108 4
            $this->restUtils->getOptionRoutes()
109
        );
110
111 4
        $mainPage->thirdparty = $this->registerThirdPartyServices();
112
113 4
        $response->setContent(json_encode($mainPage));
114 4
        $response->setStatusCode(Response::HTTP_OK);
115 4
        $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 4
        $response->headers->set('Content-Type', 'application/json');
120
121 4
        return $this->render(
122 4
            'GravitonCoreBundle:Main:index.json.twig',
123 4
            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 4
    public function render($view, array $parameters = array(), Response $response = null)
138
    {
139 4
        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 5
    protected function determineServices(array $optionRoutes)
150
    {
151 5
        $sortArr = array();
152 5
        $router = $this->router;
153 5
        foreach ($this->addditionalRoutes as $route) {
154
            // hack because only array keys are used
155 4
            $optionRoutes[$route] = null;
156
        }
157
158 5
        $services = array_map(
159
            function ($routeName) use ($router) {
160 5
                list($app, $bundle, $rest, $document) = explode('.', $routeName);
161 5
                $schemaRoute = implode('.', array($app, $bundle, $rest, $document, 'canonicalSchema'));
162
163
                return array(
164 5
                    '$ref' => $router->generate($routeName, array(), true),
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
165 5
                    'profile' => $router->generate($schemaRoute, array(), true),
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
166
                );
167 5
            },
168
            array_keys($optionRoutes)
169
        );
170
171 5
        foreach ($services as $key => $val) {
172 5
            if ($this->isRelevantForMainPage($val)) {
173 5
                $sortArr[$key] = $val['$ref'];
174
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
175
            } else {
176 5
                unset($services[$key]);
177
            }
178
        }
179 5
        array_multisort($sortArr, SORT_ASC, $services);
180
181 5
        return $services;
182
    }
183
184
    /**
185
     * Prepares the header field containing information about pagination.
186
     *
187
     * @return string
188
     */
189 5
    protected function prepareLinkHeader()
190
    {
191 5
        $links = new LinkHeader(array());
192 5
        $links->add(
193 5
            new LinkHeaderItem(
194 5
                $this->router->generate('graviton.core.rest.app.all', array (), true),
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
195 5
                array ('rel' => 'apps', 'type' => 'application/json')
196
            )
197
        );
198
199 5
        return (string) $links;
200
    }
201
202
    /**
203
     * tells if a service is relevant for the mainpage
204
     *
205
     * @param array $val value of service spec
206
     *
207
     * @return boolean
208
     */
209 5
    private function isRelevantForMainPage($val)
210
    {
211 5
        return (substr($val['$ref'], -1) === '/')
212 5
            || in_array(parse_url($val['$ref'], PHP_URL_PATH), $this->pathWhitelist);
213
    }
214
215
    /**
216
     * Resolves all third party routes and add schema info
217
     *
218
     * @param array $thirdApiRoutes list of all routes from an API
219
     *
220
     * @return array
221
     */
222
    protected function determineThirdPartyServices(array $thirdApiRoutes)
223
    {
224
        $definition = $this->apiLoader;
225
        $mainRoute = $this->router->generate(
226
            'graviton.core.static.main.all',
227
            array(),
228
            true
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
229
        );
230
        $services = array_map(
231
            function ($apiRoute) use ($mainRoute, $definition) {
232
233
                return array (
234
                    '$ref' => $mainRoute.$apiRoute,
235
                    'profile' => $mainRoute."schema/".$apiRoute."/item",
236
                );
237
            },
238
            $thirdApiRoutes
239
        );
240
241
        return $services;
242
    }
243
244
    /**
245
     * Finds configured external apis to be exposed via G2.
246
     *
247
     * @return array
248
     */
249 4
    private function registerThirdPartyServices()
250
    {
251 4
        $services = [];
252
        // getenv()... it's a workaround for run all tests on travis! will be removed!
253 4
        if (array_key_exists('swagger', $this->proxySourceConfiguration)
254 4
            && getenv('USER') !== 'travis'
255 4
            && getenv('HAS_JOSH_K_SEAL_OF_APPROVAL') !== true) {
256
            //@todo: this needs to be refactored in case there are other sources than swagger configuration files
257
            foreach ($this->proxySourceConfiguration['swagger'] as $thirdparty => $option) {
258
                $this->apiLoader->setOption($option);
259
                $services[$thirdparty] = $this->determineThirdPartyServices(
260
                    $this->apiLoader->getAllEndpoints(false, true)
261
                );
262
            }
263
        }
264
265 4
        return $services;
266
    }
267
}
268