Complex classes like ManyToManyPersister often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use ManyToManyPersister, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
40 | class ManyToManyPersister extends AbstractCollectionPersister |
||
41 | { |
||
42 | /** |
||
43 | 17 | * {@inheritdoc} |
|
44 | */ |
||
45 | 17 | public function delete(PersistentCollection $collection) |
|
46 | { |
||
47 | 17 | $mapping = $collection->getMapping(); |
|
48 | |||
49 | if ( ! $mapping['isOwningSide']) { |
||
50 | return; // ignore inverse side |
||
51 | 17 | } |
|
52 | 17 | ||
53 | $types = array(); |
||
54 | 17 | $class = $this->em->getClassMetadata($mapping['sourceEntity']); |
|
55 | 17 | ||
56 | foreach ($mapping['joinTable']['joinColumns'] as $joinColumn) { |
||
57 | $types[] = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $class, $this->em); |
||
|
|||
58 | 17 | } |
|
59 | 17 | ||
60 | $this->conn->executeUpdate($this->getDeleteSQL($collection), $this->getDeleteSQLParameters($collection), $types); |
||
61 | } |
||
62 | |||
63 | /** |
||
64 | 329 | * {@inheritdoc} |
|
65 | */ |
||
66 | 329 | public function update(PersistentCollection $collection) |
|
67 | { |
||
68 | 329 | $mapping = $collection->getMapping(); |
|
69 | 231 | ||
70 | if ( ! $mapping['isOwningSide']) { |
||
71 | return; // ignore inverse side |
||
72 | 328 | } |
|
73 | 328 | ||
74 | list($deleteSql, $deleteTypes) = $this->getDeleteRowSQL($collection); |
||
75 | 328 | list($insertSql, $insertTypes) = $this->getInsertRowSQL($collection); |
|
76 | 12 | ||
77 | foreach ($collection->getDeleteDiff() as $element) { |
||
78 | 12 | $this->conn->executeUpdate( |
|
79 | $deleteSql, |
||
80 | $this->getDeleteRowSQLParameters($collection, $element), |
||
81 | $deleteTypes |
||
82 | ); |
||
83 | 328 | } |
|
84 | 328 | ||
85 | foreach ($collection->getInsertDiff() as $element) { |
||
86 | 328 | $this->conn->executeUpdate( |
|
87 | $insertSql, |
||
88 | $this->getInsertRowSQLParameters($collection, $element), |
||
89 | $insertTypes |
||
90 | 328 | ); |
|
91 | } |
||
92 | } |
||
93 | |||
94 | /** |
||
95 | 3 | * {@inheritdoc} |
|
96 | */ |
||
97 | 3 | public function get(PersistentCollection $collection, $index) |
|
98 | { |
||
99 | 3 | $mapping = $collection->getMapping(); |
|
100 | |||
101 | if ( ! isset($mapping['indexBy'])) { |
||
102 | throw new \BadMethodCallException("Selecting a collection by index is only supported on indexed collections."); |
||
103 | 3 | } |
|
104 | 3 | ||
105 | 2 | $persister = $this->uow->getEntityPersister($mapping['targetEntity']); |
|
106 | 3 | $mappedKey = $mapping['isOwningSide'] |
|
107 | ? $mapping['inversedBy'] |
||
108 | 3 | : $mapping['mappedBy']; |
|
109 | |||
110 | return $persister->load(array($mappedKey => $collection->getOwner(), $mapping['indexBy'] => $index), null, $mapping, array(), 0, 1); |
||
111 | } |
||
112 | |||
113 | /** |
||
114 | 18 | * {@inheritdoc} |
|
115 | */ |
||
116 | 18 | public function count(PersistentCollection $collection) |
|
117 | 18 | { |
|
118 | 18 | $conditions = array(); |
|
119 | 18 | $params = array(); |
|
120 | 18 | $types = array(); |
|
121 | 18 | $mapping = $collection->getMapping(); |
|
122 | 18 | $id = $this->uow->getEntityIdentifier($collection->getOwner()); |
|
123 | 18 | $sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']); |
|
124 | 4 | $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); |
|
125 | 18 | $association = ( ! $mapping['isOwningSide']) |
|
126 | ? $targetClass->associationMappings[$mapping['mappedBy']] |
||
127 | 18 | : $mapping; |
|
128 | 18 | ||
129 | 4 | $joinTableName = $this->quoteStrategy->getJoinTableName($association, $sourceClass, $this->platform); |
|
130 | 18 | $joinColumns = ( ! $mapping['isOwningSide']) |
|
131 | ? $association['joinTable']['inverseJoinColumns'] |
||
132 | 18 | : $association['joinTable']['joinColumns']; |
|
133 | 18 | ||
134 | 18 | foreach ($joinColumns as $joinColumn) { |
|
135 | 18 | $columnName = $this->quoteStrategy->getJoinColumnName($joinColumn, $sourceClass, $this->platform); |
|
136 | 18 | $referencedName = $joinColumn['referencedColumnName']; |
|
137 | 18 | $conditions[] = 't.' . $columnName . ' = ?'; |
|
138 | $params[] = $id[$sourceClass->getFieldForColumn($referencedName)]; |
||
139 | $types[] = PersisterHelper::getTypeOfColumn($referencedName, $sourceClass, $this->em); |
||
140 | 18 | } |
|
141 | |||
142 | 18 | list($joinTargetEntitySQL, $filterSql) = $this->getFilterSql($mapping); |
|
143 | 3 | ||
144 | if ($filterSql) { |
||
145 | $conditions[] = $filterSql; |
||
146 | } |
||
147 | |||
148 | // If there is a provided criteria, make part of conditions |
||
149 | // @todo Fix this. Current SQL returns something like: |
||
150 | // |
||
151 | /*if ($criteria && ($expression = $criteria->getWhereExpression()) !== null) { |
||
152 | // A join is needed on the target entity |
||
153 | $targetTableName = $this->quoteStrategy->getTableName($targetClass, $this->platform); |
||
154 | $targetJoinSql = ' JOIN ' . $targetTableName . ' te' |
||
155 | . ' ON' . implode(' AND ', $this->getOnConditionSQL($association)); |
||
156 | |||
157 | // And criteria conditions needs to be added |
||
158 | $persister = $this->uow->getEntityPersister($targetClass->name); |
||
159 | $visitor = new SqlExpressionVisitor($persister, $targetClass); |
||
160 | $conditions[] = $visitor->dispatch($expression); |
||
161 | |||
162 | $joinTargetEntitySQL = $targetJoinSql . $joinTargetEntitySQL; |
||
163 | }*/ |
||
164 | 18 | ||
165 | 18 | $sql = 'SELECT COUNT(*)' |
|
166 | 18 | . ' FROM ' . $joinTableName . ' t' |
|
167 | . $joinTargetEntitySQL |
||
168 | 18 | . ' WHERE ' . implode(' AND ', $conditions); |
|
169 | |||
170 | return $this->conn->fetchColumn($sql, $params, 0, $types); |
||
171 | } |
||
172 | |||
173 | /** |
||
174 | 8 | * {@inheritDoc} |
|
175 | */ |
||
176 | 8 | public function slice(PersistentCollection $collection, $offset, $length = null) |
|
177 | 8 | { |
|
178 | $mapping = $collection->getMapping(); |
||
179 | 8 | $persister = $this->uow->getEntityPersister($mapping['targetEntity']); |
|
180 | |||
181 | return $persister->getManyToManyCollection($mapping, $collection->getOwner(), $offset, $length); |
||
182 | } |
||
183 | /** |
||
184 | 7 | * {@inheritdoc} |
|
185 | */ |
||
186 | 7 | public function containsKey(PersistentCollection $collection, $key) |
|
187 | { |
||
188 | 7 | $mapping = $collection->getMapping(); |
|
189 | |||
190 | if ( ! isset($mapping['indexBy'])) { |
||
191 | throw new \BadMethodCallException("Selecting a collection by index is only supported on indexed collections."); |
||
192 | 7 | } |
|
193 | |||
194 | 7 | list($quotedJoinTable, $whereClauses, $params, $types) = $this->getJoinTableRestrictionsWithKey($collection, $key, true); |
|
195 | |||
196 | 7 | $sql = 'SELECT 1 FROM ' . $quotedJoinTable . ' WHERE ' . implode(' AND ', $whereClauses); |
|
197 | |||
198 | return (bool) $this->conn->fetchColumn($sql, $params, 0, $types); |
||
199 | } |
||
200 | |||
201 | /** |
||
202 | 7 | * {@inheritDoc} |
|
203 | */ |
||
204 | 7 | public function contains(PersistentCollection $collection, $element) |
|
205 | 2 | { |
|
206 | if ( ! $this->isValidEntityState($element)) { |
||
207 | return false; |
||
208 | 7 | } |
|
209 | |||
210 | 7 | list($quotedJoinTable, $whereClauses, $params, $types) = $this->getJoinTableRestrictions($collection, $element, true); |
|
211 | |||
212 | 7 | $sql = 'SELECT 1 FROM ' . $quotedJoinTable . ' WHERE ' . implode(' AND ', $whereClauses); |
|
213 | |||
214 | return (bool) $this->conn->fetchColumn($sql, $params, 0, $types); |
||
215 | } |
||
216 | |||
217 | /** |
||
218 | 2 | * {@inheritDoc} |
|
219 | */ |
||
220 | 2 | public function removeElement(PersistentCollection $collection, $element) |
|
221 | 2 | { |
|
222 | if ( ! $this->isValidEntityState($element)) { |
||
223 | return false; |
||
224 | 2 | } |
|
225 | |||
226 | 2 | list($quotedJoinTable, $whereClauses, $params, $types) = $this->getJoinTableRestrictions($collection, $element, false); |
|
227 | |||
228 | 2 | $sql = 'DELETE FROM ' . $quotedJoinTable . ' WHERE ' . implode(' AND ', $whereClauses); |
|
1 ignored issue
–
show
|
|||
229 | |||
230 | return (bool) $this->conn->executeUpdate($sql, $params, $types); |
||
231 | } |
||
232 | |||
233 | /** |
||
234 | 7 | * {@inheritDoc} |
|
235 | */ |
||
236 | 7 | public function loadCriteria(PersistentCollection $collection, Criteria $criteria) |
|
237 | 7 | { |
|
238 | 7 | $mapping = $collection->getMapping(); |
|
239 | 7 | $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); |
|
240 | 7 | ||
241 | 7 | $queryBuilder = $this->createQueryBuilderForAssociation($collection); |
|
242 | 7 | ||
243 | if ($whereExpr = $criteria->getWhereExpression()) { |
||
244 | 7 | $mappingVisitor = new MappingVisitor( |
|
245 | 1 | $this->quoteStrategy, |
|
246 | 1 | $targetClass, |
|
247 | 1 | $this->platform |
|
248 | ); |
||
249 | 6 | ||
250 | 6 | $mappedExpr = $mappingVisitor->dispatch($criteria->getWhereExpression()); |
|
251 | |||
252 | $whereClauseExpressionVisitor = new QueryExpressionVisitor(['te']); |
||
253 | 7 | $whereExpr = $whereClauseExpressionVisitor->dispatch($mappedExpr); |
|
254 | 7 | $queryBuilder->where($whereExpr . ''); |
|
255 | 7 | ||
256 | /** @var Parameter $parameter */ |
||
257 | 7 | foreach($whereClauseExpressionVisitor->getParameters() as $parameter) { |
|
258 | $queryBuilder->setParameter($parameter->getName(), $parameter->getValue(), $parameter->getType()); |
||
259 | } |
||
260 | 7 | } |
|
261 | |||
262 | 7 | $this->applyCriteriaOrdering($queryBuilder, $criteria, $targetClass); |
|
263 | 2 | ||
264 | 2 | $this->applyCriteriaLimit($queryBuilder, $criteria); |
|
265 | 2 | ||
266 | 2 | $rsm = new Query\ResultSetMappingBuilder($this->em); |
|
267 | $rsm->addRootEntityFromClassMetadata($targetClass->name, 'te'); |
||
268 | |||
269 | 7 | $stmt = $queryBuilder->execute(); |
|
270 | 7 | ||
271 | return $this |
||
272 | 7 | ->em |
|
273 | 7 | ->newHydrator(Query::HYDRATE_OBJECT) |
|
274 | ->hydrateAll($stmt, $rsm); |
||
275 | 7 | } |
|
276 | 7 | ||
277 | 7 | /** |
|
278 | 7 | * Generates the filter SQL for a given mapping. |
|
279 | 7 | * |
|
280 | * This method is not used for actually grabbing the related entities |
||
281 | 7 | * but when the extra-lazy collection methods are called on a filtered |
|
282 | * association. This is why besides the many to many table we also |
||
283 | 7 | * have to join in the actual entities table leading to additional |
|
284 | * JOIN. |
||
285 | 7 | * |
|
286 | * @param array $mapping Array containing mapping information. |
||
287 | * |
||
288 | 7 | * @return string[] ordered tuple: |
|
289 | 7 | * - JOIN condition to add to the SQL |
|
290 | 7 | * - WHERE condition to add to the SQL |
|
291 | */ |
||
292 | public function getFilterSql($mapping) |
||
293 | { |
||
294 | $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); |
||
295 | $rootClass = $this->em->getClassMetadata($targetClass->rootEntityName); |
||
296 | $filterSql = $this->generateFilterConditionSQL($rootClass, 'te'); |
||
297 | |||
298 | if ('' === $filterSql) { |
||
299 | return array('', ''); |
||
300 | } |
||
301 | |||
302 | // A join is needed if there is filtering on the target entity |
||
303 | $tableName = $this->quoteStrategy->getTableName($rootClass, $this->platform); |
||
304 | $joinSql = ' JOIN ' . $tableName . ' te' |
||
305 | . ' ON' . implode(' AND ', $this->getOnConditionSQL($mapping)); |
||
306 | |||
307 | return array($joinSql, $filterSql); |
||
308 | 32 | } |
|
309 | |||
310 | 32 | /** |
|
311 | 32 | * Generates the filter SQL for a given entity and table alias. |
|
312 | 32 | * |
|
313 | * @param ClassMetadata $targetEntity Metadata of the target entity. |
||
314 | 32 | * @param string $targetTableAlias The table alias of the joined/selected table. |
|
315 | 32 | * |
|
316 | * @return string The SQL query part to add to a query. |
||
317 | */ |
||
318 | protected function generateFilterConditionSQL(ClassMetadata $targetEntity, $targetTableAlias) |
||
319 | 6 | { |
|
320 | 6 | $filterClauses = array(); |
|
321 | 6 | ||
322 | foreach ($this->em->getFilters()->getEnabledFilters() as $filter) { |
||
323 | 6 | if ($filterExpr = $filter->addFilterConstraint($targetEntity, $targetTableAlias)) { |
|
324 | $filterClauses[] = '(' . $filterExpr . ')'; |
||
325 | } |
||
326 | } |
||
327 | |||
328 | return $filterClauses |
||
329 | ? '(' . implode(' AND ', $filterClauses) . ')' |
||
330 | : ''; |
||
331 | } |
||
332 | |||
333 | /** |
||
334 | 32 | * Generate ON condition |
|
335 | * |
||
336 | 32 | * @param array $mapping |
|
337 | * |
||
338 | 32 | * @return array |
|
339 | 6 | */ |
|
340 | 6 | protected function getOnConditionSQL($mapping) |
|
341 | { |
||
342 | $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); |
||
343 | $association = ( ! $mapping['isOwningSide']) |
||
344 | 32 | ? $targetClass->associationMappings[$mapping['mappedBy']] |
|
345 | 6 | : $mapping; |
|
346 | 32 | ||
347 | $joinColumns = $mapping['isOwningSide'] |
||
348 | ? $association['joinTable']['inverseJoinColumns'] |
||
349 | : $association['joinTable']['joinColumns']; |
||
350 | |||
351 | $conditions = array(); |
||
352 | |||
353 | foreach ($joinColumns as $joinColumn) { |
||
354 | $joinColumnName = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform); |
||
355 | $refColumnName = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $targetClass, $this->platform); |
||
356 | 13 | ||
357 | $conditions[] = ' t.' . $joinColumnName . ' = ' . 'te.' . $refColumnName; |
||
358 | 13 | } |
|
359 | 13 | ||
360 | 3 | return $conditions; |
|
361 | 13 | } |
|
362 | |||
363 | 13 | /** |
|
364 | 10 | * {@inheritdoc} |
|
365 | 13 | * |
|
366 | * @override |
||
367 | 13 | */ |
|
368 | protected function getDeleteSQL(PersistentCollection $collection) |
||
369 | 13 | { |
|
370 | 13 | $columns = array(); |
|
371 | 13 | $mapping = $collection->getMapping(); |
|
372 | $class = $this->em->getClassMetadata(get_class($collection->getOwner())); |
||
373 | 13 | $joinTable = $this->quoteStrategy->getJoinTableName($mapping, $class, $this->platform); |
|
374 | |||
375 | foreach ($mapping['joinTable']['joinColumns'] as $joinColumn) { |
||
376 | 13 | $columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); |
|
377 | } |
||
378 | |||
379 | return 'DELETE FROM ' . $joinTable |
||
380 | . ' WHERE ' . implode(' = ? AND ', $columns) . ' = ?'; |
||
381 | } |
||
382 | |||
383 | /** |
||
384 | 17 | * {@inheritdoc} |
|
385 | * |
||
386 | 17 | * Internal note: Order of the parameters must be the same as the order of the columns in getDeleteSql. |
|
387 | 17 | * @override |
|
388 | 17 | */ |
|
389 | 17 | protected function getDeleteSQLParameters(PersistentCollection $collection) |
|
390 | { |
||
391 | 17 | $mapping = $collection->getMapping(); |
|
392 | 17 | $identifier = $this->uow->getEntityIdentifier($collection->getOwner()); |
|
393 | |||
394 | // Optimization for single column identifier |
||
395 | 17 | if (count($mapping['relationToSourceKeyColumns']) === 1) { |
|
396 | 17 | return array(reset($identifier)); |
|
397 | } |
||
398 | |||
399 | // Composite identifier |
||
400 | $sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']); |
||
401 | $params = array(); |
||
402 | |||
403 | foreach ($mapping['relationToSourceKeyColumns'] as $columnName => $refColumnName) { |
||
404 | $params[] = isset($sourceClass->fieldNames[$refColumnName]) |
||
405 | 17 | ? $identifier[$sourceClass->fieldNames[$refColumnName]] |
|
406 | : $identifier[$sourceClass->getFieldForColumn($columnName)]; |
||
407 | 17 | } |
|
408 | 17 | ||
409 | return $params; |
||
410 | } |
||
411 | 17 | ||
412 | 15 | /** |
|
413 | * Gets the SQL statement used for deleting a row from the collection. |
||
414 | * |
||
415 | * @param \Doctrine\ORM\PersistentCollection $collection |
||
416 | 2 | * |
|
417 | 2 | * @return string[]|string[][] ordered tuple containing the SQL to be executed and an array |
|
418 | * of types for bound parameters |
||
419 | 2 | */ |
|
420 | 2 | protected function getDeleteRowSQL(PersistentCollection $collection) |
|
421 | 1 | { |
|
422 | 2 | $mapping = $collection->getMapping(); |
|
423 | $class = $this->em->getClassMetadata($mapping['sourceEntity']); |
||
424 | $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); |
||
425 | 2 | $columns = array(); |
|
426 | $types = array(); |
||
427 | |||
428 | foreach ($mapping['joinTable']['joinColumns'] as $joinColumn) { |
||
429 | $columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); |
||
430 | $types[] = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $class, $this->em); |
||
431 | } |
||
432 | |||
433 | foreach ($mapping['joinTable']['inverseJoinColumns'] as $joinColumn) { |
||
434 | $columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform); |
||
435 | $types[] = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em); |
||
436 | 328 | } |
|
437 | |||
438 | 328 | return array( |
|
439 | 328 | 'DELETE FROM ' . $this->quoteStrategy->getJoinTableName($mapping, $class, $this->platform) |
|
440 | 328 | . ' WHERE ' . implode(' = ? AND ', $columns) . ' = ?', |
|
441 | 328 | $types, |
|
442 | 328 | ); |
|
443 | } |
||
444 | 328 | ||
445 | 328 | /** |
|
446 | 328 | * Gets the SQL parameters for the corresponding SQL statement to delete the given |
|
447 | * element from the given collection. |
||
448 | * |
||
449 | 328 | * Internal note: Order of the parameters must be the same as the order of the columns in getDeleteRowSql. |
|
450 | 328 | * |
|
451 | 328 | * @param \Doctrine\ORM\PersistentCollection $collection |
|
452 | * @param mixed $element |
||
453 | * |
||
454 | * @return array |
||
455 | 328 | */ |
|
456 | 328 | protected function getDeleteRowSQLParameters(PersistentCollection $collection, $element) |
|
460 | |||
461 | /** |
||
462 | * Gets the SQL statement used for inserting a row in the collection. |
||
463 | * |
||
464 | * @param \Doctrine\ORM\PersistentCollection $collection |
||
465 | * |
||
466 | * @return string[]|string[][] ordered tuple containing the SQL to be executed and an array |
||
467 | * of types for bound parameters |
||
468 | */ |
||
469 | protected function getInsertRowSQL(PersistentCollection $collection) |
||
470 | { |
||
471 | $columns = array(); |
||
472 | 12 | $types = array(); |
|
473 | $mapping = $collection->getMapping(); |
||
474 | 12 | $class = $this->em->getClassMetadata($mapping['sourceEntity']); |
|
475 | $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); |
||
476 | |||
477 | foreach ($mapping['joinTable']['joinColumns'] as $joinColumn) { |
||
478 | $columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform); |
||
479 | $types[] = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $class, $this->em); |
||
480 | } |
||
481 | |||
482 | foreach ($mapping['joinTable']['inverseJoinColumns'] as $joinColumn) { |
||
483 | $columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform); |
||
484 | $types[] = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em); |
||
485 | 328 | } |
|
486 | |||
487 | 328 | return array( |
|
488 | 328 | 'INSERT INTO ' . $this->quoteStrategy->getJoinTableName($mapping, $class, $this->platform) |
|
489 | 328 | . ' (' . implode(', ', $columns) . ')' |
|
490 | 328 | . ' VALUES' |
|
491 | 328 | . ' (' . implode(', ', array_fill(0, count($columns), '?')) . ')', |
|
492 | $types, |
||
493 | 328 | ); |
|
494 | 328 | } |
|
495 | 328 | ||
496 | /** |
||
497 | * Gets the SQL parameters for the corresponding SQL statement to insert the given |
||
498 | 328 | * element of the given collection into the database. |
|
499 | 328 | * |
|
500 | 328 | * Internal note: Order of the parameters must be the same as the order of the columns in getInsertRowSql. |
|
501 | * |
||
502 | * @param \Doctrine\ORM\PersistentCollection $collection |
||
503 | * @param mixed $element |
||
504 | 328 | * |
|
505 | 328 | * @return array |
|
506 | 328 | */ |
|
507 | 328 | protected function getInsertRowSQLParameters(PersistentCollection $collection, $element) |
|
511 | |||
512 | /** |
||
513 | * Collects the parameters for inserting/deleting on the join table in the order |
||
514 | * of the join table columns as specified in ManyToManyMapping#joinTableColumns. |
||
515 | * |
||
516 | * @param \Doctrine\ORM\PersistentCollection $collection |
||
517 | * @param object $element |
||
518 | * |
||
519 | * @return array |
||
520 | */ |
||
521 | private function collectJoinTableColumnParameters(PersistentCollection $collection, $element) |
||
522 | { |
||
523 | 328 | $params = array(); |
|
524 | $mapping = $collection->getMapping(); |
||
525 | 328 | $isComposite = count($mapping['joinTableColumns']) > 2; |
|
526 | |||
527 | $identifier1 = $this->uow->getEntityIdentifier($collection->getOwner()); |
||
555 | 307 | ||
556 | /** |
||
557 | 307 | * @param \Doctrine\ORM\PersistentCollection $collection |
|
558 | * @param string $key |
||
559 | * @param boolean $addFilters Whether the filter SQL should be included or not. |
||
560 | 21 | * |
|
561 | 21 | * @return array ordered vector: |
|
562 | * - quoted join table name |
||
563 | 21 | * - where clauses to be added for filtering |
|
564 | * - parameters to be bound for filtering |
||
565 | * - types of the parameters to be bound for filtering |
||
566 | 21 | */ |
|
567 | private function getJoinTableRestrictionsWithKey(PersistentCollection $collection, $key, $addFilters) |
||
640 | 4 | ||
641 | 7 | /** |
|
642 | * @param \Doctrine\ORM\PersistentCollection $collection |
||
643 | * @param object $element |
||
644 | * @param boolean $addFilters Whether the filter SQL should be included or not. |
||
645 | 7 | * |
|
646 | 7 | * @return array ordered vector: |
|
647 | * - quoted join table name |
||
648 | 7 | * - where clauses to be added for filtering |
|
649 | * - parameters to be bound for filtering |
||
650 | * - types of the parameters to be bound for filtering |
||
651 | */ |
||
652 | private function getJoinTableRestrictions(PersistentCollection $collection, $element, $addFilters) |
||
706 | 9 | ||
707 | /** |
||
708 | * @param QueryBuilder $queryBuilder |
||
709 | 9 | * @param Criteria $criteria |
|
710 | 7 | * @param ClassMetadata $targetClass |
|
711 | */ |
||
712 | 7 | private function applyCriteriaOrdering(QueryBuilder $queryBuilder, Criteria $criteria, ClassMetadata $targetClass) |
|
727 | |||
728 | /** |
||
729 | * @param QueryBuilder $queryBuilder |
||
730 | * @param Criteria $criteria |
||
731 | 7 | */ |
|
732 | private function applyCriteriaLimit(QueryBuilder $queryBuilder, Criteria $criteria) |
||
737 | |||
738 | /** |
||
739 | 2 | * @param PersistentCollection $collection |
|
740 | * @return \Doctrine\DBAL\Query\QueryBuilder |
||
741 | 2 | */ |
|
742 | private function createQueryBuilderForAssociation(PersistentCollection $collection) |
||
783 | } |
||
784 |
This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.
Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.