Completed
Push — master ( a0071b...e33605 )
by Michael
12s
created

lib/Doctrine/ORM/Query/ResultSetMapping.php (1 issue)

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
10
/**
11
 * A ResultSetMapping describes how a result set of an SQL query maps to a Doctrine result.
12
 *
13
 * IMPORTANT NOTE:
14
 * The properties of this class are only public for fast internal READ access and to (drastically)
15
 * reduce the size of serialized instances for more effective caching due to better (un-)serialization
16
 * performance.
17
 *
18
 * <b>Users should use the public methods.</b>
19
 *
20
 * @todo Think about whether the number of lookup maps can be reduced.
21
 */
22
class ResultSetMapping
23
{
24
    /**
25
     * Whether the result is mixed (contains scalar values together with field values).
26
     *
27
     * @ignore
28
     * @var bool
29
     */
30
    public $isMixed = false;
31
32
    /**
33
     * Whether the result is a select statement.
34
     *
35
     * @ignore
36
     * @var bool
37
     */
38
    public $isSelect = true;
39
40
    /**
41
     * Maps alias names to class names.
42
     *
43
     * @ignore
44
     * @var string[]
45
     */
46
    public $aliasMap = [];
47
48
    /**
49
     * Maps alias names to related association field names.
50
     *
51
     * @ignore
52
     * @var string[]
53
     */
54
    public $relationMap = [];
55
56
    /**
57
     * Maps alias names to parent alias names.
58
     *
59
     * @ignore
60
     * @var string[]
61
     */
62
    public $parentAliasMap = [];
63
64
    /**
65
     * Maps column names in the result set to field names for each class.
66
     *
67
     * @ignore
68
     * @var string[]
69
     */
70
    public $fieldMappings = [];
71
72
    /**
73
     * Maps column names in the result set to the alias/field name to use in the mapped result.
74
     *
75
     * @ignore
76
     * @var string[]
77
     */
78
    public $scalarMappings = [];
79
80
    /**
81
     * Maps column names in the result set to the alias/field type to use in the mapped result.
82
     *
83
     * @ignore
84
     * @var Type[]
85
     */
86
    public $typeMappings = [];
87
88
    /**
89
     * Maps entities in the result set to the alias name to use in the mapped result.
90
     *
91
     * @ignore
92
     * @var string[]
93
     */
94
    public $entityMappings = [];
95
96
    /**
97
     * Maps column names of meta columns (foreign keys, discriminator columns, ...) to field names.
98
     *
99
     * @ignore
100
     * @var string[]
101
     */
102
    public $metaMappings = [];
103
104
    /**
105
     * Maps column names in the result set to the alias they belong to.
106
     *
107
     * @ignore
108
     * @var string[]
109
     */
110
    public $columnOwnerMap = [];
111
112
    /**
113
     * List of columns in the result set that are used as discriminator columns.
114
     *
115
     * @ignore
116
     * @var string[]
117
     */
118
    public $discriminatorColumns = [];
119
120
    /**
121
     * Maps alias names to field names that should be used for indexing.
122
     *
123
     * @ignore
124
     * @var string[]
125
     */
126
    public $indexByMap = [];
127
128
    /**
129
     * Map from column names to class names that declare the field the column is mapped to.
130
     *
131
     * @ignore
132
     * @var string[]
133
     */
134
    public $declaringClasses = [];
135
136
    /**
137
     * This is necessary to hydrate derivate foreign keys correctly.
138
     *
139
     * @var bool[]
140
     */
141
    public $isIdentifierColumn = [];
142
143
    /**
144
     * Maps column names in the result set to field names for each new object expression.
145
     *
146
     * @var mixed[][]
147
     */
148
    public $newObjectMappings = [];
149
150
    /**
151
     * Maps metadata parameter names to the metadata attribute.
152
     *
153
     * @var mixed[]
154
     */
155
    public $metadataParameterMapping = [];
156
157
    /**
158
     * Contains query parameter names to be resolved as discriminator values
159
     *
160
     * @var string[]
161
     */
162
    public $discriminatorParameters = [];
163
164
    /**
165
     * Adds an entity result to this ResultSetMapping.
166
     *
167
     * @param string      $class       The class name of the entity.
168
     * @param string      $alias       The alias for the class. The alias must be unique among all entity
169
     *                                 results or joined entity results within this ResultSetMapping.
170
     * @param string|null $resultAlias The result alias with which the entity result should be
171
     *                                 placed in the result structure.
172
     *
173
     * @return ResultSetMapping This ResultSetMapping instance.
174
     *
175
     * @todo Rename: addRootEntity
176
     */
177 1100
    public function addEntityResult($class, $alias, $resultAlias = null)
178
    {
179 1100
        $this->aliasMap[$alias]       = $class;
180 1100
        $this->entityMappings[$alias] = $resultAlias;
181
182 1100
        if ($resultAlias !== null) {
183 45
            $this->isMixed = true;
184
        }
185
186 1100
        return $this;
187
    }
188
189
    /**
190
     * Sets a discriminator column for an entity result or joined entity result.
191
     * The discriminator column will be used to determine the concrete class name to
192
     * instantiate.
193
     *
194
     * @param string $alias       The alias of the entity result or joined entity result the discriminator
195
     *                            column should be used for.
196
     * @param string $discrColumn The name of the discriminator column in the SQL result set.
197
     *
198
     * @return ResultSetMapping This ResultSetMapping instance.
199
     *
200
     * @todo Rename: addDiscriminatorColumn
201
     */
202 178
    public function setDiscriminatorColumn($alias, $discrColumn)
203
    {
204 178
        $this->discriminatorColumns[$alias] = $discrColumn;
205 178
        $this->columnOwnerMap[$discrColumn] = $alias;
206
207 178
        return $this;
208
    }
209
210
    /**
211
     * Sets a field to use for indexing an entity result or joined entity result.
212
     *
213
     * @param string $alias     The alias of an entity result or joined entity result.
214
     * @param string $fieldName The name of the field to use for indexing.
215
     *
216
     * @return ResultSetMapping This ResultSetMapping instance.
217
     */
218 42
    public function addIndexBy($alias, $fieldName)
219
    {
220 42
        $found = false;
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 40
            $found = true;
229
230 40
            break;
231
        }
232
233
        /* TODO: check if this exception can be put back, for now it's gone because of assumptions made by some ORM internals
234
        if ( ! $found) {
235
            $message = sprintf(
236
                'Cannot add index by for DQL alias %s and field %s without calling addFieldResult() for them before.',
237
                $alias,
238
                $fieldName
239
            );
240
241
            throw new \LogicException($message);
242
        }
243
        */
244
245 42
        return $this;
246
    }
