1 <?php
2
3 namespace Balance\Model\Persistence\Db;
4
5 use Balance\Model\AccountType;
6 use Balance\Model\BooleanType;
7 use Balance\Model\ModelException;
8 use Balance\Model\Persistence\PersistenceInterface;
9 use Balance\Model\Persistence\ValueOptionsInterface;
10 use Exception;
11 use Zend\Db\Sql\Expression;
12 use Zend\Db\Sql\Select;
13 use Zend\ServiceManager\ServiceLocatorAwareInterface;
14 use Zend\ServiceManager\ServiceLocatorAwareTrait;
15 use Zend\Stdlib\Parameters;
16
17 18 19
20 class Accounts implements PersistenceInterface, ServiceLocatorAwareInterface, ValueOptionsInterface
21 {
22 use ServiceLocatorAwareTrait;
23
24 25 26
27 public function fetch(Parameters $params)
28 {
29
30 $result = array();
31
32 $db = $this->getServiceLocator()->get('db');
33
34 $expression = 'CASE "a"."type"';
35 $definition = (new AccountType())->getDefinition();
36 foreach ($definition as $identifier => $value) {
37 $expression = $expression . sprintf(" WHEN '%s' THEN '%s'", $identifier, $value);
38 }
39 $expression = $expression . ' END';
40
41 $eType = new Expression($expression);
42
43 $select = (new Select())
44 ->from(array('a' => 'accounts'))
45 ->columns(array('id', 'name', 'type' => $eType));
46
47 if ($params['type']) {
48 $select->where(function ($where) use ($params) {
49 $where->equalTo('a.type', $params['type']);
50 });
51 }
52
53 if ($params['keywords']) {
54
55 $select->where(function ($where) use ($params) {
56
57 $language = locale_get_display_language(null, 'en');
58
59 $document = new Expression(
60 'TO_TSVECTOR(\'' . $language . '\', "a"."name")'
61 . ' || TO_TSVECTOR(\'' . $language . '\', "a"."description")'
62 );
63
64 $search = (new Select())
65 ->from(array('a' => 'accounts'))
66 ->columns(array('account_id' => 'id', 'document' => $document));
67
68 $subselect = (new Select())
69 ->from(array('search' => $search))
70 ->columns(array('account_id'))
71 ->where(function ($where) use ($params, $language) {
72 $where->expression(
73 '"search"."document" @@ TO_TSQUERY(\'' . $language . '\', ?)',
74 sprintf("'%s'", addslashes($params['keywords']))
75 );
76 });
77
78 $where->in('a.id', $subselect);
79 });
80 }
81
82 $select->order(array('a.position'));
83
84 $rowset = $db->query($select->getSqlString($db->getPlatform()))->execute();
85
86 foreach ($rowset as $row) {
87 $result[] = array(
88 'id' => (int) $row['id'],
89 'name' => $row['name'],
90 'type' => $row['type'],
91 );
92 }
93
94 return $result;
95 }
96
97 98 99
100 public function find(Parameters $params)
101 {
102
103 if (! $params['id']) {
104 throw new ModelException('Unknown Primary Key');
105 }
106
107 $db = $this->getServiceLocator()->get('db');
108
109 $select = (new Select())
110 ->from(array('a' => 'accounts'))
111 ->columns(array('id', 'name', 'type', 'description', 'accumulate'))
112 ->where(function ($where) use ($params) {
113 $where->equalTo('a.id', (int) $params['id']);
114 });
115
116 $row = $db->query($select->getSqlString($db->getPlatform()))->execute()->current();
117
118 if (! $row) {
119 throw new ModelException('Unknown Element');
120 }
121
122 $element = array(
123 'id' => (int) $row['id'],
124 'type' => $row['type'],
125 'name' => $row['name'],
126 'description' => $row['description'],
127 'accumulate' => $row['accumulate'] === 't' ? BooleanType::YES : BooleanType::NO,
128 );
129
130 return $element;
131 }
132
133 134 135
136 public function save(Parameters $data)
137 {
138
139 $tbAccounts = $this->getServiceLocator()->get('Balance\Db\TableGateway\Accounts');
140 $db = $this->getServiceLocator()->get('db');
141 $connection = $db->getDriver()->getConnection();
142
143 try {
144
145 $connection->beginTransaction();
146
147 if ($data['id']) {
148
149 $tbAccounts->update(array(
150 'type' => $data['type'],
151 'name' => $data['name'],
152 'description' => $data['description'],
153 'accumulate' => $data['accumulate'] === BooleanType::YES ? 't' : 'f',
154 ), function ($where) use ($data) {
155 $where->equalTo('id', $data['id']);
156 });
157 } else {
158
159 $select = (new Select())
160 ->from(array('a' => 'accounts'))
161 ->columns(array('position' => new Expression('MAX("a"."position") + 1')));
162
163 $position = (int) $db->query($select->getSqlString($db->getPlatform()))->execute()
164 ->current()['position'];
165
166 $tbAccounts->insert(array(
167 'type' => $data['type'],
168 'name' => $data['name'],
169 'description' => $data['description'],
170 'position' => $position,
171 'accumulate' => $data['accumulate'] === BooleanType::YES ? 't' : 'f',
172 ));
173
174 $data['id'] = (int) $tbAccounts->getLastInsertValue();
175 }
176
177 $connection->commit();
178 } catch (Exception $e) {
179
180 $connection->rollback();
181
182 throw new ModelException('Database Error', null, $e);
183 }
184
185 return $this;
186 }
187
188 189 190
191 public function remove(Parameters $params)
192 {
193
194 if (! $params['id']) {
195 throw new ModelException('Unknown Primary Key');
196 }
197
198 $db = $this->getServiceLocator()->get('db');
199 $tbAccounts = $this->getServiceLocator()->get('Balance\Db\TableGateway\Accounts');
200 $connection = $db->getDriver()->getConnection();
201
202 try {
203
204 $connection->beginTransaction();
205
206 $select = (new Select())
207 ->from(array('a' => 'accounts'))
208 ->columns(array('position'))
209 ->where(function ($where) use ($params) {
210 $where->equalTo('a.id', $params['id']);
211 });
212
213 $row = $db->query($select->getSqlString($db->getPlatform()))->execute()->current();
214
215 if (! $row) {
216 throw new ModelException('Unknown Element');
217 }
218
219 $tbAccounts->delete(function ($delete) use ($params) {
220 $delete->where(function ($where) use ($params) {
221 $where->equalTo('id', $params['id']);
222 });
223 });
224
225 $tbAccounts->update(array(
226 'position' => new Expression('"position" - 1'),
227 ), function ($where) use ($row) {
228 $where->greaterThan('position', $row['position']);
229 });
230
231 $connection->commit();
232 } catch (Exception $e) {
233
234 $connection->rollback();
235
236 throw new ModelException('Database Error', null, $e);
237 }
238
239 return $this;
240 }
241
242 243 244
245 public function getValueOptions()
246 {
247
248 $definition = (new AccountType())->getDefinition();
249
250 $result = array(
251 AccountType::ACTIVE => array(
252 'label' => $definition[AccountType::ACTIVE],
253 'options' => array(),
254 ),
255 AccountType::PASSIVE => array(
256 'label' => $definition[AccountType::PASSIVE],
257 'options' => array(),
258 ),
259 );
260
261 $db = $this->getServiceLocator()->get('db');
262
263 $select = (new Select())
264 ->from(array('a' => 'accounts'))
265 ->columns(array('id', 'type', 'name'))
266 ->order(array('a.type', 'a.name'));
267
268 $rowset = $db->query($select->getSqlString($db->getPlatform()))->execute();
269
270 foreach ($rowset as $row) {
271 $result[$row['type']]['options'][$row['id']] = $row['name'];
272 }
273
274 foreach ($result as $identifier => $container) {
275 if (! $container['options']) {
276 unset($result[$identifier]);
277 }
278 }
279
280 $result = array_values($result);
281
282 return $result;
283 }
284
285 286 287 288 289 290 291
292 private function getPosition($id)
293 {
294
295 $db = $this->getServiceLocator()->get('db');
296
297 $select = (new Select())
298 ->from(array('a' => 'accounts'))
299 ->columns(array('position'))
300 ->where(function ($where) use ($id) {
301 $where->equalTo('a.id', $id);
302 });
303
304 $row = $db->query($select->getSqlString($db->getPlatform()))->execute()->current();
305
306 if (! $row) {
307 throw new ModelException('Unknown Element');
308 }
309
310 return (int) $row['position'];
311 }
312
313 314 315 316 317 318
319 public function order(Parameters $params)
320 {
321
322 $id = (int) $params['id'];
323 $previous = (int) $params['previous'];
324
325
326 $tbAccounts = $this->getServiceLocator()->get('Balance\Db\TableGateway\Accounts');
327 $db = $this->getServiceLocator()->get('db');
328 $connection = $db->getDriver()->getConnection();
329
330
331 $positionBefore = $this->getPosition($id);
332 $positionAfter = -1;
333
334
335 if ($previous) {
336
337 $positionAfter = $this->getPosition($previous);
338 }
339
340
341 if ($positionBefore === $positionAfter) {
342
343 return $this;
344 }
345
346
347 if ($positionBefore > $positionAfter) {
348
349 $positionAfter = $positionAfter + 1;
350 }
351
352
353 try {
354
355 $connection->beginTransaction();
356
357
358 $parameters = array($positionBefore, $positionAfter, ($positionBefore < $positionAfter ? '-1' : '+1'));
359
360 $expression = new Expression('(CASE WHEN "position" = ? THEN ? ELSE "position" + ? END)', $parameters);
361
362
363 $tbAccounts->update(array(
364 'position' => $expression,
365 ), function ($where) use ($positionBefore, $positionAfter) {
366 $where->between(
367 'position',
368 min($positionBefore, $positionAfter),
369 max($positionBefore, $positionAfter)
370 );
371 });
372
373
374 $connection->commit();
375 } catch (Exception $e) {
376
377 $connection->rollback();
378
379 throw new ModelException('Database Error', null, $e);
380 }
381
382
383 return $this;
384 }
385 }
386