Completed
Push — master ( d8d25b...3f99c9 )
by Quentin
59s
created

DoctrineLoaderTrait::assertIsConfigured()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 3
Bugs 0 Features 1
Metric Value
c 3
b 0
f 1
dl 0
loc 10
ccs 0
cts 10
cp 0
rs 9.2
cc 4
eloc 6
nc 2
nop 0
crap 20
1
<?php
2
3
namespace Majora\Framework\Loader\Bridge\Doctrine;
4
5
use Doctrine\Common\Collections\Collection;
6
use Doctrine\ORM\EntityRepository;
7
use Majora\Framework\Loader\LoaderTrait;
8
9
/**
10
 * Trait to use into Doctrine loaders to get a simple implementation of LoaderInterface.
11
 *
12
 * @method getEntityRepository : EntityRepository
13
 * @method setEntityRepository(EntityRepository)
14
 *
15
 * @property $entityClass
16
 * @property $collectionClass
17
 * @property $filterResolver
18
 */
19
trait DoctrineLoaderTrait
20
{
21
    use LoaderTrait;
22
23
    /**
24
     * Construct.
25
     *
26
     * @param EntityRepository $entityRepository (optionnal)
27
     */
28
    public function __construct(EntityRepository $entityRepository = null)
29
    {
30
        if ($entityRepository) {
31
            @trigger_error('Repository constructor injection is deprecated for ORM implementation due to circular references with Doctrine events and will be removed in 2.0. Use setEntityRepository() instead.', E_USER_DEPRECATED);
1 ignored issue
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
32
            $this->setEntityRepository($entityRepository);
33
        }
34
    }
35
36
    /**
37
     * Checks if loader is properly configured.
38
     *
39
     * @throws \RuntimeException if not configured
40
     */
41
    private function assertIsConfigured()
42
    {
43
        if (!$this->entityClass || !$this->collectionClass || !$this->filterResolver) {
44
            throw new \RuntimeException(sprintf(
45
                '%s methods cannot be used while it has not been initialize through %s::configureMetadata().',
46
                static::class,
47
                static::class
48
            ));
49
        }
50
    }
51
52
    /**
53
     * Hook called with every entity or collection loaded through this loader.
54
     *
55
     * @param CollectionnableInterface|EntityCollection $entity
56
     *
57
     * @return $object same entity or collection
0 ignored issues
show
Documentation introduced by
The doc-type $object could not be parsed: Unknown type name "$object" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
58
     */
59
    protected function onLoad($entity)
60
    {
61
        @trigger_error(__METHOD__.' is deprecated and will be removed in 2.0. Use full class delegate instead, see Majora\Framework\Loader\LazyLoaderInterface.', E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
62
63
        return $entity;
64
    }
65
66
    /**
67
     * Convert given array or Collection result set to managed entity collection class.
68
     *
69
     * @param array|Collection $result
70
     *
71
     * @return EntityCollection
72
     */
73
    protected function toEntityCollection($result)
74
    {
75
        switch (true) {
76
77
            // already a collection ?
78
            case is_object($result) && is_subclass_of($result, $this->collectionClass) :
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if $this->collectionClass can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
79
                $collection = $result;
80
                break;
81
82
            // already a collection ?
83
            case $result instanceof Collection :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
84
                $collection = new $this->collectionClass($result->toArray());
85
                break;
86
87
            // simple related entity ?
88
            case is_object($result) && is_subclass_of($result, $this->entityClass) :
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if $this->entityClass can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
89
                $collection = new $this->collectionClass(array($result));
90
                break;
91
92
            // simple array ?
93
            case is_array($result) :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
94
                $collection = new $this->collectionClass($result);
95
                break;
96
97
            default:
98
                $collection = new $this->collectionClass();
99
                break;
100
        }
101
102
        return $this->onLoad($collection);
103
    }
104
105
    /**
106
     * Create entity query.
107
     * Proxy to base query builder method to use to custom all queries from this loader.
108
     *
109
     * @param string $alias
110
     *
111
     * @return QueryBuilder
112
     */
113
    protected function createQuery($alias = 'entity')
114
    {
115
        return $this->getEntityRepository()
0 ignored issues
show
Bug introduced by
It seems like getEntityRepository() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
116
            ->createQueryBuilder($alias)
117
        ;
118
    }
119
120
    /**
121
     * create query an filter it with given data.
122
     *
123
     * @param array $filters
124
     *
125
     * @return Query
126
     */
127
    private function createFilteredQuery(array $filters)
128
    {
129
        $qb = $this->createQuery('entity');
130
131
        foreach ($filters as $field => $filter) {
132
            $qb->andWhere(is_array($filter)
133
                    ? sprintf('entity.%s in (:%s)', $field, $field)
134
                    : sprintf('entity.%s = :%s', $field, $field)
135
                )
136
                ->setParameter(sprintf(':%s', $field), $filter)
137
            ;
138
        }
139
140
        return $qb->getQuery();
141
    }
142
143
    /**
144
     * @see LoaderInterface::retrieveAll()
145
     */
146
    public function retrieveAll(array $filters = array(), $limit = null, $offset = null)
147
    {
148
        $this->assertIsConfigured();
149
150
        $query = $this->createFilteredQuery(
151
            $this->filterResolver->resolve($filters)
152
        );
153
154
        if ($limit) {
155
            $query->setMaxResults($limit);
156
        }
157
        if ($offset) {
158
            $query->setFirstResult($offset);
159
        }
160
161
        return $this->toEntityCollection(
162
            $query->getResult()
163
        );
164
    }
165
166
    /**
167
     * @see LoaderInterface::retrieveOne()
168
     */
169
    public function retrieveOne(array $filters = array())
170
    {
171
        $this->assertIsConfigured();
172
173
        return $this->onLoad($this->createFilteredQuery($filters)
174
            ->setMaxResults(1)
175
            ->getOneOrNullResult()
176
        );
177
    }
178
179
    /**
180
     * @see LoaderInterface::retrieve()
181
     */
182
    public function retrieve($id)
183
    {
184
        return $this->onLoad($this->retrieveOne(array('id' => $id)));
185
    }
186
}
187