Make Db class static as other classes
This commit is contained in:
parent
d0eb50cf22
commit
dbf5b0a54c
15 changed files with 562 additions and 527 deletions
|
@ -22,8 +22,14 @@ repos:
|
||||||
rev: 1.4.0
|
rev: 1.4.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: php-stan
|
- id: php-stan
|
||||||
files: \.(php)$
|
files: ^(?!example/).*\.(php)$
|
||||||
args: ["--configuration=phpstan.neon"]
|
args: ["--configuration=phpstan.neon"]
|
||||||
|
- repo: https://github.com/digitalpulp/pre-commit-php.git
|
||||||
|
rev: 1.4.0
|
||||||
|
hooks:
|
||||||
|
- id: php-stan
|
||||||
|
files: ^example/.*\.(php)$
|
||||||
|
args: ["--configuration=example/phpstan.neon"]
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v4.4.0
|
rev: v4.4.0
|
||||||
hooks:
|
hooks:
|
||||||
|
|
3
example/.gitignore
vendored
Normal file
3
example/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Exclude composer installed libs
|
||||||
|
/vendor
|
||||||
|
/composer.lock
|
35
example/composer.json
Normal file
35
example/composer.json
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
{
|
||||||
|
"name": "brenard/eesyphpexample",
|
||||||
|
"description": "Example app using EesyPHP framework",
|
||||||
|
"type": "project",
|
||||||
|
"license": "GPL-3.0-or-later",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"EesyPHPExample\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Benjamin Renard",
|
||||||
|
"email": "brenard@easter-eggs.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"minimum-stability": "dev",
|
||||||
|
"repositories": [
|
||||||
|
{
|
||||||
|
"type": "path",
|
||||||
|
"url": "../"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"brenard/eesyphp": "@dev"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"allow-plugins": {
|
||||||
|
"php-http/discovery": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpstan/phpstan": "2.0.x-dev"
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,8 @@ use EesyPHP\Cli;
|
||||||
use EesyPHP\Date;
|
use EesyPHP\Date;
|
||||||
use EesyPHP\Log;
|
use EesyPHP\Log;
|
||||||
|
|
||||||
|
use EesyPHPExample\Db;
|
||||||
|
|
||||||
use function EesyPHP\___;
|
use function EesyPHP\___;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -75,7 +77,7 @@ function cli_list($command_args) {
|
||||||
if (!empty($patterns))
|
if (!empty($patterns))
|
||||||
$params['pattern'] = implode(' ', $patterns);
|
$params['pattern'] = implode(' ', $patterns);
|
||||||
|
|
||||||
$items = search_items($params);
|
$items = Db :: search_items($params);
|
||||||
if (!is_array($items)) {
|
if (!is_array($items)) {
|
||||||
Log :: error("Invalid DB info return.\n");
|
Log :: error("Invalid DB info return.\n");
|
||||||
return False;
|
return False;
|
||||||
|
@ -130,7 +132,7 @@ function cli_show($command_args) {
|
||||||
Cli :: usage(_('You must provide a valid ID.'));
|
Cli :: usage(_('You must provide a valid ID.'));
|
||||||
|
|
||||||
$item_id = $command_args[0];
|
$item_id = $command_args[0];
|
||||||
$item = get_item($item_id);
|
$item = Db :: get_item($item_id);
|
||||||
|
|
||||||
if (!$item)
|
if (!$item)
|
||||||
Log :: fatal(_("Item #%s not found."), $item_id);
|
Log :: fatal(_("Item #%s not found."), $item_id);
|
||||||
|
@ -155,7 +157,7 @@ function cli_delete($command_args) {
|
||||||
|
|
||||||
// Check exist
|
// Check exist
|
||||||
$item_id = $command_args[0];
|
$item_id = $command_args[0];
|
||||||
$item = get_item($item_id);
|
$item = Db :: get_item($item_id);
|
||||||
if (!$item)
|
if (!$item)
|
||||||
Log :: fatal(_("Item #%s not found."), $item_id);
|
Log :: fatal(_("Item #%s not found."), $item_id);
|
||||||
|
|
||||||
|
@ -171,7 +173,7 @@ function cli_delete($command_args) {
|
||||||
}
|
}
|
||||||
echo "\n";
|
echo "\n";
|
||||||
|
|
||||||
if (!delete_item($item['id']))
|
if (!Db :: delete_item($item['id']))
|
||||||
Log :: fatal(_("An error occurred deleting item #%d."), $item_id);
|
Log :: fatal(_("An error occurred deleting item #%d."), $item_id);
|
||||||
|
|
||||||
return True;
|
return True;
|
||||||
|
@ -185,7 +187,7 @@ Cli :: add_command(
|
||||||
|
|
||||||
function cli_export($command_args) {
|
function cli_export($command_args) {
|
||||||
$fd = fopen((count($command_args) >= 1?$command_args[0]:'php://output'), 'w');
|
$fd = fopen((count($command_args) >= 1?$command_args[0]:'php://output'), 'w');
|
||||||
export_items($fd);
|
Db :: export_items($fd);
|
||||||
fclose($fd);
|
fclose($fd);
|
||||||
Log :: info("Items export to '".(count($command_args) >= 1?$command_args[0]:'STDOUT')."'.");
|
Log :: info("Items export to '".(count($command_args) >= 1?$command_args[0]:'STDOUT')."'.");
|
||||||
}
|
}
|
||||||
|
@ -198,7 +200,7 @@ Cli :: add_command(
|
||||||
|
|
||||||
function cli_restore($command_args) {
|
function cli_restore($command_args) {
|
||||||
$fd = fopen((count($command_args) >= 1?$command_args[0]:'php://stdin'), 'r');
|
$fd = fopen((count($command_args) >= 1?$command_args[0]:'php://stdin'), 'r');
|
||||||
restore_items($fd);
|
Db :: restore_items($fd);
|
||||||
fclose($fd);
|
fclose($fd);
|
||||||
Log :: info(
|
Log :: info(
|
||||||
"Items restored from '%s'",
|
"Items restored from '%s'",
|
||||||
|
@ -244,7 +246,7 @@ function cli_cron($command_args) {
|
||||||
$limit = time() - ($item_max_age * 86400);
|
$limit = time() - ($item_max_age * 86400);
|
||||||
Log :: debug("Handle items expiration with creation date limit ".Date :: format($limit).".");
|
Log :: debug("Handle items expiration with creation date limit ".Date :: format($limit).".");
|
||||||
|
|
||||||
$items = search_items(array('all' => true));
|
$items = Db :: search_items(array('all' => true));
|
||||||
$error = false;
|
$error = false;
|
||||||
foreach($items['items'] as $item) {
|
foreach($items['items'] as $item) {
|
||||||
if ($item['date'] < $limit) {
|
if ($item['date'] < $limit) {
|
||||||
|
@ -253,7 +255,7 @@ function cli_cron($command_args) {
|
||||||
$item['id'], $item['name'], Date :: format($item['date'])
|
$item['id'], $item['name'], Date :: format($item['date'])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if (delete_item($item['id'])) {
|
else if (Db :: delete_item($item['id'])) {
|
||||||
Log :: info('Item #%s (%s) deleted (creation date: %s)',
|
Log :: info('Item #%s (%s) deleted (creation date: %s)',
|
||||||
$item['id'], $item['name'], Date :: format($item['date'])
|
$item['id'], $item['name'], Date :: format($item['date'])
|
||||||
);
|
);
|
||||||
|
|
|
@ -3,13 +3,15 @@
|
||||||
use EesyPHP\App;
|
use EesyPHP\App;
|
||||||
use EesyPHP\SentrySpan;
|
use EesyPHP\SentrySpan;
|
||||||
|
|
||||||
|
use EesyPHPExample\Db;
|
||||||
|
|
||||||
use function EesyPHP\___;
|
use function EesyPHP\___;
|
||||||
|
|
||||||
error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED);
|
error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED);
|
||||||
|
|
||||||
// Root directory path
|
// Root directory path
|
||||||
$script = null;
|
$script = null;
|
||||||
if (defined('__FILE__') && constant('__FILE__')) { // @phpstan-ignore-line
|
if (defined('__FILE__') && constant('__FILE__')) {
|
||||||
$script = __FILE__;
|
$script = __FILE__;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -69,7 +71,8 @@ foreach($status_list as $key => $value)
|
||||||
require_once('cli.php');
|
require_once('cli.php');
|
||||||
require_once('templates.php');
|
require_once('templates.php');
|
||||||
require_once('url-helpers.php');
|
require_once('url-helpers.php');
|
||||||
require_once('db.php');
|
|
||||||
|
Db :: init();
|
||||||
|
|
||||||
$sentry_span->finish();
|
$sentry_span->finish();
|
||||||
|
|
||||||
|
|
|
@ -1,390 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use EesyPHP\App;
|
|
||||||
use EesyPHP\Db;
|
|
||||||
use EesyPHP\Hook;
|
|
||||||
use EesyPHP\Log;
|
|
||||||
|
|
||||||
use Unidecode\Unidecode;
|
|
||||||
|
|
||||||
$db = new Db(
|
|
||||||
App::get('db.dsn', null, 'string'),
|
|
||||||
App::get('db.user', null, 'string'),
|
|
||||||
App::get('db.password', null, 'string'),
|
|
||||||
App::get('db.options', array(), 'array'),
|
|
||||||
App::get('db.date_format', null, 'string'),
|
|
||||||
App::get('db.datetime_format', null, 'string'),
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Methods to handle items
|
|
||||||
*/
|
|
||||||
function get_items($orderby='id', $raw_values=false) {
|
|
||||||
global $db;
|
|
||||||
try {
|
|
||||||
$info = $db -> get_many('item', null, null, $orderby);
|
|
||||||
if (!is_array($info))
|
|
||||||
return;
|
|
||||||
if ($raw_values)
|
|
||||||
return $info;
|
|
||||||
|
|
||||||
$items = array();
|
|
||||||
foreach ($info as $item)
|
|
||||||
$items[$item['id']] = $db -> format_row_info($item, array('date'));
|
|
||||||
return $items;
|
|
||||||
}
|
|
||||||
catch (Exception $e) {
|
|
||||||
Log :: error("Error retrieving items info from database : ".$e->getMessage());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_item($id, $raw_values=false) {
|
|
||||||
global $db;
|
|
||||||
try {
|
|
||||||
$info = $db -> get_one('item', array('id' => $id));
|
|
||||||
|
|
||||||
if (!is_array($info))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if ($raw_values)
|
|
||||||
return $info;
|
|
||||||
|
|
||||||
return $db -> format_row_info($info, array('date'));
|
|
||||||
}
|
|
||||||
catch (Exception $e) {
|
|
||||||
Log :: error("Error retrieving item #$id info from database : ".$e->getMessage());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function add_item($values) {
|
|
||||||
global $db;
|
|
||||||
$values['date'] = $db -> time2datetime(time());
|
|
||||||
try {
|
|
||||||
$result = $db -> fpdo -> insertInto('item')
|
|
||||||
-> values($values)
|
|
||||||
-> execute();
|
|
||||||
|
|
||||||
if ($result !== false) {
|
|
||||||
$item = get_item($result);
|
|
||||||
Log :: info("New item #$result added");
|
|
||||||
Hook :: trigger('item_added', $item);
|
|
||||||
return $item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception $e) {
|
|
||||||
Log :: error("Error creating item in database : ".$e->getMessage());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function update_item($id, $changes) {
|
|
||||||
global $db;
|
|
||||||
|
|
||||||
if (!is_array($changes))
|
|
||||||
return false;
|
|
||||||
if (empty($changes))
|
|
||||||
return true;
|
|
||||||
$item = get_item($id, true);
|
|
||||||
if (!is_array($item)) return false;
|
|
||||||
|
|
||||||
if (isset($changes['date']) && $changes['date'])
|
|
||||||
$changes['date'] = $db -> time2datetime($changes['date']);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$result = $db -> fpdo -> update('item')
|
|
||||||
-> set($changes)
|
|
||||||
-> where('id', $id)
|
|
||||||
-> execute();
|
|
||||||
|
|
||||||
if ($result !== false) {
|
|
||||||
Log :: info("Item #$id updated");
|
|
||||||
Hook :: trigger('item_updated', $item);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception $e) {
|
|
||||||
Log :: error("Error updating item #$id in database : ".$e->getMessage());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function change_item_status($id, $status) {
|
|
||||||
if (update_item($id, array('status' => $status))) {
|
|
||||||
Log :: info("Status of item #$id changed to $status.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function archive_item($id) {
|
|
||||||
return change_item_status($id, 'archived');
|
|
||||||
}
|
|
||||||
|
|
||||||
function delete_item($id) {
|
|
||||||
global $db;
|
|
||||||
try {
|
|
||||||
$result = $db -> fpdo -> deleteFrom('item')
|
|
||||||
-> where('id', $id)
|
|
||||||
-> execute();
|
|
||||||
|
|
||||||
if ($result !== false) {
|
|
||||||
Log :: info("Item #$id deleted");
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception $e) {
|
|
||||||
Log :: error("Error deleting item #$id from database : ".$e->getMessage());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function search_items($params) {
|
|
||||||
global $db;
|
|
||||||
|
|
||||||
// Detect PgSQL backend
|
|
||||||
$is_pgsql = (strpos(App::get('db.dsn', '', 'string'), "pgsql:") === 0);
|
|
||||||
|
|
||||||
$where = array();
|
|
||||||
if (isset($params['status']) && $params['status'] && $params['status'] != 'all')
|
|
||||||
$where['status'] = $params['status'];
|
|
||||||
|
|
||||||
$patterns_where = array();
|
|
||||||
if (isset($params['pattern']) && $params['pattern']) {
|
|
||||||
foreach(preg_split('/\s+/', trim($params['pattern'])) as $word) {
|
|
||||||
if (!$word) continue;
|
|
||||||
$patterns_word=array();
|
|
||||||
|
|
||||||
// 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 ($is_pgsql) {
|
|
||||||
$word = Unidecode::unidecode($word);
|
|
||||||
$patterns_word["unaccent($field) ILIKE ?"] = "%$word%";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
$patterns_word["$field LIKE ?"] = "%$word%";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$patterns_where[] = $patterns_word;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$order='id';
|
|
||||||
$orders=array('id', 'name', 'date', 'status', 'description');
|
|
||||||
if (isset($params['order'])) {
|
|
||||||
if (!in_array($order, $orders))
|
|
||||||
return -1;
|
|
||||||
$order=$params['order'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$order_direction='DESC';
|
|
||||||
if (isset($params['order_direction']) && $params['order_direction']) {
|
|
||||||
if (!in_array($params['order_direction'], array('ASC', 'DESC')))
|
|
||||||
return -1;
|
|
||||||
$order_direction=$params['order_direction'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$orderby="$order $order_direction";
|
|
||||||
|
|
||||||
$limit = "";
|
|
||||||
$page = 1;
|
|
||||||
$nb_by_page = 10;
|
|
||||||
$offset = 0;
|
|
||||||
if (!isset($params['all'])) {
|
|
||||||
if (isset($params['page']) && $params['page']>0) {
|
|
||||||
if (isset($params['nb_by_page']) && $params['nb_by_page']>0) {
|
|
||||||
$nb_by_page = intval($params['nb_by_page']);
|
|
||||||
}
|
|
||||||
$page = intval($params['page']);
|
|
||||||
}
|
|
||||||
$offset = ($page-1)*$nb_by_page;
|
|
||||||
$limit = $nb_by_page;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$query = $db -> fpdo -> from('item');
|
|
||||||
if (!empty($where))
|
|
||||||
$query -> where($where);
|
|
||||||
foreach ($patterns_where as $patterns_word)
|
|
||||||
call_user_func_array(
|
|
||||||
array($query, 'where'),
|
|
||||||
array_merge(
|
|
||||||
array('('.implode(' OR ', array_keys($patterns_word)).')'),
|
|
||||||
array_values($patterns_word)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$result = $query -> orderBy($orderby)
|
|
||||||
-> limit($limit)
|
|
||||||
-> offset($offset)
|
|
||||||
-> execute();
|
|
||||||
|
|
||||||
if ($result === false) {
|
|
||||||
Log :: error('search_items() : search in DB return false');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$rows = $result -> fetchAll();
|
|
||||||
$items = array();
|
|
||||||
foreach ($rows as $row) {
|
|
||||||
$items[] = $db -> format_row_info($row, array('date'));
|
|
||||||
}
|
|
||||||
if (isset($params['all'])) {
|
|
||||||
return array(
|
|
||||||
'count' => count($items),
|
|
||||||
'first' => 1,
|
|
||||||
'last' => count($items),
|
|
||||||
'nb_pages' => 1,
|
|
||||||
'page' => 1,
|
|
||||||
'items' => $items
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$query_count = $db -> fpdo -> from('item')
|
|
||||||
-> select(null)
|
|
||||||
-> select('count(*) as count');
|
|
||||||
if (!empty($where))
|
|
||||||
$query_count -> where($where);
|
|
||||||
foreach ($patterns_where as $patterns_word)
|
|
||||||
call_user_func_array(
|
|
||||||
array($query_count, 'where'),
|
|
||||||
array_merge(
|
|
||||||
array('('.implode(' OR ', array_keys($patterns_word)).')'),
|
|
||||||
array_values($patterns_word)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$result_count = $query_count -> execute();
|
|
||||||
|
|
||||||
if ($result_count === false) {
|
|
||||||
Log :: debug('search_items() : search for count in DB return false');
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
$count = $result_count -> fetch();
|
|
||||||
return array(
|
|
||||||
'count' => $count['count'],
|
|
||||||
'first' => $offset+1,
|
|
||||||
'last' => (
|
|
||||||
$offset+$nb_by_page<$count['count']?
|
|
||||||
$offset+$nb_by_page:$count['count']),
|
|
||||||
'nb_pages' => ceil($count['count']/$nb_by_page),
|
|
||||||
'page' => $page,
|
|
||||||
'items' => $items,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
catch (Exception $e) {
|
|
||||||
Log :: exception(
|
|
||||||
$e, "An exception occurred searching items with params %s infos from database : ",
|
|
||||||
preg_replace("/\n[ \t]*/", " ", print_r($params, true))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function export_items($fd=null) {
|
|
||||||
if (!$fd) $fd = fopen('php://output', 'w');
|
|
||||||
fputcsv(
|
|
||||||
$fd,
|
|
||||||
array (
|
|
||||||
'id',
|
|
||||||
'name',
|
|
||||||
'date',
|
|
||||||
'status',
|
|
||||||
'description',
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$items = get_items();
|
|
||||||
foreach($items as $item) {
|
|
||||||
fputcsv(
|
|
||||||
$fd,
|
|
||||||
array(
|
|
||||||
$item['id'],
|
|
||||||
$item['name'],
|
|
||||||
$item['date'],
|
|
||||||
$item['status'],
|
|
||||||
$item['description'],
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
function restore_items($fd=null) {
|
|
||||||
global $db;
|
|
||||||
if (!$fd) $fd = fopen('php://stdin', 'r');
|
|
||||||
try {
|
|
||||||
$result = $db -> fpdo -> deleteFrom('item')
|
|
||||||
-> execute();
|
|
||||||
if ($result === false) {
|
|
||||||
Log :: error("An unknown error occurred truncating item table in database.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception $e) {
|
|
||||||
Log :: error("Error truncating item table in database : ".$e->getMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$first_row = false;
|
|
||||||
$line = 0;
|
|
||||||
$restored = 0;
|
|
||||||
$error = false;
|
|
||||||
$datetime_fields = array (
|
|
||||||
'date',
|
|
||||||
);
|
|
||||||
// Map fields to support hold CSV files format
|
|
||||||
$mapping = array (
|
|
||||||
'creation_date' => 'date',
|
|
||||||
'desc' => 'description',
|
|
||||||
);
|
|
||||||
|
|
||||||
while (($row = fgetcsv($fd)) !== FALSE) {
|
|
||||||
$line++;
|
|
||||||
if ($first_row === false) {
|
|
||||||
$first_row = $row;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
$values = array();
|
|
||||||
for ($i=0; $i < count($first_row); $i++) {
|
|
||||||
if (!$row[$i]) continue;
|
|
||||||
$field = (
|
|
||||||
array_key_exists($first_row[$i], $mapping)?
|
|
||||||
$mapping[$first_row[$i]]:
|
|
||||||
$first_row[$i]);
|
|
||||||
$value = (in_array($field, $datetime_fields)?$db -> time2datetime($row[$i]):$row[$i]);
|
|
||||||
$values[$field] = $value;
|
|
||||||
}
|
|
||||||
$result = $db -> fpdo -> insertInto('item')
|
|
||||||
-> values($values)
|
|
||||||
-> execute();
|
|
||||||
|
|
||||||
if ($result !== false) {
|
|
||||||
$restored++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Log :: error("Unknown error occurred restoring item from line #$line :\n".print_r($values, true));
|
|
||||||
$error = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception $e) {
|
|
||||||
Log :: error(
|
|
||||||
"Error restoring item from line #$line : ".$e->getMessage()."\n".print_r($values, true));
|
|
||||||
$error = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Log :: info("$restored items restored");
|
|
||||||
|
|
||||||
// Trigger hooks
|
|
||||||
Hook :: trigger('items_restored');
|
|
||||||
|
|
||||||
return !$error;
|
|
||||||
}
|
|
||||||
|
|
||||||
# vim: tabstop=2 shiftwidth=2 softtabstop=2 expandtab
|
|
|
@ -4,11 +4,13 @@ use EesyPHP\Check;
|
||||||
use EesyPHP\Log;
|
use EesyPHP\Log;
|
||||||
use EesyPHP\Tpl;
|
use EesyPHP\Tpl;
|
||||||
|
|
||||||
|
use EesyPHPExample\Db;
|
||||||
|
|
||||||
function get_item_from_url($id, $fatal=false) {
|
function get_item_from_url($id, $fatal=false) {
|
||||||
if (!Check :: id($id))
|
if (!Check :: id($id))
|
||||||
Log :: fatal(_('Invalid element identifier.'));
|
Log :: fatal(_('Invalid element identifier.'));
|
||||||
|
|
||||||
$item = get_item($id);
|
$item = Db :: get_item($id);
|
||||||
if(!is_array($item)) {
|
if(!is_array($item)) {
|
||||||
$error = sprintf(_("Item #%s not found."), $id);
|
$error = sprintf(_("Item #%s not found."), $id);
|
||||||
if ($fatal)
|
if ($fatal)
|
||||||
|
|
|
@ -5,6 +5,8 @@ use EesyPHP\Log;
|
||||||
use EesyPHP\Tpl;
|
use EesyPHP\Tpl;
|
||||||
use EesyPHP\Url;
|
use EesyPHP\Url;
|
||||||
|
|
||||||
|
use EesyPHPExample\Db;
|
||||||
|
|
||||||
use function EesyPHP\vardump;
|
use function EesyPHP\vardump;
|
||||||
|
|
||||||
if (php_sapi_name() == "cli")
|
if (php_sapi_name() == "cli")
|
||||||
|
@ -90,7 +92,7 @@ function handle_search($request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Log :: debug('Search params : '.vardump($_SESSION['search']));
|
Log :: debug('Search params : '.vardump($_SESSION['search']));
|
||||||
$result = search_items($_SESSION['search']);
|
$result = Db :: search_items($_SESSION['search']);
|
||||||
if (!is_array($result))
|
if (!is_array($result))
|
||||||
Tpl :: fatal_error(
|
Tpl :: fatal_error(
|
||||||
_("An error occurred while listing the items. ".
|
_("An error occurred while listing the items. ".
|
||||||
|
@ -154,7 +156,7 @@ function handle_create($request) {
|
||||||
$info = array();
|
$info = array();
|
||||||
$field_errors = handle_item_post_data($info);
|
$field_errors = handle_item_post_data($info);
|
||||||
if (isset($_POST['submit']) && empty($field_errors)) {
|
if (isset($_POST['submit']) && empty($field_errors)) {
|
||||||
$item = add_item($info);
|
$item = Db :: add_item($info);
|
||||||
if (is_array($item)) {
|
if (is_array($item)) {
|
||||||
Tpl :: add_message(_("The element '%s' has been created."), $item['name']);
|
Tpl :: add_message(_("The element '%s' has been created."), $item['name']);
|
||||||
Url :: redirect('item/'.$item['id']);
|
Url :: redirect('item/'.$item['id']);
|
||||||
|
@ -199,7 +201,7 @@ function handle_modify($request) {
|
||||||
Tpl :: add_message(_("You have not made any changes to element '%s'."), $item['name']);
|
Tpl :: add_message(_("You have not made any changes to element '%s'."), $item['name']);
|
||||||
Url :: redirect('item/'.$item['id']);
|
Url :: redirect('item/'.$item['id']);
|
||||||
}
|
}
|
||||||
if (update_item($item['id'], $changes) === true) {
|
if (Db :: update_item($item['id'], $changes) === true) {
|
||||||
Tpl :: add_message(_("The element '%s' has been updated successfully."), $item['name']);
|
Tpl :: add_message(_("The element '%s' has been updated successfully."), $item['name']);
|
||||||
Url :: redirect('item/'.$item['id']);
|
Url :: redirect('item/'.$item['id']);
|
||||||
}
|
}
|
||||||
|
@ -238,7 +240,7 @@ function handle_archive($request) {
|
||||||
else if (!can_archive($item)) {
|
else if (!can_archive($item)) {
|
||||||
Tpl :: add_error(_('You cannot archive this item.'));
|
Tpl :: add_error(_('You cannot archive this item.'));
|
||||||
}
|
}
|
||||||
else if (archive_item($item['id']) === true) {
|
else if (Db :: archive_item($item['id']) === true) {
|
||||||
Tpl :: add_message(_("The element '%s' has been archived successfully."), $item['name']);
|
Tpl :: add_message(_("The element '%s' has been archived successfully."), $item['name']);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -261,7 +263,7 @@ function handle_delete($request) {
|
||||||
else if (!can_delete($item)) {
|
else if (!can_delete($item)) {
|
||||||
Tpl :: add_error(_('You cannot delete this item.'));
|
Tpl :: add_error(_('You cannot delete this item.'));
|
||||||
}
|
}
|
||||||
else if (delete_item($item['id']) === true) {
|
else if (Db :: delete_item($item['id']) === true) {
|
||||||
Tpl :: add_message(_("The element '%s' has been deleted successfully."), $item['name']);
|
Tpl :: add_message(_("The element '%s' has been deleted successfully."), $item['name']);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
17
example/phpstan.neon
Normal file
17
example/phpstan.neon
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
parameters:
|
||||||
|
level: 5
|
||||||
|
paths:
|
||||||
|
- src
|
||||||
|
- includes
|
||||||
|
- public_html
|
||||||
|
universalObjectCratesClasses:
|
||||||
|
- EesyPHP\HookEvent
|
||||||
|
- EesyPHP\UrlRequest
|
||||||
|
- EesyPHP\Auth\User
|
||||||
|
treatPhpDocTypesAsCertain: false
|
||||||
|
ignoreErrors:
|
||||||
|
-
|
||||||
|
message: "#Variable \\$status_list might not be defined\\.#"
|
||||||
|
paths:
|
||||||
|
- includes/cli.php
|
||||||
|
|
374
example/src/Db.php
Normal file
374
example/src/Db.php
Normal file
|
@ -0,0 +1,374 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace EesyPHPExample;
|
||||||
|
|
||||||
|
use EesyPHP\App;
|
||||||
|
use EesyPHP\Hook;
|
||||||
|
use EesyPHP\Log;
|
||||||
|
use Unidecode\Unidecode;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class Db extends \EesyPHP\Db {
|
||||||
|
/*
|
||||||
|
* Methods to handle items
|
||||||
|
*/
|
||||||
|
static public function get_items($orderby='id', $raw_values=false) {
|
||||||
|
try {
|
||||||
|
$info = self :: get_many('item', null, null, $orderby);
|
||||||
|
if (!is_array($info))
|
||||||
|
return;
|
||||||
|
if ($raw_values)
|
||||||
|
return $info;
|
||||||
|
|
||||||
|
$items = array();
|
||||||
|
foreach ($info as $item)
|
||||||
|
$items[$item['id']] = self :: format_row_info($item, array('date'));
|
||||||
|
return $items;
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
Log :: error("Error retrieving items info from database : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function get_item($id, $raw_values=false) {
|
||||||
|
try {
|
||||||
|
$info = self :: get_one('item', array('id' => $id));
|
||||||
|
|
||||||
|
if (!is_array($info))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ($raw_values)
|
||||||
|
return $info;
|
||||||
|
|
||||||
|
return self :: format_row_info($info, array('date'));
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
Log :: error("Error retrieving item #$id info from database : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function add_item($values) {
|
||||||
|
$values['date'] = self :: time2datetime(time());
|
||||||
|
try {
|
||||||
|
$result = self :: $fpdo -> insertInto('item')
|
||||||
|
-> values($values)
|
||||||
|
-> execute();
|
||||||
|
|
||||||
|
if ($result !== false) {
|
||||||
|
$item = self :: get_item($result);
|
||||||
|
Log :: info("New item #$result added");
|
||||||
|
Hook :: trigger('item_added', $item);
|
||||||
|
return $item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
Log :: error("Error creating item in database : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function update_item($id, $changes) {
|
||||||
|
if (!is_array($changes))
|
||||||
|
return false;
|
||||||
|
if (empty($changes))
|
||||||
|
return true;
|
||||||
|
$item = self :: get_item($id, true);
|
||||||
|
if (!is_array($item)) return false;
|
||||||
|
|
||||||
|
if (isset($changes['date']) && $changes['date'])
|
||||||
|
$changes['date'] = self :: time2datetime($changes['date']);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = self :: $fpdo -> update('item')
|
||||||
|
-> set($changes)
|
||||||
|
-> where('id', $id)
|
||||||
|
-> execute();
|
||||||
|
|
||||||
|
if ($result !== false) {
|
||||||
|
Log :: info("Item #$id updated");
|
||||||
|
Hook :: trigger('item_updated', $item);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
Log :: error("Error updating item #$id in database : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function change_item_status($id, $status) {
|
||||||
|
if (self :: update_item($id, array('status' => $status))) {
|
||||||
|
Log :: info("Status of item #$id changed to $status.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function archive_item($id) {
|
||||||
|
return self :: change_item_status($id, 'archived');
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function delete_item($id) {
|
||||||
|
try {
|
||||||
|
$result = self :: $fpdo -> deleteFrom('item')
|
||||||
|
-> where('id', $id)
|
||||||
|
-> execute();
|
||||||
|
|
||||||
|
if ($result !== false) {
|
||||||
|
Log :: info("Item #$id deleted");
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
Log :: error("Error deleting item #$id from database : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function search_items($params) {
|
||||||
|
// Detect PgSQL backend
|
||||||
|
$is_pgsql = (strpos(App::get('db.dsn', '', 'string'), "pgsql:") === 0);
|
||||||
|
|
||||||
|
$where = array();
|
||||||
|
if (isset($params['status']) && $params['status'] && $params['status'] != 'all')
|
||||||
|
$where['status'] = $params['status'];
|
||||||
|
|
||||||
|
$patterns_where = array();
|
||||||
|
if (isset($params['pattern']) && $params['pattern']) {
|
||||||
|
foreach(preg_split('/\s+/', trim($params['pattern'])) as $word) {
|
||||||
|
if (!$word) continue;
|
||||||
|
$patterns_word=array();
|
||||||
|
|
||||||
|
// 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 ($is_pgsql) {
|
||||||
|
$word = Unidecode::unidecode($word);
|
||||||
|
$patterns_word["unaccent($field) ILIKE ?"] = "%$word%";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$patterns_word["$field LIKE ?"] = "%$word%";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$patterns_where[] = $patterns_word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$order='id';
|
||||||
|
$orders=array('id', 'name', 'date', 'status', 'description');
|
||||||
|
if (isset($params['order'])) {
|
||||||
|
if (!in_array($order, $orders))
|
||||||
|
return -1;
|
||||||
|
$order=$params['order'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$order_direction='DESC';
|
||||||
|
if (isset($params['order_direction']) && $params['order_direction']) {
|
||||||
|
if (!in_array($params['order_direction'], array('ASC', 'DESC')))
|
||||||
|
return -1;
|
||||||
|
$order_direction=$params['order_direction'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$orderby="$order $order_direction";
|
||||||
|
|
||||||
|
$limit = "";
|
||||||
|
$page = 1;
|
||||||
|
$nb_by_page = 10;
|
||||||
|
$offset = 0;
|
||||||
|
if (!isset($params['all'])) {
|
||||||
|
if (isset($params['page']) && $params['page']>0) {
|
||||||
|
if (isset($params['nb_by_page']) && $params['nb_by_page']>0) {
|
||||||
|
$nb_by_page = intval($params['nb_by_page']);
|
||||||
|
}
|
||||||
|
$page = intval($params['page']);
|
||||||
|
}
|
||||||
|
$offset = ($page-1)*$nb_by_page;
|
||||||
|
$limit = $nb_by_page;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$query = self :: $fpdo -> from('item');
|
||||||
|
if (!empty($where))
|
||||||
|
$query -> where($where);
|
||||||
|
foreach ($patterns_where as $patterns_word)
|
||||||
|
call_user_func_array(
|
||||||
|
array($query, 'where'),
|
||||||
|
array_merge(
|
||||||
|
array('('.implode(' OR ', array_keys($patterns_word)).')'),
|
||||||
|
array_values($patterns_word)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$result = $query -> orderBy($orderby)
|
||||||
|
-> limit($limit)
|
||||||
|
-> offset($offset)
|
||||||
|
-> execute();
|
||||||
|
|
||||||
|
if ($result === false) {
|
||||||
|
Log :: error('search_items() : search in DB return false');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows = $result -> fetchAll();
|
||||||
|
$items = array();
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
$items[] = self :: format_row_info($row, array('date'));
|
||||||
|
}
|
||||||
|
if (isset($params['all'])) {
|
||||||
|
return array(
|
||||||
|
'count' => count($items),
|
||||||
|
'first' => 1,
|
||||||
|
'last' => count($items),
|
||||||
|
'nb_pages' => 1,
|
||||||
|
'page' => 1,
|
||||||
|
'items' => $items
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$query_count = self :: $fpdo -> from('item')
|
||||||
|
-> select(null)
|
||||||
|
-> select('count(*) as count');
|
||||||
|
if (!empty($where))
|
||||||
|
$query_count -> where($where);
|
||||||
|
foreach ($patterns_where as $patterns_word)
|
||||||
|
call_user_func_array(
|
||||||
|
array($query_count, 'where'),
|
||||||
|
array_merge(
|
||||||
|
array('('.implode(' OR ', array_keys($patterns_word)).')'),
|
||||||
|
array_values($patterns_word)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$result_count = $query_count -> execute();
|
||||||
|
|
||||||
|
if ($result_count === false) {
|
||||||
|
Log :: debug('search_items() : search for count in DB return false');
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
$count = $result_count -> fetch();
|
||||||
|
return array(
|
||||||
|
'count' => $count['count'],
|
||||||
|
'first' => $offset+1,
|
||||||
|
'last' => (
|
||||||
|
$offset+$nb_by_page<$count['count']?
|
||||||
|
$offset+$nb_by_page:$count['count']),
|
||||||
|
'nb_pages' => ceil($count['count']/$nb_by_page),
|
||||||
|
'page' => $page,
|
||||||
|
'items' => $items,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
Log :: exception(
|
||||||
|
$e, "An exception occurred searching items with params %s infos from database : ",
|
||||||
|
preg_replace("/\n[ \t]*/", " ", print_r($params, true))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function export_items($fd=null) {
|
||||||
|
if (!$fd) $fd = fopen('php://output', 'w');
|
||||||
|
fputcsv(
|
||||||
|
$fd,
|
||||||
|
array (
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'date',
|
||||||
|
'status',
|
||||||
|
'description',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$items = self :: get_items();
|
||||||
|
foreach($items as $item) {
|
||||||
|
fputcsv(
|
||||||
|
$fd,
|
||||||
|
array(
|
||||||
|
$item['id'],
|
||||||
|
$item['name'],
|
||||||
|
$item['date'],
|
||||||
|
$item['status'],
|
||||||
|
$item['description'],
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function restore_items($fd=null) {
|
||||||
|
if (!$fd) $fd = fopen('php://stdin', 'r');
|
||||||
|
try {
|
||||||
|
$result = self :: $fpdo -> deleteFrom('item')
|
||||||
|
-> execute();
|
||||||
|
if ($result === false) {
|
||||||
|
Log :: error("An unknown error occurred truncating item table in database.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
Log :: error("Error truncating item table in database : ".$e->getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$first_row = false;
|
||||||
|
$line = 0;
|
||||||
|
$restored = 0;
|
||||||
|
$error = false;
|
||||||
|
$datetime_fields = array (
|
||||||
|
'date',
|
||||||
|
);
|
||||||
|
// Map fields to support hold CSV files format
|
||||||
|
$mapping = array (
|
||||||
|
'creation_date' => 'date',
|
||||||
|
'desc' => 'description',
|
||||||
|
);
|
||||||
|
|
||||||
|
while (($row = fgetcsv($fd)) !== FALSE) {
|
||||||
|
$line++;
|
||||||
|
if ($first_row === false) {
|
||||||
|
$first_row = $row;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$values = array();
|
||||||
|
for ($i=0; $i < count($first_row); $i++) {
|
||||||
|
if (!$row[$i]) continue;
|
||||||
|
$field = (
|
||||||
|
array_key_exists($first_row[$i], $mapping)?
|
||||||
|
$mapping[$first_row[$i]]:
|
||||||
|
$first_row[$i]);
|
||||||
|
$value = (in_array($field, $datetime_fields)?self :: time2datetime($row[$i]):$row[$i]);
|
||||||
|
$values[$field] = $value;
|
||||||
|
}
|
||||||
|
$result = self :: $fpdo -> insertInto('item')
|
||||||
|
-> values($values)
|
||||||
|
-> execute();
|
||||||
|
|
||||||
|
if ($result !== false) {
|
||||||
|
$restored++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Log :: error("Unknown error occurred restoring item from line #$line :\n".print_r($values, true));
|
||||||
|
$error = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
Log :: error(
|
||||||
|
"Error restoring item from line #$line : ".$e->getMessage()."\n".print_r($values, true));
|
||||||
|
$error = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log :: info("$restored items restored");
|
||||||
|
|
||||||
|
// Trigger hooks
|
||||||
|
Hook :: trigger('items_restored');
|
||||||
|
|
||||||
|
return !$error;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1 +0,0 @@
|
||||||
../vendor
|
|
|
@ -2,11 +2,6 @@ parameters:
|
||||||
level: 5
|
level: 5
|
||||||
paths:
|
paths:
|
||||||
- src
|
- src
|
||||||
- example/includes
|
|
||||||
- example/public_html
|
|
||||||
excludePaths:
|
|
||||||
- example/includes/config.local.php
|
|
||||||
- example/data/tmp/templates_c
|
|
||||||
universalObjectCratesClasses:
|
universalObjectCratesClasses:
|
||||||
- EesyPHP\HookEvent
|
- EesyPHP\HookEvent
|
||||||
- EesyPHP\UrlRequest
|
- EesyPHP\UrlRequest
|
||||||
|
|
|
@ -54,6 +54,7 @@ class App {
|
||||||
'mail.enabled' => true,
|
'mail.enabled' => true,
|
||||||
'i18n.enabled' => true,
|
'i18n.enabled' => true,
|
||||||
'cli.enabled' => true,
|
'cli.enabled' => true,
|
||||||
|
'db.enabled' => false,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -88,6 +89,8 @@ class App {
|
||||||
I18n::init();
|
I18n::init();
|
||||||
if (self :: get('cli.enabled', null, 'bool'))
|
if (self :: get('cli.enabled', null, 'bool'))
|
||||||
Cli::init();
|
Cli::init();
|
||||||
|
if (self :: get('db.enabled', null, 'bool'))
|
||||||
|
Db::init();
|
||||||
|
|
||||||
// Define common upload_tmp_dir & upload_max_filesize PHP ini
|
// Define common upload_tmp_dir & upload_max_filesize PHP ini
|
||||||
if (self::isset('upload_tmp_directory'))
|
if (self::isset('upload_tmp_directory'))
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
namespace EesyPHP\Auth;
|
namespace EesyPHP\Auth;
|
||||||
|
|
||||||
use EesyPHP\App;
|
use EesyPHP\App;
|
||||||
use EesyPHP\Db as DbConnection;
|
|
||||||
use EesyPHP\Log;
|
use EesyPHP\Log;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
@ -12,33 +11,9 @@ class Db extends Backend {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database connection object
|
* Database connection object
|
||||||
* @var \EesyPHP\Db|null
|
* @var class-string|null
|
||||||
*/
|
*/
|
||||||
private static $db = null;
|
private static $class = null;
|
||||||
|
|
||||||
/**
|
|
||||||
* Database connection parameters
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private static $dsn;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string|null
|
|
||||||
*/
|
|
||||||
private static $user;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string|null
|
|
||||||
*/
|
|
||||||
private static $password;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private static $options;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Users table name
|
* Users table name
|
||||||
|
@ -73,24 +48,21 @@ class Db extends Backend {
|
||||||
App :: set_default(
|
App :: set_default(
|
||||||
'auth.db',
|
'auth.db',
|
||||||
array(
|
array(
|
||||||
'dsn' => null,
|
'class' => '\\EesyPHP\\Db',
|
||||||
'user' => null,
|
|
||||||
'password' => null,
|
|
||||||
'options' => array(),
|
|
||||||
'users_table' => 'users',
|
'users_table' => 'users',
|
||||||
'username_field' => 'username',
|
'username_field' => 'username',
|
||||||
'password_field' => 'password',
|
'password_field' => 'password',
|
||||||
'exposed_fields' => array('name', 'mail'),
|
'exposed_fields' => array('name', 'mail'),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
self :: $dsn = App::get('auth.db.dsn', null, 'string');
|
self :: $class = App::get('auth.db.class', null, 'string');
|
||||||
if (!self :: $dsn) {
|
if (!self :: $class || !class_exists(self :: $class)) {
|
||||||
Log :: warning('No database DSN configured, can not initialize this authentication backend');
|
Log :: warning(
|
||||||
|
'Database class %s configured as authentication backend does not exists, can not '.
|
||||||
|
'initialize this authentication backend.', self :: $class
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
self :: $user = App::get('auth.db.user', null, 'string');
|
|
||||||
self :: $password = App::get('auth.db.password', null, 'string');
|
|
||||||
self :: $options = App::get('auth.db.options', null, 'array');
|
|
||||||
self :: $users_table = App::get('auth.db.users_table', null, 'string');
|
self :: $users_table = App::get('auth.db.users_table', null, 'string');
|
||||||
self :: $username_field = App::get('auth.db.username_field', null, 'string');
|
self :: $username_field = App::get('auth.db.username_field', null, 'string');
|
||||||
self :: $password_field = App::get('auth.db.password_field', null, 'string');
|
self :: $password_field = App::get('auth.db.password_field', null, 'string');
|
||||||
|
@ -103,10 +75,7 @@ class Db extends Backend {
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private static function connect() {
|
private static function connect() {
|
||||||
if (!self :: $db)
|
self :: $class :: connect();
|
||||||
self :: $db = new DbConnection(
|
|
||||||
self :: $dsn, self :: $user, self :: $password, self :: $options
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -117,7 +86,7 @@ class Db extends Backend {
|
||||||
public static function get_user($username) {
|
public static function get_user($username) {
|
||||||
self :: connect();
|
self :: connect();
|
||||||
try {
|
try {
|
||||||
$query = self :: $db -> fpdo -> from(self :: $users_table)
|
$query = self :: $class :: $fpdo -> from(self :: $users_table)
|
||||||
-> select(null)
|
-> select(null)
|
||||||
-> select(self :: $exposed_fields)
|
-> select(self :: $exposed_fields)
|
||||||
-> where(self :: $username_field, $username);
|
-> where(self :: $username_field, $username);
|
||||||
|
@ -143,7 +112,7 @@ class Db extends Backend {
|
||||||
public static function check_password($user, $password) {
|
public static function check_password($user, $password) {
|
||||||
self :: connect();
|
self :: connect();
|
||||||
try {
|
try {
|
||||||
$query = self :: $db -> fpdo -> from(self :: $users_table)
|
$query = self :: $class :: $fpdo -> from(self :: $users_table)
|
||||||
-> select(null)
|
-> select(null)
|
||||||
-> select(self :: $password_field)
|
-> select(self :: $password_field)
|
||||||
-> where(self :: $username_field, $user->username);
|
-> where(self :: $username_field, $user->username);
|
||||||
|
|
157
src/Db.php
157
src/Db.php
|
@ -9,34 +9,22 @@ use \Envms\FluentPDO\Query;
|
||||||
class Db {
|
class Db {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The PDO object of the database connection
|
* Configuration prefix
|
||||||
* @var PDO
|
* @var string
|
||||||
*/
|
*/
|
||||||
public $pdo;
|
protected static $config_prefix = 'db';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The PDO object of the database connection
|
* The PDO object of the database connection
|
||||||
* @var \Envms\FluentPDO\Query
|
* @var PDO|null
|
||||||
*/
|
*/
|
||||||
public $fpdo;
|
public static $pdo = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Date format as returned by database
|
* The PDO object of the database connection
|
||||||
* @var string
|
* @var \Envms\FluentPDO\Query|null
|
||||||
*/
|
*/
|
||||||
protected $date_format = '%Y-%m-%d';
|
public static $fpdo = null;
|
||||||
|
|
||||||
/**
|
|
||||||
* Datetime format as returned by database
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $datetime_format = '%Y-%m-%d %H:%M:%S';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Locale for time (as expected by LC_TIME)
|
|
||||||
* @var string|null
|
|
||||||
*/
|
|
||||||
protected $locale_time = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keep trace of total queries times (in ns)
|
* Keep trace of total queries times (in ns)
|
||||||
|
@ -45,31 +33,58 @@ class Db {
|
||||||
public static $total_query_time = 0;
|
public static $total_query_time = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to database and return FluentPDO Query object
|
* Initialization
|
||||||
* @param string $dsn Database DSN
|
|
||||||
* @param string|null $user Username (optional)
|
|
||||||
* @param string|null $password password (optional)
|
|
||||||
* @param string|array $options Connection options (optional)
|
|
||||||
* @param string|null $date_format Date format in DB (optional)
|
|
||||||
* @param string|null $datetime_format Datetime format in DB (optional)
|
|
||||||
* @param string|null $locale_time Locale for time (optional)
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct($dsn, $user=null, $password=null, $options=null,
|
public static function init() {
|
||||||
$date_format=null, $datetime_format=null, $locale_time=null) {
|
// In phpstan context, do not initialize
|
||||||
if (!$dsn)
|
// @phpstan-ignore-next-line
|
||||||
Log :: fatal('Database DSN not configured');
|
if (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__'))
|
||||||
if ($date_format) $this -> date_format = $date_format;
|
return;
|
||||||
if ($datetime_format) $this -> datetime_format = $datetime_format;
|
|
||||||
if ($locale_time) $this -> locale_time = $locale_time;
|
|
||||||
|
|
||||||
|
// Set config default values
|
||||||
|
App :: set_default(
|
||||||
|
static :: $config_prefix,
|
||||||
|
array(
|
||||||
|
'dsn' => null,
|
||||||
|
'user' => null,
|
||||||
|
'password' => null,
|
||||||
|
'options' => [],
|
||||||
|
'date_format' => '%Y-%m-%d',
|
||||||
|
'datetime_format' => '%Y-%m-%d %H:%M:%S',
|
||||||
|
'locale_time' => null,
|
||||||
|
'auto_connect' => true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!App::get(static :: $config_prefix.".dsn"))
|
||||||
|
Log :: fatal('Database DSN not configured (%s.dsn)', static :: $config_prefix);
|
||||||
|
|
||||||
|
if (App::get(static :: $config_prefix.".auto_connect"))
|
||||||
|
self :: connect();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connection
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function connect() {
|
||||||
|
if (self :: $pdo && self :: $fpdo)
|
||||||
|
return;
|
||||||
|
$dsn = App::get(static :: $config_prefix.".dsn");
|
||||||
try {
|
try {
|
||||||
// Connect to database
|
// Connect to database
|
||||||
$this -> pdo = new PDO($dsn, $user, $password, $options);
|
self :: $pdo = new PDO(
|
||||||
$this -> fpdo = new Query($this -> pdo);
|
$dsn,
|
||||||
|
App::get(static :: $config_prefix.".user"),
|
||||||
|
App::get(static :: $config_prefix.".password"),
|
||||||
|
App::get(static :: $config_prefix.".options"),
|
||||||
|
);
|
||||||
|
self :: $fpdo = new Query(self :: $pdo);
|
||||||
|
|
||||||
// Register the debug query handler to log it
|
// Register the debug query handler to log it
|
||||||
$this -> fpdo -> debug = array(self :: class, 'debug_query');
|
self :: $fpdo -> debug = array(self :: class, 'debug_query');
|
||||||
|
|
||||||
Log :: trace("DB connection established (DSN: '%s')", $dsn);
|
Log :: trace("DB connection established (DSN: '%s')", $dsn);
|
||||||
}
|
}
|
||||||
|
@ -119,8 +134,8 @@ class Db {
|
||||||
* @see https://www.php.net/manual/en/pdo.setattribute.php
|
* @see https://www.php.net/manual/en/pdo.setattribute.php
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function set_autocommit($value) {
|
public static function set_autocommit($value) {
|
||||||
$this -> pdo -> setAttribute(PDO::ATTR_AUTOCOMMIT, $value);
|
self :: $pdo -> setAttribute(PDO::ATTR_AUTOCOMMIT, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -136,9 +151,9 @@ class Db {
|
||||||
* @param array<array{0: 'LEFT'|'RIGHT'|'INNER'|'OUTER'|'FULL', 1: string, 2: string}>|array{0: 'LEFT'|'RIGHT'|'INNER'|'OUTER'|'FULL', 1: string, 2: string} $joins Join specification as array (see apply_joins())
|
* @param array<array{0: 'LEFT'|'RIGHT'|'INNER'|'OUTER'|'FULL', 1: string, 2: string}>|array{0: 'LEFT'|'RIGHT'|'INNER'|'OUTER'|'FULL', 1: string, 2: string} $joins Join specification as array (see apply_joins())
|
||||||
* @return array|false
|
* @return array|false
|
||||||
*/
|
*/
|
||||||
public function get_one($table, $where, $fields=null, $joins=null) {
|
public static function get_one($table, $where, $fields=null, $joins=null) {
|
||||||
try {
|
try {
|
||||||
$query = $this -> fpdo -> from($table) -> where($where);
|
$query = self :: $fpdo -> from($table) -> where($where);
|
||||||
if ($joins)
|
if ($joins)
|
||||||
self :: apply_joins($query, $joins);
|
self :: apply_joins($query, $joins);
|
||||||
if ($fields)
|
if ($fields)
|
||||||
|
@ -169,11 +184,11 @@ class Db {
|
||||||
* @param array<array{0: 'LEFT'|'RIGHT'|'INNER'|'OUTER'|'FULL', 1: string, 2: string}>|array{0: 'LEFT'|'RIGHT'|'INNER'|'OUTER'|'FULL', 1: string, 2: string} $joins Join specification as array (see apply_joins())
|
* @param array<array{0: 'LEFT'|'RIGHT'|'INNER'|'OUTER'|'FULL', 1: string, 2: string}>|array{0: 'LEFT'|'RIGHT'|'INNER'|'OUTER'|'FULL', 1: string, 2: string} $joins Join specification as array (see apply_joins())
|
||||||
* @return array|false
|
* @return array|false
|
||||||
*/
|
*/
|
||||||
public function get_many(
|
public static function get_many(
|
||||||
$table, $where=null, $fields=null, $order_by=null, $limit=null, $joins=null
|
$table, $where=null, $fields=null, $order_by=null, $limit=null, $joins=null
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
$query = $this -> fpdo -> from($table);
|
$query = self :: $fpdo -> from($table);
|
||||||
if ($joins)
|
if ($joins)
|
||||||
self :: apply_joins($query, $joins);
|
self :: apply_joins($query, $joins);
|
||||||
if ($fields)
|
if ($fields)
|
||||||
|
@ -204,9 +219,9 @@ class Db {
|
||||||
* @param array<array{0: 'LEFT'|'RIGHT'|'INNER'|'OUTER'|'FULL', 1: string, 2: string}>|array{0: 'LEFT'|'RIGHT'|'INNER'|'OUTER'|'FULL', 1: string, 2: string} $joins Join specification as array (see apply_joins())
|
* @param array<array{0: 'LEFT'|'RIGHT'|'INNER'|'OUTER'|'FULL', 1: string, 2: string}>|array{0: 'LEFT'|'RIGHT'|'INNER'|'OUTER'|'FULL', 1: string, 2: string} $joins Join specification as array (see apply_joins())
|
||||||
* @return int|false
|
* @return int|false
|
||||||
*/
|
*/
|
||||||
public function count($table, $where, $what=null, $joins=null) {
|
public static function count($table, $where, $what=null, $joins=null) {
|
||||||
try {
|
try {
|
||||||
$query = $this -> fpdo -> from($table) -> where($where);
|
$query = self :: $fpdo -> from($table) -> where($where);
|
||||||
if ($joins)
|
if ($joins)
|
||||||
self :: apply_joins($query, $joins);
|
self :: apply_joins($query, $joins);
|
||||||
$query -> select(null) -> select(sprintf("COUNT(%s) as count", $what?$what:"*"));
|
$query -> select(null) -> select(sprintf("COUNT(%s) as count", $what?$what:"*"));
|
||||||
|
@ -274,7 +289,7 @@ class Db {
|
||||||
* @param array<array<string>>|null $joins Join specification as array (see apply_joins())
|
* @param array<array<string>>|null $joins Join specification as array (see apply_joins())
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function _log_simple_select_query_error(
|
private static function _log_simple_select_query_error(
|
||||||
$multiple, $table, $e, $where=null, $fields=null, $order_by=null, $limit=null, $joins=null
|
$multiple, $table, $e, $where=null, $fields=null, $order_by=null, $limit=null, $joins=null
|
||||||
) {
|
) {
|
||||||
$msg = "Error occurred getting %s of the table %s";
|
$msg = "Error occurred getting %s of the table %s";
|
||||||
|
@ -314,9 +329,9 @@ class Db {
|
||||||
* @param boolean $want_id Set to true if you want to retrieve the ID of the inserted row
|
* @param boolean $want_id Set to true if you want to retrieve the ID of the inserted row
|
||||||
* @return bool|int The ID of the inserted row if $want_id, or true/false in case of success/error
|
* @return bool|int The ID of the inserted row if $want_id, or true/false in case of success/error
|
||||||
*/
|
*/
|
||||||
public function insert($table, $values, $want_id=false) {
|
public static function insert($table, $values, $want_id=false) {
|
||||||
try {
|
try {
|
||||||
$id = $this -> fpdo -> insertInto($table)
|
$id = self :: $fpdo -> insertInto($table)
|
||||||
-> values($values)
|
-> values($values)
|
||||||
-> execute();
|
-> execute();
|
||||||
}
|
}
|
||||||
|
@ -346,10 +361,10 @@ class Db {
|
||||||
* default: null == 1)
|
* default: null == 1)
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function update($table, $changes, $where, $expected_row_changes=null) {
|
public static function update($table, $changes, $where, $expected_row_changes=null) {
|
||||||
if (is_null($expected_row_changes)) $expected_row_changes = 1;
|
if (is_null($expected_row_changes)) $expected_row_changes = 1;
|
||||||
try {
|
try {
|
||||||
$result = $this -> fpdo -> update($table)
|
$result = self :: $fpdo -> update($table)
|
||||||
-> set($changes)
|
-> set($changes)
|
||||||
-> where($where)
|
-> where($where)
|
||||||
-> execute();
|
-> execute();
|
||||||
|
@ -383,10 +398,10 @@ class Db {
|
||||||
* default: null == 1)
|
* default: null == 1)
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function delete($table, $where, $expected_row_changes=null) {
|
public static function delete($table, $where, $expected_row_changes=null) {
|
||||||
if (is_null($expected_row_changes)) $expected_row_changes = 1;
|
if (is_null($expected_row_changes)) $expected_row_changes = 1;
|
||||||
try {
|
try {
|
||||||
$result = $this -> fpdo -> deleteFrom($table)
|
$result = self :: $fpdo -> deleteFrom($table)
|
||||||
-> where($where)
|
-> where($where)
|
||||||
-> execute();
|
-> execute();
|
||||||
}
|
}
|
||||||
|
@ -416,37 +431,37 @@ class Db {
|
||||||
/*
|
/*
|
||||||
* Handle date/datetime format
|
* Handle date/datetime format
|
||||||
*/
|
*/
|
||||||
public function set_locale() {
|
public static function set_locale() {
|
||||||
if ($this -> locale_time)
|
if (App::get(static :: $config_prefix.".locale_time"))
|
||||||
setlocale(LC_TIME, $this -> locale_time);
|
setlocale(LC_TIME, App::get(static :: $config_prefix.".locale_time"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function date2time($date) {
|
public static function date2time($date) {
|
||||||
$this -> set_locale();
|
self :: set_locale();
|
||||||
$pdate = strptime($date, $this -> date_format);
|
$pdate = strptime($date, App::get(static :: $config_prefix.".date_format"));
|
||||||
return mktime(
|
return mktime(
|
||||||
$pdate['tm_hour'], $pdate['tm_min'], $pdate['tm_sec'],
|
$pdate['tm_hour'], $pdate['tm_min'], $pdate['tm_sec'],
|
||||||
$pdate['tm_mon'] + 1, $pdate['tm_mday'], $pdate['tm_year'] + 1900
|
$pdate['tm_mon'] + 1, $pdate['tm_mday'], $pdate['tm_year'] + 1900
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function time2date($time) {
|
public static function time2date($time) {
|
||||||
$this -> set_locale();
|
self :: set_locale();
|
||||||
return strftime($this -> date_format, $time);
|
return strftime(App::get(static :: $config_prefix.".date_format"), $time);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function datetime2time($date) {
|
public static function datetime2time($date) {
|
||||||
$this -> set_locale();
|
self :: set_locale();
|
||||||
$pdate = strptime($date, $this -> datetime_format);
|
$pdate = strptime($date, App::get(static :: $config_prefix.".datetime_format"));
|
||||||
return mktime(
|
return mktime(
|
||||||
$pdate['tm_hour'], $pdate['tm_min'], $pdate['tm_sec'],
|
$pdate['tm_hour'], $pdate['tm_min'], $pdate['tm_sec'],
|
||||||
$pdate['tm_mon'] + 1, $pdate['tm_mday'], $pdate['tm_year'] + 1900
|
$pdate['tm_mon'] + 1, $pdate['tm_mday'], $pdate['tm_year'] + 1900
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function time2datetime($time) {
|
public static function time2datetime($time) {
|
||||||
$this -> set_locale();
|
self :: set_locale();
|
||||||
return strftime($this -> datetime_format, $time);
|
return strftime(App::get(static :: $config_prefix.".datetime_format"), $time);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -456,17 +471,17 @@ class Db {
|
||||||
* @param array<string> $date_fields List of field in date format
|
* @param array<string> $date_fields List of field in date format
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function format_row_info($row, $datetime_fields=null, $date_fields=null) {
|
public static function format_row_info($row, $datetime_fields=null, $date_fields=null) {
|
||||||
// Convert datetime fields
|
// Convert datetime fields
|
||||||
if (is_array($datetime_fields))
|
if (is_array($datetime_fields))
|
||||||
foreach($datetime_fields as $field)
|
foreach($datetime_fields as $field)
|
||||||
if ($row[$field])
|
if ($row[$field])
|
||||||
$row[$field] = $this -> datetime2time($row[$field]);
|
$row[$field] = self :: datetime2time($row[$field]);
|
||||||
// Convert date fields
|
// Convert date fields
|
||||||
if (is_array($date_fields))
|
if (is_array($date_fields))
|
||||||
foreach($date_fields as $field)
|
foreach($date_fields as $field)
|
||||||
if ($row[$field])
|
if ($row[$field])
|
||||||
$row[$field] = $this -> date2time($row[$field]);
|
$row[$field] = self :: date2time($row[$field]);
|
||||||
return $row;
|
return $row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue