Completed
Push — master ( d81c19...f57266 )
by Kamil
20s
created

Doctrine/ODM/MongoDB/DocumentRepository.php (1 issue)

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
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Sylius\Bundle\ResourceBundle\Doctrine\ODM\MongoDB;
15
16
use Doctrine\MongoDB\Query\Builder as QueryBuilder;
17
use Doctrine\ODM\MongoDB\DocumentRepository as BaseDocumentRepository;
18
use Pagerfanta\Adapter\DoctrineODMMongoDBAdapter;
19
use Pagerfanta\Pagerfanta;
20
use Sylius\Component\Resource\Model\ResourceInterface;
21
use Sylius\Component\Resource\Repository\RepositoryInterface;
22
23
/**
24
 * Doctrine ODM driver resource manager.
25
 */
26
class DocumentRepository extends BaseDocumentRepository implements RepositoryInterface
27
{
28
    /**
29
     * @param int $id
30
     *
31
     * @return object
32
     */
33
    public function find($id)
34
    {
35
        return $this
36
            ->getQueryBuilder()
37
            ->field('id')->equals(new \MongoId($id))
38
            ->getQuery()
39
            ->getSingleResult()
40
        ;
41
    }
42
43
    /**
44
     * @return array
45
     */
46
    public function findAll()
47
    {
48
        return $this
49
            ->getCollectionQueryBuilder()
50
            ->getQuery()
51
            ->getIterator()
52
        ;
53
    }
54
55
    /**
56
     * @param array $criteria
57
     *
58
     * @return object
59
     */
60
    public function findOneBy(array $criteria)
61
    {
62
        $queryBuilder = $this->getQueryBuilder();
63
64
        $this->applyCriteria($queryBuilder, $criteria);
65
66
        return $queryBuilder
67
            ->getQuery()
68
            ->getSingleResult()
69
        ;
70
    }
71
72
    /**
73
     * @param array $criteria
74
     * @param array|null $sorting
75
     * @param int $limit
76
     * @param int $offset
77
     *
78
     * @return array
79
     */
80
    public function findBy(array $criteria, ?array $sorting = null, $limit = null, $offset = null)
81
    {
82
        $queryBuilder = $this->getCollectionQueryBuilder();
83
84
        $this->applyCriteria($queryBuilder, $criteria);
85
        $this->applySorting($queryBuilder, $sorting);
86
87
        if (null !== $limit) {
88
            $queryBuilder->limit($limit);
89
        }
90
91
        if (null !== $offset) {
92
            $queryBuilder->skip($offset);
93
        }
94
95
        return $queryBuilder
96
            ->getQuery()
97
            ->getIterator()
98
        ;
99
    }
100
101
    /**
102
     * {@inheritdoc}
103
     */
104
    public function createPaginator(array $criteria = [], array $sorting = [])
105
    {
106
        $queryBuilder = $this->getCollectionQueryBuilder();
107
108
        $this->applyCriteria($queryBuilder, $criteria);
109
        $this->applySorting($queryBuilder, $sorting);
110
111
        return $this->getPaginator($queryBuilder);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->getPaginator($queryBuilder); (Pagerfanta\Pagerfanta) is incompatible with the return type declared by the interface Sylius\Component\Resourc...erface::createPaginator of type Sylius\Component\Resource\Repository\iterable.

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...
112
    }
113
114
    /**
115
     * {@inheritdoc}
116
     */
117
    public function add(ResourceInterface $resource)
118
    {
119
        $this->dm->persist($resource);
120
        $this->dm->flush();
121
    }
122
123
    /**
124
     * {@inheritdoc}
125
     */
126
    public function remove(ResourceInterface $resource)
127
    {
128
        if (null !== $this->find($resource->getId())) {
129
            $this->dm->remove($resource);
130
            $this->dm->flush();
131
        }
132
    }
133
134
    /**
135
     * @param QueryBuilder $queryBuilder
136
     *
137
     * @return Pagerfanta
138
     */
139
    public function getPaginator(QueryBuilder $queryBuilder)
140
    {
141
        return new Pagerfanta(new DoctrineODMMongoDBAdapter($queryBuilder));
142
    }
143
144
    /**
145
     * @return QueryBuilder
146
     */
147
    protected function getQueryBuilder()
148
    {
149
        return $this->createQueryBuilder();
150
    }
151
152
    /**
153
     * @return QueryBuilder
154
     */
155
    protected function getCollectionQueryBuilder()
156
    {
157
        return $this->createQueryBuilder();
158
    }
159
160
    /**
161
     * @param QueryBuilder $queryBuilder
162
     * @param array        $criteria
163
     */
164
    protected function applyCriteria(QueryBuilder $queryBuilder, array $criteria = [])
165
    {
166
        foreach ($criteria as $property => $value) {
167
            $queryBuilder->field($property)->equals($value);
168
        }
169
    }
170
171
    /**
172
     * @param QueryBuilder $queryBuilder
173
     * @param array        $sorting
174
     */
175
    protected function applySorting(QueryBuilder $queryBuilder, array $sorting = [])
176
    {
177
        foreach ($sorting as $property => $order) {
178
            $queryBuilder->sort($property, $order);
179
        }
180
    }
181
}
182