3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
10 * Copyright © 2007-2014 The Galette Team
12 * This file is part of Galette (http://galette.tuxfamily.org).
14 * Galette is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
19 * Galette is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2007-2014 The Galette Team
32 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
33 * @link http://galette.tuxfamily.org
34 * @since Available since 0.7dev - 2007-10-27
37 namespace Galette\Entity
;
40 use Laminas\Db\Sql\Expression
;
41 use Laminas\Db\Adapter\Adapter
;
45 * Entitled handling. Manage:
48 * - extra (that may differ from one entity to another)
53 * @author Johan Cwiklinski <johan@x-tnd.be>
54 * @copyright 2007-2014 The Galette Team
55 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
56 * @link http://galette.tuxfamily.org
57 * @since Available since 0.7dev - 2007-10-27
60 abstract class Entitled
64 const ID_NOT_EXITS
= -1;
73 public static $fields;
74 protected static $defaults;
76 protected $order_field = false;
82 private $errors = array();
87 * @param Db $zdb Database
88 * @param string $table Table name
89 * @param string $fpk Primary key field name
90 * @param string $flabel Label fields name
91 * @param string $fthird The third field name
92 * @param string $used Table name for isUsed function
93 * @param mixed $args Either an int or a resultset to load
95 public function __construct(Db
$zdb, $table, $fpk, $flabel, $fthird, $used, $args = null)
98 $this->table
= $table;
100 $this->flabel
= $flabel;
101 $this->fthird
= $fthird;
105 } elseif (is_object($args)) {
106 $this->loadFromRS($args);
111 * Loads an entry from its id
113 * @param int $id Entry ID
115 * @return boolean true if query succeed, false otherwise
117 public function load($id)
120 $select = $this->zdb
->select($this->table
);
121 $select->where($this->fpk
. ' = ' . $id);
123 $results = $this->zdb
->execute($select);
124 if ($results->count() > 0) {
125 $result = $results->current();
126 $this->loadFromRS($result);
130 throw new \
RuntimeException(
131 'Unknown ID ' . $id . '!'
134 } catch (\Exception
$e) {
136 'Cannot load ' . $this->getType() . ' from id `' . $id . '` | ' .
145 * Populate object from a resultset row
147 * @param ResultSet $r the resultset row
151 private function loadFromRS($r)
155 $flabel = $this->flabel
;
156 $this->label
= $r->$flabel;
157 $fthird = $this->fthird
;
158 $this->third
= $r->$fthird;
162 * Set defaults at install time
164 * @return boolean|Exception
166 public function installInit()
168 $class = get_class($this);
171 //first, we drop all values
172 $delete = $this->zdb
->delete($this->table
);
173 $this->zdb
->execute($delete);
176 foreach ($class::$fields as $key => $f) {
177 $values[$f] = ':' . $key;
180 $insert = $this->zdb
->insert($this->table
);
181 $insert->values($values);
182 $stmt = $this->zdb
->sql
->prepareStatementForSqlObject($insert);
184 $this->zdb
->handleSequence(
186 count(static::$defaults)
189 $fnames = array_keys($values);
190 foreach ($class::$defaults as $d) {
192 if (isset($d['priority'])) {
193 $val = $d['priority'];
195 $val = $d['extension'];
200 $fnames[0] => $d['id'],
201 $fnames[1] => $d['libelle'],
208 'Defaults (' . $this->getType() .
209 ') were successfully stored into database.',
213 } catch (\Exception
$e) {
215 'Unable to initialize defaults (' . $this->getType() . ').' .
224 * Get list in an array built as:
225 * $array[id] = "translated label"
227 * @param int $extent Filter on (non) cotisations types
229 * @return array|false
231 public function getList($extent = null)
236 $select = $this->zdb
->select($this->table
);
237 $fields = array($this->fpk
, $this->flabel
);
239 $this->order_field
!== false
240 && $this->order_field
!== $this->fpk
241 && $this->order_field
!== $this->flabel
243 $fields[] = $this->order_field
;
245 $select->quantifier('DISTINCT');
246 $select->columns($fields);
248 if ($this->order_field
!== false) {
249 $select->order($this->order_field
, $this->fpk
);
251 if ($extent !== null) {
252 if ($extent === true) {
253 $select->where(array($this->fthird
=> new Expression('true')));
254 } elseif ($extent === false) {
255 $select->where(array($this->fthird
=> new Expression('false')));
259 $results = $this->zdb
->execute($select);
261 foreach ($results as $r) {
263 $flabel = $this->flabel
;
264 $list[$r->$fpk] = _T($r->$flabel);
267 } catch (\Exception
$e) {
269 __METHOD__
. ' | ' . $e->getMessage(),
279 * @return array of all objects if succeed, false otherwise
281 public function getCompleteList()
286 $select = $this->zdb
->select($this->table
);
287 if ($this->order_field
!== false) {
288 $select->order(array($this->order_field
, $this->fpk
));
291 $results = $this->zdb
->execute($select);
293 if ($results->count() == 0) {
295 'No entries (' . $this->getType() . ') defined in database.',
300 $flabel = $this->flabel
;
301 $fprio = $this->fthird
;
303 foreach ($results as $r) {
304 $list[$r->$pk] = array(
305 'name' => _T($r->$flabel),
306 'extra' => $r->$fprio
311 } catch (\Exception
$e) {
313 'Cannot list entries (' . $this->getType() .
314 ') | ' . $e->getMessage(),
324 * @param integer $id Entry ID
326 * @return mixed|false Row if succeed ; false: no such id
328 public function get($id)
330 if (!is_numeric($id)) {
331 $this->errors
[] = _T("ID must be an integer!");
336 $select = $this->zdb
->select($this->table
);
337 $select->where($this->fpk
. '=' . $id);
339 $results = $this->zdb
->execute($select);
340 $result = $results->current();
343 $this->errors
[] = _T("Label does not exist");
348 } catch (\Exception
$e) {
350 __METHOD__
. ' | ' . $e->getMessage(),
360 * @param integer $id Id
361 * @param boolean $translated Do we want translated or original label?
366 public function getLabel($id, $translated = true)
368 $res = $this->get($id);
369 if ($res === false) {
371 return self
::ID_NOT_EXITS
;
373 $field = $this->flabel
;
374 return ($translated) ?
_T($res->$field) : $res->$field;
378 * Get an ID from a label
380 * @param string $label The label
382 * @return int|false Return id if it exists false otherwise
384 public function getIdByLabel($label)
388 $select = $this->zdb
->select($this->table
);
389 $select->columns(array($pk))
390 ->where(array($this->flabel
=> $label));
392 $results = $this->zdb
->execute($select);
393 $result = $results->current();
399 } catch (\Exception
$e) {
401 'Unable to retrieve ' . $this->getType() . ' from label `' .
402 $label . '` | ' . $e->getMessage(),
412 * @param string $label The label
413 * @param integer $extra Extra values (priority for statuses,
414 * extension for contributions types, ...)
416 * @return integer id if success ; -1 : DB error ; -2 : label already exists
418 public function add($label, $extra)
421 $ret = $this->getIdByLabel($label);
423 if ($ret !== false) {
425 $this->getType() . ' with label `' . $label . '` already exists',
432 $this->zdb
->connection
->beginTransaction();
434 $this->flabel
=> $label,
435 $this->fthird
=> $extra
438 $insert = $this->zdb
->insert($this->table
);
439 $insert->values($values);
441 $ret = $this->zdb
->execute($insert);
443 if ($ret->count() > 0) {
445 'New ' . $this->getType() . ' `' . $label .
446 '` added successfully.',
450 if ($this->zdb
->isPostgres()) {
451 $this->id
= $this->zdb
->driver
->getLastGeneratedValue(
452 PREFIX_DB
. $this->table
. '_id_seq'
455 $this->id
= $this->zdb
->driver
->getLastGeneratedValue();
458 $this->addTranslation($label);
460 throw new \
Exception('New ' . $this->getType() . ' not added.');
462 $this->zdb
->connection
->commit();
464 } catch (\Exception
$e) {
465 $this->zdb
->connection
->rollBack();
467 'Unable to add new entry `' . $label . '` | ' .
476 * Update in database.
478 * @param integer $id Entry ID
479 * @param string $label The label
480 * @param integer $extra Extra values (priority for statuses,
481 * extension for contributions types, ...)
483 * @return ID_NOT_EXITS|boolean
485 public function update($id, $label, $extra)
487 $ret = $this->get($id);
489 /* get() already logged and set $this->error. */
490 return self
::ID_NOT_EXITS
;
493 $class = get_class($this);
496 $oldlabel = $ret->{$this->flabel
};
497 $this->zdb
->connection
->beginTransaction();
499 $this->flabel
=> $label,
500 $this->fthird
=> $extra
503 $update = $this->zdb
->update($this->table
);
504 $update->set($values);
505 $update->where($this->fpk
. ' = ' . $id);
507 $ret = $this->zdb
->execute($update);
509 if ($oldlabel != $label) {
510 $this->deleteTranslation($oldlabel);
511 $this->addTranslation($label);
515 $this->getType() . ' #' . $id . ' updated successfully.',
518 $this->zdb
->connection
->commit();
520 } catch (\Exception
$e) {
521 $this->zdb
->connection
->rollBack();
523 'Unable to update ' . $this->getType() . ' #' . $id . ' | ' .
534 * @param integer $id Entry ID
536 * @return ID_NOT_EXITS|boolean
538 public function delete($id)
540 $ret = $this->get($id);
542 /* get() already logged */
543 return self
::ID_NOT_EXITS
;
546 if ($this->isUsed($id)) {
547 $this->errors
[] = _T("Cannot delete this label: it's still used");
552 $this->zdb
->connection
->beginTransaction();
553 $delete = $this->zdb
->delete($this->table
);
554 $delete->where($this->fpk
. ' = ' . $id);
556 $this->zdb
->execute($delete);
557 $this->deleteTranslation($ret->{$this->flabel
});
560 $this->getType() . ' ' . $id . ' deleted successfully.',
564 $this->zdb
->connection
->commit();
566 } catch (\Exception
$e) {
567 $this->zdb
->connection
->rollBack();
569 'Unable to delete ' . $this->getType() . ' ' . $id .
570 ' | ' . $e->getMessage(),
578 * Check if this entry is used.
580 * @param integer $id Entry ID
584 public function isUsed($id)
587 $select = $this->zdb
->select($this->used
);
588 $select->where($this->fpk
. ' = ' . $id);
590 $results = $this->zdb
->execute($select);
591 $result = $results->current();
593 if ($result !== null) {
598 } catch (\Exception
$e) {
600 'Unable to check if ' . $this->getType
. ' `' . $id .
601 '` is used. | ' . $e->getMessage(),
604 //in case of error, we consider that it is used, to avoid errors
610 * Get textual type representation
614 abstract protected function getType();
617 * Get translated textual representation
621 abstract public function getI18nType();
624 * Global getter method
626 * @param string $name name of the property we want to retrive
628 * @return false|object the called property
630 public function __get($name)
632 $forbidden = array();
633 $virtuals = array('extension', 'libelle');
635 in_array($name, $virtuals)
636 ||
!in_array($name, $forbidden)
637 && isset($this->$name)
641 return _T($this->label
);
660 public function getErrors(): array
662 return $this->errors
;