227 lines
6 KiB
PHP
227 lines
6 KiB
PHP
<?php
|
|
|
|
namespace EesyPHPExample\Db;
|
|
|
|
use EesyPHP\Check;
|
|
use EesyPHP\Hook;
|
|
use EesyPHP\Log;
|
|
use EesyPHP\Tpl;
|
|
|
|
use EesyPHP\Db\AttrBool;
|
|
use EesyPHP\Db\AttrInt;
|
|
use EesyPHP\Db\AttrSet;
|
|
use EesyPHP\Db\AttrStr;
|
|
use EesyPHP\Db\AttrTimestamp;
|
|
use EesyPHP\Db\DbObject;
|
|
|
|
use EesyPHP\Export\CSV;
|
|
|
|
use Unidecode\Unidecode;
|
|
|
|
/**
|
|
* Item database object
|
|
* @property int|null $id
|
|
* @property string $name
|
|
* @property \DateTime|null $date
|
|
* @property string $status
|
|
* @property string|null $description
|
|
*/
|
|
class Item extends DbObject {
|
|
protected const TABLE = 'item';
|
|
protected const PRIMARY_KEYS = ['id'];
|
|
protected const DEFAULT_ORDER = 'id';
|
|
protected const DEFAULT_ORDER_DIRECTION = 'DESC';
|
|
protected const POSSIBLE_ORDERS = ['id', 'name', 'date', 'status'];
|
|
|
|
/**
|
|
* Get status possible values with their translated label
|
|
* @param boolean $with_all_choice Set to true to add the 'all' value (optional, default: false)
|
|
* @return array<string,string>
|
|
*/
|
|
public static function statuses($with_all_choice=false) {
|
|
$statuses = array (
|
|
'pending' => _('Pending'),
|
|
'validated' => _('Validated'),
|
|
'refused' => _('Refused'),
|
|
'archived' => _('Archived'),
|
|
);
|
|
if ($with_all_choice)
|
|
$statuses['all'] = _('Any');
|
|
return $statuses;
|
|
}
|
|
|
|
/**
|
|
* Check item status value
|
|
* @param mixed $value Value to check
|
|
* @param boolean $allow_all Set to true to allow the 'all' value (optional, default: false)
|
|
* @return boolean
|
|
*/
|
|
public static function check_status($value, $allow_all=false) {
|
|
return array_key_exists($value, self :: statuses($allow_all));
|
|
}
|
|
|
|
protected static function get_schema() {
|
|
return [
|
|
'id' => new AttrInt(['autoincrement' => true]),
|
|
'name' => new AttrStr(['required' => true]),
|
|
'date' => new AttrTimestamp(['default' => 'time']),
|
|
'status' => new AttrSet([
|
|
'required' => true,
|
|
'default' => 'pending',
|
|
'possible_values' => array_keys(self :: statuses()),
|
|
]),
|
|
'description' => new AttrStr(),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Get item from URL
|
|
* @param mixed $id Item ID as retrieved from URL
|
|
* @param boolean $fatal Set to true to trigger fatal error if item is not found in DB
|
|
* @return Item|false
|
|
*/
|
|
public static function get_from_url($id, $fatal=false) {
|
|
if (!Check :: id($id))
|
|
Log :: fatal(_('Invalid element identifier.'));
|
|
|
|
$item = self :: get($id);
|
|
if(!$item instanceof Item) {
|
|
$error = sprintf(_("Item #%s not found."), $id);
|
|
if ($fatal)
|
|
Log :: fatal($error);
|
|
Tpl :: add_error($error);
|
|
return false;
|
|
}
|
|
return $item;
|
|
}
|
|
|
|
/**
|
|
* Change item status in DB
|
|
* @param string $status New item status
|
|
* @return bool
|
|
*/
|
|
public function change_status($status) {
|
|
$this->status = $status;
|
|
if ($this -> save()) {
|
|
Log :: info("Status of item #$this->id changed to $status.");
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Set item as archived in DB
|
|
* @return bool
|
|
*/
|
|
public function archive() {
|
|
return $this -> change_status('archived');
|
|
}
|
|
|
|
|
|
/**
|
|
* Compute WHERE clauses from word pattern
|
|
* @throws \EesyPHP\Db\DbException
|
|
* @return array
|
|
*/
|
|
public static function word_to_filters($word) {
|
|
$patterns_word = [];
|
|
// If numeric pattern ?
|
|
if (preg_match('/^[0-9]+$/', $word)) {
|
|
// Numeric pattern
|
|
$word = intval($word);
|
|
$patterns_word['id = ?'] = $word;
|
|
}
|
|
else {
|
|
// Text pattern
|
|
foreach (array('name', 'description') as $field) {
|
|
if (self :: DB_CLASS :: is_pgsql()) {
|
|
$word = Unidecode::unidecode($word);
|
|
$patterns_word["unaccent($field) ILIKE ?"] = "%$word%";
|
|
}
|
|
else
|
|
$patterns_word["$field LIKE ?"] = "%$word%";
|
|
}
|
|
}
|
|
return $patterns_word;
|
|
}
|
|
|
|
/**
|
|
* Search objects
|
|
* @throws \EesyPHP\Db\DbException
|
|
* @see \EesyPHP\Db\DbObject::search()
|
|
* @return array|false The search result as an array, or False in case of error.
|
|
*/
|
|
public static function search($params) {
|
|
if (
|
|
$params &&
|
|
isset($params['filters']) &&
|
|
isset($params['filters']['status']) &&
|
|
$params['filters']['status'] == 'all'
|
|
)
|
|
unset($params['filters']['status']);
|
|
return parent :: search($params);
|
|
}
|
|
|
|
/**
|
|
* Export items
|
|
* @param resource|null $fd The file pointer where to export (optional, default: php://output)
|
|
* @param array<int,array<string,mixed>>|null $items Items to export
|
|
* @param array<string,\EesyPHP\Db\Attr> $schema The object schema (optional)
|
|
* @return boolean
|
|
*/
|
|
static function export($fd=null, $items=null, $schema=null) {
|
|
$schema = $schema ? $schema : static :: get_schema();
|
|
$export = new CSV(static :: csv_export_fields($schema));
|
|
$items = $items?$items:static :: list();
|
|
if ($items === false)
|
|
return false;
|
|
$rows = [];
|
|
foreach ($items as $item) {
|
|
$row = [];
|
|
foreach($schema as $attr => $attr_type)
|
|
$row[$attr] = $item->$attr;
|
|
$rows[] = $row;
|
|
}
|
|
return $export->export($rows, $fd);
|
|
}
|
|
|
|
static function restore($fd=null, $schema=null) {
|
|
$schema = $schema ? $schema : static :: get_schema();
|
|
$import = new CSV(static :: csv_export_fields($schema));
|
|
$items = $import->load($fd);
|
|
if ($items === false) {
|
|
Log :: error("Error loading items.");
|
|
return false;
|
|
}
|
|
|
|
if (!$items) {
|
|
Log :: error("No item loaded.");
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
if (self :: DB_CLASS :: truncate(self :: TABLE)) {
|
|
Log :: debug("Table %s truncated", self :: TABLE);
|
|
}
|
|
else {
|
|
Log :: error("An unknown error occurred truncating table %s in database.", self :: TABLE);
|
|
return false;
|
|
}
|
|
}
|
|
catch (\Exception $e) {
|
|
Log :: error("Error truncating item table in database : ".$e->getMessage());
|
|
return false;
|
|
}
|
|
|
|
$success = true;
|
|
foreach($items as $item) {
|
|
$obj = new Item();
|
|
$obj->apply($item);
|
|
$success = $success && $obj->save();
|
|
}
|
|
|
|
// Trigger hooks
|
|
Hook :: trigger('items_restored');
|
|
return $success;
|
|
}
|
|
}
|