Failed Conditions
Pull Request — master (#7297)
by Gabriel
11:59
created

ResultSetMapping::setDiscriminatorColumn()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 6
ccs 4
cts 4
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\ORM\Query;
6
7
use Doctrine\DBAL\Types\Type;
8
use Doctrine\ORM\Mapping\AssociationMetadata;
9
use function array_merge;
10
use function count;
11
12
/**
13
 * A ResultSetMapping describes how a result set of an SQL query maps to a Doctrine result.
14
 *
15
 * IMPORTANT NOTE:
16
 * The properties of this class are only public for fast internal READ access and to (drastically)
17
 * reduce the size of serialized instances for more effective caching due to better (un-)serialization
18
 * performance.
19
 *
20
 * <b>Users should use the public methods.</b>
21
 *
22
 * @todo Think about whether the number of lookup maps can be reduced.
23
 */
24
class ResultSetMapping
25
{
26
    /**
27
     * Whether the result is mixed (contains scalar values together with field values).
28
     *
29
     * @ignore
30
     * @var bool
31
     */
32
    public $isMixed = false;
33
34
    /**
35
     * Whether the result is a select statement.
36
     *
37
     * @ignore
38
     * @var bool
39
     */
40
    public $isSelect = true;
41
42
    /**
43
     * Maps alias names to class names.
44
     *
45
     * @ignore
46
     * @var string[]
47
     */
48
    public $aliasMap = [];
49
50
    /**
51
     * Maps alias names to related association field names.
52
     *
53
     * @ignore
54
     * @var string[]
55
     */
56
    public $relationMap = [];
57
58
    /**
59
     * Maps alias names to parent alias names.
60
     *
61
     * @ignore
62
     * @var string[]
63
     */
64
    public $parentAliasMap = [];
65
66
    /**
67
     * Maps column names in the result set to field names for each class.
68
     *
69
     * @ignore
70
     * @var string[]
71
     */
72
    public $fieldMappings = [];
73
74
    /**
75
     * Maps column names in the result set to the alias/field name to use in the mapped result.
76
     *
77
     * @ignore
78
     * @var string[]
79
     */
80
    public $scalarMappings = [];
81
82
    /**
83
     * Maps column names in the result set to the alias/field type to use in the mapped result.
84
     *
85
     * @ignore
86
     * @var Type[]
87
     */
88
    public $typeMappings = [];
89
90
    /**
91
     * Maps entities in the result set to the alias name to use in the mapped result.
92
     *
93
     * @ignore
94
     * @var string[]
95
     */
96
    public $entityMappings = [];
97
98
    /**
99
     * Maps column names of meta columns (foreign keys, discriminator columns, ...) to field names.
100
     *
101
     * @ignore
102
     * @var string[]
103
     */
104
    public $metaMappings = [];
105
106
    /**
107
     * Maps column names in the result set to the alias they belong to.
108
     *
109
     * @ignore
110
     * @var string[]
111
     */
112
    public $columnOwnerMap = [];
113
114
    /**
115
     * List of columns in the result set that are used as discriminator columns.
116
     *
117
     * @ignore
118
     * @var string[]
119
     */
120
    public $discriminatorColumns = [];
121
122
    /**
123
     * Maps alias names to field names that should be used for indexing.
124
     *
125
     * @ignore
126
     * @var string[]
127
     */
128
    public $indexByMap = [];
129
130
    /**
131
     * Map from column names to class names that declare the field the column is mapped to.
132
     *
133
     * @ignore
134
     * @var string[]
135
     */
136
    public $declaringClasses = [];
137
138
    /**
139
     * This is necessary to hydrate derivate foreign keys correctly.
140
     *
141
     * @var bool[][]
142
     */
143
    public $isIdentifierColumn = [];
144
145
    /**
146
     * Maps column names in the result set to field names for each new object expression.
147
     *
148
     * @var mixed[][]
149
     */
150
    public $newObjectMappings = [];
151
152
    /**
153
     * Maps metadata parameter names to the metadata attribute.
154
     *
155
     * @var mixed[]
156
     */
157
    public $metadataParameterMapping = [];
158
159
    /**
160
     * Contains query parameter names to be resolved as discriminator values
161
     *
162
     * @var string[]
163
     */
164
    public $discriminatorParameters = [];
165
166
    /**
167
     * Adds an entity result to this ResultSetMapping.
168
     *
169
     * @param string      $class       The class name of the entity.
170
     * @param string      $alias       The alias for the class. The alias must be unique among all entity
171
     *                                 results or joined entity results within this ResultSetMapping.
172
     * @param string|null $resultAlias The result alias with which the entity result should be
173
     *                                 placed in the result structure.
174
     *
175
     * @return ResultSetMapping This ResultSetMapping instance.
176
     *
177
     * @todo Rename: addRootEntity
178
     */
179 1084
    public function addEntityResult($class, $alias, $resultAlias = null)
180
    {
181 1084
        $this->aliasMap[$alias]       = $class;
182 1084
        $this->entityMappings[$alias] = $resultAlias;
183
184 1084
        if ($resultAlias !== null) {
185 45
            $this->isMixed = true;
186
        }
187
188 1084
        return $this;
189
    }
190
191
    /**
192
     * Sets a discriminator column for an entity result or joined entity result.
193
     * The discriminator column will be used to determine the concrete class name to
194
     * instantiate.
195
     *
196
     * @param string $alias       The alias of the entity result or joined entity result the discriminator
197
     *                            column should be used for.
198
     * @param string $discrColumn The name of the discriminator column in the SQL result set.
199
     *
200
     * @return ResultSetMapping This ResultSetMapping instance.
201
     *
202
     * @todo Rename: addDiscriminatorColumn
203
     */
204 181
    public function setDiscriminatorColumn($alias, $discrColumn)
205
    {
206 181
        $this->discriminatorColumns[$alias] = $discrColumn;
207 181
        $this->columnOwnerMap[$discrColumn] = $alias;
208
209 181
        return $this;
210
    }
211
212
    /**
213
     * Sets a field to use for indexing an entity result or joined entity result.
214
     *
215
     * @param string $alias     The alias of an entity result or joined entity result.
216
     * @param string $fieldName The name of the field to use for indexing.
217
     *
218
     * @return ResultSetMapping This ResultSetMapping instance.
219
     */
220 42
    public function addIndexBy($alias, $fieldName)
221
    {
222 42
        foreach (array_merge($this->metaMappings, $this->fieldMappings) as $columnName => $columnFieldName) {
223 42
            if (! ($columnFieldName === $fieldName && $this->columnOwnerMap[$columnName] === $alias)) {
224 32
                continue;
225
            }
226
227 40
            $this->addIndexByColumn($alias, $columnName);
228
229 40
            break;
230
        }
231
232
        /* TODO: check if this exception can be put back, for now it's gone because of assumptions made by some ORM internals
233
        if ( ! $found) {
234
            $message = sprintf(
235
                'Cannot add index by for DQL alias %s and field %s without calling addFieldResult() for them before.',
236
                $alias,
237
                $fieldName
238
            );
239
240
            throw new \LogicException($message);
241
        }
242
        */
243
244 42
        return $this;
245
    }
246
247
    /**
248
     * Sets to index by a scalar result column name.
249
     *
250
     * @param string $resultColumnName
251
     *
252
     * @return ResultSetMapping This ResultSetMapping instance.
253
     */
254 3
    public function addIndexByScalar($resultColumnName)
255
    {
256 3
        $this->indexByMap['scalars'] = $resultColumnName;
257
258 3
        return $this;
259
    }
260
261
    /**
262
     * Sets a column to use for indexing an entity or joined entity result by the given alias name.
263
     *
264
     * @param string $alias
265
     * @param string $resultColumnName
266
     *
267
     * @return ResultSetMapping This ResultSetMapping instance.
268
     */
269 41
    public function addIndexByColumn($alias, $resultColumnName)
270
    {
271 41
        $this->indexByMap[$alias] = $resultColumnName;
272
273 41
        return $this;
274
    }
275
276
    /**
277
     * Checks whether an entity result or joined entity result with a given alias has
278
     * a field set for indexing.
279
     *
280
     * @param string $alias
281
     *
282
     * @return bool
283
     *
284
     * @todo Rename: isIndexed($alias)
285
     */
286 2
    public function hasIndexBy($alias)
287
    {
288 2
        return isset($this->indexByMap[$alias]);
289
    }
290
291
    /**
292
     * Checks whether the column with the given name is mapped as a field result
293
     * as part of an entity result or joined entity result.
294
     *
295
     * @param string $columnName The name of the column in the SQL result set.
296
     *
297
     * @return bool
298
     *
299
     * @todo Rename: isField
300
     */
301 1
    public function isFieldResult($columnName)
302
    {
303 1
        return isset($this->fieldMappings[$columnName]);
304
    }
305
306
    /**
307
     * Adds a field to the result that belongs to an entity or joined entity.
308
     *
309
     * @param string      $alias          The alias of the root entity or joined entity to which the field belongs.
310
     * @param string      $columnName     The name of the column in the SQL result set.
311
     * @param string      $fieldName      The name of the field on the declaring class.
312
     * @param string|null $declaringClass The name of the class that declares/owns the specified field.
313
     *                                    When $alias refers to a superclass in a mapped hierarchy but
314
     *                                    the field $fieldName is defined on a subclass, specify that here.
315
     *                                    If not specified, the field is assumed to belong to the class
316
     *                                    designated by $alias.
317
     *
318
     * @return ResultSetMapping This ResultSetMapping instance.
319
     *
320
     * @todo Rename: addField
321
     */
322 1068
    public function addFieldResult($alias, $columnName, $fieldName, $declaringClass = null)
323
    {
324
        // column name (in result set) => field name
325 1068
        $this->fieldMappings[$columnName] = $fieldName;
326
        // column name => alias of owner
327 1068
        $this->columnOwnerMap[$columnName] = $alias;
328
        // field name => class name of declaring class
329 1068
        $this->declaringClasses[$columnName] = $declaringClass ?: $this->aliasMap[$alias];
330
331 1068
        if (! $this->isMixed && $this->scalarMappings) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->scalarMappings of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
332 10
            $this->isMixed = true;
333
        }
334
335 1068
        return $this;
336
    }
337
338
    /**
339
     * Adds a joined entity result.
340
     *
341
     * @param string $class       The class name of the joined entity.
342
     * @param string $alias       The unique alias to use for the joined entity.
343
     * @param string $parentAlias The alias of the entity result that is the parent of this joined result.
344
     * @param string $relation    The association field that connects the parent entity result
345
     *                            with the joined entity result.
346
     *
347
     * @return ResultSetMapping This ResultSetMapping instance.
348
     *
349
     * @todo Rename: addJoinedEntity
350
     */
351 367
    public function addJoinedEntityResult($class, $alias, $parentAlias, $relation)
352
    {
353 367
        $this->aliasMap[$alias]       = $class;
354 367
        $this->parentAliasMap[$alias] = $parentAlias;
355 367
        $this->relationMap[$alias]    = $relation;
356
357 367
        return $this;
358
    }
359
360
    /**
361
     * Adds a scalar result mapping.
362
     *
363
     * @param string $columnName The name of the column in the SQL result set.
364
     * @param string $alias      The result alias with which the scalar result should be placed in the result structure.
365
     * @param Type   $type       The column type
366
     *
367
     * @return ResultSetMapping This ResultSetMapping instance.
368
     *
369
     * @todo Rename: addScalar
370
     */
371 341
    public function addScalarResult($columnName, $alias, Type $type)
372
    {
373 341
        $this->scalarMappings[$columnName] = $alias;
374 341
        $this->typeMappings[$columnName]   = $type;
375
376 341
        if (! $this->isMixed && $this->fieldMappings) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->fieldMappings of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
377 116
            $this->isMixed = true;
378
        }
379
380 341
        return $this;
381
    }
382
383
    /**
384
     * Checks whether a column with a given name is mapped as a scalar result.
385
     *
386
     * @param string $columnName The name of the column in the SQL result set.
387
     *
388
     * @return bool
389
     *
390
     * @todo Rename: isScalar
391
     */
392 2
    public function isScalarResult($columnName)
393
    {
394 2
        return isset($this->scalarMappings[$columnName]);
395
    }
396
397
    /**
398
     * Gets the name of the class of an entity result or joined entity result,
399
     * identified by the given unique alias.
400
     *
401
     * @param string $alias
402
     *
403
     * @return string
404
     */
405 2
    public function getClassName($alias)
406
    {
407 2
        return $this->aliasMap[$alias];
408
    }
409
410
    /**
411
     * Gets the field alias for a column that is mapped as a scalar value.
412
     *
413
     * @param string $columnName The name of the column in the SQL result set.
414
     *
415
     * @return string
416
     */
417
    public function getScalarAlias($columnName)
418
    {
419
        return $this->scalarMappings[$columnName];
420
    }
421
422
    /**
423
     * Gets the name of the class that owns a field mapping for the specified column.
424
     *
425
     * @param string $columnName
426
     *
427
     * @return string
428
     */
429 1
    public function getDeclaringClass($columnName)
430
    {
431 1
        return $this->declaringClasses[$columnName];
432
    }
433
434
    /**
435
     * @param string $alias
436
     *
437
     * @return AssociationMetadata
438
     */
439
    public function getRelation($alias)
440
    {
441
        return $this->relationMap[$alias];
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->relationMap[$alias] returns the type string which is incompatible with the documented return type Doctrine\ORM\Mapping\AssociationMetadata.
Loading history...
442
    }
443
444
    /**
445
     * @param string $alias
446
     *
447
     * @return bool
448
     */
449 1
    public function isRelation($alias)
450
    {
451 1
        return isset($this->relationMap[$alias]);
452
    }
453
454
    /**
455
     * Gets the alias of the class that owns a field mapping for the specified column.
456
     *
457
     * @param string $columnName
458
     *
459
     * @return string
460
     */
461 1
    public function getEntityAlias($columnName)
462
    {
463 1
        return $this->columnOwnerMap[$columnName];
464
    }
465
466
    /**
467
     * Gets the parent alias of the given alias.
468
     *
469
     * @param string $alias
470
     *
471
     * @return string
472
     */
473
    public function getParentAlias($alias)
474
    {
475
        return $this->parentAliasMap[$alias];
476
    }
477
478
    /**
479
     * Checks whether the given alias has a parent alias.
480
     *
481
     * @param string $alias
482
     *
483
     * @return bool
484
     */
