Completed
Push — master ( a11a2f...a1ae8b )
by Asmir
03:55
created

DoctrineProxySubscriber::getSubscribedEvents()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 9.4285
cc 1
eloc 4
nc 1
nop 0
crap 1
1
<?php
2
3
/*
4
 * Copyright 2016 Johannes M. Schmitt <[email protected]>
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
namespace JMS\Serializer\EventDispatcher\Subscriber;
20
21
use Doctrine\Common\Persistence\Proxy;
22
use Doctrine\ODM\MongoDB\PersistentCollection as MongoDBPersistentCollection;
23
use Doctrine\ODM\PHPCR\PersistentCollection as PHPCRPersistentCollection;
24
use Doctrine\ORM\PersistentCollection;
25
use Doctrine\ORM\Proxy\Proxy as ORMProxy;
26
use JMS\Serializer\EventDispatcher\EventDispatcherInterface;
27
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
28
use JMS\Serializer\EventDispatcher\PreSerializeEvent;
29
30
class DoctrineProxySubscriber implements EventSubscriberInterface
31
{
32
    /**
33
     * @var bool
34
     */
35
    private $skipVirtualTypeInit = false;
36
37
    /**
38
     * @var bool
39
     */
40
    private $initializeExcluded = true;
41
42 386
    public function __construct($skipVirtualTypeInit = false, $initializeExcluded = true)
43
    {
44 386
        $this->skipVirtualTypeInit = (bool)$skipVirtualTypeInit;
45 386
        $this->initializeExcluded = (bool)$initializeExcluded;
46 386
    }
47
48 239
    public function onPreSerialize(PreSerializeEvent $event)
49
    {
50 239
        $object = $event->getObject();
51 239
        $type = $event->getType();
52
53
        // If the set type name is not an actual class, but a faked type for which a custom handler exists, we do not
54
        // modify it with this subscriber. Also, we forgo autoloading here as an instance of this type is already created,
55
        // so it must be loaded if its a real class.
56 239
        $virtualType = !class_exists($type['name'], false);
57
58
        if ($object instanceof PersistentCollection
59 239
            || $object instanceof MongoDBPersistentCollection
0 ignored issues
show
Bug introduced by
The class Doctrine\ODM\MongoDB\PersistentCollection does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
60 239
            || $object instanceof PHPCRPersistentCollection
61 239
        ) {
62 1
            if (!$virtualType) {
63 1
                $event->setType('ArrayCollection');
64 1
            }
65
66 1
            return;
67
        }
68
69 239
        if (($this->skipVirtualTypeInit && $virtualType) ||
70 238
            (!$object instanceof Proxy && !$object instanceof ORMProxy)
71 239
        ) {
72 227
            return;
73
        }
74
75
        // do not initialize the proxy if is going to be excluded by-class by some exclusion strategy
76 13
        if ($this->initializeExcluded === false && !$virtualType) {
77 1
            $context = $event->getContext();
78 1
            $exclusionStrategy = $context->getExclusionStrategy();
79 1
            if ($exclusionStrategy !== null && $exclusionStrategy->shouldSkipClass($context->getMetadataFactory()->getMetadataForClass(get_parent_class($object)), $context)) {
0 ignored issues
show
Documentation introduced by
$context->getMetadataFac..._parent_class($object)) is of type object<Metadata\ClassMetadata>|null, but the function expects a object<JMS\Serializer\Metadata\ClassMetadata>.

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...
80 1
                return;
81
            }
82
        }
83
84 13
        $object->__load();
85
86 13
        if (!$virtualType) {
87 10
            $event->setType(get_parent_class($object));
88 10
        }
89 13
    }
90
91 235
    public function onPreSerializeTypedProxy(PreSerializeEvent $event, $eventName, $class, $format, EventDispatcherInterface $dispatcher)
92
    {
93 235
        $type = $event->getType();
94
        // is a virtual type? then there is no need to change the event name
95 235
        if (!class_exists($type['name'], false)) {
96 14
            return;
97
        }
98
99 234
        $object = $event->getObject();
100 234
        if ($object instanceof Proxy) {
101 9
            $parentClassName = get_parent_class($object);
102
103
            // check if this is already a re-dispatch
104 9
            if (strtolower($class) !== strtolower($parentClassName)) {
105 9
                $event->stopPropagation();
106 9
                $newEvent = new PreSerializeEvent($event->getContext(), $object, array('name' => $parentClassName, 'params' => $type['params']));
107 9
                $dispatcher->dispatch($eventName, $parentClassName, $format, $newEvent);
108
109
                // update the type in case some listener changed it
110 9
                $newType = $newEvent->getType();
111 9
                $event->setType($newType['name'], $newType['params']);
112 9
            }
113 9
        }
114 234
    }
115
116 386
    public static function getSubscribedEvents()
117
    {
118
        return array(
119 386
            array('event' => 'serializer.pre_serialize', 'method' => 'onPreSerializeTypedProxy'),
120 386
            array('event' => 'serializer.pre_serialize', 'method' => 'onPreSerialize'),
121 386
        );
122
    }
123
}
124