Issues (21)

src/Capsule/Collection.php (6 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Facile\MongoDbBundle\Capsule;
6
7
use Facile\MongoDbBundle\Event\QueryEvent;
8
use Facile\MongoDbBundle\Models\Query;
9
use MongoDB\Collection as MongoCollection;
10
use MongoDB\Driver\Manager;
11
use MongoDB\Driver\ReadPreference;
12
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
13
use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy;
14
15
/**
16
 * Class Collection.
17
 *
18
 * @internal
19
 */
20
final class Collection extends MongoCollection
21
{
22
    /** @var EventDispatcherInterface */
23
    private $eventDispatcher;
24
25
    /** @var string */
26
    private $clientName;
27
28
    /** @var string */
29
    private $databaseName;
30
31
    /**
32
     * Collection constructor.
33
     *
34
     * @param Manager $manager
35
     * @param string $clientName
36
     * @param string $databaseName
37 15
     * @param string $collectionName
38
     * @param array $options
39
     * @param EventDispatcherInterface $eventDispatcher
40
     *
41
     * @internal param DataCollectorLoggerInterface $logger
42
     */
43
    public function __construct(
44
        Manager $manager,
45 15
        string $clientName,
46 15
        string $databaseName,
47 15
        string $collectionName,
48 15
        array $options = [],
49 15
        EventDispatcherInterface $eventDispatcher
50
    ) {
51
        parent::__construct($manager, $databaseName, $collectionName, $options);
52
        $this->eventDispatcher = $eventDispatcher;
53
        $this->clientName = $clientName;
54 1
        $this->databaseName = $databaseName;
55
    }
56 1
57 1
    /**
58 1
     * {@inheritdoc}
59
     */
60 1
    public function aggregate(array $pipeline, array $options = [])
61
    {
62
        $query = $this->prepareQuery(__FUNCTION__, null, $pipeline, $options);
63
        $result = parent::aggregate($query->getData(), $query->getOptions());
0 ignored issues
show
It seems like $query->getData() can also be of type object; however, parameter $pipeline of MongoDB\Collection::aggregate() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

63
        $result = parent::aggregate(/** @scrutinizer ignore-type */ $query->getData(), $query->getOptions());
Loading history...
64
        $this->notifyQueryExecution($query);
65
66 1
        return $result;
67
    }
68 1
69 1
    /**
70 1
     * {@inheritdoc}
71
     */
72 1
    public function count($filter = [], array $options = [])
73
    {
74
        $query = $this->prepareQuery(__FUNCTION__, $filter, null, $options);
75
        $result = parent::count($query->getFilters(), $query->getOptions());
0 ignored issues
show
Deprecated Code introduced by
The function MongoDB\Collection::count() has been deprecated: 1.4 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

75
        $result = /** @scrutinizer ignore-deprecated */ parent::count($query->getFilters(), $query->getOptions());

This function has been deprecated. The supplier of the function has supplied an explanatory message.

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

Loading history...
76
        $this->notifyQueryExecution($query);
77
78 1
        return $result;
79
    }
80 1
81 1
    /**
82 1
     * {@inheritdoc}
83
     */
84 1
    public function find($filter = [], array $options = [])
85
    {
86
        $query = $this->prepareQuery(__FUNCTION__, $filter, null, $options);
87
        $result = parent::find($query->getFilters(), $query->getOptions());
88
        $this->notifyQueryExecution($query);
89
90 1
        return $result;
91
    }
92 1
93 1
    /**
94 1
     * {@inheritdoc}
95
     */
96 1
    public function findOne($filter = [], array $options = [])
97
    {
98
        $query = $this->prepareQuery(__FUNCTION__, $filter, null, $options);
99
        $result = parent::findOne($query->getFilters(), $query->getOptions());
100
        $this->notifyQueryExecution($query);
101
102 1
        return $result;
103
    }
104 1
105 1
    /**
106 1
     * {@inheritdoc}
107
     */
108 1
    public function findOneAndUpdate($filter, $update, array $options = [])
109
    {
110
        $query = $this->prepareQuery(__FUNCTION__, $filter, $update, $options);
111
        $result = parent::findOneAndUpdate($query->getFilters(), $query->getData(), $query->getOptions());
112
        $this->notifyQueryExecution($query);
113
114 1
        return $result;
115
    }
116 1
117 1
    /**
118 1
     * {@inheritdoc}
119
     */
120 1
    public function findOneAndDelete($filter, array $options = [])
121
    {
122
        $query = $this->prepareQuery(__FUNCTION__, $filter, null, $options);
123
        $result = parent::findOneAndDelete($query->getFilters(), $query->getOptions());
124
        $this->notifyQueryExecution($query);
125
126 2
        return $result;
127
    }
128 2
129 2
    /**
130 2
     * {@inheritdoc}
131
     */
132 2
    public function deleteMany($filter, array $options = [])
133
    {
134
        $query = $this->prepareQuery(__FUNCTION__, $filter, null, $options);
135
        $result = parent::deleteMany($query->getFilters(), $query->getOptions());
136
        $this->notifyQueryExecution($query);
137
138 1
        return $result;
139
    }
140 1
141 1
    /**
142 1
     * {@inheritdoc}
143
     */
144 1
    public function deleteOne($filter, array $options = [])
145
    {
146
        $query = $this->prepareQuery(__FUNCTION__, $filter, null, $options);
147
        $result = parent::deleteOne($query->getFilters(), $query->getOptions());
148
        $this->notifyQueryExecution($query);
149
150 1
        return $result;
151
    }
152 1
153 1
    /**
154 1
     * {@inheritdoc}
155
     */
156 1
    public function replaceOne($filter, $replacement, array $options = [])
157
    {
158
        $query = $this->prepareQuery(__FUNCTION__, $filter, $replacement, $options);
159
        $result = parent::replaceOne($query->getFilters(), $query->getData(), $query->getOptions());
160
        $this->notifyQueryExecution($query);
161
162 2
        return $result;
163
    }
164 2
165 2
    /**
166 2
     * {@inheritdoc}
167
     */
168 2
    public function insertOne($document, array $options = [])
169
    {
170
        $query = $this->prepareQuery(__FUNCTION__, [], $document, $options);
171
        $result = parent::insertOne($query->getData(), $query->getOptions());
172
        $this->notifyQueryExecution($query);
173
174 1
        return $result;
175
    }
176 1
177 1
    /**
178 1
     * {@inheritdoc}
179
     */
180 1
    public function updateOne($filter, $update, array $options = [])
181
    {
182
        $query = $this->prepareQuery(__FUNCTION__, $filter, $update, $options);
183
        $result = parent::updateOne($query->getFilters(), $query->getData(), $query->getOptions());
184
        $this->notifyQueryExecution($query);
185
186 1
        return $result;
187
    }
188 1
189 1
    /**
190 1
     * {@inheritdoc}
191
     */
192 1
    public function distinct($fieldName, $filter = [], array $options = [])
193
    {
194
        $query = $this->prepareQuery(__FUNCTION__, $filter, ['fieldName' => $fieldName], $options);
195
        $result = parent::distinct($fieldName, $query->getFilters(), $query->getOptions());
196
        $this->notifyQueryExecution($query);
197
198
        return $result;
199
    }
200
201
    /**
202
     * @param string $method
203 12
     * @param array|object $filters
204
     * @param array|object $data
205 12
     * @param array $options
206 12
     *
207 12
     * @return Query
208 12
     */
209 12
    private function prepareQuery(string $method, $filters = null, $data = null, array $options): Query
210 12
    {
211 12
        $query = new Query();
212 12
        $query->setFilters($filters ?? []);
213 12
        $query->setData($data ?? []);
214 12
        $query->setOptions($options);
215
        $query->setMethod($method);
216
        $query->setClient($this->getClientName());
217 12
        $query->setDatabase($this->getDatabaseName());
218
        $query->setCollection($this->getCollectionName());
219 12
        $query->setReadPreference(
220
            $this->translateReadPreference($options['readPreference'] ?? $this->__debugInfo()['readPreference'])
221
        );
222
223
        $event = new QueryEvent($query);
224
        if (class_exists(LegacyEventDispatcherProxy::class)) {
225
            $this->eventDispatcher->dispatch($event, QueryEvent::QUERY_PREPARED);
0 ignored issues
show
The call to Symfony\Contracts\EventD...erInterface::dispatch() has too many arguments starting with Facile\MongoDbBundle\Eve...ryEvent::QUERY_PREPARED. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

225
            $this->eventDispatcher->/** @scrutinizer ignore-call */ 
226
                                    dispatch($event, QueryEvent::QUERY_PREPARED);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
226
        } else {
227 12
            $this->eventDispatcher->dispatch(QueryEvent::QUERY_PREPARED, $event);
0 ignored issues
show
Facile\MongoDbBundle\Eve...ryEvent::QUERY_PREPARED of type string is incompatible with the type object expected by parameter $event of Symfony\Contracts\EventD...erInterface::dispatch(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

227
            $this->eventDispatcher->dispatch(/** @scrutinizer ignore-type */ QueryEvent::QUERY_PREPARED, $event);
Loading history...
228
        }
229 12
230 12
        return $query;
231
    }
232 12
233 12
    /**
234
     * @param ReadPreference $readPreference
235
     *
236
     * @return string
237
     */
238
    private function translateReadPreference(ReadPreference $readPreference): string
239
    {
240
        switch ($readPreference->getMode()) {
241
            case ReadPreference::RP_PRIMARY:
242
                return 'primary';
243
            case ReadPreference::RP_PRIMARY_PREFERRED:
244
                return 'primaryPreferred';
245
            case ReadPreference::RP_SECONDARY:
246
                return 'secondary';
247
            case ReadPreference::RP_SECONDARY_PREFERRED:
248 12
                return 'secondaryPreferred';
249
            case ReadPreference::RP_NEAREST:
250 12
                return 'nearest';
251
            default:
252 12
                return 'undefined';
253 12
        }
254
    }
255
256
    /**
257
     * @param Query $queryLog
258 12
     */
259
    private function notifyQueryExecution(Query $queryLog)
260 12
    {
261
        $queryLog->setExecutionTime(microtime(true) - $queryLog->getStart());
262
263
        $event = new QueryEvent($queryLog);
264
        if (class_exists(LegacyEventDispatcherProxy::class)) {
265
            $this->eventDispatcher->dispatch($event, QueryEvent::QUERY_EXECUTED);
0 ignored issues
show
The call to Symfony\Contracts\EventD...erInterface::dispatch() has too many arguments starting with Facile\MongoDbBundle\Eve...ryEvent::QUERY_EXECUTED. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

265
            $this->eventDispatcher->/** @scrutinizer ignore-call */ 
266
                                    dispatch($event, QueryEvent::QUERY_EXECUTED);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
266 12
        } else {
267
            $this->eventDispatcher->dispatch(QueryEvent::QUERY_EXECUTED, $event);
0 ignored issues
show
Facile\MongoDbBundle\Eve...ryEvent::QUERY_EXECUTED of type string is incompatible with the type object expected by parameter $event of Symfony\Contracts\EventD...erInterface::dispatch(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

267
            $this->eventDispatcher->dispatch(/** @scrutinizer ignore-type */ QueryEvent::QUERY_EXECUTED, $event);
Loading history...
268 12
        }
269
    }
270
271
    /**
272
     * @return string
273
     */
274
    public function getClientName(): string
275
    {
276
        return $this->clientName;
277
    }
278
279
    /**
280
     * @return string
281
     */
282
    public function getDatabaseName(): string
283
    {
284
        return $this->databaseName;
285
    }
286
}
287