BaseFeatureContext::createClient()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 0
cts 7
cp 0
rs 9.6666
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 1
crap 2
1
<?php
2
3
namespace TreeHouse\BaseApiBundle\Behat;
4
5
use Behat\Behat\Context\SnippetAcceptingContext;
6
use Behat\Symfony2Extension\Context\KernelAwareContext;
7
use Doctrine\ORM\EntityManager;
8
use Doctrine\ORM\EntityManagerInterface;
9
use Doctrine\ORM\Mapping\ClassMetadata;
10
use Doctrine\ORM\Tools\SchemaTool;
11
use Symfony\Component\DependencyInjection\ContainerInterface;
12
use Symfony\Component\HttpFoundation\BinaryFileResponse;
13
use Symfony\Component\HttpFoundation\Response;
14
use Symfony\Component\HttpKernel\Client;
15
use Symfony\Component\HttpKernel\KernelInterface;
16
use Symfony\Component\PropertyAccess\PropertyAccess;
17
18
/**
19
 * Feature context.
20
 */
21
abstract class BaseFeatureContext implements SnippetAcceptingContext, KernelAwareContext
0 ignored issues
show
Deprecated Code introduced by
The interface Behat\Behat\Context\SnippetAcceptingContext has been deprecated with message: will be removed in 4.0. Use --snippets-for CLI option instead

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
22
{
23
    /**
24
     * @var KernelInterface
25
     */
26
    protected $kernel;
27
28
    /**
29
     * @var Response
30
     */
31
    protected static $response;
32
33
    /**
34
     * @param KernelInterface $kernel
35
     */
36
    public function setKernel(KernelInterface $kernel)
37
    {
38
        $this->kernel = $kernel;
39
    }
40
41
    /**
42
     * Builds schema for all Doctrine's managers
43
     *
44
     * @return void
45
     */
46
    public function buildSchemas()
47
    {
48
        /** @var EntityManagerInterface[] $managers */
49
        $managers = $this->get('doctrine')->getManagers();
50
        foreach ($managers as $manager) {
51
            $metadata = $manager->getMetadataFactory()->getAllMetadata();
52
53
            if (!empty($metadata)) {
54
                $tool = new SchemaTool($manager);
55
                $tool->dropSchema($metadata);
56
                $tool->createSchema($metadata);
57
            }
58
        }
59
    }
60
61
    /**
62
     * Drops all databases
63
     *
64
     * @return void
65
     */
66
    public function dropDatabases()
67
    {
68
        /** @var EntityManagerInterface[] $managers */
69
        $managers = $this->get('doctrine')->getManagers();
70
        foreach ($managers as $manager) {
71
            $tool = new SchemaTool($manager);
72
            $tool->dropDatabase();
73
        }
74
    }
75
76
    /**
77
     * Closes all open database connections
78
     *
79
     * @return void
80
     */
81
    public function closeDbalConnections()
82
    {
83
        /** @var EntityManagerInterface[] $managers */
84
        $managers = $this->get('doctrine')->getManagers();
85
        foreach ($managers as $manager) {
86
            $manager->clear();
87
            $manager->getConnection()->close();
88
        }
89
    }
90
91
    /**
92
     * @param string       $method
93
     * @param string       $uri
94
     * @param string|array $data
95
     * @param array        $headers
96
     * @param array        $server
97
     *
98
     * @return Response
99
     */
100
    protected function request($method, $uri, $data = null, array $headers = [], array $server = [])
101
    {
102
        if (!array_key_exists('HTTP_HOST', $server)) {
103
            $server['HTTP_HOST'] = $this->getContainer()->getParameter('fp_base_api.api_host');
104
        }
105
106
        $client = $this->createClient($server);
107
108
        $server = [];
109
        foreach ($headers as $headerKey => $headerValue) {
110
            $server['HTTP_' . $headerKey] = $headerValue;
111
        }
112
113
        $client->request($method, '/' . ltrim($uri, '/'), [], [], $server, $data);
0 ignored issues
show
Bug introduced by
It seems like $data defined by parameter $data on line 100 can also be of type array; however, Symfony\Component\BrowserKit\Client::request() does only seem to accept string|null, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
114
115
        return static::$response = $client->getResponse();
116
    }
117
118
    /**
119
     * Creates a Client.
120
     *
121
     * @param array $server An array of server parameters
122
     *
123
     * @return Client A Client instance
124
     */
125
    protected function createClient(array $server = [])
126
    {
127
        $client = $this->get('test.client');
128
129
        $client->setServerParameters($server);
130
        $client->followRedirects();
131
132
        return $client;
133
    }
134
135
    /**
136
     * @param string $entityName
137
     * @param array  $rows
138
     */
139
    protected function persistEntities($entityName, array $rows)
140
    {
141
        /** @var EntityManager $doctrine */
142
        $doctrine = $this->get('doctrine')->getManager();
143
        $meta = $doctrine->getClassMetadata($entityName);
144
        $meta->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_NONE);
145
146
        $class = $meta->getName();
147
148
        foreach ($rows as $id => $row) {
149
            // try to find existing entity with this id
150
            if (null === $entity = $doctrine->getRepository($entityName)->find($id)) {
151
                // create a new one
152
                $entity = new $class();
153
154
                // use reflection to set the id (we don't have a setter for this)
155
                $reflectionClass    = $meta->getReflectionClass();
156
                $reflectionProperty = $reflectionClass->getProperty('id');
157
                $reflectionProperty->setAccessible(true);
158
                $reflectionProperty->setValue($entity, $id);
159
160
                $doctrine->persist($entity);
161
            }
162
163
            $accessor = PropertyAccess::createPropertyAccessor();
164
            foreach ($row as $field => $value) {
165
                $accessor->setValue($entity, $field, $value);
166
            }
167
168
            $doctrine->persist($entity);
0 ignored issues
show
Bug introduced by
It seems like $entity defined by $doctrine->getRepository($entityName)->find($id) on line 150 can also be of type array; however, Doctrine\ORM\EntityManager::persist() does only seem to accept object, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
169
            $doctrine->flush();
170
        }
171
172
        $doctrine->clear();
173
    }
174
175
    /**
176
     * Returns the content of the current response. File responses will be read first.
177
     *
178
     * @return string
179
     *
180
     * @throws \RuntimeException
181
     */
182
    protected function getResponseContent()
183
    {
184
        if (!static::$response instanceof Response) {
185
            throw new \RuntimeException('No response available');
186
        }
187
188
        $content = static::$response->getContent();
189
        if (static::$response instanceof BinaryFileResponse) {
190
            $content = file_get_contents(static::$response->getFile()->getPathname());
191
        }
192
193
        return $content;
194
    }
195
196
    /**
197
     * @return ContainerInterface
198
     */
199
    protected function getContainer()
200
    {
201
        return $this->kernel->getContainer();
202
    }
203
204
    /**
205
     * @param string $service
206
     *
207
     * @return object
208
     */
209
    protected function get($service)
210
    {
211
        return $this->getContainer()->get($service);
212
    }
213
}
214