1 | <?php |
||
24 | class CollectionPersister |
||
25 | { |
||
26 | /** |
||
27 | * The DocumentManager instance. |
||
28 | * |
||
29 | * @var DocumentManager |
||
30 | */ |
||
31 | private $dm; |
||
32 | |||
33 | /** |
||
34 | * The PersistenceBuilder instance. |
||
35 | * |
||
36 | * @var PersistenceBuilder |
||
37 | */ |
||
38 | private $pb; |
||
39 | |||
40 | /** |
||
41 | * Constructs a new CollectionPersister instance. |
||
42 | * |
||
43 | * @param DocumentManager $dm |
||
44 | * @param PersistenceBuilder $pb |
||
45 | * @param UnitOfWork $uow |
||
46 | */ |
||
47 | 1084 | public function __construct(DocumentManager $dm, PersistenceBuilder $pb, UnitOfWork $uow) |
|
53 | |||
54 | /** |
||
55 | * Deletes a PersistentCollection instance completely from a document using $unset. |
||
56 | * |
||
57 | * @param PersistentCollectionInterface $coll |
||
58 | * @param array $options |
||
59 | */ |
||
60 | 34 | public function delete(PersistentCollectionInterface $coll, array $options) |
|
73 | |||
74 | /** |
||
75 | * Updates a PersistentCollection instance deleting removed rows and |
||
76 | * inserting new rows. |
||
77 | * |
||
78 | * @param PersistentCollectionInterface $coll |
||
79 | * @param array $options |
||
80 | */ |
||
81 | 97 | public function update(PersistentCollectionInterface $coll, array $options) |
|
82 | { |
||
83 | 97 | $mapping = $coll->getMapping(); |
|
84 | |||
85 | 97 | if ($mapping['isInverseSide']) { |
|
86 | return; // ignore inverse side |
||
87 | } |
||
88 | |||
89 | 97 | switch ($mapping['strategy']) { |
|
90 | case ClassMetadataInfo::STORAGE_STRATEGY_ATOMIC_SET: |
||
91 | case ClassMetadataInfo::STORAGE_STRATEGY_ATOMIC_SET_ARRAY: |
||
92 | throw new \UnexpectedValueException($mapping['strategy'] . ' update collection strategy should have been handled by DocumentPersister. Please report a bug in issue tracker'); |
||
93 | |||
94 | case ClassMetadataInfo::STORAGE_STRATEGY_SET: |
||
95 | case ClassMetadataInfo::STORAGE_STRATEGY_SET_ARRAY: |
||
96 | 10 | $this->setCollection($coll, $options); |
|
97 | 10 | break; |
|
98 | |||
99 | case ClassMetadataInfo::STORAGE_STRATEGY_ADD_TO_SET: |
||
100 | case ClassMetadataInfo::STORAGE_STRATEGY_PUSH_ALL: |
||
101 | 88 | $coll->initialize(); |
|
102 | 88 | $this->deleteElements($coll, $options); |
|
103 | 88 | $this->insertElements($coll, $options); |
|
104 | 87 | break; |
|
105 | |||
106 | default: |
||
107 | throw new \UnexpectedValueException('Unsupported collection strategy: ' . $mapping['strategy']); |
||
108 | } |
||
109 | 96 | } |
|
110 | |||
111 | /** |
||
112 | * Sets a PersistentCollection instance. |
||
113 | * |
||
114 | * This method is intended to be used with the "set" or "setArray" |
||
115 | * strategies. The "setArray" strategy will ensure that the collection is |
||
116 | * set as a BSON array, which means the collection elements will be |
||
117 | * reindexed numerically before storage. |
||
118 | * |
||
119 | * @param PersistentCollectionInterface $coll |
||
120 | * @param array $options |
||
121 | */ |
||
122 | 10 | private function setCollection(PersistentCollectionInterface $coll, array $options) |
|
131 | |||
132 | /** |
||
133 | * Deletes removed elements from a PersistentCollection instance. |
||
134 | * |
||
135 | * This method is intended to be used with the "pushAll" and "addToSet" |
||
136 | * strategies. |
||
137 | * |
||
138 | * @param PersistentCollectionInterface $coll |
||
139 | * @param array $options |
||
140 | */ |
||
141 | 88 | private function deleteElements(PersistentCollectionInterface $coll, array $options) |
|
167 | |||
168 | /** |
||
169 | * Inserts new elements for a PersistentCollection instance. |
||
170 | * |
||
171 | * This method is intended to be used with the "pushAll" and "addToSet" |
||
172 | * strategies. |
||
173 | * |
||
174 | * @param PersistentCollectionInterface $coll |
||
175 | * @param array $options |
||
176 | */ |
||
177 | 88 | private function insertElements(PersistentCollectionInterface $coll, array $options) |
|
178 | { |
||
179 | 88 | $insertDiff = $coll->getInsertDiff(); |
|
180 | |||
181 | 88 | if (empty($insertDiff)) { |
|
182 | 21 | return; |
|
183 | } |
||
184 | |||
185 | 73 | $mapping = $coll->getMapping(); |
|
186 | |||
187 | 73 | switch ($mapping['strategy']) { |
|
188 | case ClassMetadataInfo::STORAGE_STRATEGY_PUSH_ALL: |
||
189 | 69 | $operator = 'push'; |
|
190 | 69 | break; |
|
191 | |||
192 | case ClassMetadataInfo::STORAGE_STRATEGY_ADD_TO_SET: |
||
193 | 6 | $operator = 'addToSet'; |
|
194 | 6 | break; |
|
195 | |||
196 | default: |
||
197 | throw new \LogicException("Invalid strategy {$mapping['strategy']} given for insertElements"); |
||
198 | } |
||
199 | |||
200 | 73 | list($propertyPath, $parent) = $this->getPathAndParent($coll); |
|
201 | |||
202 | 73 | $callback = isset($mapping['embedded']) |
|
203 | ? function($v) use ($mapping) { return $this->pb->prepareEmbeddedDocumentValue($mapping, $v); } |
||
204 | : function($v) use ($mapping) { return $this->pb->prepareReferencedDocumentValue($mapping, $v); }; |
||
205 | |||
206 | 73 | $value = array_values(array_map($callback, $insertDiff)); |
|
207 | |||
208 | 73 | $query = ['$' . $operator => [$propertyPath => ['$each' => $value]]]; |
|
209 | |||
210 | 73 | $this->executeQuery($parent, $query, $options); |
|
211 | 72 | } |
|
212 | |||
213 | /** |
||
214 | * Gets the parent information for a given PersistentCollection. It will |
||
215 | * retrieve the top-level persistent Document that the PersistentCollection |
||
216 | * lives in. We can use this to issue queries when updating a |
||
217 | * PersistentCollection that is multiple levels deep inside an embedded |
||
218 | * document. |
||
219 | * |
||
220 | * <code> |
||
221 | * list($path, $parent) = $this->getPathAndParent($coll) |
||
222 | * </code> |
||
223 | * |
||
224 | * @param PersistentCollectionInterface $coll |
||
225 | * @return array $pathAndParent |
||
226 | */ |
||
227 | 107 | private function getPathAndParent(PersistentCollectionInterface $coll) |
|
247 | |||
248 | /** |
||
249 | * Executes a query updating the given document. |
||
250 | * |
||
251 | * @param object $document |
||
252 | * @param array $newObj |
||
253 | * @param array $options |
||
254 | */ |
||
255 | 107 | private function executeQuery($document, array $newObj, array $options) |
|
270 | } |
||
271 |
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: