Verbose::__invoke()   C
last analyzed

Complexity

Conditions 11
Paths 2

Size

Total Lines 83
Code Lines 56

Duplication

Lines 8
Ratio 9.64 %

Code Coverage

Tests 44
CRAP Score 11

Importance

Changes 0
Metric Value
dl 8
loc 83
ccs 44
cts 44
cp 1
rs 5.2653
c 0
b 0
f 0
cc 11
eloc 56
nc 2
nop 1
crap 11

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Akamai {OPEN} EdgeGrid Auth Client
4
 *
5
 * @author Davey Shafik <[email protected]>
6
 * @copyright Copyright 2016 Akamai Technologies, Inc. All rights reserved.
7
 * @license Apache 2.0
8
 * @link https://github.com/akamai-open/AkamaiOPEN-edgegrid-php-client
9
 * @link https://developer.akamai.com
10
 * @link https://developer.akamai.com/introduction/Client_Auth.html
11
 */
12
namespace Akamai\Open\EdgeGrid\Handler;
13
14
use Akamai\Open\EdgeGrid\Exception\HandlerException\IOException;
15
16
/**
17
 * Verbose Response Guzzle Middleware Handler
18
 *
19
 * @package Akamai\Open\EdgeGrid\Client
20
 */
21
class Verbose
22
{
23
    protected $outputStream;
24
25
    protected $errorStream;
26
27
    /**
28
     * Verbose constructor.
29
     *
30
     * This method accepts stream resources or a valid stream URLs
31
     * (including file paths). It will use the output stream for
32
     * both output and error streams if no error stream is passed in.
33
     *
34
     * If neither is passed in, stdout and stderr are used.
35
     *
36
     * @param resource|string|null $outputStream
37
     * @param resource|string|null $errorStream
38
     * @throws \Akamai\Open\EdgeGrid\Exception\HandlerException\IOException
39
     */
40 19
    public function __construct($outputStream = null, $errorStream = null)
41
    {
42 19
        $errorStreamException = null;
43 19 View Code Duplication
        if (!is_resource($errorStream) && $errorStream !== null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
44 3
            $fp = @fopen($errorStream, 'ab+');
45 3
            if (!$fp) {
46 2
                $errorStreamException = new IOException('Unable to use error stream: ' . (string) $errorStream);
47
            }
48 3
            $errorStream = $fp;
49
        }
50
51 19 View Code Duplication
        if (!is_resource($outputStream) && $outputStream !== null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
52 6
            $fp = @fopen($outputStream, 'ab+');
53 6
            if (!$fp) {
54 2
                throw new IOException('Unable to use output stream: ' . (string) $outputStream);
55
            }
56 4
            $outputStream = $fp;
57
        }
58
59 17
        if ($errorStreamException instanceof \Exception) {
60 1
            throw $errorStreamException;
61
        }
62
63 16
        if ($outputStream !== null && $errorStream === null) {
64 1
            $errorStream = $outputStream;
65
        }
66
67 16
        if ($outputStream === null && $errorStream === null) {
68 11
            $errorStream = fopen('php://stderr', 'ab');
69
        }
70
71 16
        if ($outputStream === null) {
72 11
            $outputStream = fopen('php://output', 'ab');
73
        }
74
75 16
        $this->outputStream = $outputStream;
76 16
        $this->errorStream = $errorStream;
77 16
    }
78
79
    /**
80
     * Handle the request/response
81
     *
82
     * @param callable $handler
83
     * @return \Closure
84
     */
85 14
    public function __invoke(callable $handler)
86
    {
87
        $colors = [
88 14
            'red' => '',
89
            'yellow' => '',
90
            'cyan' => '',
91
            'reset' => '',
92
        ];
93
94 14 View Code Duplication
        if (PHP_SAPI === 'cli') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
95
            $colors = [
96 14
                'red' => "\x1b[31;01m",
97
                'yellow' => "\x1b[33;01m",
98
                'cyan' => "\x1b[36;01m",
99
                'reset' => "\x1b[39;49;00m",
100
            ];
101
        }
102
103
        return function (
104
            \Psr\Http\Message\RequestInterface $request,
105
            array $config
106
        ) use (
107 14
            $handler,
108 14
            $colors
109
        ) {
110 14
            fwrite($this->outputStream, "{$colors['cyan']}===> [VERBOSE] Request: \n");
111 14
            fwrite($this->outputStream, "{$colors['yellow']}" . $this->getBody($request));
112 14
            fwrite($this->outputStream, "{$colors['reset']}\n");
113
114 14
            return $handler($request, $config)->then(
115
                function (\Psr\Http\Message\ResponseInterface $response) use ($colors) {
116 11
                    $statusCode = $response->getStatusCode();
117 11
                    if ($statusCode > 299 && $statusCode < 400) {
118 1
                        fwrite($this->outputStream, "{$colors['cyan']}===> [VERBOSE] Redirected: ");
119 1
                        fwrite($this->outputStream, $response->getHeader('Location')[0]);
120 1
                        fwrite($this->outputStream, "{$colors['reset']}\n");
121
                    } else {
122 11
                        $responseBody = $this->getBody($response);
123
124 11
                        if ($statusCode > 399 && $statusCode < 600) {
125 3
                            fwrite($this->errorStream, "{$colors['red']}===> [ERROR] An error occurred: \n");
126 3
                            fwrite($this->errorStream, "{$colors['yellow']}" . $responseBody);
127 3
                            fwrite($this->errorStream, "{$colors['reset']}\n");
128
                        } else {
129 9
                            fwrite($this->outputStream, "{$colors['cyan']}===> [VERBOSE] Response: \n");
130 9
                            fwrite($this->outputStream, "{$colors['yellow']}" . $responseBody);
131 9
                            fwrite($this->outputStream, "{$colors['reset']}\n");
132
                        }
133
                    }
134
135 11
                    return $response;
136 14
                },
137 14
                function (\Exception $reason) use ($colors) {
138 3
                    fwrite($this->outputStream, "{$colors['red']}===> [ERROR] An error occurred: \n");
139 3
                    fwrite($this->outputStream, "{$colors['yellow']}");
140
141 3
                    $code = $reason->getCode();
142 3
                    if (!empty($code)) {
143 2
                        $code .= ': ';
144
                    }
145
146 3
                    $message = $reason->getMessage();
147
148 3
                    fwrite($this->outputStream, ((!empty($code)) ? $code : '') . $message);
149
150 3
                    $response = $reason instanceof \GuzzleHttp\Exception\RequestException
151 3
                        ? $reason->getResponse()
152 3
                        : false;
153
154 3
                    if ($response instanceof \Psr\Http\Message\ResponseInterface) {
155 2
                        $body = $response->getBody()->getContents();
156 2
                        if (!empty($body)) {
157 1
                            fwrite($this->outputStream, "\n{$colors['yellow']}" . $body);
158
                        }
159
                    }
160
161 3
                    fwrite($this->outputStream, "{$colors['reset']}\n");
162
163 3
                    return new \GuzzleHttp\Promise\RejectedPromise($reason);
164 14
                }
165
            );
166 14
        };
167
    }
168
169
    /**
170
     * Get response body
171
     *
172
     * @param \Psr\Http\Message\MessageInterface $message
173
     *
174
     * @return string
175
     */
176 14
    protected function getBody(\Psr\Http\Message\MessageInterface $message)
177
    {
178 14
        $body = trim($message->getBody());
179
180 14
        if ($message->getBody()->getSize() === 0 || empty($body)) {
181 14
            if ($message instanceof \Psr\Http\Message\ResponseInterface) {
182 1
                return 'No response body returned';
183
            }
184 14
            return 'No request body sent';
185
        }
186 10
        $result = json_decode($body);
187 10
        if ($result !== null) {
188 7
            return json_encode($result, JSON_PRETTY_PRINT);
189
        }
190
191 3
        return $body;
192
    }
193
}
194