Completed
Pull Request — master (#129)
by Eric
257:01 queued 192:06
created

Guzzle4HttpAdapter::createRequest()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 59
Code Lines 39

Duplication

Lines 9
Ratio 15.25 %

Code Coverage

Tests 48
CRAP Score 3.0017

Importance

Changes 0
Metric Value
dl 9
loc 59
ccs 48
cts 51
cp 0.9412
rs 9.597
c 0
b 0
f 0
cc 3
eloc 39
nc 4
nop 3
crap 3.0017

How to fix   Long Method   

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
/*
4
 * This file is part of the Ivory Http Adapter package.
5
 *
6
 * (c) Eric GELOEN <[email protected]>
7
 *
8
 * For the full copyright and license information, please read the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Ivory\HttpAdapter;
13
14
use GuzzleHttp\Client;
15
use GuzzleHttp\ClientInterface;
16
use GuzzleHttp\Event\CompleteEvent;
17
use GuzzleHttp\Event\ErrorEvent;
18
use GuzzleHttp\Exception\RequestException;
19
use GuzzleHttp\Pool;
20
use Ivory\HttpAdapter\Message\InternalRequestInterface;
21
use Ivory\HttpAdapter\Normalizer\BodyNormalizer;
22
23
/**
24
 * Guzzle 4 http adapter.
25
 *
26
 * @author GeLo <[email protected]>
27
 */
28
class Guzzle4HttpAdapter extends AbstractCurlHttpAdapter
29
{
30
    /** @var \GuzzleHttp\ClientInterface */
31
    private $client;
32
33
    /**
34
     * Creates a guzzle 5 http adapter.
35
     *
36
     * @param \GuzzleHttp\ClientInterface|null               $client        The guzzle 4 client.
37
     * @param \Ivory\HttpAdapter\ConfigurationInterface|null $configuration The configuration.
38
     */
39 704
    public function __construct(ClientInterface $client = null, ConfigurationInterface $configuration = null)
40
    {
41 704
        parent::__construct($configuration, false);
42
43 704
        $this->client = $client ?: new Client();
44 704
    }
45
46
    /**
47
     * {@inheritdoc}
48
     */
49 24
    public function getName()
50
    {
51 24
        return 'guzzle4';
52
    }
53
54
    /**
55
     * {@inheritdoc}
56
     */
57 672
    protected function sendInternalRequest(InternalRequestInterface $internalRequest)
58
    {
59
        try {
60 656
            $response = $this->client->send($this->createRequest($internalRequest));
61 656
        } catch (RequestException $e) {
62 24
            throw HttpAdapterException::cannotFetchUri(
63 24
                $e->getRequest()->getUrl(),
0 ignored issues
show
Bug introduced by
The method getUrl() does not seem to exist on object<Psr\Http\Message\RequestInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
64 24
                $this->getName(),
65 24
                $e->getMessage()
66 24
            );
67
        }
68
69 632
        return $this->getConfiguration()->getMessageFactory()->createResponse(
70 632
            (integer) $response->getStatusCode(),
71 632
            $response->getProtocolVersion(),
72 632
            $response->getHeaders(),
73 632
            BodyNormalizer::normalize(
74
                function () use ($response) {
75 584
                    return $response->getBody()->detach();
76 648
                },
77 632
                $internalRequest->getMethod()
78 644
            )
79 672
        );
80
    }
81
82
    /**
83
     * {@inheritdoc}
84
     */
85 16
    protected function sendInternalRequests(array $internalRequests, $success, $error)
86
    {
87 16
        $requests = array();
88 16
        foreach ($internalRequests as $internalRequest) {
89 16
            $requests[] = $this->createRequest($internalRequest, $success, $error);
90 16
        }
91
92 16
        class_exists('GuzzleHttp\Pool')
93 16
            ? Pool::batch($this->client, $requests)
94 16
            : \GuzzleHttp\batch($this->client, $requests);
95 16
    }
96
97
    /**
98
     * {@inheritdoc}
99
     */
100 80
    protected function createFile($file)
101
    {
102 80
        return fopen($file, 'r');
0 ignored issues
show
Bug Best Practice introduced by
The return type of return fopen($file, 'r'); (resource) is incompatible with the return type of the parent method Ivory\HttpAdapter\Abstra...HttpAdapter::createFile of type CurlFile|string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
103
    }
104
105
    /**
106
     * Creates a request.
107
     *
108
     * @param \Ivory\HttpAdapter\Message\InternalRequestInterface $internalRequest The internal request.
109
     * @param callable|null                                       $success         The success callable.
110
     * @param callable|null                                       $error           The error callable.
111
     *
112
     * @return \GuzzleHttp\Message\RequestInterface The request.
113
     */
114 672
    private function createRequest(InternalRequestInterface $internalRequest, $success = null, $error = null)
115
    {
116 672
        $request = $this->client->createRequest(
0 ignored issues
show
Bug introduced by
The method createRequest() does not exist on GuzzleHttp\ClientInterface. Did you maybe mean request()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
117 672
            $internalRequest->getMethod(),
118 672
            (string) $internalRequest->getUri(),
119
            array(
120 672
                'exceptions'      => false,
121 672
                'allow_redirects' => false,
122 672
                'timeout'         => $this->getConfiguration()->getTimeout(),
123 672
                'connect_timeout' => $this->getConfiguration()->getTimeout(),
124 672
                'version'         => $internalRequest->getProtocolVersion(),
125 672
                'headers'         => $this->prepareHeaders($internalRequest),
126 672
                'body'            => $this->prepareContent($internalRequest),
127
            )
128 672
        );
129
130 672
        if (is_callable($success)) {
131 16
            $messageFactory = $this->getConfiguration()->getMessageFactory();
132
133 16
            $request->getEmitter()->on(
134 16
                'complete',
135
                function (CompleteEvent $event) use ($success, $internalRequest, $messageFactory) {
136 16
                    $response = $messageFactory->createResponse(
137 16
                        (integer) $event->getResponse()->getStatusCode(),
138 16
                        $event->getResponse()->getProtocolVersion(),
139 16
                        $event->getResponse()->getHeaders(),
140 16
                        BodyNormalizer::normalize(
141
                            function () use ($event) {
142 16
                                return $event->getResponse()->getBody()->detach();
143 16
                            },
144 16
                            $internalRequest->getMethod()
145 16
                        )
146 16
                    );
147
148 16
                    $response = $response->withParameter('request', $internalRequest);
149 16
                    call_user_func($success, $response);
150 16
                }
151 16
            );
152 16
        }
153
154 672
        if (is_callable($error)) {
155 16
            $httpAdapterName = $this->getName();
156
157 16
            $request->getEmitter()->on(
158 16
                'error',
159 10 View Code Duplication
                function (ErrorEvent $event) use ($error, $internalRequest, $httpAdapterName) {
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...
160 8
                    $exception = HttpAdapterException::cannotFetchUri(
161 10
                        $event->getException()->getRequest()->getUrl(),
162 8
                        $httpAdapterName,
163 8
                        $event->getException()->getMessage()
164 8
                    );
165 8
                    $exception->setRequest($internalRequest);
166 8
                    call_user_func($error, $exception);
167 8
                }
168 16
            );
169 16
        }
170
171 672
        return $request;
172 6
    }
173
}
174