Completed
Push — master ( 2c86a7...690ed0 )
by
unknown
36:26 queued 28:50
created

WidgetManager::cloneEntity()   B

Complexity

Conditions 6
Paths 7

Size

Total Lines 35
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 35
rs 8.439
c 1
b 0
f 0
cc 6
eloc 22
nc 7
nop 1
1
<?php
2
3
namespace Victoire\Bundle\WidgetBundle\Model;
4
5
use Doctrine\ORM\EntityManager;
6
use Doctrine\ORM\Mapping\ClassMetadataInfo;
7
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
8
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
9
use Symfony\Component\HttpFoundation\Request;
10
use Symfony\Component\PropertyAccess\PropertyAccess;
11
use Victoire\Bundle\BusinessEntityBundle\Entity\BusinessEntity;
12
use Victoire\Bundle\BusinessEntityBundle\Reader\BusinessEntityCacheReader;
13
use Victoire\Bundle\BusinessPageBundle\Entity\VirtualBusinessPage;
14
use Victoire\Bundle\BusinessPageBundle\Transformer\VirtualToBusinessPageTransformer;
15
use Victoire\Bundle\CoreBundle\Entity\View;
16
use Victoire\Bundle\FormBundle\Helper\FormErrorHelper;
17
use Victoire\Bundle\PageBundle\Helper\PageHelper;
18
use Victoire\Bundle\WidgetBundle\Builder\WidgetFormBuilder;
19
use Victoire\Bundle\WidgetBundle\Helper\WidgetHelper;
20
use Victoire\Bundle\WidgetBundle\Renderer\WidgetRenderer;
21
use Victoire\Bundle\WidgetBundle\Resolver\WidgetContentResolver;
22
use Victoire\Bundle\WidgetMapBundle\Builder\WidgetMapBuilder;
23
use Victoire\Bundle\WidgetMapBundle\Entity\WidgetMap;
24
use Victoire\Bundle\WidgetMapBundle\Helper\WidgetMapHelper;
25
use Victoire\Bundle\WidgetMapBundle\Manager\WidgetMapManager;
26
27
/**
28
 * This manager handles crud operations on a Widget.
29
 */
