grabInFromRepositoryFirstRecordsOrderedByMatching()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 12
c 1
b 0
f 0
dl 0
loc 18
ccs 0
cts 16
cp 0
rs 9.8666
cc 4
nc 4
nop 5
crap 20
1
<?php
2
/*******************************************************************************
3
 *  This file is part of the GraphQL Bundle package.
4
 *
5
 *  (c) YnloUltratech <[email protected]>
6
 *
7
 *  For the full copyright and license information, please view the LICENSE
8
 *  file that was distributed with this source code.
9
 ******************************************************************************/
10
11
namespace Ynlo\GraphQLBundle\Behat\Context;
12
13
use Behat\Behat\Context\Context;
14
use Doctrine\Bundle\DoctrineBundle\Registry;
15
use Doctrine\Common\Persistence\ObjectRepository;
16
use Doctrine\ORM\EntityRepository;
17
use PHPUnit\Framework\Assert;
18
use Symfony\Component\HttpKernel\KernelInterface;
19
use Symfony\Component\PropertyAccess\PropertyAccessor;
20
use Ynlo\GraphQLBundle\Behat\Client\ClientAwareInterface;
21
use Ynlo\GraphQLBundle\Behat\Client\ClientAwareTrait;
22
use Ynlo\GraphQLBundle\Behat\Gherkin\YamlStringNode;
23
use Ynlo\GraphQLBundle\Behat\Storage\StorageAwareInterface;
24
use Ynlo\GraphQLBundle\Behat\Storage\StorageAwareTrait;
25
26
/**
27
 * Context for Doctrine integration
28
 *
29
 * @property KernelInterface $kernel
30
 */