247
248
    /**
249
     * Sets to index by a scalar result column name.
250
     *
251
     * @param string $resultColumnName
252
     *
253
     * @return ResultSetMapping This ResultSetMapping instance.
254
     */
255 3
    public function addIndexByScalar($resultColumnName)
256
    {
257 3
        $this->indexByMap['scalars'] = $resultColumnName;
258
259 3
        return $this;
260
    }
261
262
    /**
263
     * Sets a column to use for indexing an entity or joined entity result by the given alias name.
264
     *
265
     * @param string $alias
266
     * @param string $resultColumnName
267
     *
268
     * @return ResultSetMapping This ResultSetMapping instance.
269
     */
270 41
    public function addIndexByColumn($alias, $resultColumnName)
271
    {
272 41
        $this->indexByMap[$alias] = $resultColumnName;
273
274 41
        return $this;
275
    }
276
277
    /**
278
     * Checks whether an entity result or joined entity result with a given alias has
279
     * a field set for indexing.
280
     *
281
     * @param string $alias
282
     *
283
     * @return bool
284
     *
285
     * @todo Rename: isIndexed($alias)
286
     */
287 2
    public function hasIndexBy($alias)
288
    {
289 2
        return isset($this->indexByMap[$alias]);
290
    }
291
292
    /**
293
     * Checks whether the column with the given name is mapped as a field result
294
     * as part of an entity result or joined entity result.
295
     *
296
     * @param string $columnName The name of the column in the SQL result set.
297
     *
298
     * @return bool
299
     *
300
     * @todo Rename: isField
301
     */
