Completed
Push — feature/EVO-7964_fundInfo-exte... ( cf9459...eda009 )
by Bastian
15:13 queued 08:52
created

PagingLinkResponseListener::generateLink()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 22
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 2
Bugs 1 Features 1
Metric Value
c 2
b 1
f 1
dl 0
loc 22
ccs 0
cts 20
cp 0
rs 8.9197
cc 4
eloc 15
nc 6
nop 6
crap 20
1
<?php
2
/**
3
 * FilterResponseListener for adding a rel=self Link header to a response.
4
 */
5
6
namespace Graviton\RestBundle\Listener;
7
8
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
9
use Symfony\Component\HttpFoundation\Request;
10
use Symfony\Bundle\FrameworkBundle\Routing\Router;
11
use Graviton\RestBundle\HttpFoundation\LinkHeader;
12
use Graviton\RestBundle\HttpFoundation\LinkHeaderItem;
13
14
/**
15
 * FilterResponseListener for adding a rel=self Link header to a response.
16
 *
17
 * @author   List of contributors <https://github.com/libgraviton/graviton/graphs/contributors>
18
 * @license  http://opensource.org/licenses/gpl-license.php GNU Public License
19
 * @link     http://swisscom.ch
20
 */
21
class PagingLinkResponseListener
22
{
23
    use GetRqlUrlTrait;
24
25
    /**
26
     * @var Router
27
     */
28
    private $router;
29
30
    /**
31
     * @var \Graviton\RestBundle\HttpFoundation\LinkHeader
32
     */
33
    private $linkHeader;
34
35
    /**
36
     * @param Router $router router
37
     */
38
    public function __construct(Router $router)
39
    {
40
        $this->router = $router;
41
    }
42
43
    /**
44
     * add a rel=self Link header to the response
45
     *
46
     * @param FilterResponseEvent $event response listener event
47
     *
48
     * @return void
49
     */
50
    public function onKernelResponse(FilterResponseEvent $event)
51
    {
52
        $response = $event->getResponse();
53
        $request = $event->getRequest();
54
55
        // extract various info from route
56
        $routeName = $request->get('_route');
57
        $routeParts = explode('.', $routeName);
58
        $routeType = end($routeParts);
59
60
        // only collections have paging
61
        if ($routeType == 'all' && $request->attributes->get('paging')) {
62
            $rql = '';
63
            if ($request->attributes->get('hasRql', false)) {
64
                $rql = $request->attributes->get('rawRql', '');
65
            }
66
67
            $this->linkHeader = LinkHeader::fromResponse($response);
68
69
            $this->generateLinks(
70
                $routeName,
71
                $request->attributes->get('page'),
72
                $request->attributes->get('numPages'),
73
                $request->attributes->get('perPage'),
74
                $request,
75
                $rql
76
            );
77
            $response->headers->set(
78
                'Link',
79
                (string) $this->linkHeader
80
            );
81
            $response->headers->set(
82
                'X-Total-Count',
83
                (string) $request->attributes->get('totalCount')
84
            );
85
        }
86
    }
87
88
    /**
89
     * generate headers for all paging links
90
     *
91
     * @param string  $route    name of route
92
     * @param integer $page     page to link to
93
     * @param integer $numPages number of all pages
94
     * @param integer $perPage  number of records per page
95
     * @param Request $request  request to get rawRql from
96
     * @param string  $rql      rql query string
97
     *
98
     * @return void
99
     */
100
    private function generateLinks($route, $page, $numPages, $perPage, Request $request, $rql)
101
    {
102
        if ($page > 2) {
103
            $this->generateLink($route, 1, $perPage, 'first', $request, $rql);
104
        }
105
        if ($page > 1) {
106
            $this->generateLink($route, $page - 1, $perPage, 'prev', $request, $rql);
107
        }
108
        if ($page < $numPages) {
109
            $this->generateLink($route, $page + 1, $perPage, 'next', $request, $rql);
110
        }
111
        if ($page != $numPages) {
112
            $this->generateLink($route, $numPages, $perPage, 'last', $request, $rql);
113
        }
114
    }
115
116
    /**
117
     * generate link header passed on params and type
118
     *
119
     * @param string  $routeName use with router to generate urls
120
     * @param integer $page      page to link to
121
     * @param integer $perPage   number of items per page
122
     * @param string  $type      rel type of link to generate
123
     * @param Request $request   request to get rawRql from
124
     * @param string  $rql       rql query string
125
     *
126
     * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
127
     */
128
    private function generateLink($routeName, $page, $perPage, $type, Request $request, $rql)
129
    {
130
        $limit = '';
131
        if ($perPage) {
132
            $page = ($page - 1) * $perPage;
133
            $limit = sprintf('limit(%s,%s)', $perPage, $page);
134
        }
135
        if (strpos($rql, 'limit') !== false) {
136
            $rql = preg_replace('/limit\(.*\)/U', $limit, $rql);
137
        } elseif (empty($rql)) {
138
            $rql .= $limit;
139
        } else {
140
            $rql .= '&'.$limit;
141
        }
142
143
        $url = $this->getRqlUrl(
144
            $request,
145
            $this->router->generate($routeName, [], true) . '?' . strtr($rql, [',' => '%2C'])
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...
146
        );
147
148
        $this->linkHeader->add(new LinkHeaderItem($url, array('rel' => $type)));
149
    }
150
}
151