31
final class DoctrineContext implements Context, ClientAwareInterface, StorageAwareInterface
32
{
33
    use ClientAwareTrait;
34
    use StorageAwareTrait;
35
36
    /**
37
     * Use a YAML syntax to populate a repository with multiple records
38
     *
39
     * Example: Given the following records in the repository "App\Entity\Post"
40
     *          """
41
     *          - title: "Welcome"
42
     *            body: "Welcome to web page"
43
     *          - title: "Another Post"
44
     *            body: "This is another post"
45
     *          """
46
     *
47
     * @Given /^the following records in the repository "([^"]*)"$/
48
     */
49
    public function theFollowingRecordsInTheRepository($entity, YamlStringNode $records)
50
    {
51
        $manager = $this->getDoctrine()->getManager();
52
        $accessor = new PropertyAccessor();
53
        foreach ($records->toArray() as $record) {
54
            $instance = new $entity();
55
            foreach ($record as $prop => $value) {
56
                $accessor->setValue($instance, $prop, $value);
57
            }
58
59
            $manager->persist($instance);
60
        }
61
        $manager->flush();
62
    }
63
64
    /**
65
     * Use a YAML syntax to create a criteria to match a record in given repository
66
     *
67
     * Example: Then should exist in repository "AppBundle:Post" a record matching:
68
     *   """
69
     *   title: "Welcome"
70
     *   body: "Welcome to web page"
71
     *   """
72
     *
73
     * Expression syntax is allowed
74
     *
75
     * Example: Then should exist in table "post" a record matching:
76
     *   """
77
     *   title: "{variables.input.title}"
78
     *   body: "{variables.input.body}"
79
     *   """
80
     *
81
     * @Given /^should exist in repository "([^"]*)" a record matching:$/
82
     */
83
    public function shouldExistInRepositoryARecordMatching($repo, YamlStringNode $criteria)
84
    {
85
        $exists = (boolean) $this->getDoctrine()->getRepository($repo)->findOneBy($criteria->toArray());
86
        Assert::assertTrue($exists, sprintf('Does not exist any record in the repository "%s" matching given conditions', $repo));
87
    }
88
89
    /**
90
     * Use a YAML syntax to create a criteria to match a record in given repository
91
     *
92
     * Example: Then should not exist in repository "AppBundle:Post" a record matching:
93
     *   """
94
     *   title: "Welcome"
95
     *   body: "Welcome to web page"
96
     *   """
97
     *
98
     * Expression syntax is allowed
99
     *
100
     * Example: Then should not exist in table "post" a record matching:
101
     *   """
102
     *   title: "{variables.input.title}"
103
     *   body: "{variables.input.body}"
104
     *   """
105
     *
106
     * @Given /^should not exist in repository "([^"]*)" a record matching:$/
107
     */
108
    public function shouldNotExistInRepositoryARecordMatching($repo, YamlStringNode $criteria)
109
    {
110
        $exists = (boolean) $this->getDoctrine()->getRepository($repo)->findOneBy($criteria->toArray());
111
        Assert::assertFalse($exists, sprintf('Exist at least one record in the repository "%s" matching given conditions', $repo));
112
    }
113
114
    /**
115
     * Grab a set of records from database in a temp variable inside the `"storage"` in order to use latter in an expression
116
     *
117
     * The prefix `"grab in"` is optional and can be used in "Then" for readability
118
     *
119
     * <code>
120
     * Given "users" from ....
121
     * Then grab in "users" from ...
122
     * </code>
123
     *
124
     * The suffix `"matching:"` is optional too and can be used to set array of conditions to match.
125
     *
126
     * ### Placeholders:
127
     * - **$variable:** `(string)` name of the variable to save in the storage
128
     * - **$entity:** `(string)` name of the entity using bundle notation `"AppBundle:Entity"` or FQN
129
     * - **$limitAndOffset:** `(int|string)` amount of records to fetch `"limit"` or use `"limit:offset"` to use pagination
130
     * - **$orderBy:** `(string|array)` string like `"title:ASC"` or array inside expression like `"{ [{status: 'DESC', title: 'ASC'}] }"`
131
     * - **$criteria:** `(yaml)` YAML node to convert to array of criteria
132
     *
133
     * ### Examples:
134
     *
135
     * <code>
136
     * - Given "orderedUsers" from repository "AppBundle:User" first 5 records ordered by "username:ASC" matching:
137
     *          """
138
     *          enabled: true
139
     *          """
140
     * - Given "orderedUsers" from repository "AppBundle:User" first 5 records ordered by "username:ASC"
141
     * - And "orderedUsersWithOffset" from repository "AppBundle:User" first "10:20" records ordered by "username:ASC"
142
     * - Then grab in "orderedPosts" from repository "AppBundle:Post" first 10 records ordered by "{ [{status: 'DESC', title: 'ASC'}] }"
143
     * </code>
144
     *
145
     * and later can be used:
146
     *
147
     * <code>
148
     * - And "{orderedUsers[0].getUsername()}" should be equal to "{response.data.users.all.edges[0].node.login}"
149
     * </code>
150
     *
151
     * @Given /^(?:grab in )?"([^"]*)" from repository "([^"]*)" first "?([^"]*)"? records ordered by "([^"]*)"(?: matching:)?$/
152
     */
153
    public function grabInFromRepositoryFirstRecordsOrderedByMatching($variable, $repo, $limitAndOffset = null, $orderBy = null, YamlStringNode $criteria = null)
154
    {
155
        //support to use "limit:offset"
156
        if (strpos($limitAndOffset, ':') !== false) {
157
            list($limit, $offset) = explode(':', $limitAndOffset);
158
        } else {
159
            $limit = $limitAndOffset;
160
            $offset = null;
161
        }
162
        // support field:ORDER, eg. name:ASC
163
        if (is_string($orderBy)) {
164
            list($field, $order) = explode(':', $orderBy);
165
            $orderBy = [$field => $order];
166
        }
167
        $records = $this->getDoctrine()
168
                        ->getRepository($repo)
169
                        ->findBy($criteria ? $criteria->toArray() : [], $orderBy, $limit, $offset);
170
        $this->storage->setValue($variable, $records);
171
    }
172
173
    public function getDoctrine(): Registry
174
    {
175
        return $this->client->getContainer()->get('doctrine');
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->client->ge...iner()->get('doctrine') could return the type null which is incompatible with the type-hinted return Doctrine\Bundle\DoctrineBundle\Registry. Consider adding an additional type-check to rule them out.
Loading history...
176
    }
177
178
    /**
179
     * @param string $class
180
     *
181
     * @return ObjectRepository|EntityRepository
182
     */
183
    public function getRepository(string $class): ObjectRepository
184
    {
185
        return $this->getDoctrine()->getRepository($class);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getDoctrin...->getRepository($class) returns the type Doctrine\Persistence\ObjectRepository which includes types incompatible with the type-hinted return Doctrine\Common\Persistence\ObjectRepository.
Loading history...
186
    }
187
}
188