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
Pull Request — develop ( #41 )
by
unknown
27:26 queued 12:27
created

ApiOneCollectionPlugin::getContent()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.7998
c 0
b 0
f 0
cc 4
nc 3
nop 1
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\Plugin;
11
12
use Http\Client\Common\Plugin;
13
use Http\Discovery\MessageFactoryDiscovery;
14
use Http\Message\ResponseFactory;
15
use Psr\Http\Message\RequestInterface;
16
use Psr\Http\Message\ResponseInterface;
17
18
/**
19
 * Helper for `Pager`
20
 *
21
 * Inserts pagination metadata (_as is expected by `Pager`_),
22
 * in any response coming from v1 of the API which contains
23
 * a collection.
24
 *
25
 * @author Alexandru Guzinschi <[email protected]>
26
 */
27
class ApiOneCollectionPlugin implements Plugin
28
{
29
    /** @var ResponseFactory */
30
    private $responseFactory;
31
32
    /** @var array */
33
    private $urlQueryComponents;
34
35
    /** @var string */
36
    private $resource;
37
38
    /** @var array */
39
    private $content;
40
41
    public function __construct(ResponseFactory $responseFactory = null)
42
    {
43
        $this->responseFactory = $responseFactory ?: MessageFactoryDiscovery::find();
44
    }
45
46
    public function handleRequest(RequestInterface $request, callable $next, callable $first)
47
    {
48
        return $next($request)->then(function (ResponseInterface $response) use ($request) {
49
            if ($this->isLegacyApiVersion($request)) {
50
                $this->parseRequest($request);
51
52
                if ($this->canPaginate($response)) {
53
                    $content = $this->insertPaginationMeta(
54
                        $this->getContent($response),
55
                        $this->getPaginationMeta($response),
56
                        $request
57
                    );
58
59
                    return $this->responseFactory->createResponse(
60
                        $response->getStatusCode(),
61
                        $response->getReasonPhrase(),
62
                        $response->getHeaders(),
63
                        json_encode($content),
64
                        $response->getProtocolVersion()
65
                    );
66
                }
67
68
                return $this->responseFactory->createResponse(
69
                    $response->getStatusCode(),
70
                    $response->getReasonPhrase(),
71
                    $response->getHeaders(),
72
                    json_encode($this->getContent($response)),
73
                    $response->getProtocolVersion()
74
                );
75
            }
76
        });
77
    }
78
79
    /**
80
     * @access public
81
     * @param  RequestInterface $request
82
     * @return bool
83
     */
84
    private function isLegacyApiVersion(RequestInterface $request)
85
    {
86
        /** @var RequestInterface $request */
87
        return strpos($request->getUri()->getPath(), '/1.0/') !== false;
88
    }
89
90
    /**
91
     * @access public
92
     * @param  RequestInterface $request
93
     * @return void
94
     */
95
    private function parseRequest(RequestInterface $request)
96
    {
97
        if ($request->getUri()->getQuery()) {
98
            parse_str($request->getUri()->getQuery(), $this->urlQueryComponents);
99
        } else {
100
            $this->urlQueryComponents = [];
101
        }
102
103
        $this->urlQueryComponents['start'] = array_key_exists('start', $this->urlQueryComponents) ?
104
            (int)$this->urlQueryComponents['start'] :
105
            0
106
        ;
107
        $this->urlQueryComponents['limit'] = array_key_exists('limit', $this->urlQueryComponents) ?
108
            (int)$this->urlQueryComponents['limit'] :
109
            15
110
        ;
111
112
        $pcs = explode('/', $request->getUri()->getPath());
113
        $this->resource = strtolower(array_pop($pcs));
114
    }
115
116
    /**
117
     * @access public
118
     * @param  ResponseInterface $response
119
     * @return bool
120
     */
121
    private function canPaginate(ResponseInterface $response)
122
    {
123
        $content = $this->getContent($response);
124
        return array_key_exists('count', $content) && array_key_exists($this->resource, $content);
125
    }
126
127
    /**
128
     * @access private
129
     * @param  ResponseInterface $response
130
     * @return array
131
     */
132
    private function getContent(ResponseInterface $response)
133
    {
134
        if (null === $this->content) {
135
            $content = json_decode($response->getBody()->getContents(), true);
136
137
            if (is_array($content) && JSON_ERROR_NONE === json_last_error()) {
138
                $this->content = $content;
139
            } else {
140
                $this->content = [];
141
            }
142
        }
143
144
        return $this->content;
145
    }
146
147
    /**
148
     * @access private
149
     * @param  array $content
150
     * @param  array $pagination
151
     * @return array
152
     */
153
    private function insertPaginationMeta(array $content, array $pagination, RequestInterface $request)
154
    {
155
        // This is just a reference because duplicate data in response could create confusion between some users.
156
        $content['values']  = '.'.$this->resource;
157
        $content['size']    = $content['count'];
158
159
        // insert pagination links only if everything does not fit in a single page
160
        if ($content['count'] > count($content[$this->resource])) {
161
            if ($pagination['page'] > 1 || $pagination['page'] === $pagination['pages']) {
162
                $query = $this->urlQueryComponents;
163
                $query['start'] -= $this->urlQueryComponents['limit'];
164
165
                $content['previous'] = sprintf(
166
                    '%s://%s%s?%s',
167
                    $request->getUri()->getScheme(),
168
                    $request->getUri()->getHost(),
169
                    $request->getUri()->getPath(),
170
                    http_build_query($query)
171
                );
172
            }
173
174
            if ($pagination['page'] < $pagination['pages']) {
175
                $query = $this->urlQueryComponents;
176
                $query['start'] += $this->urlQueryComponents['limit'];
177
178
                $content['next'] = sprintf(
179
                    '%s://%s%s?%s',
180
                    $request->getUri()->getScheme(),
181
                    $request->getUri()->getHost(),
182
                    $request->getUri()->getPath(),
183
                    http_build_query($query)
184
                );
185
            }
186
        }
187
188
        return $content;
189
    }
190
191
    /**
192
     * @access private
193
     * @param  ResponseInterface $response
194
     * @return array
195
     */
196
    private function getPaginationMeta(ResponseInterface $response)
197
    {
198
        $meta = [];
199
200
        $content        = $this->getContent($response);
201
        $meta['total']  = $content['count'];
202
        $meta['pages']  = (int)ceil($meta['total'] / $this->urlQueryComponents['limit']);
203
        $meta['page']   = ($this->urlQueryComponents['start']/$this->urlQueryComponents['limit']) === 0 ?
204
            1 :
205
            ($this->urlQueryComponents['start']/$this->urlQueryComponents['limit'])+1
206
        ;
207
208
        if ($meta['page'] > $meta['pages']) {
209
            $meta['page'] = $meta['pages'];
210
        }
211
212
        return $meta;
213
    }
214
}
215