Completed
Push — master ( b893a1...9df8e6 )
by Fabien
03:59
created

ProfilePlugin::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 5
cts 5
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 3
crap 1
1
<?php
2
3
namespace Http\HttplugBundle\Collector;
4
5
use Exception;
6
use Http\Client\Common\Plugin;
7
use Psr\Http\Message\RequestInterface;
8
use Psr\Http\Message\ResponseInterface;
9
10
/**
11
 * The ProfilePlugin decorates any Plugin to fill Profile to keep representation of plugin input/output. Created profile
12
 * is pushed in the current Stack.
13
 *
14
 * @author Fabien Bourigault <[email protected]>
15
 *
16
 * @internal
17
 */
18
class ProfilePlugin implements Plugin
19
{
20
    /**
21
     * @var Plugin
22
     */
23
    private $plugin;
24
25
    /**
26
     * @var Collector
27
     */
28
    private $collector;
29
30
    /**
31
     * @var Formatter
32
     */
33
    private $formatter;
34
35
    /**
36
     * @param Plugin    $plugin
37
     * @param Collector $collector
38
     * @param Formatter $formatter
39
     */
40 9
    public function __construct(Plugin $plugin, Collector $collector, Formatter $formatter)
41
    {
42 9
        $this->plugin = $plugin;
43 9
        $this->collector = $collector;
44 9
        $this->formatter = $formatter;
45 9
    }
46
47
    /**
48
     * {@inheritdoc}
49
     */
50 8
    public function handleRequest(RequestInterface $request, callable $next, callable $first)
51
    {
52 8
        $profile = new Profile(get_class($this->plugin));
53
54 8
        $stack = $this->collector->getCurrentStack();
55 8
        if (null !== $stack) {
56 8
            $stack->addProfile($profile);
57 8
        }
58
59
        // wrap the next callback to profile the plugin request changes
60
        $wrappedNext = function (RequestInterface $request) use ($next, $profile) {
61 7
            $this->onOutgoingRequest($request, $profile);
62
63 7
            return $next($request);
64 8
        };
65
66
        // wrap the first callback to profile the plugin request changes
67
        $wrappedFirst = function (RequestInterface $request) use ($first, $profile) {
68
            $this->onOutgoingRequest($request, $profile);
69
70
            return $first($request);
71 8
        };
72
73
        try {
74 8
            $promise = $this->plugin->handleRequest($request, $wrappedNext, $wrappedFirst);
75 8
        } catch (Exception $e) {
76 1
            $this->onException($request, $profile, $e, $stack);
77
78 1
            throw $e;
79
        }
80
81
        return $promise->then(function (ResponseInterface $response) use ($profile, $request, $stack) {
82 6
            $this->onOutgoingResponse($response, $profile, $request, $stack);
83
84 6
            return $response;
85 7
        }, function (Exception $exception) use ($profile, $request, $stack) {
86 1
            $this->onException($request, $profile, $exception, $stack);
87
88 1
            throw $exception;
89 7
        });
90
    }
91
92
    /**
93
     * @param RequestInterface $request
94
     * @param Profile          $profile
95
     * @param Exception        $exception
96
     * @param Stack            $stack
97
     */
98 2
    private function onException(
99
        RequestInterface $request,
100
        Profile $profile,
101
        Exception $exception,
102
        Stack $stack = null
103
    ) {
104 2
        $profile->setFailed(true);
105 2
        $profile->setResponse($this->formatter->formatException($exception));
106 2
        $this->collectRequestInformation($request, $stack);
107 2
    }
108
109
    /**
110
     * @param RequestInterface $request
111
     * @param Profile          $profile
112
     */
113 7
    private function onOutgoingRequest(RequestInterface $request, Profile $profile)
114
    {
115 7
        $profile->setRequest($this->formatter->formatRequest($request));
116 7
    }
117
118
    /**
119
     * @param ResponseInterface $response
120
     * @param Profile           $profile
121
     * @param RequestInterface  $request
122
     * @param Stack             $stack
123
     */
124 6
    private function onOutgoingResponse(ResponseInterface $response, Profile $profile, RequestInterface $request, Stack $stack = null)
125
    {
126 6
        $profile->setResponse($this->formatter->formatResponse($response));
127 6
        $this->collectRequestInformation($request, $stack);
128 6
    }
129
130
    /**
131
     * Collect request information when not already done by the HTTP client. This happens when using the CachePlugin
132
     * and the cache is hit without re-validation.
133
     *
134
     * @param RequestInterface $request
135
     * @param Stack|null       $stack
136
     */
137 8
    private function collectRequestInformation(RequestInterface $request, Stack $stack = null)
138
    {
139 8
        if (null === $stack) {
140
            return;
141
        }
142
143 8
        if (empty($stack->getRequestTarget())) {
144 7
            $stack->setRequestTarget($request->getRequestTarget());
145 7
        }
146 8
        if (empty($stack->getRequestMethod())) {
147 7
            $stack->setRequestMethod($request->getMethod());
148 7
        }
149 8
        if (empty($stack->getRequestScheme())) {
150 7
            $stack->setRequestScheme($request->getUri()->getScheme());
151 7
        }
152 8
        if (empty($stack->getRequestHost())) {
153 7
            $stack->setRequestHost($request->getUri()->getHost());
154 7
        }
155 8
        if (empty($stack->getClientRequest())) {
156 7
            $stack->setClientRequest($this->formatter->formatRequest($request));
157 7
        }
158 8
        if (empty($stack->getCurlCommand())) {
159 7
            $stack->setCurlCommand($this->formatter->formatAsCurlCommand($request));
160 7
        }
161 8
    }
162
}
163