Failed Conditions
Pull Request — master (#7210)
by Michael
12:25
created

InvalidArgument::invalidAssociation()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 1
nop 3
dl 0
loc 10
ccs 8
cts 8
cp 1
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\ORM\Exception;
6
7
use Doctrine\ORM\Mapping\AssociationMetadata;
8
use Doctrine\ORM\Mapping\ClassMetadata;
9
use function array_map;
10
use function count;
11
use function get_class;
12
use function gettype;
13
use function implode;
14
use function is_object;
15
use function method_exists;
16
use function reset;
17
use function spl_object_id;
18
use function sprintf;
19
20
/**
21
 * Contains exception messages for all invalid lifecycle state exceptions inside UnitOfWork
22
 *
23
 * @todo Split into smaller exceptions.
24
 */
25
final class InvalidArgument extends \InvalidArgumentException
26
{
27
    /**
28
     * @param object $entity
29
     *
30
     * @return InvalidArgument
31
     */
32 1
    public static function scheduleInsertForManagedEntity($entity)
33
    {
34 1
        return new self('A managed+dirty entity ' . self::objToStr($entity) . ' can not be scheduled for insertion.');
35
    }
36
37
    /**
38
     * @param object $entity
39
     *
40
     * @return InvalidArgument
41
     */
42 1
    public static function scheduleInsertForRemovedEntity($entity)
43
    {
44 1
        return new self('Removed entity ' . self::objToStr($entity) . ' can not be scheduled for insertion.');
45
    }
46
47
    /**
48
     * @param object $entity
49
     *
50
     * @return InvalidArgument
51
     */
52 1
    public static function scheduleInsertTwice($entity)
53
    {
54 1
        return new self('Entity ' . self::objToStr($entity) . ' can not be scheduled for insertion twice.');
55
    }
56
57
    /**
58
     * @param string $className
59
     * @param object $entity
60
     *
61
     * @return InvalidArgument
62
     */
63 6
    public static function entityWithoutIdentity($className, $entity)
64
    {
65 6
        return new self(
66 6
            "The given entity of type '" . $className . "' (" . self::objToStr($entity) . ') has no identity/no ' .
67 6
            'id values set. It cannot be added to the identity map.'
68
        );
69
    }
70
71
    /**
72
     * @param object $entity
73
     *
74
     * @return InvalidArgument
75
     */
76 1
    public static function readOnlyRequiresManagedEntity($entity)
77
    {
78 1
        return new self('Only managed entities can be marked or checked as read only. But ' . self::objToStr($entity) . ' is not');
79
    }
80
81
    /**
82
     * @param array[][]|object[][] $newEntitiesWithAssociations non-empty an array of [$associationMetadata, $entity] pairs
83
     *
84
     * @return InvalidArgument
85
     */
86 4
    public static function newEntitiesFoundThroughRelationships($newEntitiesWithAssociations)
87
    {
88 4
        $errorMessages = array_map(
89
            function (array $newEntityWithAssociation) : string {
90 4
                [$associationMetadata, $entity] = $newEntityWithAssociation;
91
92 4
                return self::newEntityFoundThroughRelationshipMessage($associationMetadata, $entity);
93 4
            },
94 4
            $newEntitiesWithAssociations
95
        );
96
97 4
        if (count($errorMessages) === 1) {
98 4
            return new self(reset($errorMessages));
99
        }
100
101
        return new self(
102
            'Multiple non-persisted new entities were found through the given association graph:'
103
            . "\n\n * "
104
            . implode("\n * ", $errorMessages)
105
        );
106
    }
107
108
    /**
109
     * @param object $entry
110
     *
111
     * @return InvalidArgument
112
     */
113
    public static function newEntityFoundThroughRelationship(AssociationMetadata $association, $entry)
114
    {
115
        $message = "A new entity was found through the relationship '%s#%s' that was not configured to cascade "
116
            . 'persist operations for entity: %s. To solve this issue: Either explicitly call EntityManager#persist() '
117
            . 'on this unknown entity or configure cascade persist this association in the mapping for example '
118
            . '@ManyToOne(..,cascade={"persist"}).%s';
119
120
        $messageAppend = method_exists($entry, '__toString')
121
            ? ''
122
            : " If you cannot find out which entity causes the problem implement '%s#__toString()' to get a clue."
123
        ;
124
125
        return new self(sprintf(
126
            $message,
127
            $association->getSourceEntity(),
128
            $association->getName(),
129
            self::objToStr($entry),
130
            sprintf($messageAppend, $association->getTargetEntity())
131
        ));
132
    }
133
134
    /**
135
     * @param object $entry
136
     *
137
     * @return InvalidArgument
138
     */
139
    public static function detachedEntityFoundThroughRelationship(AssociationMetadata $association, $entry)
140
    {
141
        $messsage = "A detached entity of type %s (%s) was found through the relationship '%s#%s' during cascading a persist operation.";
142
143
        return new self(sprintf(
144
            $messsage,
145
            $association->getTargetEntity(),
146
            self::objToStr($entry),
147
            $association->getSourceEntity(),
148
            $association->getName()
149
        ));
150
    }
151
152
    /**
153
     * @param object $entity
154
     *
155
     * @return InvalidArgument
156
     */
157 1
    public static function entityNotManaged($entity)
158
    {
159 1
        return new self('Entity ' . self::objToStr($entity) . ' is not managed. An entity is managed if its fetched ' .
160 1
            'from the database or registered as new through EntityManager#persist');
161
    }
162
163
    /**
164
     * @param object $entity
165
     * @param string $operation
166
     *
167
     * @return InvalidArgument
168
     */
169
    public static function entityHasNoIdentity($entity, $operation)
170
    {
171
        return new self('Entity has no identity, therefore ' . $operation . ' cannot be performed. ' . self::objToStr($entity));
172
    }
173
174
    /**
175
     * @param object $entity
176
     * @param string $operation
177
     *
178
     * @return InvalidArgument
179
     */
180
    public static function entityIsRemoved($entity, $operation)
181
    {
182
        return new self('Entity is removed, therefore ' . $operation . ' cannot be performed. ' . self::objToStr($entity));
183
    }
184
185
    /**
186
     * @param object $entity
187
     * @param string $operation
188
     *
189
     * @return InvalidArgument
190
     */
191
    public static function detachedEntityCannot($entity, $operation)
192
    {
193
        return new self('Detached entity ' . self::objToStr($entity) . ' cannot be ' . $operation);
194
    }
195
196
    /**
197
     * @param string $context
198
     * @param mixed  $given
199
     * @param int    $parameterIndex
200
     *
201
     * @return InvalidArgument
202
     */
203 3
    public static function invalidObject($context, $given, $parameterIndex = 1)
204
    {
205 3
        return new self($context . ' expects parameter ' . $parameterIndex .
206 3
            ' to be an entity object, ' . gettype($given) . ' given.');
207
    }
208
209
    /**
210
     * @return InvalidArgument
211
     */
212
    public static function invalidCompositeIdentifier()
213
    {
214
        return new self('Binding an entity with a composite primary key to a query is not supported. ' .
215
            'You should split the parameter into the explicit fields and bind them separately.');
216
    }
217
218
    /**
219
     * @return InvalidArgument
220
     */
221 1
    public static function invalidIdentifierBindingEntity()
222
    {
223 1
        return new self('Binding entities to query parameters only allowed for entities that have an identifier.');
224
    }
225
226
    /**
227
     * @param mixed $actualValue
228
     *
229
     * @return self
230
     */
231 15
    public static function invalidAssociation(ClassMetadata $targetClass, AssociationMetadata $association, $actualValue)
232
    {
233 15
        $expectedType = $targetClass->getClassName();
234
235 15
        return new self(sprintf(
236 15
            'Expected value of type "%s" for association field "%s#$%s", got "%s" instead.',
237 15
            $expectedType,
238 15
            $association->getSourceEntity(),
239 15
            $association->getName(),
240 15
            is_object($actualValue) ? get_class($actualValue) : gettype($actualValue)
241
        ));
242
    }
243
244
    /**
245
     * Helper method to show an object as string.
246
     *
247
     * @param object $obj
248
     */
249 15
    private static function objToStr($obj) : string
250
    {
251 15
        return method_exists($obj, '__toString') ? (string) $obj : get_class($obj) . '@' . spl_object_id($obj);
252
    }
253
254
    /**
255
     * @param object $entity
256
     */
257 4
    private static function newEntityFoundThroughRelationshipMessage(AssociationMetadata $association, $entity) : string
258
    {
259
        return 'A new entity was found through the relationship \''
260 4
            . $association->getSourceEntity() . '#' . $association->getName() . '\' that was not'
261 4
            . ' configured to cascade persist operations for entity: ' . self::objToStr($entity) . '.'
262 4
            . ' To solve this issue: Either explicitly call EntityManager#persist()'
263 4
            . ' on this unknown entity or configure cascade persist'
264 4
            . ' this association in the mapping for example @ManyToOne(..,cascade={"persist"}).'
265 4
            . (method_exists($entity, '__toString')
266 1
                ? ''
267
                : ' If you cannot find out which entity causes the problem implement \''
268 4
                . $association->getTargetEntity() . '#__toString()\' to get a clue.'
269
            );
270
    }
271
}
272