1
|
|
|
<?php |
2
|
|
|
namespace ZfcUser\Mapper; |
3
|
|
|
use Zend\Db\Adapter\Adapter; |
4
|
|
|
use Zend\Db\Adapter\Driver\ResultInterface; |
5
|
|
|
use Zend\Db\ResultSet\HydratingResultSet; |
6
|
|
|
use Zend\Db\Sql\Select; |
7
|
|
|
use Zend\Db\Sql\Sql; |
8
|
|
|
use Zend\Db\Sql\TableIdentifier; |
9
|
|
|
use Zend\Hydrator\HydratorInterface; |
10
|
|
|
use Zend\Hydrator\ClassMethods; |
11
|
|
|
use ZfcUser\EventManager\EventProvider; |
12
|
|
|
use ZfcUser\Db\Adapter\MasterSlaveAdapterInterface; |
13
|
|
|
abstract class AbstractDbMapper extends EventProvider |
14
|
|
|
{ |
15
|
|
|
/** |
16
|
|
|
* @var Adapter |
17
|
|
|
*/ |
18
|
|
|
protected $dbAdapter; |
19
|
|
|
/** |
20
|
|
|
* @var Adapter |
21
|
|
|
*/ |
22
|
|
|
protected $dbSlaveAdapter; |
23
|
|
|
/** |
24
|
|
|
* @var HydratorInterface |
25
|
|
|
*/ |
26
|
|
|
protected $hydrator; |
27
|
|
|
/** |
28
|
|
|
* @var object |
29
|
|
|
*/ |
30
|
|
|
protected $entityPrototype; |
31
|
|
|
/** |
32
|
|
|
* @var HydratingResultSet |
33
|
|
|
*/ |
34
|
|
|
protected $resultSetPrototype; |
35
|
|
|
/** |
36
|
|
|
* @var Select |
37
|
|
|
*/ |
38
|
|
|
protected $selectPrototype; |
39
|
|
|
/** |
40
|
|
|
* @var Sql |
41
|
|
|
*/ |
42
|
|
|
private $sql; |
43
|
|
|
/** |
44
|
|
|
* @var Sql |
45
|
|
|
*/ |
46
|
|
|
private $slaveSql; |
47
|
|
|
/** |
48
|
|
|
* @var string |
49
|
|
|
*/ |
50
|
|
|
protected $tableName; |
51
|
|
|
/** |
52
|
|
|
* @var boolean |
53
|
|
|
*/ |
54
|
|
|
private $isInitialized = false; |
55
|
|
|
/** |
56
|
|
|
* Performs some basic initialization setup and checks before running a query |
57
|
|
|
* @throws \Exception |
58
|
|
|
* @return null |
59
|
|
|
*/ |
60
|
|
|
protected function initialize() |
61
|
|
|
{ |
62
|
|
|
if ($this->isInitialized) { |
63
|
|
|
return; |
64
|
|
|
} |
65
|
|
|
if (!$this->dbAdapter instanceof Adapter) { |
66
|
|
|
throw new \Exception('No db adapter present'); |
67
|
|
|
} |
68
|
|
|
if (!$this->hydrator instanceof HydratorInterface) { |
69
|
|
|
$this->hydrator = new ClassMethods; |
70
|
|
|
} |
71
|
|
|
if (!is_object($this->entityPrototype)) { |
72
|
|
|
throw new \Exception('No entity prototype set'); |
73
|
|
|
} |
74
|
|
|
$this->isInitialized = true; |
75
|
|
|
} |
76
|
|
|
/** |
77
|
|
|
* @param string|null $table |
78
|
|
|
* @return Select |
79
|
|
|
*/ |
80
|
|
|
protected function getSelect($table = null) |
81
|
|
|
{ |
82
|
|
|
$this->initialize(); |
83
|
|
|
return $this->getSlaveSql()->select($table ?: $this->getTableName()); |
84
|
|
|
} |
85
|
|
|
/** |
86
|
|
|
* @param Select $select |
87
|
|
|
* @param object|null $entityPrototype |
88
|
|
|
* @param HydratorInterface|null $hydrator |
89
|
|
|
* @return HydratingResultSet |
90
|
|
|
*/ |
91
|
|
|
protected function select(Select $select, $entityPrototype = null, HydratorInterface $hydrator = null) |
92
|
|
|
{ |
93
|
|
|
$this->initialize(); |
94
|
|
|
$stmt = $this->getSlaveSql()->prepareStatementForSqlObject($select); |
95
|
|
|
$resultSet = new HydratingResultSet($hydrator ?: $this->getHydrator(), |
96
|
|
|
$entityPrototype ?: $this->getEntityPrototype()); |
97
|
|
|
$resultSet->initialize($stmt->execute()); |
98
|
|
|
return $resultSet; |
99
|
|
|
} |
100
|
|
|
/** |
101
|
|
|
* @param object|array $entity |
102
|
|
|
* @param string|TableIdentifier|null $tableName |
103
|
|
|
* @param HydratorInterface|null $hydrator |
104
|
|
|
* @return ResultInterface |
105
|
|
|
*/ |
106
|
|
|
protected function insert($entity, $tableName = null, HydratorInterface $hydrator = null) |
107
|
|
|
{ |
108
|
|
|
$this->initialize(); |
109
|
|
|
$tableName = $tableName ?: $this->tableName; |
110
|
|
|
$sql = $this->getSql()->setTable($tableName); |
111
|
|
|
$insert = $sql->insert(); |
112
|
|
|
$rowData = $this->entityToArray($entity, $hydrator); |
|
|
|
|
113
|
|
|
$insert->values($rowData); |
114
|
|
|
$statement = $sql->prepareStatementForSqlObject($insert); |
115
|
|
|
return $statement->execute(); |
116
|
|
|
} |
117
|
|
|
/** |
118
|
|
|
* @param object|array $entity |
119
|
|
|
* @param string|array|\Closure $where |
120
|
|
|
* @param string|TableIdentifier|null $tableName |
121
|
|
|
* @param HydratorInterface|null $hydrator |
122
|
|
|
* @return ResultInterface |
123
|
|
|
*/ |
124
|
|
|
protected function update($entity, $where, $tableName = null, HydratorInterface $hydrator = null) |
125
|
|
|
{ |
126
|
|
|
$this->initialize(); |
127
|
|
|
$tableName = $tableName ?: $this->tableName; |
128
|
|
|
$sql = $this->getSql()->setTable($tableName); |
129
|
|
|
$update = $sql->update(); |
130
|
|
|
$rowData = $this->entityToArray($entity, $hydrator); |
|
|
|
|
131
|
|
|
$update->set($rowData) |
132
|
|
|
->where($where); |
133
|
|
|
$statement = $sql->prepareStatementForSqlObject($update); |
134
|
|
|
return $statement->execute(); |
135
|
|
|
} |
136
|
|
|
/** |
137
|
|
|
* @param string|array|\Closure $where |
138
|
|
|
* @param string|TableIdentifier|null $tableName |
139
|
|
|
* @return ResultInterface |
140
|
|
|
*/ |
141
|
|
|
protected function delete($where, $tableName = null) |
142
|
|
|
{ |
143
|
|
|
$tableName = $tableName ?: $this->tableName; |
144
|
|
|
$sql = $this->getSql()->setTable($tableName); |
145
|
|
|
$delete = $sql->delete(); |
146
|
|
|
$delete->where($where); |
147
|
|
|
$statement = $sql->prepareStatementForSqlObject($delete); |
148
|
|
|
return $statement->execute(); |
149
|
|
|
} |
150
|
|
|
/** |
151
|
|
|
* @return string |
152
|
|
|
*/ |
153
|
|
|
protected function getTableName() |
154
|
|
|
{ |
155
|
|
|
return $this->tableName; |
156
|
|
|
} |
157
|
|
|
/** |
158
|
|
|
* @return object |
159
|
|
|
*/ |
160
|
|
|
public function getEntityPrototype() |
161
|
|
|
{ |
162
|
|
|
return $this->entityPrototype; |
163
|
|
|
} |
164
|
|
|
/** |
165
|
|
|
* @param object $entityPrototype |
166
|
|
|
* @return AbstractDbMapper |
167
|
|
|
*/ |
168
|
|
|
public function setEntityPrototype($entityPrototype) |
169
|
|
|
{ |
170
|
|
|
$this->entityPrototype = $entityPrototype; |
171
|
|
|
$this->resultSetPrototype = null; |
172
|
|
|
return $this; |
173
|
|
|
} |
174
|
|
|
/** |
175
|
|
|
* @return Adapter |
176
|
|
|
*/ |
177
|
|
|
public function getDbAdapter() |
178
|
|
|
{ |
179
|
|
|
return $this->dbAdapter; |
180
|
|
|
} |
181
|
|
|
/** |
182
|
|
|
* @param Adapter $dbAdapter |
183
|
|
|
* @return AbstractDbMapper |
184
|
|
|
*/ |
185
|
|
|
public function setDbAdapter(Adapter $dbAdapter) |
186
|
|
|
{ |
187
|
|
|
$this->dbAdapter = $dbAdapter; |
188
|
|
|
if ($dbAdapter instanceof MasterSlaveAdapterInterface) { |
189
|
|
|
$this->setDbSlaveAdapter($dbAdapter->getSlaveAdapter()); |
190
|
|
|
} |
191
|
|
|
return $this; |
192
|
|
|
} |
193
|
|
|
/** |
194
|
|
|
* @return Adapter |
195
|
|
|
*/ |
196
|
|
|
public function getDbSlaveAdapter() |
197
|
|
|
{ |
198
|
|
|
return $this->dbSlaveAdapter ?: $this->dbAdapter; |
199
|
|
|
} |
200
|
|
|
/** |
201
|
|
|
* @param Adapter $dbSlaveAdapter |
202
|
|
|
* @return AbstractDbMapper |
203
|
|
|
*/ |
204
|
|
|
public function setDbSlaveAdapter(Adapter $dbSlaveAdapter) |
205
|
|
|
{ |
206
|
|
|
$this->dbSlaveAdapter = $dbSlaveAdapter; |
207
|
|
|
return $this; |
208
|
|
|
} |
209
|
|
|
/** |
210
|
|
|
* @return HydratorInterface |
211
|
|
|
*/ |
212
|
|
|
public function getHydrator() |
213
|
|
|
{ |
214
|
|
|
if (!$this->hydrator) { |
215
|
|
|
$this->hydrator = new ClassMethods(false); |
216
|
|
|
} |
217
|
|
|
return $this->hydrator; |
218
|
|
|
} |
219
|
|
|
/** |
220
|
|
|
* @param HydratorInterface $hydrator |
221
|
|
|
* @return AbstractDbMapper |
222
|
|
|
*/ |
223
|
|
|
public function setHydrator(HydratorInterface $hydrator) |
224
|
|
|
{ |
225
|
|
|
$this->hydrator = $hydrator; |
226
|
|
|
$this->resultSetPrototype = null; |
227
|
|
|
return $this; |
228
|
|
|
} |
229
|
|
|
/** |
230
|
|
|
* @return Sql |
231
|
|
|
*/ |
232
|
|
|
protected function getSql() |
233
|
|
|
{ |
234
|
|
|
if (!$this->sql instanceof Sql) { |
235
|
|
|
$this->sql = new Sql($this->getDbAdapter()); |
236
|
|
|
} |
237
|
|
|
return $this->sql; |
238
|
|
|
} |
239
|
|
|
/** |
240
|
|
|
* @param Sql $sql |
241
|
|
|
* @return AbstractDbMapper |
242
|
|
|
*/ |
243
|
|
|
protected function setSql(Sql $sql) |
244
|
|
|
{ |
245
|
|
|
$this->sql = $sql; |
246
|
|
|
return $this; |
247
|
|
|
} |
248
|
|
|
/** |
249
|
|
|
* @return Sql |
250
|
|
|
*/ |
251
|
|
|
protected function getSlaveSql() |
252
|
|
|
{ |
253
|
|
|
if (!$this->slaveSql instanceof Sql) { |
254
|
|
|
$this->slaveSql = new Sql($this->getDbSlaveAdapter()); |
255
|
|
|
} |
256
|
|
|
return $this->slaveSql; |
257
|
|
|
} |
258
|
|
|
/** |
259
|
|
|
* @param Sql $sql |
260
|
|
|
* @return AbstractDbMapper |
261
|
|
|
*/ |
262
|
|
|
protected function setSlaveSql(Sql $sql) |
263
|
|
|
{ |
264
|
|
|
$this->slaveSql = $sql; |
265
|
|
|
return $this; |
266
|
|
|
} |
267
|
|
|
/** |
268
|
|
|
* Uses the hydrator to convert the entity to an array. |
269
|
|
|
* |
270
|
|
|
* Use this method to ensure that you're working with an array. |
271
|
|
|
* |
272
|
|
|
* @param object $entity |
273
|
|
|
* @param HydratorInterface|null $hydrator |
274
|
|
|
* @return array |
275
|
|
|
*/ |
276
|
|
|
protected function entityToArray($entity, HydratorInterface $hydrator = null) |
277
|
|
|
{ |
278
|
|
|
if (is_array($entity)) { |
279
|
|
|
return $entity; // cut down on duplicate code |
280
|
|
|
} elseif (is_object($entity)) { |
281
|
|
|
if (!$hydrator) { |
282
|
|
|
$hydrator = $this->getHydrator(); |
283
|
|
|
} |
284
|
|
|
return $hydrator->extract($entity); |
285
|
|
|
} |
286
|
|
|
throw new Exception\InvalidArgumentException('Entity passed to db mapper should be an array or object.'); |
287
|
|
|
} |
288
|
|
|
} |
289
|
|
|
|
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.