302 1
    public function isFieldResult($columnName)
303
    {
304 1
        return isset($this->fieldMappings[$columnName]);
305
    }
306
307
    /**
308
     * Adds a field to the result that belongs to an entity or joined entity.
309
     *
310
     * @param string      $alias          The alias of the root entity or joined entity to which the field belongs.
311
     * @param string      $columnName     The name of the column in the SQL result set.
312
     * @param string      $fieldName      The name of the field on the declaring class.
313
     * @param string|null $declaringClass The name of the class that declares/owns the specified field.
314
     *                                    When $alias refers to a superclass in a mapped hierarchy but
315
     *                                    the field $fieldName is defined on a subclass, specify that here.
316
     *                                    If not specified, the field is assumed to belong to the class
317
     *                                    designated by $alias.
318
     *
319
     * @return ResultSetMapping This ResultSetMapping instance.
320
     *
321
     * @todo Rename: addField
322
     */
323 1084
    public function addFieldResult($alias, $columnName, $fieldName, $declaringClass = null)
324
    {
325
        // column name (in result set) => field name
326 1084
        $this->fieldMappings[$columnName] = $fieldName;
327
        // column name => alias of owner
328 1084
        $this->columnOwnerMap[$columnName] = $alias;
329
        // field name => class name of declaring class
330 1084
        $this->declaringClasses[$columnName] = $declaringClass ?: $this->aliasMap[$alias];
331
332 1084
        if (! $this->isMixed && $this->scalarMappings) {
333 10
            $this->isMixed = true;
334
        }
335
336 1084
        return $this;
337
    }
338
339
    /**
340
     * Adds a joined entity result.
341
     *
342
     * @param string $class       The class name of the joined entity.
343
     * @param string $alias       The unique alias to use for the joined entity.
344
     * @param string $parentAlias The alias of the entity result that is the parent of this joined result.
345
     * @param string $relation    The association field that connects the parent entity result
346
     *                            with the joined entity result.
347
     *
348
     * @return ResultSetMapping This ResultSetMapping instance.
349
     *
350
     * @todo Rename: addJoinedEntity
351
     */
352 372
    public function addJoinedEntityResult($class, $alias, $parentAlias, $relation)
353
    {
354 372
        $this->aliasMap[$alias]       = $class;
355 372
        $this->parentAliasMap[$alias] = $parentAlias;
356 372
        $this->relationMap[$alias]    = $relation;
357
358 372
        return $this;
359
    }
360
361
    /**
362
     * Adds a scalar result mapping.
363
     *
364
     * @param string $columnName The name of the column in the SQL result set.
365
     * @param string $alias      The result alias with which the scalar result should be placed in the result structure.
366
     * @param Type   $type       The column type
367
     *
368
     * @return ResultSetMapping This ResultSetMapping instance.
369
     *
370
     * @todo Rename: addScalar
371
     */
372 345
    public function addScalarResult($columnName, $alias, Type $type)
373
    {
374 345
        $this->scalarMappings[$columnName] = $alias;
375 345
        $this->typeMappings[$columnName]   = $type;
376
377 345
        if (! $this->isMixed && $this->fieldMappings) {
378 120
            $this->isMixed = true;
379
        }
380
381 345
        return $this;
382
    }
383
384
    /**
385
     * Checks whether a column with a given name is mapped as a scalar result.
386
     *
387
     * @param string $columnName The name of the column in the SQL result set.
388
     *
389
     * @return bool
390
     *
391
     * @todo Rename: isScalar
392
     */
393 2
    public function isScalarResult($columnName)
394
    {
395 2
        return isset($this->scalarMappings[$columnName]);
396
    }
397
398
    /**
399
     * Gets the name of the class of an entity result or joined entity result,
400
     * identified by the given unique alias.
401
     *
402
     * @param string $alias
403
     *
404
     * @return string
405
     */
406 7
    public function getClassName($alias)
407
    {
408 7
        return $this->aliasMap[$alias];
409
    }
410
411
    /**
412
     * Gets the field alias for a column that is mapped as a scalar value.
413
     *
414
     * @param string $columnName The name of the column in the SQL result set.
415
     *
416
     * @return string
417
     */
418 2
    public function getScalarAlias($columnName)
419
    {
420 2
        return $this->scalarMappings[$columnName];
421
    }
422
423
    /**
424
     * Gets the name of the class that owns a field mapping for the specified column.
425
     *
426
     * @param string $columnName
427
     *
428
     * @return string
429
     */
430 4
    public function getDeclaringClass($columnName)
431
    {
432 4
        return $this->declaringClasses[$columnName];
433
    }
434
435
    /**
436
     * @param string $alias
437
     *
438
     * @return AssociationMetadata
439
     */
440
    public function getRelation($alias)
441
    {
442
        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...
443
    }
444
445
    /**
446
     * @param string $alias
447
     *
448
     * @return bool
449
     */
450 1
    public function isRelation($alias)
451
    {
452 1
        return isset($this->relationMap[$alias]);
453
    }
454
455
    /**
456
     * Gets the alias of the class that owns a field mapping for the specified column.
457
     *
458
     * @param string $columnName
459
     *
460
     * @return string
461
     */
462 4
    public function getEntityAlias($columnName)
463
    {
464 4
        return $this->columnOwnerMap[$columnName];
465
    }
466
467
    /**
468
     * Gets the parent alias of the given alias.
469
     *
470
     * @param string $alias
471
     *
472
     * @return string
473
     */
474
    public function getParentAlias($alias)
475
    {
476
        return $this->parentAliasMap[$alias];
477
    }
478
479
    /**
480
     * Checks whether the given alias has a parent alias.
481
     *
482
     * @param string $alias
483
     *
484
     * @return bool
485
     */
486 1
    public function hasParentAlias($alias)
487
    {
488 1
        return isset($this->parentAliasMap[$alias]);
489
    }
490
491
    /**
492
     * Gets the field name for a column name.
493
     *
494
     * @param string $columnName
495
     *
496
     * @return string
497
     */
498 1
    public function getFieldName($columnName)
499
    {
500 1
        return $this->fieldMappings[$columnName];
501
    }
502
503
    /**
504
     * @return string[]
505
     */
506
    public function getAliasMap()
507
    {
508
        return $this->aliasMap;
509
    }
510
511
    /**
512
     * Gets the number of different entities that appear in the mapped result.
513
     *
514
     * @return int
515
     */
516
    public function getEntityResultCount()
517
    {
518
        return count($this->aliasMap);
519
    }
520
521
    /**
522
     * Checks whether this ResultSetMapping defines a mixed result.
523
     *
524
     * Mixed results can only occur in object and array (graph) hydration. In such a
525
     * case a mixed result means that scalar values are mixed with objects/array in
526
     * the result.
527
     *
528
     * @return bool
529
     */
530 1
    public function isMixedResult()
531
    {
532 1
        return $this->isMixed;
533
    }
534
535
    /**
536
     * Adds a meta column (foreign key or discriminator column) to the result set.
537
     *
538
     * @param string $alias              The result alias with which the meta result should be placed in the result structure.
539
     * @param string $columnName         The name of the column in the SQL result set.
540
     * @param string $fieldName          The name of the field on the declaring class.
541
     * @param bool   $isIdentifierColumn
542
     * @param Type   $type               The column type
543
     *
544
     * @return ResultSetMapping This ResultSetMapping instance.
545
     */
546 738
    public function addMetaResult($alias, $columnName, $fieldName, $isIdentifierColumn, Type $type)
547
    {
548 738
        $this->metaMappings[$columnName]   = $fieldName;
549 738
        $this->columnOwnerMap[$columnName] = $alias;
550 738
        $this->typeMappings[$columnName]   = $type;
551
552 738
        if ($isIdentifierColumn) {
553 65
            $this->isIdentifierColumn[$alias][$columnName] = true;
554
        }
555
556 738
        return $this;
557
    }
558
}
559