485 1
    public function hasParentAlias($alias)
486
    {
487 1
        return isset($this->parentAliasMap[$alias]);
488
    }
489
490
    /**
491
     * Gets the field name for a column name.
492
     *
493
     * @param string $columnName
494
     *
495
     * @return string
496
     */
497 1
    public function getFieldName($columnName)
498
    {
499 1
        return $this->fieldMappings[$columnName];
500
    }
501
502
    /**
503
     * @return string[]
504
     */
505
    public function getAliasMap()
506
    {
507
        return $this->aliasMap;
508
    }
509
510
    /**
511
     * Gets the number of different entities that appear in the mapped result.
512
     *
513
     * @return int
514
     */
515
    public function getEntityResultCount()
516
    {
517
        return count($this->aliasMap);
518
    }
519
520
    /**
521
     * Checks whether this ResultSetMapping defines a mixed result.
522
     *
523
     * Mixed results can only occur in object and array (graph) hydration. In such a
524
     * case a mixed result means that scalar values are mixed with objects/array in
525
     * the result.
526
     *
527
     * @return bool
528
     */
529 1
    public function isMixedResult()
530
    {
531 1
        return $this->isMixed;
532
    }
533
534
    /**
535
     * Adds a meta column (foreign key or discriminator column) to the result set.
536
     *
537
     * @param string $alias              The result alias with which the meta result should be placed in the result structure.
538
     * @param string $columnName         The name of the column in the SQL result set.
539
     * @param string $fieldName          The name of the field on the declaring class.
540
     * @param bool   $isIdentifierColumn
541
     * @param Type   $type               The column type
542
     *
543
     * @return ResultSetMapping This ResultSetMapping instance.
544
     */
545 728
    public function addMetaResult($alias, $columnName, $fieldName, $isIdentifierColumn, Type $type)
546
    {
547 728
        $this->metaMappings[$columnName]   = $fieldName;
548 728
        $this->columnOwnerMap[$columnName] = $alias;
549 728
        $this->typeMappings[$columnName]   = $type;
550
551 728
        if ($isIdentifierColumn) {
552 66
            $this->isIdentifierColumn[$alias][$columnName] = true;
553
        }
554
555 728
        return $this;
556
    }
557
}
558