Passed
Push — master ( 9b342b...cbda31 )
by San
02:50
created

src/HttpCall/Request/BrowserKit.php (4 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Behatch\HttpCall\Request;
4
5
use Behat\Mink\Driver\Goutte\Client as GoutteClient;
6
use Behat\Mink\Mink;
7
use Symfony\Component\BrowserKit\Client as BrowserKitClient;
8
use Symfony\Component\HttpFoundation\File\UploadedFile;
9
10
class BrowserKit
11
{
12
    protected $mink;
13
14
    public function __construct(Mink $mink)
15
    {
16
        $this->mink = $mink;
17
    }
18
19
    public function getMethod()
20
    {
21
        return $this->getRequest()
22
            ->getMethod();
23
    }
24
25
    public function getUri()
26
    {
27
        return $this->getRequest()
28
            ->getUri();
29
    }
30
31
    public function getServer()
32
    {
33
        return $this->getRequest()
34
            ->getServer();
35
    }
36
37
    public function getParameters()
38
    {
39
        return $this->getRequest()
40
            ->getParameters();
41
    }
42
43
    protected function getRequest()
44
    {
45
        $client = $this->mink->getSession()->getDriver()->getClient();
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Behat\Mink\Driver\DriverInterface as the method getClient() does only exist in the following implementations of said interface: Behat\Mink\Driver\BrowserKitDriver, Behat\Mink\Driver\GoutteDriver.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
46
        // BC layer for BrowserKit 2.2.x and older
47
        if (method_exists($client, 'getInternalRequest')) {
48
            $request = $client->getInternalRequest();
49
        } else {
50
            $request = $client->getRequest();
51
        }
52
        return $request;
53
    }
54
55
    public function getContent()
56
    {
57
        return $this->mink->getSession()->getPage()->getContent();
58
    }
59
60
    public function send($method, $url, $parameters = [], $files = [], $content = null, $headers = [])
61
    {
62
        foreach ($files as $originalName => &$file) {
63
            if (is_string($file)) {
64
                $file = new UploadedFile($file, $originalName);
65
            }
66
        }
67
68
        $client = $this->mink->getSession()->getDriver()->getClient();
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Behat\Mink\Driver\DriverInterface as the method getClient() does only exist in the following implementations of said interface: Behat\Mink\Driver\BrowserKitDriver, Behat\Mink\Driver\GoutteDriver.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
69
70
        $client->followRedirects(false);
71
        $client->request($method, $url, $parameters, $files, $headers, $content);
72
        $client->followRedirects(true);
73
        $this->resetHttpHeaders();
74
75
        return $this->mink->getSession()->getPage();
76
    }
77
78
    public function setHttpHeader($name, $value)
79
    {
80
        $client = $this->mink->getSession()->getDriver()->getClient();
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Behat\Mink\Driver\DriverInterface as the method getClient() does only exist in the following implementations of said interface: Behat\Mink\Driver\BrowserKitDriver, Behat\Mink\Driver\GoutteDriver.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
81
        // Goutte\Client
82
        if (method_exists($client, 'setHeader')) {
83
            $client->setHeader($name, $value);
84
        } else {
85
            // Symfony\Component\BrowserKit\Client
86
87
            /* taken from Behat\Mink\Driver\BrowserKitDriver::setRequestHeader */
88
            $contentHeaders = ['CONTENT_LENGTH' => true, 'CONTENT_MD5' => true, 'CONTENT_TYPE' => true];
89
            $name = str_replace('-', '_', strtoupper($name));
90
91
            // CONTENT_* are not prefixed with HTTP_ in PHP when building $_SERVER
92
            if (!isset($contentHeaders[$name])) {
93
                $name = 'HTTP_' . $name;
94
            }
95
            /* taken from Behat\Mink\Driver\BrowserKitDriver::setRequestHeader */
96
97
            $client->setServerParameter($name, $value);
98
        }
99
    }
100
101
    public function getHttpHeaders()
102
    {
103
        return array_change_key_case(
104
            $this->mink->getSession()->getResponseHeaders(),
105
            CASE_LOWER
106
        );
107
    }
108
109
    public function getHttpHeader($name)
110
    {
111
        $values = $this->getHttpRawHeader($name);
112
113
        return implode(', ', $values);
114
    }
115
116
    public function getHttpRawHeader($name)
117
    {
118
        $name = strtolower($name);
119
        $headers = $this->getHttpHeaders();
120
121
        if (isset($headers[$name])) {
122
            $value = $headers[$name];
123
            if (!is_array($headers[$name])) {
124
                $value = [$headers[$name]];
125
            }
126
        } else {
127
            throw new \OutOfBoundsException(
128
                "The header '$name' doesn't exist"
129
            );
130
        }
131
        return $value;
132
    }
133
134
    protected function resetHttpHeaders()
135
    {
136
        /** @var GoutteClient|BrowserKitClient $client */
137
        $client = $this->mink->getSession()->getDriver()->getClient();
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Behat\Mink\Driver\DriverInterface as the method getClient() does only exist in the following implementations of said interface: Behat\Mink\Driver\BrowserKitDriver, Behat\Mink\Driver\GoutteDriver.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
138
139
        $client->setServerParameters([]);
140
        if ($client instanceof GoutteClient) {
141
            $client->restart();
142
        }
143
    }
144
}
145