30
class WidgetManager
31
{
32
    protected $widgetFormBuilder;
33
    protected $widgetHelper;
34
    protected $widgetContentResolver;
35
    protected $entityManager;
36
    protected $formErrorHelper; // @victoire_form.error_helper
37
    protected $request; // @request
38
    protected $widgetMapManager;
39
    protected $cacheReader; // @victoire_business_entity.cache_reader
40
    protected $templating;
41
    protected $pageHelper;
42
    protected $slots; // %victoire_core.slots%
43
    protected $virtualToBpTransformer; // %victoire_core.slots%
44
45
    /**
46
     * construct.
47
     *
48
     * @param WidgetHelper              $widgetHelper
49
     * @param WidgetFormBuilder         $widgetFormBuilder
50
     * @param WidgetContentResolver     $widgetContentResolver
51
     * @param WidgetRenderer            $widgetRenderer
52
     * @param EntityManager             $entityManager
53
     * @param FormErrorHelper           $formErrorHelper
54
     * @param Request                   $request
55
     * @param WidgetMapManager          $widgetMapManager
56
     * @param WidgetMapBuilder          $widgetMapBuilder
57
     * @param BusinessEntityCacheReader $cacheReader
58
     * @param EngineInterface           $templating
59
     * @param PageHelper                $pageHelper
60
     * @param array                     $slots
61
     */
62
    public function __construct(
63
        WidgetHelper $widgetHelper,
64
        WidgetFormBuilder $widgetFormBuilder,
65
        WidgetContentResolver $widgetContentResolver,
66
        WidgetRenderer $widgetRenderer,
67
        EntityManager $entityManager,
0 ignored issues
show
Bug introduced by
You have injected the EntityManager via parameter $entityManager. This is generally not recommended as it might get closed and become unusable. Instead, it is recommended to inject the ManagerRegistry and retrieve the EntityManager via getManager() each time you need it.

The EntityManager might become unusable for example if a transaction is rolled back and it gets closed. Let’s assume that somewhere in your application, or in a third-party library, there is code such as the following:

function someFunction(ManagerRegistry $registry) {
    $em = $registry->getManager();
    $em->getConnection()->beginTransaction();
    try {
        // Do something.
        $em->getConnection()->commit();
    } catch (\Exception $ex) {
        $em->getConnection()->rollback();
        $em->close();

        throw $ex;
    }
}

If that code throws an exception and the EntityManager is closed. Any other code which depends on the same instance of the EntityManager during this request will fail.

On the other hand, if you instead inject the ManagerRegistry, the getManager() method guarantees that you will always get a usable manager instance.

Loading history...
68
        FormErrorHelper $formErrorHelper,
69
        Request $request,
0 ignored issues
show
Bug introduced by
You have injected the Request via parameter $request. This is generally not recommended as there might be multiple instances during a request cycle (f.e. when using sub-requests). Instead, it is recommended to inject the RequestStack and retrieve the current request each time you need it via getCurrentRequest().
Loading history...
70
        WidgetMapManager $widgetMapManager,
71
        WidgetMapBuilder $widgetMapBuilder,
72
        BusinessEntityCacheReader $cacheReader,
73
        EngineInterface $templating,
74
        PageHelper $pageHelper,
75
        $slots,
76
        VirtualToBusinessPageTransformer $virtualToBpTransformer
77
    ) {
78
        $this->widgetFormBuilder = $widgetFormBuilder;
79
        $this->widgetHelper = $widgetHelper;
80
        $this->widgetContentResolver = $widgetContentResolver;
81
        $this->widgetRenderer = $widgetRenderer;
0 ignored issues
show
Bug introduced by
The property widgetRenderer does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
82
        $this->entityManager = $entityManager;
83
        $this->formErrorHelper = $formErrorHelper;
84
        $this->request = $request;
85
        $this->widgetMapManager = $widgetMapManager;
86
        $this->widgetMapBuilder = $widgetMapBuilder;
0 ignored issues
show
Bug introduced by
The property widgetMapBuilder does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
87
        $this->cacheReader = $cacheReader;
88
        $this->templating = $templating;
89
        $this->pageHelper = $pageHelper;
90
        $this->slots = $slots;
91
        $this->virtualToBpTransformer = $virtualToBpTransformer;
92
    }
93
94
    /**
95
     * new widget.
96
     *
97
     * @param string $type
98
     * @param string $slot
99
     * @param View   $view
100
     * @param int    $position
101
     *
102
     * @return array
103
     */
104
    public function newWidget($mode, $type, $slot, $view, $position, $parentWidgetMap, $quantum)
105
    {
106
        $widget = $this->widgetHelper->newWidgetInstance($type, $view, $slot, $mode);
107
        $widgets = ['static' => $widget];
108
109
        /** @var BusinessEntity[] $classes */
110
        $classes = $this->cacheReader->getBusinessClassesForWidget($widget);
111
        $forms = $this->widgetFormBuilder->renderNewQuantumForms($slot, $view, $widgets, $widget, $classes, $position, $parentWidgetMap, $quantum);
112
113
        return [
114
            'widget' => $widget,
115
            'html'   => $this->templating->render(
116
                'VictoireCoreBundle:Widget:Form/new.html.twig',
117
                [
118
                    'id'                 => time(),
119
                    'view'               => $view,
120
                    'slot'               => $slot,
121
                    'position'           => $position,
122
                    'parentWidgetMap'    => $parentWidgetMap,
123
                    'classes'            => $classes,
124
                    'widgets'            => $widgets,
125
                    'widget'             => $widget,
126
                    'forms'              => $forms,
127
                    'quantum'            => $quantum,
128
                ]
129
            ),
130
        ];
131
    }
132
133
    /**
134
     * Create a widget.
135
     *
136
     * @param string $mode
137
     * @param string $type
138
     * @param string $slotId
139
     * @param View   $view
140
     * @param string $entity
141
     * @param string $type
142
     *
143
     * @throws \Exception
144
     *
145
     * @return Template
146
     */
147
    public function createWidget($mode, $type, $slotId, View $view, $entity, $position, $widgetReference, $quantum)
148
    {
149
        //services
150
        $formErrorHelper = $this->formErrorHelper;
151
        $request = $this->request;
152
153
        if ($view instanceof VirtualBusinessPage) {
154
            $this->virtualToBpTransformer->transform($view);
155
        }
156
        //create a new widget
157
        $widget = $this->widgetHelper->newWidgetInstance($type, $view, $slotId, $mode);
158
159
        $form = $this->widgetFormBuilder->callBuildFormSwitchParameters($widget, $view, $entity, $position, $widgetReference, $slotId, $quantum);
160
161
        $noValidate = $request->query->get('novalidate', false);
162
163
        $form->handleRequest($request);
164
        if ($noValidate === false && $form->isValid()) {
165
            if (!$view->getId()) {
166
                //create a view for the business entity instance if we are currently on a virtual one
167
                $this->entityManager->persist($view);
168
            }
169
170
            //get the widget from the form
171
            $widget = $form->getData();
172
173
            //update fields of the widget
174
            $widget->setBusinessEntityId($entity);
175
176
            //persist the widget
177
            $this->entityManager->persist($widget);
178
            $this->entityManager->flush();
179
180
            $this->widgetMapManager->insert($widget, $view, $slotId, $position, $widgetReference);
181
182
            $this->entityManager->persist($view);
183
            $this->entityManager->flush();
184
185
            $widget->setCurrentView($view);
186
187
            $this->widgetMapBuilder->build($view);
188
189
            //get the html for the widget
190
            $htmlWidget = $this->widgetRenderer->renderContainer($widget, $view);
191
192
            $response = [
193
                'success'  => true,
194
                'widgetId' => $widget->getId(),
195
                'html'     => $htmlWidget,
196
            ];
197
        } else {
198
            //get the errors as a string
199
            $response = [
200
                'success' => false,
201
                'message' => $noValidate === false ? $formErrorHelper->getRecursiveReadableErrors($form) : null,
202
                'html'    => $this->widgetFormBuilder->renderNewForm($form, $widget, $slotId, $view, $quantum, $entity),
203
            ];
204
        }
205
206
        return $response;
207
    }
208
209
    /**
210
     * edit a widget.
211
     *
212
     * @param Request $request
213
     * @param Widget  $widget
214
     * @param View    $currentView
215
     * @param string  $businessEntityId The entity name is used to know which form to submit
216
     *
217
     * @return template
218
     */
219
    public function editWidget(Request $request, Widget $widget, View $currentView, $quantum = null, $businessEntityId = null, $widgetMode = Widget::MODE_STATIC)
220
    {
221
        /** @var BusinessEntity[] $classes */
222
        $classes = $this->cacheReader->getBusinessClassesForWidget($widget);
0 ignored issues
show
Compatibility introduced by
$widget of type object<Victoire\Bundle\WidgetBundle\Model\Widget> is not a sub-type of object<Victoire\Bundle\W...etBundle\Entity\Widget>. It seems like you assume a child class of the class Victoire\Bundle\WidgetBundle\Model\Widget to be always present.

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.

Loading history...
223
224
        //the id of the edited widget
225
        //a new widget might be created in the case of a legacy
226
        $initialWidgetId = $widget->getId();
227
228
        //the type of method used
229
        $requestMethod = $request->getMethod();
230
231
        //if the form is posted
232
        if ($requestMethod === 'POST') {
233
            //the widget view
234
            $widgetView = $widget->getWidgetMap()->getView();
235
236
            //we only copy the widget if the view of the widget is not the current view
237
            if ($widgetView !== $currentView) {
238
                $widget = $this->overwriteWidget($currentView, $widget);
239
            }
240
            if ($businessEntityId !== null) {
241
                $form = $this->widgetFormBuilder->buildForm($widget, $currentView, $businessEntityId, $classes[$businessEntityId]->getClass(), $widgetMode, null, null, null, $quantum);
0 ignored issues
show
Compatibility introduced by
$widget of type object<Victoire\Bundle\WidgetBundle\Model\Widget> is not a sub-type of object<Victoire\Bundle\W...etBundle\Entity\Widget>. It seems like you assume a child class of the class Victoire\Bundle\WidgetBundle\Model\Widget to be always present.

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.

Loading history...
242
            } else {
243
                $form = $this->widgetFormBuilder->buildForm($widget, $currentView, null, null, $widgetMode, null, null, null, $quantum);
0 ignored issues
show
Compatibility introduced by
$widget of type object<Victoire\Bundle\WidgetBundle\Model\Widget> is not a sub-type of object<Victoire\Bundle\W...etBundle\Entity\Widget>. It seems like you assume a child class of the class Victoire\Bundle\WidgetBundle\Model\Widget to be always present.

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.

Loading history...
244
            }
245
246
            $noValidate = $request->query->get('novalidate', false);
247
            $form->handleRequest($request);
248
            if ($noValidate === false && $form->isValid()) {
249
                $widget->setBusinessEntityId($businessEntityId);
250
251
                //force cache invalidation
252
                $widget->setUpdatedAt(new \DateTime());
253
                $this->entityManager->persist($widget);
254
255
                $this->entityManager->persist($currentView);
256
                $this->entityManager->flush();
257
258
                $response = [
259
                    'view'        => $currentView,
260
                    'success'     => true,
261
                    'html'        => $this->widgetRenderer->render($widget, $currentView),
262
                    'widgetId'    => $initialWidgetId,
263
                    'slot'        => $widget->getWidgetMap()->getSlot(),
264
                    'viewCssHash' => $currentView->getCssHash(),
265
                ];
266
            } else {
267
                $formErrorHelper = $this->formErrorHelper;
268
                //Return a message for developer in console and form view in order to refresh view and show form errors
269
                $response = [
270
                    'success'     => false,
271
                    'widgetId'    => $initialWidgetId,
272
                    'slot'        => $widget->getWidgetMap()->getSlot(),
273
                    'message'     => $noValidate === false ? $formErrorHelper->getRecursiveReadableErrors($form) : null,
274
                    'html'        => $this->widgetFormBuilder->renderForm($form, $widget, $businessEntityId),
0 ignored issues
show
Compatibility introduced by
$widget of type object<Victoire\Bundle\WidgetBundle\Model\Widget> is not a sub-type of object<Victoire\Bundle\W...etBundle\Entity\Widget>. It seems like you assume a child class of the class Victoire\Bundle\WidgetBundle\Model\Widget to be always present.

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.

Loading history...
Bug introduced by
It seems like $businessEntityId defined by parameter $businessEntityId on line 219 can also be of type string; however, Victoire\Bundle\WidgetBu...rmBuilder::renderForm() does only seem to accept object|null, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
275
                ];
276
            }
277
        } else {
278
            $widgets = $widget->getWidgetMap()->getWidgets();
279
            $forms = $this->widgetFormBuilder->renderNewQuantumForms($widget->getSlot(), $currentView, $widgets, $widget, $classes);
280
281
            $response = [
282
                'success'  => true,
283
                'html'     => $this->templating->render(
284
                    'VictoireCoreBundle:Widget:Form/edit.html.twig',
285
                    [
286
                        'view'               => $currentView,
287
                        'slot'               => $widget->getWidgetMap()->getSlot(),
288
                        'position'           => $widget->getWidgetMap()->getPosition(),
289
                        'parentWidgetMap'    => $widget->getWidgetMap()->getParent() ? $widget->getWidgetMap()->getParent()->getId() : null,
290
                        'classes'            => $classes,
291
                        'forms'              => $forms,
292
                        'widgets'            => $widgets,
293
                        'widget'             => $widget,
294
                    ]
295
                ),
296
            ];
297
        }
298
299
        return $response;
300
    }
301
302
    /**
303
     * Remove a widget.
304
     *
305
     * @param Widget $widget
306
     *
307
     * @return array The parameter for the view
308
     */
309
    public function deleteWidget(Widget $widget, View $view)
310
    {
311
        //Used to update view in callback (we do it before delete it else it'll not exists anymore)
312
        $widgetId = $widget->getId();
313
        //we update the widget map of the view
314
        $this->widgetMapBuilder->build($view);
315
        $widgetMap = WidgetMapHelper::getWidgetMapByWidgetAndView($widget, $view);
0 ignored issues
show
Compatibility introduced by
$widget of type object<Victoire\Bundle\WidgetBundle\Model\Widget> is not a sub-type of object<Victoire\Bundle\W...etBundle\Entity\Widget>. It seems like you assume a child class of the class Victoire\Bundle\WidgetBundle\Model\Widget to be always present.

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.

Loading history...
316
        //the widget is removed only if the current view is the view of the widget
317
        if ($widgetMap->getView() == $view && $widgetMap->getAction() != WidgetMap::ACTION_DELETE) {
0 ignored issues
show
Bug introduced by
The method getView does only exist in Victoire\Bundle\WidgetMapBundle\Entity\WidgetMap, but not in Victoire\Bundle\WidgetMa...getMapNotFoundException.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
Bug introduced by
The method getAction does only exist in Victoire\Bundle\WidgetMapBundle\Entity\WidgetMap, but not in Victoire\Bundle\WidgetMa...getMapNotFoundException.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
318
            //we remove the widget
319
            $this->entityManager->remove($widget);
320
        }
321
322
        //we update the view
323
        $this->entityManager->persist($view);
324
        //update the view deleting the widget
325
        $this->widgetMapManager->delete($view, $widget);
0 ignored issues
show
Compatibility introduced by
$widget of type object<Victoire\Bundle\WidgetBundle\Model\Widget> is not a sub-type of object<Victoire\Bundle\W...etBundle\Entity\Widget>. It seems like you assume a child class of the class Victoire\Bundle\WidgetBundle\Model\Widget to be always present.

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.

Loading history...
326
327
        $this->entityManager->flush();
328
329
        return [
330
            'success'     => true,
331
            'widgetId'    => $widgetId,
332
            'viewCssHash' => $view->getCssHash(),
333
        ];
334
    }
335
336
    /**
337
     * Overwrite the widget for the current view because the widget is not linked to the current view, a copy is created.
338
     *
339
     * @param View   $view
340
     * @param Widget $widget
341
     *
342
     * @throws \Exception The slot does not exists
343
     *
344
     * @return Widget The widget
345
     */
346
    public function overwriteWidget(View $view, Widget $widget)
347
    {
348
        $widgetCopy = $this->cloneEntity($widget);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->cloneEntity($widget); of type object|array adds the type array to the return on line 352 which is incompatible with the return type documented by Victoire\Bundle\WidgetBu...anager::overwriteWidget of type Victoire\Bundle\WidgetBundle\Model\Widget.
Loading history...
349
        $originalWidgetMap = $widget->getWidgetMap();
350
        $this->widgetMapManager->overwrite($view, $originalWidgetMap, $widgetCopy);
0 ignored issues
show
Documentation introduced by
$widgetCopy is of type object|array, but the function expects a object<Victoire\Bundle\W...etBundle\Entity\Widget>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
351
352
        return $widgetCopy;
353
    }
354
355
    /**
356
     * @param Widget $entity
357
     */
358
    public function cloneEntity(Widget $entity)
359
    {
360
        $entityCopy = clone $entity;
361
        $entityCopy->setWidgetMap(null);
362
        //Look for on_to_many relations, if found, duplicate related entities.
363
        //It is necessary for 'list' widgets, this algo duplicates and persists list items.
364
        $associations = $this->entityManager->getClassMetadata(get_class($entityCopy))->getAssociationMappings();
365
        $accessor = PropertyAccess::createPropertyAccessor();
366
        foreach ($associations as $name => $values) {
367
            if ($values['type'] === ClassMetadataInfo::ONE_TO_MANY) {
368
                $relatedEntities = $accessor->getValue($entityCopy, $values['fieldName']);
369
                $relatedEntitiesCopies = [];
370
                foreach ($relatedEntities as $relatedEntity) {
371
                    $relatedEntityCopy = clone $relatedEntity;
372
                    $this->entityManager->persist($relatedEntity);
373
                    $relatedEntitiesCopies[] = $relatedEntityCopy;
374
                }
375
                $accessor->setValue($entityCopy, $name, $relatedEntitiesCopies);
376
            }
377
378
            //Clone OneToOne relation objects
379
            if ($values['type'] === ClassMetadataInfo::ONE_TO_ONE) {
380
                $relatedEntity = $accessor->getValue($entityCopy, $values['fieldName']);
381
                if ($relatedEntity) {
382
                    $relatedEntityCopy = clone $relatedEntity;
383
                    $this->entityManager->persist($relatedEntity);
384
                    $accessor->setValue($entityCopy, $name, $relatedEntityCopy);
385
                }
386
            }
387
        }
388
389
        $this->entityManager->persist($entityCopy);
0 ignored issues
show
Bug introduced by
It seems like $entityCopy can also be of type array; however, Doctrine\ORM\EntityManager::persist() does only seem to accept object, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
390
391
        return $entityCopy;
392
    }
393
}
394