Completed
Push — master ( 87aba0...0e8729 )
by Andreas
25s queued 16s
created

lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadata.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace Doctrine\ODM\MongoDB\Mapping;
21
22
use Doctrine\Instantiator\Instantiator;
23
24
/**
25
 * A <tt>ClassMetadata</tt> instance holds all the object-document mapping metadata
26
 * of a document and it's references.
27
 *
28
 * Once populated, ClassMetadata instances are usually cached in a serialized form.
29
 *
30
 * <b>IMPORTANT NOTE:</b>
31
 *
32
 * The fields of this class are only public for 2 reasons:
33
 * 1) To allow fast READ access.
34
 * 2) To drastically reduce the size of a serialized instance (private/protected members
35
 *    get the whole class name, namespace inclusive, prepended to every property in
36
 *    the serialized representation).
37
 *
38
 * @since       1.0
39
 */
40
class ClassMetadata extends ClassMetadataInfo
41
{
42
    /**
43
     * The ReflectionProperty instances of the mapped class.
44
     *
45
     * @var \ReflectionProperty[]
46
     */
47
    public $reflFields = array();
48
49
    /**
50
     * @var \Doctrine\Instantiator\InstantiatorInterface|null
51
     */
52
    private $instantiator;
53
54
    /**
55
     * Initializes a new ClassMetadata instance that will hold the object-document mapping
56
     * metadata of the class with the given name.
57
     *
58
     * @param string $documentName The name of the document class the new instance is used for.
59
     */
60 937
    public function __construct($documentName)
61
    {
62 937
        parent::__construct($documentName);
63 937
        $this->reflClass = new \ReflectionClass($documentName);
64 937
        $this->namespace = $this->reflClass->getNamespaceName();
65 937
        $this->setCollection($this->reflClass->getShortName());
66 937
        $this->instantiator = new Instantiator();
67 937
    }
68
69
    /**
70
     * Map a field.
71
     *
72
     * @param array $mapping The mapping information.
73
     * @return void
74
     */
75 927
    public function mapField(array $mapping)
76
    {
77 927
        $mapping = parent::mapField($mapping);
78
79 926
        $reflProp = $this->reflClass->getProperty($mapping['fieldName']);
80 925
        $reflProp->setAccessible(true);
81 925
        $this->reflFields[$mapping['fieldName']] = $reflProp;
82 925
    }
83
84
    /**
85
     * Determines which fields get serialized.
86
     *
87
     * It is only serialized what is necessary for best unserialization performance.
88
     * That means any metadata properties that are not set or empty or simply have
89
     * their default value are NOT serialized.
90
     *
91
     * Parts that are also NOT serialized because they can not be properly unserialized:
92
     *      - reflClass (ReflectionClass)
93
     *      - reflFields (ReflectionProperty array)
94
     *
95
     * @return array The names of all the fields that should be serialized.
96
     */
97 6
    public function __sleep()
98
    {
99
        // This metadata is always serialized/cached.
100
        $serialized = array(
101 6
            'fieldMappings',
102
            'associationMappings',
103
            'identifier',
104
            'name',
105
            'namespace', // TODO: REMOVE
106
            'db',
107
            'collection',
108
            'writeConcern',
109
            'rootDocumentName',
110
            'generatorType',
111
            'generatorOptions',
112
            'idGenerator',
113
            'indexes',
114
            'shardKey',
115
        );
116
117
        // The rest of the metadata is only serialized if necessary.
118 6
        if ($this->changeTrackingPolicy != self::CHANGETRACKING_DEFERRED_IMPLICIT) {
119
            $serialized[] = 'changeTrackingPolicy';
120
        }
121
122 6
        if ($this->customRepositoryClassName) {
123 1
            $serialized[] = 'customRepositoryClassName';
124
        }
125
126 6
        if ($this->inheritanceType != self::INHERITANCE_TYPE_NONE || $this->discriminatorField !== null) {
127 4
            $serialized[] = 'inheritanceType';
128 4
            $serialized[] = 'discriminatorField';
129 4
            $serialized[] = 'discriminatorValue';
130 4
            $serialized[] = 'discriminatorMap';
131 4
            $serialized[] = 'defaultDiscriminatorValue';
132 4
            $serialized[] = 'parentClasses';
133 4
            $serialized[] = 'subClasses';
134
        }
135
136 6
        if ($this->isMappedSuperclass) {
137 1
            $serialized[] = 'isMappedSuperclass';
138
        }
139
140 6
        if ($this->isEmbeddedDocument) {
141 1
            $serialized[] = 'isEmbeddedDocument';
142
        }
143
144 6
        if ($this->isQueryResultDocument) {
145
            $serialized[] = 'isQueryResultDocument';
146
        }
147
148 6
        if ($this->isVersioned) {
149
            $serialized[] = 'isVersioned';
150
            $serialized[] = 'versionField';
151
        }
152
153 6
        if ($this->lifecycleCallbacks) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->lifecycleCallbacks of type array 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...
154
            $serialized[] = 'lifecycleCallbacks';
155
        }
156
157 6
        if ($this->file) {
158 1
            $serialized[] = 'file';
159
        }
160
161 6
        if ($this->slaveOkay) {
0 ignored issues
show
Deprecated Code introduced by
The property Doctrine\ODM\MongoDB\Map...etadataInfo::$slaveOkay has been deprecated with message: in version 1.2 and will be removed in 2.0.

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
162 1
            $serialized[] = 'slaveOkay';
163
        }
164
165 6
        if ($this->distance) {
166 1
            $serialized[] = 'distance';
167
        }
168
169 6
        if ($this->collectionCapped) {
170 1
            $serialized[] = 'collectionCapped';
171 1
            $serialized[] = 'collectionSize';
172 1
            $serialized[] = 'collectionMax';
173
        }
174
175 6
        return $serialized;
176
    }
177
178
    /**
179
     * Restores some state that can not be serialized/unserialized.
180
     *
181
     * @return void
182
     */
183 6
    public function __wakeup()
184
    {
185
        // Restore ReflectionClass and properties
186 6
        $this->reflClass = new \ReflectionClass($this->name);
187 6
        $this->instantiator = $this->instantiator ?: new Instantiator();
188
189 6
        foreach ($this->fieldMappings as $field => $mapping) {
190 3
            if (isset($mapping['declared'])) {
191 1
                $reflField = new \ReflectionProperty($mapping['declared'], $field);
192
            } else {
193 3
                $reflField = $this->reflClass->getProperty($field);
194
            }
195 3
            $reflField->setAccessible(true);
196 3
            $this->reflFields[$field] = $reflField;
197
        }
198 6
    }
199
200
    /**
201
     * Creates a new instance of the mapped class, without invoking the constructor.
202
     *
203
     * @return object
204
     */
205 396
    public function newInstance()
206
    {
207 396
        return $this->instantiator->instantiate($this->name);
208
    }
209
}
210