Notification Setup Error

We have detected an error in your notification set-up (Event-ID dab39dc24f564ec7bd4628d1305fd03c). Currently, we cannot inform you about inspection progress. Please check that the user 557058:bca11929-8c2d-43f2-8a82-c5416880d395 still has access to your repository or update the API account.

Completed
Push — master ( 39a550...af7430 )
by Alexandru
08:39 queued 10s
created

ApiOneCollectionListener::getContent()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 5
cts 5
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 5
nc 2
nop 1
crap 3
1
<?php
2
/**
3
 * This file is part of the bitbucket-api package.
4
 *
5
 * (c) Alexandru G. <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace Bitbucket\API\Http\Listener;
11
12
use Buzz\Message\MessageInterface;
13
use Buzz\Message\Request;
14
use Buzz\Message\RequestInterface;
15
16
/**
17
 * Helper for `Pager`
18
 *
19
 * Inserts pagination metadata (_as is expected by `Pager`_),
20
 * in any response coming from v1 of the API which contains
21
 * a collection.
22
 *
23
 * @author Alexandru Guzinschi <[email protected]>
24
 */
25
class ApiOneCollectionListener implements ListenerInterface
26
{
27
    /** @var array */
28
    private $urlComponents;
29
30
    /** @var string */
31
    private $resource;
32
33
    /**
34
     * {@inheritDoc}
35
     */
36 283
    public function getName()
37
    {
38 283
        return 'api_one_collection';
39
    }
40
41
    /**
42
     * {@inheritDoc}
43
     * @codeCoverageIgnore
44
     */
45
    public function preSend(RequestInterface $request)
46
    {
47
    }
48
49
    /**
50
     * {@inheritDoc}
51
     */
52 8
    public function postSend(RequestInterface $request, MessageInterface $response)
53
    {
54 8
        if ($this->isLegacyApiVersion($request)) {
55 6
            $this->parseRequest($request);
56
57 6
            if ($this->canPaginate($response)) {
58 2
                $content = $this->insertPaginationMeta(
59 2
                    $this->getContent($response),
60 2
                    $this->getPaginationMeta($response)
61 2
                );
62
63 2
                $response->setContent(json_encode($content));
64 2
            }
65 6
        }
66 8
    }
67
68
    /**
69
     * @access public
70
     * @param  MessageInterface $request
71
     * @return bool
72
     */
73 8
    private function isLegacyApiVersion(MessageInterface $request)
74
    {
75
        /** @var Request $request */
76 8
        return strpos($request->getResource(), '/1.0/') !== false;
77
    }
78
79
    /**
80
     * @access public
81
     * @param  RequestInterface $request
82
     * @return void
83
     */
84 6
    private function parseRequest(RequestInterface $request)
85
    {
86
        /** @var Request $request */
87 6
        $this->urlComponents = parse_url($request->getUrl());
0 ignored issues
show
Documentation Bug introduced by
It seems like parse_url($request->getUrl()) can also be of type false. However, the property $urlComponents is declared as type array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
88
89 6
        if (array_key_exists('query', $this->urlComponents)) {
90 5
            parse_str($this->urlComponents['query'], $this->urlComponents['query']);
91 5
        } else {
92 1
            $this->urlComponents['query'] = [];
93
        }
94
95 6
        $this->urlComponents['query']['start'] = array_key_exists('start', $this->urlComponents['query']) ?
96 6
            (int)$this->urlComponents['query']['start'] :
97
            0
98 3
        ;
99 6
        $this->urlComponents['query']['limit'] = array_key_exists('limit', $this->urlComponents['query']) ?
100 6
            (int)$this->urlComponents['query']['limit'] :
101
            15
102 3
        ;
103
104 6
        $pcs = explode('/', $this->urlComponents['path']);
105 6
        $this->resource = strtolower(array_pop($pcs));
106 6
    }
107
108
    /**
109
     * @access public
110
     * @param  MessageInterface $response
111
     * @return bool
112
     */
113 6
    private function canPaginate(MessageInterface $response)
114
    {
115 6
        $content = $this->getContent($response);
116 6
        return array_key_exists('count', $content) && array_key_exists($this->resource, $content);
117
    }
118
119
    /**
120
     * @access private
121
     * @param  MessageInterface $response
122
     * @return array
123
     */
124 6
    private function getContent(MessageInterface $response)
125
    {
126 6
        $content = json_decode($response->getContent(), true);
127
128 6
        if (is_array($content) && JSON_ERROR_NONE === json_last_error()) {
129 3
            return $content;
130
        }
131
132 3
        return [];
133
    }
134
135
    /**
136
     * @access private
137
     * @param  array $content
138
     * @param  array $pagination
139
     * @return array
140
     */
141 2
    private function insertPaginationMeta(array $content, array $pagination)
142
    {
143
        // This is just a reference because duplicate data in response could create confusion between some users.
144 2
        $content['values']  = '.'.$this->resource;
145 2
        $content['size']    = $content['count'];
146 2
        $parts              = $this->urlComponents;
147
148
        // insert pagination links only if everything does not fit in a single page
149 2
        if ($content['count'] > count($content[$this->resource])) {
150 2
            if ($pagination['page'] > 1 || $pagination['page'] === $pagination['pages']) {
151 2
                $query = $parts['query'];
152 2
                $query['start'] -= $parts['query']['limit'];
153
154 2
                $content['previous'] = sprintf(
155 2
                    '%s://%s%s?%s',
156 2
                    $parts['scheme'],
157 2
                    $parts['host'],
158 2
                    $parts['path'],
159 2
                    http_build_query($query)
160 2
                );
161 2
            }
162
163 2
            if ($pagination['page'] < $pagination['pages']) {
164 1
                $query = $parts['query'];
165 1
                $query['start'] += $parts['query']['limit'];
166
167 1
                $content['next'] = sprintf(
168 1
                    '%s://%s%s?%s',
169 1
                    $parts['scheme'],
170 1
                    $parts['host'],
171 1
                    $parts['path'],
172 1
                    http_build_query($query)
173 1
                );
174 1
            }
175 2
        }
176
177 2
        return $content;
178
    }
179
180
    /**
181
     * @access private
182
     * @param  MessageInterface $response
183
     * @return array
184
     */
185 2
    private function getPaginationMeta(MessageInterface $response)
186
    {
187 2
        $meta = [];
188
189 2
        $content        = $this->getContent($response);
190 2
        $meta['total']  = $content['count'];
191 2
        $meta['pages']  = (int)ceil($meta['total'] / $this->urlComponents['query']['limit']);
192 2
        $meta['page']   = ($this->urlComponents['query']['start']/$this->urlComponents['query']['limit']) === 0 ?
193 2
            1 :
194 2
            ($this->urlComponents['query']['start']/$this->urlComponents['query']['limit'])+1
195 2
        ;
196
197 2
        if ($meta['page'] > $meta['pages']) {
198 1
            $meta['page'] = $meta['pages'];
199 1
        }
200
201 2
        return $meta;
202
    }
203
}
204