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\CouchDB\Mapping; |
||
21 | |||
22 | use Doctrine\Common\Collections\ArrayCollection; |
||
23 | use Doctrine\ODM\CouchDB\Mapping\ClassMetadata; |
||
24 | use Doctrine\ODM\CouchDB\Types\Type; |
||
25 | use Doctrine\Common\Util\ClassUtils; |
||
26 | |||
27 | /** |
||
28 | * Helper class serializing/unserializing embedded documents. |
||
29 | * |
||
30 | * @license http://www.opensource.org/licenses/lgpl-license.php LGPL |
||
31 | * @link www.doctrine-project.com |
||
32 | * @since 1.0 |
||
33 | * @author Bartfai Tamas <[email protected]> |
||
34 | */ |
||
35 | class EmbeddedDocumentSerializer |
||
36 | { |
||
37 | private $metadataFactory; |
||
38 | |||
39 | private $metadataResolver; |
||
40 | |||
41 | public function __construct($metadataFactory, $metadataResolver) |
||
42 | { |
||
43 | $this->metadataFactory = $metadataFactory; |
||
44 | $this->metadataResolver = $metadataResolver; |
||
45 | } |
||
46 | |||
47 | /** |
||
48 | * Serializes an embedded document value into array given the mapping |
||
49 | * metadata for the class. |
||
50 | * |
||
51 | * @param object $embeddedValue |
||
52 | * @param array $embeddedFieldMapping |
||
53 | * @param $embedMany |
||
54 | * @return array |
||
55 | * @throws \InvalidArgumentException |
||
56 | */ |
||
57 | public function serializeEmbeddedDocument($embeddedValue, $embeddedFieldMapping, $embedMany = false) |
||
58 | { |
||
59 | if ($embeddedValue === null) { |
||
60 | return null; |
||
61 | } |
||
62 | |||
63 | if (!$embedMany && 'many' == $embeddedFieldMapping['embedded'] && (is_array($embeddedValue) || $embeddedValue instanceof \Traversable)) { |
||
64 | $data = array(); |
||
65 | foreach ($embeddedValue as $key => $val) { |
||
66 | $data[$key] = $this->serializeEmbeddedDocument($val, $embeddedFieldMapping, true); |
||
67 | } |
||
68 | } else { |
||
69 | $embeddedClass = null; |
||
0 ignored issues
–
show
|
|||
70 | if (isset($embeddedFieldMapping['targetDocument'])) { |
||
71 | $embeddedClass = $this->metadataFactory->getMetadataFor(ClassUtils::getClass($embeddedValue)); |
||
72 | |||
73 | if ($embeddedClass->name !== $embeddedFieldMapping['targetDocument'] && |
||
74 | !is_subclass_of($embeddedClass->name, $embeddedFieldMapping['targetDocument']) ) { |
||
75 | |||
76 | throw new \InvalidArgumentException( |
||
77 | 'Mismatching metadata description in the EmbeddedDocument, expected class ' . |
||
78 | $embeddedFieldMapping['targetDocument'] . ' but got ' . get_class($embeddedValue) |
||
79 | ); |
||
80 | } |
||
81 | } else { |
||
82 | $embeddedClass = $this->metadataFactory->getMetadataFor(get_class($embeddedValue)); |
||
83 | } |
||
84 | |||
85 | $data = $this->metadataResolver->createDefaultDocumentStruct($embeddedClass); |
||
86 | foreach($embeddedClass->reflFields AS $fieldName => $reflProperty) { |
||
87 | $value = $reflProperty->getValue($embeddedValue); |
||
88 | $fieldMapping = $embeddedClass->fieldMappings[$fieldName]; |
||
89 | |||
90 | if ($value === null) { |
||
91 | continue; |
||
92 | } else if (isset($fieldMapping['embedded'])) { |
||
93 | $data[$fieldMapping['jsonName']] = $this->serializeEmbeddedDocument($value, $fieldMapping); |
||
94 | } else { |
||
95 | $data[$fieldMapping['jsonName']] = Type::getType($fieldMapping['type']) |
||
96 | ->convertToCouchDBValue($value); |
||
97 | } |
||
98 | } |
||
99 | } |
||
100 | return $data; |
||
101 | } |
||
102 | |||
103 | /** |
||
104 | * Create a document for an embedded document field mapping from json data. |
||
105 | * |
||
106 | * @param array $data |
||
107 | * @param object $embeddedFieldMapping |
||
108 | * @return object |
||
109 | * @throws \InvalidArgumentException |
||
110 | */ |
||
111 | public function createEmbeddedDocument($data, $embeddedFieldMapping) |
||
112 | { |
||
113 | if ($data === null) { |
||
114 | return null; |
||
115 | } else if (!is_array($data)) { |
||
116 | throw new \InvalidArgumentException("Cannot hydrate embedded if the data given is not an array"); |
||
117 | } |
||
118 | |||
119 | if ('many' == $embeddedFieldMapping['embedded']) { |
||
120 | |||
121 | $result = array(); |
||
122 | foreach ($data as $jsonName => $jsonValue) { |
||
123 | if (!is_array($jsonValue)) { |
||
124 | throw new \InvalidArgumentException("Cannot hydrate many embedded if the data given is not an array"); |
||
125 | } |
||
126 | |||
127 | $result[$jsonName] = $this->doCreateEmbeddedDocument($jsonValue, $embeddedFieldMapping); |
||
128 | } |
||
129 | ksort($result); |
||
130 | return new ArrayCollection($result); |
||
131 | } else { |
||
132 | return $this->doCreateEmbeddedDocument($data, $embeddedFieldMapping); |
||
133 | } |
||
134 | } |
||
135 | |||
136 | public function doCreateEmbeddedDocument($data, $embeddedFieldMapping) |
||
137 | { |
||
138 | if (!$this->metadataResolver->canMapDocument($data)) { |
||
139 | if (!isset($embeddedFieldMapping['targetDocument'])) { |
||
140 | throw new \InvalidArgumentException("Missing or missmatching metadata description in the EmbeddedDocument, cannot hydrate!"); |
||
141 | } |
||
142 | $type = $embeddedFieldMapping['targetDocument']; |
||
143 | } else { |
||
144 | $type = $this->metadataResolver->getDocumentType($data); |
||
145 | } |
||
146 | |||
147 | $class = $this->metadataFactory->getMetadataFor($type); |
||
148 | $instance = $class->newInstance(); |
||
149 | |||
150 | $documentState = array(); |
||
0 ignored issues
–
show
$documentState is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
151 | foreach ($data as $jsonName => $jsonValue) { |
||
152 | if ($this->metadataResolver->canResolveJsonField($jsonName)) { |
||
153 | continue; |
||
154 | } |
||
155 | if (isset($class->jsonNames[$jsonName])) { |
||
156 | $fieldName = $class->jsonNames[$jsonName]; |
||
157 | if (isset($class->fieldMappings[$fieldName])) { |
||
158 | if ($jsonValue === null) { |
||
159 | $fieldValue = null; |
||
160 | } else if (isset($class->fieldMappings[$fieldName]['embedded'])) { |
||
161 | $fieldValue = $this->createEmbeddedDocument($jsonValue, $class->fieldMappings[$fieldName]); |
||
162 | } else { |
||
163 | $fieldValue = |
||
164 | Type::getType($class->fieldMappings[$fieldName]['type']) |
||
165 | ->convertToPHPValue($jsonValue); |
||
166 | } |
||
167 | |||
168 | $class->setFieldValue($instance, |
||
169 | $class->fieldMappings[$fieldName]['fieldName'], |
||
170 | $fieldValue); |
||
171 | |||
172 | |||
173 | } |
||
174 | } else { |
||
0 ignored issues
–
show
This
else statement is empty and can be removed.
This check looks for the These if (rand(1, 6) > 3) {
print "Check failed";
} else {
//print "Check succeeded";
}
could be turned into if (rand(1, 6) > 3) {
print "Check failed";
}
This is much more concise to read.
Loading history...
|
|||
175 | //$nonMappedData[$jsonName] = $jsonValue; |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
67% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them.
Loading history...
|
|||
176 | } |
||
177 | } |
||
178 | return $instance; |
||
179 | } |
||
180 | |||
181 | |||
182 | /** |
||
183 | * Compares the two representation of an embedded document. |
||
184 | * |
||
185 | * If the original misses doctrine_metadata, but the values are the same, we assume there is no change |
||
186 | * If the original has doctrine_metadata, and the new value has different class, that's a change, |
||
187 | * even if the values are the same. |
||
188 | * |
||
189 | * @param array $value |
||
190 | * @param object $originalData |
||
191 | * @param array $valueFieldMapping Mapping of the field that contains the embedded document in the embedder document. |
||
192 | * @return boolean |
||
193 | */ |
||
194 | public function isChanged($value, $originalData, $valueFieldMapping) |
||
195 | { |
||
196 | // EmbedMany case |
||
197 | if ('many' == $valueFieldMapping['embedded'] && (is_array($value) || $value instanceof \Doctrine\Common\Collections\ArrayCollection)) { |
||
198 | if (count($originalData) != count($value)) { |
||
199 | return true; |
||
200 | } |
||
201 | foreach ($value as $key => $valueElement) { |
||
202 | if (!isset($originalData[$key]) |
||
203 | || $this->isChanged($valueElement, $originalData[$key], $valueFieldMapping)) { |
||
204 | return true; |
||
205 | } |
||
206 | } |
||
207 | return false; |
||
208 | } |
||
209 | |||
210 | // EmbedOne case, or one instance of and EmbedMany |
||
211 | if ($this->metadataResolver->canMapDocument($originalData) |
||
212 | && get_class($value) !== $this->metadataResolver->getDocumentType($originalData)) { |
||
213 | return true; |
||
214 | } |
||
215 | |||
216 | $class = $this->metadataFactory->getMetadataFor(get_class($value)); |
||
217 | foreach ($class->reflFields as $fieldName => $fieldValue) { |
||
218 | $fieldMapping = $class->fieldMappings[$fieldName]; |
||
219 | $originalDataValue = isset($originalData[$fieldMapping['jsonName']]) |
||
220 | ? $originalData[$fieldMapping['jsonName']] |
||
221 | : null; |
||
222 | |||
223 | $currentValue = $class->getFieldValue($value, $fieldMapping['fieldName']); |
||
224 | |||
225 | if ($originalDataValue === null && $currentValue === null) { |
||
226 | continue; |
||
227 | } else if ($originalDataValue === null || $currentValue === null) { |
||
228 | return true; |
||
229 | } |
||
230 | |||
231 | if (!isset($fieldMapping['embedded'])) { |
||
232 | // simple property comparison |
||
233 | // TODO this conversion could be avoided if we store the php value in the original data |
||
234 | // as with the simple property mapping in UOW. |
||
235 | $originalValue = Type::getType($fieldMapping['type']) |
||
236 | ->convertToPHPValue($originalDataValue); |
||
237 | if ($originalValue != $currentValue) { |
||
238 | return true; |
||
239 | } |
||
240 | } else { |
||
241 | |||
242 | if ('many' == $fieldMapping['embedded']) { |
||
243 | if (count($originalDataValue) != count($currentValue)) { |
||
244 | return true; |
||
245 | } |
||
246 | foreach ($currentValue as $currentKey => $currentElem) { |
||
247 | if (!isset($originalDataValue[$currentKey])) { |
||
248 | return true; |
||
249 | } |
||
250 | if ($this->isChanged($currentElem, $originalDataValue[$currentKey], $fieldMapping)) { |
||
251 | return true; |
||
252 | } |
||
253 | } |
||
254 | } else { // embedOne |
||
255 | if ($this->isChanged($currentValue, $originalDataValue, $fieldMapping)) { |
||
256 | return true; |
||
257 | } |
||
258 | } |
||
259 | |||
260 | } |
||
261 | } |
||
262 | return false; |
||
263 | } |
||
264 | } |
||
265 |
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.
Both the
$myVar
assignment in line 1 and the$higher
assignment in line 2 are dead. The first because$myVar
is never used and the second because$higher
is always overwritten for every possible time line.