1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* This file is part of the PHPMongo package. |
5
|
|
|
* |
6
|
|
|
* (c) Dmytro Sokil <[email protected]> |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Sokil\Mongo; |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* Class use MongoWriteBatch classes from PECL driver above v. 1.5.0. |
16
|
|
|
* Before this version legacy persistencee must be used |
17
|
|
|
*/ |
18
|
|
|
class Persistence implements \Countable |
19
|
|
|
{ |
20
|
|
|
const STATE_SAVE = 0; |
21
|
|
|
const STATE_REMOVE = 1; |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* @var \SplObjectStorage |
25
|
|
|
*/ |
26
|
|
|
protected $pool; |
27
|
|
|
|
28
|
|
|
public function __construct() |
29
|
|
|
{ |
30
|
|
|
$this->pool = new \SplObjectStorage; |
31
|
|
|
} |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* Check if document already watched |
35
|
|
|
* |
36
|
|
|
* @param Document $document |
37
|
|
|
* @return bool |
38
|
|
|
*/ |
39
|
|
|
public function contains(Document $document) |
40
|
|
|
{ |
41
|
|
|
return $this->pool->contains($document); |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* Get count of documents in pool |
46
|
|
|
* @return int |
47
|
|
|
*/ |
48
|
|
|
public function count() |
49
|
|
|
{ |
50
|
|
|
return $this->pool->count(); |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* Add document to watching pool for save |
55
|
|
|
* |
56
|
|
|
* @param Document $document |
57
|
|
|
* @return \Sokil\Mongo\Persistence |
58
|
|
|
*/ |
59
|
|
|
public function persist(Document $document) |
60
|
|
|
{ |
61
|
|
|
$this->pool->attach($document, self::STATE_SAVE); |
62
|
|
|
|
63
|
|
|
return $this; |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* Add document to watching pool for remove |
68
|
|
|
* |
69
|
|
|
* @param Document $document |
70
|
|
|
* @return \Sokil\Mongo\Persistence |
71
|
|
|
*/ |
72
|
|
|
public function remove(Document $document) |
73
|
|
|
{ |
74
|
|
|
$this->pool->attach($document, self::STATE_REMOVE); |
75
|
|
|
|
76
|
|
|
return $this; |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* Send data to database |
81
|
|
|
* |
82
|
|
|
* @return \Sokil\Mongo\Persistence |
83
|
|
|
*/ |
84
|
|
|
public function flush() |
85
|
|
|
{ |
86
|
|
|
$insert = array(); |
87
|
|
|
$update = array(); |
88
|
|
|
$delete = array(); |
89
|
|
|
|
90
|
|
|
// fill batch objects |
91
|
|
|
foreach ($this->pool as $document) { |
92
|
|
|
/* @var $document \Sokil\Mongo\Document */ |
93
|
|
|
|
94
|
|
|
// collection |
95
|
|
|
$collection = $document->getCollection(); |
96
|
|
|
$collectionName = $collection->getName(); |
97
|
|
|
|
98
|
|
|
// persisting |
99
|
|
|
switch ($this->pool->offsetGet($document)) { |
100
|
|
|
case self::STATE_SAVE: |
101
|
|
|
if ($document->isStored()) { |
102
|
|
|
if (!isset($update[$collectionName])) { |
103
|
|
|
$update[$collectionName] = new \MongoUpdateBatch($collection->getMongoCollection()); |
104
|
|
|
} |
105
|
|
|
$update[$collectionName]->add(array( |
106
|
|
|
'q' => array( |
107
|
|
|
'_id' => $document->getId(), |
108
|
|
|
), |
109
|
|
|
'u' => $document->getOperator()->toArray(), |
110
|
|
|
)); |
111
|
|
|
} else { |
112
|
|
|
if (!isset($insert[$collectionName])) { |
113
|
|
|
$insert[$collectionName] = new \MongoInsertBatch($collection->getMongoCollection()); |
114
|
|
|
} |
115
|
|
|
$insert[$collectionName]->add($document->toArray()); |
116
|
|
|
} |
117
|
|
|
break; |
118
|
|
|
|
119
|
|
|
case self::STATE_REMOVE: |
120
|
|
|
// delete document form db |
121
|
|
|
if ($document->isStored()) { |
122
|
|
|
if (!isset($delete[$collectionName])) { |
123
|
|
|
$delete[$collectionName] = new \MongoDeleteBatch($collection->getMongoCollection()); |
124
|
|
|
} |
125
|
|
|
$delete[$collectionName]->add(array( |
126
|
|
|
'q' => array( |
127
|
|
|
'_id' => $document->getId(), |
128
|
|
|
), |
129
|
|
|
'limit' => 1, |
130
|
|
|
)); |
131
|
|
|
} |
132
|
|
|
// remove link form pool |
133
|
|
|
$this->detach($document); |
134
|
|
|
break; |
135
|
|
|
} |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
// write operations |
139
|
|
|
$writeOptions = array('w' => 1); |
140
|
|
|
|
141
|
|
|
// execute batch insert operations |
142
|
|
|
if ($insert) { |
|
|
|
|
143
|
|
|
foreach ($insert as $collectionName => $collectionInsert) { |
144
|
|
|
$collectionInsert->execute($writeOptions); |
145
|
|
|
} |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
// execute batch update operations |
149
|
|
|
if ($update) { |
|
|
|
|
150
|
|
|
foreach ($update as $collectionName => $collectionUpdate) { |
151
|
|
|
$collectionUpdate->execute($writeOptions); |
152
|
|
|
} |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
// execute batch delete operations |
156
|
|
|
if ($delete) { |
|
|
|
|
157
|
|
|
foreach ($delete as $collectionName => $collectionDelete) { |
158
|
|
|
$collectionDelete->execute($writeOptions); |
159
|
|
|
} |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
return $this; |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* Stop watching document |
167
|
|
|
* |
168
|
|
|
* @param Document $document |
169
|
|
|
* @return \Sokil\Mongo\Persistence |
170
|
|
|
*/ |
171
|
|
|
public function detach(Document $document) |
172
|
|
|
{ |
173
|
|
|
$this->pool->detach($document); |
174
|
|
|
|
175
|
|
|
return $this; |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* Detach all documents from pool |
180
|
|
|
* @return \Sokil\Mongo\Persistence |
181
|
|
|
*/ |
182
|
|
|
public function clear() |
183
|
|
|
{ |
184
|
|
|
$this->pool->removeAll($this->pool); |
185
|
|
|
|
186
|
|
|
return $this; |
187
|
|
|
} |
188
|
|
|
} |
189
|
|
|
|
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.