Completed
Push — master ( 73492b...2db3cf )
by Jeremy
11:56
created

ClassMetadata::mapField()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 6
cts 6
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 1
crap 1
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 945
    public function __construct($documentName)
61
    {
62 945
        parent::__construct($documentName);
63 945
        $this->reflClass = new \ReflectionClass($documentName);
64 945
        $this->namespace = $this->reflClass->getNamespaceName();
65 945
        $this->setCollection($this->reflClass->getShortName());
66 945
        $this->instantiator = new Instantiator();
67 945
    }
68
69
    /**
70
     * Map a field.
71
     *
72
     * @param array $mapping The mapping information.
73
     * @return void
74
     */
75 935
    public function mapField(array $mapping)
76
    {
77 935
        $mapping = parent::mapField($mapping);
78
79 934
        $reflProp = $this->reflClass->getProperty($mapping['fieldName']);
80 933
        $reflProp->setAccessible(true);
81 933
        $this->reflFields[$mapping['fieldName']] = $reflProp;
82 933
    }
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) {
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