From: Nicolas Boisselier Date: Sun, 28 Jan 2018 04:58:14 +0000 (+0000) Subject: lib/php/db/table.php X-Git-Url: https://git.nbdom.net/?a=commitdiff_plain;h=0fff06394b4e61cb67f9f5b107b50c46fd71c3ff;p=nb.git lib/php/db/table.php --- diff --git a/lib/php/db.php b/lib/php/db.php index 5c79d7f2..4278c183 100644 --- a/lib/php/db.php +++ b/lib/php/db.php @@ -1,9 +1,9 @@ false, - ]; - - public $conn; - public $pdo; - public $options = [ # See: http://php.net/manual/en/pdo.error-handling.php - PDO::ATTR_ERRMODE => DB_DEFAUL_ERRMODE, + public static $table_rows_dump = [ + 'praser' => false, + ]; + + public $conn; + public $pdo; + public $options = [ # See: http://php.net/manual/en/pdo.error-handling.php + PDO::ATTR_ERRMODE => DB_DEFAUL_ERRMODE, PDO::ATTR_TIMEOUT => 0, - ]; - public $host = null; - public $port = null; - public $user = null; - public $password = null; - public $charset = 'utf8'; - - # Database infos - public $id; - public $name; - public $title; - public $notice; - public $type; - public $tables = []; - public $types = []; - public $conf = []; - public $attach = []; # for sqlite - public $row_parse_pre; # Function to call in table.rows() - public $row_parse_post; # Function to call in table.rows() - - # Encryption - public $encrypt = [ + ]; + public $host = null; + public $port = null; + public $user = null; + public $password = null; + public $charset = 'utf8'; + + # Database infos + public $id; + public $name; + public $title; + public $notice; + public $type; + public $tables = []; + public $types = []; + public $conf = []; + public $attach = []; # for sqlite + public $row_parse_pre; # Function to call in table.rows() + public $row_parse_post; # Function to call in table.rows() + + # Encryption + public $encrypt = [ # 'secret' => '32_CHAR_KEY', # 'tables' => [ # 'TABLE1' => [ @@ -68,413 +68,413 @@ class Db extends nb { # ], # ..., # ], - ]; - - # Params - protected $default_params = [ - ]; - - protected static $paliases = [ - 'd' => 'db', - 't' => 'table', - 'l' => 'limit', - 'a' => 'action', - 'h' => 'header', - - 'f' => 'format', - 'out' => 'format', - 'o' => 'format', - ]; - - protected static $action_aliases = [ - 'help' => 'db.help', - 'ls' => 'db.ls', - 'exec' => 'db.exec', - 'databases' => 'db.databases', - - 'tables' => 'db.tables', - 'fields' => 'table.fields', - 'rows' => 'table.rows', - 'insert' => 'table.insert', - 'replace' => 'table.replace', - 'update' => 'table.update', - 'delete' => 'table.delete', - ]; - - protected static $action_help = [ - ['db.help','This help'], - ['db.ls','List databases from conf'], - ['db.database','List other databases on the same server'], - ['db.tables','List tables (name=* type=* count=1 engine=*)'], - - ['table.rows','Dump one table, use format='], - ['table.fields','List fields'], - ['table.status','Table status (count= maxlen= max=)'], - ['table.sql','Sql source to create the table'], - - ['table.insert','Insert a record'], - ['table.update','Update a record'], - ['table.delete','Delete a record'], - - ]; - # Web - public $default_table; - public $sort; - public $extras; - public $format = 'json'; - public $formats = [ 'table','div','csv','xml','json','yaml','sh','sql','php' ]; - public $limits = ['20','50','100','500','1000']; - public $limit; # Here not in Table becouse of Db::out() - - # Classes - public $out; - - function __construct($opt = []) { - - # Args defaults - if ($opt==='') $opt = []; - $opt = is_scalar($opt) ? ['pdo' => $opt] : $opt; - - # Options - if (isset($opt['options'])) { - foreach ($opt['options'] as $k=>$v) $this->options[$k] = $v; - unset($opt['options']); - } - - # Charset - if (!empty($opt['charset'])) $opt['charset'] - = preg_replace('/^ *utf-8 *$/','utf8',$opt['charset']) - ; - - # Tables - if (isset($opt['tables'])) { - foreach ($opt['tables'] as $name=>$param) { - $this->table($name,$param); - } - unset($opt['tables']); - } - - # connect - $connect = false; - if (isset($opt['connect'])) { - $connect = (bool) $opt['connect']; - unset($opt['connect']); - } - - # Args into this - foreach ($opt as $k=>$v) $this->$k = $v; - #parent::__construct($opt); - - # Out Class - if (empty($this->out)) $this->out = new Out(['charset'=>$this->charset]); - - # Format - # Set format from client Accept if != html - if (!isset($opt['format'])) { - if ($this->out->client_type()) $this->format = $this->out->client_type(); - if (self::p('format')) $this->format = self::p('format'); - } - - # Pdo - $this->connect_init(); - if ($connect) $this->connect(); - - # Extras must disapear - NB 29.03.16 - if (!empty($this->extras)) self::bye($this->extras); - return true; - } - - public function __destruct() { - $this->disconnect(); - foreach (array_keys((array)$this) as $k) { if (isset($this->$k)) unset($this->$k); }; - } + ]; + + # Params + protected $default_params = [ + ]; + + protected static $paliases = [ + 'd' => 'db', + 't' => 'table', + 'l' => 'limit', + 'a' => 'action', + 'h' => 'header', + + 'f' => 'format', + 'out' => 'format', + 'o' => 'format', + ]; + + protected static $action_aliases = [ + 'help' => 'db.help', + 'ls' => 'db.ls', + 'exec' => 'db.exec', + 'databases' => 'db.databases', + + 'tables' => 'db.tables', + 'fields' => 'table.fields', + 'rows' => 'table.rows', + 'insert' => 'table.insert', + 'replace' => 'table.replace', + 'update' => 'table.update', + 'delete' => 'table.delete', + ]; + + protected static $action_help = [ + ['db.help','This help'], + ['db.ls','List databases from conf'], + ['db.database','List other databases on the same server'], + ['db.tables','List tables (name=* type=* count=1 engine=*)'], + + ['table.rows','Dump one table, use format='], + ['table.fields','List fields'], + ['table.status','Table status (count= maxlen= max=)'], + ['table.sql','Sql source to create the table'], + + ['table.insert','Insert a record'], + ['table.update','Update a record'], + ['table.delete','Delete a record'], + + ]; + # Web + public $default_table; + public $sort; + public $extras; + public $format = 'json'; + public $formats = [ 'table','div','csv','xml','json','yaml','sh','sql','php' ]; + public $limits = ['20','50','100','500','1000']; + public $limit; # Here not in Table becouse of Db::out() + + # Classes + public $out; + + function __construct($opt = []) { + + # Args defaults + if ($opt==='') $opt = []; + $opt = is_scalar($opt) ? ['pdo' => $opt] : $opt; + + # Options + if (isset($opt['options'])) { + foreach ($opt['options'] as $k=>$v) $this->options[$k] = $v; + unset($opt['options']); + } + + # Charset + if (!empty($opt['charset'])) $opt['charset'] + = preg_replace('/^ *utf-8 *$/','utf8',$opt['charset']) + ; + + # Tables + if (isset($opt['tables'])) { + foreach ($opt['tables'] as $name=>$param) { + $this->table($name,$param); + } + unset($opt['tables']); + } + + # connect + $connect = false; + if (isset($opt['connect'])) { + $connect = (bool) $opt['connect']; + unset($opt['connect']); + } + + # Args into this + foreach ($opt as $k=>$v) $this->$k = $v; + #parent::__construct($opt); + + # Out Class + if (empty($this->out)) $this->out = new Out(['charset'=>$this->charset]); + + # Format + # Set format from client Accept if != html + if (!isset($opt['format'])) { + if ($this->out->client_type()) $this->format = $this->out->client_type(); + if (self::p('format')) $this->format = self::p('format'); + } + + # Pdo + $this->connect_init(); + if ($connect) $this->connect(); + + # Extras must disapear - NB 29.03.16 + if (!empty($this->extras)) self::bye($this->extras); + return true; + } + + public function __destruct() { + $this->disconnect(); + foreach (array_keys((array)$this) as $k) { if (isset($this->$k)) unset($this->$k); }; + } function connect_init() { - if (empty($this->pdo) and $this->type) $this->pdo = $this->type.':'; - # Extract args from pdo - foreach ($this->pdo2h($this->pdo) as $k=>$v) { - $this->$k = $v; - } + if (empty($this->pdo) and $this->type) $this->pdo = $this->type.':'; + # Extract args from pdo + foreach ($this->pdo2h($this->pdo) as $k=>$v) { + $this->$k = $v; + } - if (empty($this->type)) $this->type = strtolower(preg_replace('/^([^:]+):.*$/','\1',$this->pdo)); - if (!$this->type) return false; + if (empty($this->type)) $this->type = strtolower(preg_replace('/^([^:]+):.*$/','\1',$this->pdo)); + if (!$this->type) return false; - if ($v = $this->p('db_host')) $this->host = $v; - if ($this->conf_type('use_path')) { + if ($v = $this->p('db_host')) $this->host = $v; + if ($this->conf_type('use_path')) { - if (empty($this->host)) $this->host = preg_replace('/^\w+:/','',$this->pdo); + if (empty($this->host)) $this->host = preg_replace('/^\w+:/','',$this->pdo); - # Add file - if (trim($this->pdo,'pdo:'.$this->type)=='') $this->pdo .= $this->host; + # Add file + if (trim($this->pdo,'pdo:'.$this->type)=='') $this->pdo .= $this->host; - } else { + } else { - # Add args to pdo - foreach ([ - 'host' => 'host', - 'port' => 'port', - 'user' => 'user', - 'password' => 'password', - 'name' => 'dbname', - 'charset' => 'charset', - ] as $k => $v) { - if ($v=='charset' and $this->type=='pgsql') continue; - if (empty($this->$k)) continue; - $this->pdo = preg_replace("/\b$v=[^;]*(;|$)/","",$this->pdo); - $this->pdo .= (preg_match('/[:;]$/',$this->pdo) ? '' : ';') . "$v=".$this->$k; - } + # Add args to pdo + foreach ([ + 'host' => 'host', + 'port' => 'port', + 'user' => 'user', + 'password' => 'password', + 'name' => 'dbname', + 'charset' => 'charset', + ] as $k => $v) { + if ($v=='charset' and $this->type=='pgsql') continue; + if (empty($this->$k)) continue; + $this->pdo = preg_replace("/\b$v=[^;]*(;|$)/","",$this->pdo); + $this->pdo .= (preg_match('/[:;]$/',$this->pdo) ? '' : ';') . "$v=".$this->$k; + } - if (strpos($this->host,'/') === 0) { - $this->pdo = preg_replace("/\b(host|port)=[^;]*(;|$)/","",$this->pdo).';unix_socket='.$this->host; - } + if (strpos($this->host,'/') === 0) { + $this->pdo = preg_replace("/\b(host|port)=[^;]*(;|$)/","",$this->pdo).';unix_socket='.$this->host; + } - } + } - # Defaults - if (empty($this->title)) $this->title = prettyText($this->name); - if (empty($this->id) and !empty($this->name)) $this->id = preg_replace('/\W+/','',$this->name); + # Defaults + if (empty($this->title)) $this->title = prettyText($this->name); + if (empty($this->id) and !empty($this->name)) $this->id = preg_replace('/\W+/','',$this->name); - # Row parser - if (empty($this->row_parse_pre) and $this->conf_type('row_parse')) { - $this->row_parse_pre = $this->conf_type('row_parse'); - } + # Row parser + if (empty($this->row_parse_pre) and $this->conf_type('row_parse')) { + $this->row_parse_pre = $this->conf_type('row_parse'); + } - } # < if else 'use_path' + } # < if else 'use_path' public function connect() { - if (!empty($this->conn)) return false; + if (!empty($this->conn)) return false; - # Pdo - if (empty($this->pdo)) $this->bye("db: `".$this->id."`: Missing pdo: check host, name, user, password"); - if (empty($this->pdo)) return false; + # Pdo + if (empty($this->pdo)) $this->bye("db: `".$this->id."`: Missing pdo: check host, name, user, password"); + if (empty($this->pdo)) return false; - # Type - $this->conf_type_load(); + # Type + $this->conf_type_load(); - # Connect - try { - $this->conn = new PDO($this->pdo,$this->user,$this->password,$this->options); - #if (isset($this->pdo_error)) $this->conn->setAttribute($this->pdo_error[0], $this->pdo_error[1]); + # Connect + try { + $this->conn = new PDO($this->pdo,$this->user,$this->password,$this->options); + #if (isset($this->pdo_error)) $this->conn->setAttribute($this->pdo_error[0], $this->pdo_error[1]); - } catch (PDOException $e) { - $msg = 'Connection failed:'; + } catch (PDOException $e) { + $msg = 'Connection failed:'; - foreach(['name','host','file'] as $p) { - if (!empty($this->$p)) $msg .= " $p=".$this->$p; - } + foreach(['name','host','file'] as $p) { + if (!empty($this->$p)) $msg .= " $p=".$this->$p; + } - $msg .= "\n ".$e->getMessage(); - #throw new Exception($msg, (int)$e->getCode()); - self::bye($msg); - } + $msg .= "\n ".$e->getMessage(); + #throw new Exception($msg, (int)$e->getCode()); + self::bye($msg); + } - if (empty($this->conn)) { - $this->bye("Connection failed: ".$this->pdo_info()); - return false; - } + if (empty($this->conn)) { + $this->bye("Connection failed: ".$this->pdo_info()); + return false; + } - # Create functions - foreach ((array)$this->conf_type('sqliteCreateFunction') as $name => $fct) { - if (is_array($fct)) { - $this->conn->sqliteCreateFunction($name,$fct[0],$fct[1]); - } else { - $this->conn->sqliteCreateFunction($name,$fct); - } - } + # Create functions + foreach ((array)$this->conf_type('sqliteCreateFunction') as $name => $fct) { + if (is_array($fct)) { + $this->conn->sqliteCreateFunction($name,$fct[0],$fct[1]); + } else { + $this->conn->sqliteCreateFunction($name,$fct); + } + } - $this->method('connect'); + $this->method('connect'); - return true; - } + return true; + } public function disconnect() { - if (empty($this->conn)) return null; - $this->method('disconnect'); - } - - function exec($sql) { - - try { - #$r = $this->conn->exec($sql,$params); - $r = $this->conn->exec($sql); - } catch (PDOException $e) { - err(join(': ',[$e->getMessage(),"Db.exec()",$sql])); - $r = null; - } - - return $r; - } - - public function query($sql) { - # See: http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers - - try { - $r = $this->conn->query($sql); - } catch (PDOException $e) { - err(join(': ',[$e->getMessage(),"Db.query()",$sql])); - $r = null; - } - - return $r; - - } - - public function row($sql,$sep=' ') { - $query = $this->query($sql); - $result = $query->fetch(PDO::FETCH_NUM); - if (!is_array($result)) return $result; - return join($sep,$result); - return join($sep,$query->fetch(PDO::FETCH_NUM)); - } - - private function rows($sql,$style=PDO::FETCH_BOTH) { - return $this->query($sql)->fetchAll($style); - $sth = $this->conn->prepare($sql); - $sth->execute(); - return $sth->fetchAll($style); - } - - function query2a($sql) { - $r = $this->conn->query($sql,PDO::FETCH_COLUMN); - return $r ? $r->fetch() : $r; - } - - function query2aa($sql) { - return $this->conn->query($sql,PDO::FETCH_COLUMN); - } - - function query2h($sql) { - $r = $this->conn->query($sql,PDO::FETCH_ASSOC); - return $r ? $r->fetch() : $r; - } - - function query2ah($sql) { - return $this->conn->query($sql,PDO::FETCH_ASSOC); - } - - function quote($v) { - static $fct = false; if ($fct === false) $fct = $this->conf_type('quote'); - if ($fct) return $fct($v); - return $this->conn->quote($v); - } - - /** - * @author NB 12.08.16 - * Return a table instance - */ - public function table($name='',$params=[]) { - if ( !is_array($params) ) $this->bye('Usage: table($name,[type=>, sql=>, ...])'); - if (!$name and !empty($this->default_table)) $name = $this->default_table; - if (!$name) $this->bye('table(): Missing table'); - - if (empty($params) or empty($params['db'])) $params['db'] = $this; - - if (empty($this->tables[$name])) { - $this->tables[$name] = new Table($name,$params); - } elseif ($params) { - $this->tables[$name]->__construct($name,$params); - } - - return $this->tables[$name]; - } - - public static function localFile($name='') { - - if (!($config = self::type('localFile'))) return []; - - $config[1] = str_replace('',($name ? $name : $this->name),$config[1]); - - if (!file_exists($config[0])) return []; - - $return = []; - foreach (explode("\n",file_get_contents($config[0])) as $line) { - if (!preg_match('/'.($config[1]).'/',$line,$m)) continue; - foreach ($m as $k=>$v) if (preg_match('/^\d+$/',$k)) unset($m[$k]); - $return = array_replace_recursive($return,$m); - } + if (empty($this->conn)) return null; + $this->method('disconnect'); + } + + function exec($sql) { + + try { + #$r = $this->conn->exec($sql,$params); + $r = $this->conn->exec($sql); + } catch (PDOException $e) { + err(join(': ',[$e->getMessage(),"Db.exec()",$sql])); + $r = null; + } + + return $r; + } + + public function query($sql) { + # See: http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers + + try { + $r = $this->conn->query($sql); + } catch (PDOException $e) { + err(join(': ',[$e->getMessage(),"Db.query()",$sql])); + $r = null; + } + + return $r; + + } + + public function row($sql,$sep=' ') { + $query = $this->query($sql); + $result = $query->fetch(PDO::FETCH_NUM); + if (!is_array($result)) return $result; + return join($sep,$result); + return join($sep,$query->fetch(PDO::FETCH_NUM)); + } + + private function rows($sql,$style=PDO::FETCH_BOTH) { + return $this->query($sql)->fetchAll($style); + $sth = $this->conn->prepare($sql); + $sth->execute(); + return $sth->fetchAll($style); + } + + function query2a($sql) { + $r = $this->conn->query($sql,PDO::FETCH_COLUMN); + return $r ? $r->fetch() : $r; + } + + function query2aa($sql) { + return $this->conn->query($sql,PDO::FETCH_COLUMN); + } + + function query2h($sql) { + $r = $this->conn->query($sql,PDO::FETCH_ASSOC); + return $r ? $r->fetch() : $r; + } + + function query2ah($sql) { + return $this->conn->query($sql,PDO::FETCH_ASSOC); + } + + function quote($v) { + static $fct = false; if ($fct === false) $fct = $this->conf_type('quote'); + if ($fct) return $fct($v); + return $this->conn->quote($v); + } + + /** + * @author NB 12.08.16 + * Return a table instance + */ + public function table($name='',$params=[]) { + if ( !is_array($params) ) $this->bye('Usage: table($name,[type=>, sql=>, ...])'); + if (!$name and !empty($this->default_table)) $name = $this->default_table; + if (!$name) $this->bye('table(): Missing table'); + + if (empty($params) or empty($params['db'])) $params['db'] = $this; + + if (empty($this->tables[$name])) { + $this->tables[$name] = new Table($name,$params); + } elseif ($params) { + $this->tables[$name]->__construct($name,$params); + } + + return $this->tables[$name]; + } + + public static function localFile($name='') { + + if (!($config = self::type('localFile'))) return []; + + $config[1] = str_replace('',($name ? $name : $this->name),$config[1]); + + if (!file_exists($config[0])) return []; + + $return = []; + foreach (explode("\n",file_get_contents($config[0])) as $line) { + if (!preg_match('/'.($config[1]).'/',$line,$m)) continue; + foreach ($m as $k=>$v) if (preg_match('/^\d+$/',$k)) unset($m[$k]); + $return = array_replace_recursive($return,$m); + } #debug(self::ar_map('$a == null ? "" : $a',$return)); #debug($return); - if (empty($return['user']) and !empty($_SERVER['USER'])) $return['user'] = $_SERVER['USER']; - return $return; - } - - public function unvar($value) { - #return $value; - if (empty($value)) return $value; - if (!is_scalar($value)) { - foreach ($value as $k=>$v) { - if (is_scalar($v)) $value[$k] = $this->unvar($v); - } - return $value; - } - $replace = [ - '' => $this->name, - '' => $this->charset, - ]; - #debug( str_replace(array_keys($replace),array_values($replace),$value) ); - return str_replace(array_keys($replace),array_values($replace),$value); - } - - public function method($key=null) { - $method = $this->conf_type($key); - if (is_callable($method)) return $this->unvar($method($this)); - return $this->unvar($method); - } - - public function loadPhp($name) { - static $require = []; - - if (empty($name)) self::bye('Db file is required'); - - if (empty($require[$name])) { - $require[$name] = NB_ROOT.'/lib/php/db/'.$name.'.php'; - if (!file_exists($require[$name])) return false; - require_once($require[$name]); - } + if (empty($return['user']) and !empty($_SERVER['USER'])) $return['user'] = $_SERVER['USER']; + return $return; + } + + public function unvar($value) { + #return $value; + if (empty($value)) return $value; + if (!is_scalar($value)) { + foreach ($value as $k=>$v) { + if (is_scalar($v)) $value[$k] = $this->unvar($v); + } + return $value; + } + $replace = [ + '' => $this->name, + '' => $this->charset, + ]; + #debug( str_replace(array_keys($replace),array_values($replace),$value) ); + return str_replace(array_keys($replace),array_values($replace),$value); + } + + public function method($key=null) { + $method = $this->conf_type($key); + if (is_callable($method)) return $this->unvar($method($this)); + return $this->unvar($method); + } + + public function loadPhp($name) { + static $require = []; + + if (empty($name)) self::bye('Db file is required'); + + if (empty($require[$name])) { + $require[$name] = NB_ROOT.'/lib/php/db/'.$name.'.php'; + if (!file_exists($require[$name])) return false; + require_once($require[$name]); + } return true; - } + } - public function conf_type_load($type=null) { - global $DB_TYPES; - static $require = []; + public function conf_type_load($type=null) { + global $DB_TYPES; + static $require = []; - if (empty($type)) $type = $this->type; - if (empty($type)) self::bye('Db type is required'); + if (empty($type)) $type = $this->type; + if (empty($type)) self::bye('Db type is required'); - if (empty($require[$type])) { - $require[$type] = NB_ROOT.'/lib/php/db/types/'.$type.'.php'; - if (!file_exists($require[$type])) self::bye("Unknown type `$type`"); + if (empty($require[$type])) { + $require[$type] = NB_ROOT.'/lib/php/db/types/'.$type.'.php'; + if (!file_exists($require[$type])) self::bye("Unknown type `$type`"); # NB 10.01.18 $require[$type] = dirname(__FILE__).'/db/types/'.$type.'.php'; - require_once($require[$type]); - } + require_once($require[$type]); + } - return $DB_TYPES[$type]; - } + return $DB_TYPES[$type]; + } - public function conf_type($key=null,$die_if_empty=false) { + public function conf_type($key=null,$die_if_empty=false) { - # Load php file - $db_type = $this->conf_type_load(); + # Load php file + $db_type = $this->conf_type_load(); - # Dump all array - if ($key === null) return $db_type; + # Dump all array + if ($key === null) return $db_type; - # Search for specifics from types - if (!empty($this->types) and !empty($this->types[$key])) { - $db_type[$key] = array_merge((empty($db_type[$key]) ? [] : $db_type[$key]),$this->types[$key]); - } + # Search for specifics from types + if (!empty($this->types) and !empty($this->types[$key])) { + $db_type[$key] = array_merge((empty($db_type[$key]) ? [] : $db_type[$key]),$this->types[$key]); + } - # Check key exists - if (empty($db_type[$key])) { - if ($die_if_empty) self::bye("db_type(): Unknown key `$key` for type `".$this->type."`");#.' - '.print_r($db_type,true)); - return; - } + # Check key exists + if (empty($db_type[$key])) { + if ($die_if_empty) self::bye("db_type(): Unknown key `$key` for type `".$this->type."`");#.' - '.print_r($db_type,true)); + return; + } - return $this->unvar($db_type[$key]); - } + return $this->unvar($db_type[$key]); + } # NB 12.12.17 public function type($key=null,$die=false,$type=null) { # NB 12.12.17 if (empty($type)) $type = $this->type; @@ -483,208 +483,208 @@ class Db extends nb { # NB 12.12.17 return $this->conf_type($key,$die); # NB 12.12.17 } - public function table_exist($table) { - # NB 02.11.16: TODO NEVEW USED - $table = is_object($table) ? $table->name : $table; + public function table_exist($table) { + # NB 02.11.16: TODO NEVEW USED + $table = is_object($table) ? $table->name : $table; - if ($this->_tables === true) { - if (array_key_exists($table)) return 1; - } else { - } + if ($this->_tables === true) { + if (array_key_exists($table)) return 1; + } else { + } - return null; + return null; - } + } - public function tables() { + public function tables() { - if (!isset($this->_tables)) { - #if (!isset($this->tables)) { - $this->_tables = true; + if (!isset($this->_tables)) { + #if (!isset($this->tables)) { + $this->_tables = true; - $sql = $this->method('tables'); + $sql = $this->method('tables'); - if ($sql and !empty($this->conn)) { - foreach ($this->conn->query($sql,PDO::FETCH_ASSOC) as $row) { - $name = current($row); + if ($sql and !empty($this->conn)) { + foreach ($this->conn->query($sql,PDO::FETCH_ASSOC) as $row) { + $name = current($row); - # add to this->tables !!! - $t = $this->table($name,$row+['status'=>$row]); - } - } + # add to this->tables !!! + $t = $this->table($name,$row+['status'=>$row]); + } + } - } + } - return $this->tables; - } + return $this->tables; + } - public static function print_header($format,$value=null) { - if (empty($_SERVER['DOCUMENT_ROOT'])) return null; + public static function print_header($format,$value=null) { + if (empty($_SERVER['DOCUMENT_ROOT'])) return null; - if ($value!==null) return header("$format: $value"); + if ($value!==null) return header("$format: $value"); - if (!$mime=mime::get($format)) return false; - header('Content-type: '.$mime); + if (!$mime=mime::get($format)) return false; + header('Content-type: '.$mime); - return $mime; - } + return $mime; + } - public function sql_name($value) { - # no quote if contain comma for db - if (strpos($value,'.') !== false) return $value; + public function sql_name($value) { + # no quote if contain comma for db + if (strpos($value,'.') !== false) return $value; - # specific quote - if ($q=$this->conf_type('quote_name')) return $q.$value.$q; + # specific quote + if ($q=$this->conf_type('quote_name')) return $q.$value.$q; - # default quote - return '"'.$value.'"'; - } + # default quote + return '"'.$value.'"'; + } - public function out($rows,$head=[],$conf=[]) { + public function out($rows,$head=[],$conf=[]) { # NB 19.12.17 See www/dbq/dbq.php: $this->db->out($rows,$head,$conf); if (empty($rows)) return false; - if ($this->format) { - $format = $this->format; - - } elseif ($this->format == 'null') { - return true; + if ($this->format) { + $format = $this->format; - } elseif ($format=$this->format) { + } elseif ($this->format == 'null') { + return true; - } else { - # NB 04.12.16: TODEL one day ! - $format = $this->out->php_cli() ? 'csv' : 'table'; - } + } elseif ($format=$this->format) { - // Handle limit - if ($this->limit) { + } else { + # NB 04.12.16: TODEL one day ! + $format = $this->out->php_cli() ? 'csv' : 'table'; + } - $limit = (int)$this->limit; - $i = empty($head) ? 1 : 0; + // Handle limit + if ($this->limit) { - foreach ($rows as $k=>$v) { - if ($i>$limit) unset($rows[$k]); - $i++; - } + $limit = (int)$this->limit; + $i = empty($head) ? 1 : 0; - } + foreach ($rows as $k=>$v) { + if ($i>$limit) unset($rows[$k]); + $i++; + } - $this->out->rows($format,$rows,$head,$conf); - return true; - } + } - public function tables_rows($o=[]) { - # Options - # Filters - $type = empty($o['type']) ? '' : $o['type']; - $name = empty($o['name']) ? '' : $o['name']; - $engine = empty($o['engine']) ? '' : $o['engine']; - $database = empty($o['database']) ? '' : $o['database']; - $count = empty($o['count']) ? '' : $o['count']; - $fields = empty($o['fields']) ? '' : $o['fields']; + $this->out->rows($format,$rows,$head,$conf); + return true; + } - #var_dump ($this->tables()); + public function tables_rows($o=[]) { + # Options + # Filters + $type = empty($o['type']) ? '' : $o['type']; + $name = empty($o['name']) ? '' : $o['name']; + $engine = empty($o['engine']) ? '' : $o['engine']; + $database = empty($o['database']) ? '' : $o['database']; + $count = empty($o['count']) ? '' : $o['count']; + $fields = empty($o['fields']) ? '' : $o['fields']; + + #var_dump ($this->tables()); #foreach($this->tables as $t) debug($t->name.'='.$t->type); #bye($this->tables); - $rows = []; - foreach ($this->tables() as $t) { - #debug($t->name.'='.$t->type); - - if ($name and !$this->str_match($t->name,$name)) continue; - if ($type and !$this->str_match($t->type,$type)) continue; - if ($count and !$this->str_match($t->count,$count)) continue; - if ($engine and !$this->str_match($t->engine,$engine)) continue; - if ($database and isset($t->database) and !$this->str_match($t->database,$database)) continue; - - $row = $t->status(); - if ($count) $row['count'] = $t->status('count'); - #if ($fields) $row['fields'] = $t->status('fields'); - if ($fields) $row['fields'] = join(',',array_keys($t->fields())); - - #debug($t->name.'='.$t->database); - $rows[] = $row; - } - - $rows = self::array_fill_assoc($rows); - usort($rows,function($a,$b) { return strcmp($a['name'],$b['name']); }); - - return $rows; - } - - public function action($action,$table=null) { - #debug(($this->tables)); - $actions = explode(',',$action); + $rows = []; + foreach ($this->tables() as $t) { + #debug($t->name.'='.$t->type); + + if ($name and !$this->str_match($t->name,$name)) continue; + if ($type and !$this->str_match($t->type,$type)) continue; + if ($count and !$this->str_match($t->count,$count)) continue; + if ($engine and !$this->str_match($t->engine,$engine)) continue; + if ($database and isset($t->database) and !$this->str_match($t->database,$database)) continue; + + $row = $t->status(); + if ($count) $row['count'] = $t->status('count'); + #if ($fields) $row['fields'] = $t->status('fields'); + if ($fields) $row['fields'] = join(',',array_keys($t->fields())); + + #debug($t->name.'='.$t->database); + $rows[] = $row; + } + + $rows = self::array_fill_assoc($rows); + usort($rows,function($a,$b) { return strcmp($a['name'],$b['name']); }); + + return $rows; + } + + public function action($action,$table=null) { + #debug(($this->tables)); + $actions = explode(',',$action); # NB 02.12.16 $this->pdef('format',($this->php_cli() ? 'csv' : '')); - $rows = []; - $return = false; + $rows = []; + $return = false; - foreach ($actions as $action) { + foreach ($actions as $action) { - if ($action == 'db.help') { - $this->out(self::$action_help,['action','description']); - $return = true; + if ($action == 'db.help') { + $this->out(self::$action_help,['action','description']); + $return = true; - } elseif ($action == 'db.cryptkey') { - echo $this->out($this->cryptkey(),['key']); + } elseif ($action == 'db.cryptkey') { + echo $this->out($this->cryptkey(),['key']); - } elseif ($action == 'db.exec') { + } elseif ($action == 'db.exec') { - $count = 0; - $sql = ''; + $count = 0; + $sql = ''; - while (($line = fgets(STDIN)) !== false and !feof(STDIN)) { + while (($line = fgets(STDIN)) !== false and !feof(STDIN)) { - if (strpos($line,'--') === 0) continue; + if (strpos($line,'--') === 0) continue; - $line = preg_replace('/[\r\n]+$/','',$line); - if ($line == 'db.exec') break; + $line = preg_replace('/[\r\n]+$/','',$line); + if ($line == 'db.exec') break; - $sql .= $line; + $sql .= $line; - if (!preg_match('/;$/',$sql)) continue; - #$line = preg_replace('/^\s*(.*?)\s*;?\s*$/','$1',$line); - #if (!$line or strpos($line,'--') === 0) continue; + if (!preg_match('/;$/',$sql)) continue; + #$line = preg_replace('/^\s*(.*?)\s*;?\s*$/','$1',$line); + #if (!$line or strpos($line,'--') === 0) continue; - $count++; - #echo "$count> $line\n"; - $this->conn->exec($sql); - $sql = ''; - } - $return = $this->out([ - 'count' => $count, - ]); + $count++; + #echo "$count> $line\n"; + $this->conn->exec($sql); + $sql = ''; + } + $return = $this->out([ + 'count' => $count, + ]); - } elseif ($action == 'db.tables') { + } elseif ($action == 'db.tables') { - $rows = $this->tables_rows($this->p()); - $return = $this->out($rows); + $rows = $this->tables_rows($this->p()); + $return = $this->out($rows); - } elseif ($action == 'db.conf') { - $return = $this->out(array_values($this->conf)); + } elseif ($action == 'db.conf') { + $return = $this->out(array_values($this->conf)); - } elseif ($action == 'db.ls') { - $return = $this->out($this->ls()); + } elseif ($action == 'db.ls') { + $return = $this->out($this->ls()); - } elseif ($r=self::class_action_out($this,$action) !== null) { - return $r; + } elseif ($r=self::class_action_out($this,$action) !== null) { + return $r; - } elseif($table) { - if ($r=$table->action($action)) $return = $r; + } elseif($table) { + if ($r=$table->action($action)) $return = $r; - } - } + } + } - return $return; - } + return $return; + } - /** - * @copyright NB 05.03.16 - * @param [FILES] $files Files to load - * @return ARRAY the new/existing value of $this->db - */ - public static function ar_merge($a,$b) { + /** + * @copyright NB 05.03.16 + * @param [FILES] $files Files to load + * @return ARRAY the new/existing value of $this->db + */ + public static function ar_merge($a,$b) { return array_replace_recursive($a,$b); #return array_combine($a,$b); $n = $a; @@ -697,674 +697,674 @@ class Db extends nb { return $n; } - public static function conf_load($files=[],&$first=false) { - if (empty($files)) return []; + public static function conf_load($files=[],&$first=false) { + if (empty($files)) return []; - # - # Load all files into a $dbs if #files is not a hash - # + # + # Load all files into a $dbs if #files is not a hash + # - $DBQ = []; - $dbs = []; - $done = []; - foreach ((array)$files as $file) { + $DBQ = []; + $dbs = []; + $done = []; + foreach ((array)$files as $file) { - $file = self::untilde(realpath($file)); - if (isset($done[$file])) continue; - else $done[$file] = 1; + $file = self::untilde(realpath($file)); + if (isset($done[$file])) continue; + else $done[$file] = 1; - if (!is_readable($file)) continue; - if (preg_match('/\.(yaml|yml)$/i',$file) and ($yaml = self::yaml_parse_file($file))) { - $dbs = self::ar_merge($dbs,$yaml); + if (!is_readable($file)) continue; + if (preg_match('/\.(yaml|yml)$/i',$file) and ($yaml = self::yaml_parse_file($file))) { + $dbs = self::ar_merge($dbs,$yaml); - } elseif (preg_match('/\.php$/i',$file)) { + } elseif (preg_match('/\.php$/i',$file)) { $DBQ = []; - require($file); - if (!empty($DBQ)) $dbs = self::ar_merge($dbs,$DBQ); + require($file); + if (!empty($DBQ)) $dbs = self::ar_merge($dbs,$DBQ); - } + } - } + } - unset($yaml,$DBQ); - if (!$dbs) return false; + unset($yaml,$DBQ); + if (!$dbs) return false; - # - # First iteration: Import database conf with key _import - # - foreach ($dbs as $id=>$params) { - $params = (array)$params; + # + # First iteration: Import database conf with key _import + # + foreach ($dbs as $id=>$params) { + $params = (array)$params; - foreach ($params as $k => $v) { - if ($k != '_import') continue; + foreach ($params as $k => $v) { + if ($k != '_import') continue; - $import = is_array($v) ? $v : explode(',',$v); - foreach ($import as $v) { - if ($id == $v) self::bye("Infinite loop: _import $id = $v"); - if (empty($dbs[$v])) continue; + $import = is_array($v) ? $v : explode(',',$v); + foreach ($import as $v) { + if ($id == $v) self::bye("Infinite loop: _import $id = $v"); + if (empty($dbs[$v])) continue; - foreach ($dbs[$v] as $kk => $vv) { - if (!isset($params[$kk])) $dbs[$id][$kk] = $vv; - } - } + foreach ($dbs[$v] as $kk => $vv) { + if (!isset($params[$kk])) $dbs[$id][$kk] = $vv; + } + } - unset($dbs[$id][$k]); - } - } + unset($dbs[$id][$k]); + } + } - $default = isset($dbs['_default']) ? $dbs['_default'] : []; + $default = isset($dbs['_default']) ? $dbs['_default'] : []; - # - # Second iteration: Remove db starting with _ - # - foreach ($dbs as $db=>$params) { if (preg_match('/^_/',$db)) unset($dbs[$db]); } + # + # Second iteration: Remove db starting with _ + # + foreach ($dbs as $db=>$params) { if (preg_match('/^_/',$db)) unset($dbs[$db]); } - if (!$dbs) return false; + if (!$dbs) return false; - # - # Third iteration: Add missing and default - # - foreach ($dbs as $db=>$params) { - if (empty($params['name'])) $dbs[$db]['name'] = $db; - if (empty($params['id'])) $dbs[$db]['id'] = $db; + # + # Third iteration: Add missing and default + # + foreach ($dbs as $db=>$params) { + if (empty($params['name'])) $dbs[$db]['name'] = $db; + if (empty($params['id'])) $dbs[$db]['id'] = $db; # Ignore incomplete - if (empty($params['type'])) { + if (empty($params['type'])) { unset($dbs[$db]); continue; } - foreach ($default as $k=>$v) if (!isset($params[$k])) $dbs[$db][$k] = $v; - } - - # - # Sort by `order`, min first - # - uasort($dbs,function($a,$b){ - if (empty($a['order']) and empty($b['order'])) return strcmp($a['id'],$b['id']); - $a_ = !empty($a['order']) ? $a['order'] : 9999999; - $b_ = !empty($b['order']) ? $b['order'] : 9999999; - return($a_-$b_); - }); - - # - # Return - # - if (!$dbs) return false; - if ($first !== false) $first = self::ar_first($dbs); - return $dbs; - } - - /** - * @copyright NB 19.11.16 - * Return a db hash to create a new instance from $conf - */ - public static function conf_param_db($id) { - if (!isset($id)) $id = self::p('db'); - - if (!$id or !preg_match('/^(\w+):(.*)/',$id,$m)) return []; - $conf = [$id => []]; - - $conf[$id] = $conf[$id] + self::pdo2h($id); - # NB 10.12.16: NEW - if (empty($conf['id'])) $conf['id'] = $id; - - return $conf; - } - - /** - * @copyright NB 12.08.16 - * Return a db hash to create a new instance from $conf - */ - public static function conf_search_db($conf,$id=null) { - - if (empty($id)) $id = self::p('db'); - - # Load databases - $conf = self::is_hash($conf) ? $conf : self::conf_load($conf); - - $conf += self::conf_param_db($id); - - if (!$conf) return false; - - # Param - Default base on order hight num value - if (!$id) { - $id = self::ar_first($conf,true); - self::pset('db',$id); - } - - if (!isset($conf[$id])) { - self::bye("Can't find db: `".$id."` in `".join(",",array_keys($conf))."`",false); - } - - if (empty($conf[$id])) return []; - - # Construct assoc array - $db = array_merge($conf[$id],[ - 'conf' => $conf, - ]); - - return $db; - } - - /** - * @copyright NB 12.08.16 - * Create globals Db and Table - */ - public static function init($conf) { - - # - # Params - self::pinit(); - - # - # Load conf - $db = self::conf_search_db($conf); - if (self::p('localFile')) { - foreach (self::localFile($db['name']) as $k=>$v) { - if (empty($db[$k])) $db[$k] = $v; - } - } - - # - # Db - # - global $Db, $Table; - if (isset($Table)) self::bye("Table.init(): GLOBALS['Table'] already exists !"); - if (isset($Db)) self::bye("Db.init(): GLOBALS['Db'] already exists !"); - $Db = new self(); - # - # Connection - $Db->__construct($db); - $Db->connect(); - - # - # Table - # - if (self::p('action') and - !self::p('table') and - !preg_match('/^(table\.\w+|rows|insert|edit|delete|update)$/',self::p('action')) - ) { - - } else { - - # Search default_table - if (!self::p('table') and isset($Db->default_table)) self::pset('table',$Db->default_table); - - # Choose first table - if (!self::p('table') and ($v = array_keys($Db->tables()))) self::pset('table',$Db->ar_first($v)); - - if (self::p('table')) $Table = $Db->table(self::p('table'), - ( empty($db['tables'][$Db->p('table')]) ? [] : $db['tables'][$Db->p('table')] ) - ); - - } - - return true; - } - - /** - * @copyright NB 12.08.16 - * Transform pdo string into assoc array - */ - public static function pdo2h($pdo) { - $hash = []; - - if (preg_match('/^(\w+):(.*)/',$pdo,$m)) { - $hash['type'] = $m[1]; - $pdo = $m[2]; - } - - # YES - 'use_path' - while (preg_match('/^(\w+)=([^;]*)(?:;?)(.*?)$/',$pdo,$m)) { - if ($m[1] == 'dbname') $m[1] = 'name'; - $hash[$m[1]] = $m[2]; - $pdo = $m[3]; - } - - # NO - 'use_path' - if ($pdo) { - $hash['host'] = $pdo; - unset($pdo); - } - - return $hash; - } - - public function pdo_info() {#$pdo) { - $infos = []; - - foreach (self::pdo2h($this->pdo) as $k=>$v) { - if (!preg_match('/^(host|port|dbname|name|user)/',$k)) continue; - $infos[] = "$k=$v"; - } - - return join(' ',$infos); - } - - public function dump2csv() { - - $this->pset('format','csv'); - - # Filters - $name = self::p('name',self::p('table','')); - $sep = self::p('sep',"\t"); - - foreach ($this->tables() as $t) { - if ( - ($t->type == 'table') - and (empty($name) or $this->str_match($t->name,$name)) - ) { - $o = [ - 'preffix' => $t->name.$sep - ]; $t->rows($o); - } - } - - } - - public function dump($db_type='') { - return $this->sql(true,$db_type); - } - - public function sql($insert=null,$db_type='') { - if ($insert === null) $insert = self::p('insert'); - if (empty($db_type)) $db_type = self::p('db-type'); - - # Params ! dirty ! + foreach ($default as $k=>$v) if (!isset($params[$k])) $dbs[$db][$k] = $v; + } + + # + # Sort by `order`, min first + # + uasort($dbs,function($a,$b){ + if (empty($a['order']) and empty($b['order'])) return strcmp($a['id'],$b['id']); + $a_ = !empty($a['order']) ? $a['order'] : 9999999; + $b_ = !empty($b['order']) ? $b['order'] : 9999999; + return($a_-$b_); + }); + + # + # Return + # + if (!$dbs) return false; + if ($first !== false) $first = self::ar_first($dbs); + return $dbs; + } + + /** + * @copyright NB 19.11.16 + * Return a db hash to create a new instance from $conf + */ + public static function conf_param_db($id) { + if (!isset($id)) $id = self::p('db'); + + if (!$id or !preg_match('/^(\w+):(.*)/',$id,$m)) return []; + $conf = [$id => []]; + + $conf[$id] = $conf[$id] + self::pdo2h($id); + # NB 10.12.16: NEW + if (empty($conf['id'])) $conf['id'] = $id; + + return $conf; + } + + /** + * @copyright NB 12.08.16 + * Return a db hash to create a new instance from $conf + */ + public static function conf_search_db($conf,$id=null) { + + if (empty($id)) $id = self::p('db'); + + # Load databases + $conf = self::is_hash($conf) ? $conf : self::conf_load($conf); + + $conf += self::conf_param_db($id); + + if (!$conf) return false; + + # Param - Default base on order hight num value + if (!$id) { + $id = self::ar_first($conf,true); + self::pset('db',$id); + } + + if (!isset($conf[$id])) { + self::bye("Can't find db: `".$id."` in `".join(",",array_keys($conf))."`",false); + } + + if (empty($conf[$id])) return []; + + # Construct assoc array + $db = array_merge($conf[$id],[ + 'conf' => $conf, + ]); + + return $db; + } + + /** + * @copyright NB 12.08.16 + * Create globals Db and Table + */ + public static function init($conf) { + + # + # Params + self::pinit(); + + # + # Load conf + $db = self::conf_search_db($conf); + if (self::p('localFile')) { + foreach (self::localFile($db['name']) as $k=>$v) { + if (empty($db[$k])) $db[$k] = $v; + } + } + + # + # Db + # + global $Db, $Table; + if (isset($Table)) self::bye("Table.init(): GLOBALS['Table'] already exists !"); + if (isset($Db)) self::bye("Db.init(): GLOBALS['Db'] already exists !"); + $Db = new self(); + # + # Connection + $Db->__construct($db); + $Db->connect(); + + # + # Table + # + if (self::p('action') and + !self::p('table') and + !preg_match('/^(table\.\w+|rows|insert|edit|delete|update)$/',self::p('action')) + ) { + + } else { + + # Search default_table + if (!self::p('table') and isset($Db->default_table)) self::pset('table',$Db->default_table); + + # Choose first table + if (!self::p('table') and ($v = array_keys($Db->tables()))) self::pset('table',$Db->ar_first($v)); + + if (self::p('table')) $Table = $Db->table(self::p('table'), + ( empty($db['tables'][$Db->p('table')]) ? [] : $db['tables'][$Db->p('table')] ) + ); + + } + + return true; + } + + /** + * @copyright NB 12.08.16 + * Transform pdo string into assoc array + */ + public static function pdo2h($pdo) { + $hash = []; + + if (preg_match('/^(\w+):(.*)/',$pdo,$m)) { + $hash['type'] = $m[1]; + $pdo = $m[2]; + } + + # YES - 'use_path' + while (preg_match('/^(\w+)=([^;]*)(?:;?)(.*?)$/',$pdo,$m)) { + if ($m[1] == 'dbname') $m[1] = 'name'; + $hash[$m[1]] = $m[2]; + $pdo = $m[3]; + } + + # NO - 'use_path' + if ($pdo) { + $hash['host'] = $pdo; + unset($pdo); + } + + return $hash; + } + + public function pdo_info() {#$pdo) { + $infos = []; + + foreach (self::pdo2h($this->pdo) as $k=>$v) { + if (!preg_match('/^(host|port|dbname|name|user)/',$k)) continue; + $infos[] = "$k=$v"; + } + + return join(' ',$infos); + } + + public function dump2csv() { + + $this->pset('format','csv'); + + # Filters + $name = self::p('name',self::p('table','')); + $sep = self::p('sep',"\t"); + + foreach ($this->tables() as $t) { + if ( + ($t->type == 'table') + and (empty($name) or $this->str_match($t->name,$name)) + ) { + $o = [ + 'preffix' => $t->name.$sep + ]; $t->rows($o); + } + } + + } + + public function dump($db_type='') { + return $this->sql(true,$db_type); + } + + public function sql($insert=null,$db_type='') { + if ($insert === null) $insert = self::p('insert'); + if (empty($db_type)) $db_type = self::p('db-type'); + + # Params ! dirty ! # NB 10.01.18 $this->pset('orderby',null); # NB 10.01.18 $this->pset('extras','0'); # NB 10.01.18 $this->pset('format','sql'); - # Filters - $type = self::p('table-type',''); $type = $type ? explode(',',$type) : $type; - $name = self::p('table-name',''); $name = $name ? explode(',',$name) : $name; - - # Tables param filter - $tables = $this->tables(); - - # Caching before changing db type - $views = []; - foreach ($tables as $k=>$t) { - - if ( - ($t->type != 'table' and $t->type != 'view') - or (!empty($name) and !$this->str_match($t->name,$name)) - or (!empty($type) and !$this->str_match($t->type,$type)) - ) { - unset($tables[$k]); - continue; - } - - if ($t->type == 'view') { - $views[$k] = $t; - unset($tables[$k]); - } - unset($t->orderby); - - $t->fields(); - $t->sql(); - } - - # HEADER - echo '' - #."-- Database : ".$this->name."\n" - ."-- Date : ".strftime('%F %T')."\n" + # Filters + $type = self::p('table-type',''); $type = $type ? explode(',',$type) : $type; + $name = self::p('table-name',''); $name = $name ? explode(',',$name) : $name; + + # Tables param filter + $tables = $this->tables(); + + # Caching before changing db type + $views = []; + foreach ($tables as $k=>$t) { + + if ( + ($t->type != 'table' and $t->type != 'view') + or (!empty($name) and !$this->str_match($t->name,$name)) + or (!empty($type) and !$this->str_match($t->type,$type)) + ) { + unset($tables[$k]); + continue; + } + + if ($t->type == 'view') { + $views[$k] = $t; + unset($tables[$k]); + } + unset($t->orderby); + + $t->fields(); + $t->sql(); + } + + # HEADER + echo '' + #."-- Database : ".$this->name."\n" + ."-- Date : ".strftime('%F %T')."\n" # NB 07.01.18 ."-- Pdo : ".$this->pdo_info()."\n" - ; + ; - # Change db type if needed - $type_from = $type_to = ''; - if ($db_type) { - echo "-- Type : ".$db_type."\n"; - echo "-- Type from: ".$this->type."\n"; - $type_from = $this->type; - $type_to = $db_type; - $this->type = $type_to; + # Change db type if needed + $type_from = $type_to = ''; + if ($db_type) { + echo "-- Type : ".$db_type."\n"; + echo "-- Type from: ".$this->type."\n"; + $type_from = $this->type; + $type_to = $db_type; + $this->type = $type_to; } else { - echo "-- Type : ".$this->type."\n"; - - } - - # Specific function - $row_opt = [ - 'parser' => false, - 'format' => 'sql', - 'db_type_from' => $type_from, - ]; - - # SQL_PRE - $i = 0; foreach ((array)$this->method('schema.pre') as $s) { - if (($i++) == 0) echo "\n-- SQL.PRE\n"; - echo rtrim($s,';').";\n"; - } - - if ($type_from == 'mysql') $views = []; # Mysql store sql create view in mysql format wich only works with mysql - echo "\n-- SQL\n"; - foreach (array_merge($tables,$views) as $t) { - - # DROP / CREATE - $create = rtrim($t->create(false),';'); - $create = str_replace(';CREATE',";\nCREATE",$create); - - if (!($drop = $this->method('sql.drop'))) $drop = - 'DROP '.strtoupper($t->type).' IF EXISTS '.$t->sql_name() - ; - - $t->sql_create = $drop.';'.NB_EOL - .$create.';'.NB_EOL - ; - - if ($insert) $t->sql_create = - "\n-- ".strtoupper($t->type).": ".$t->name."\n".$t->sql_create - ; - echo $t->sql_create; - - # INSERT - if ($insert and $t->type == 'table') { + echo "-- Type : ".$this->type."\n"; + + } + + # Specific function + $row_opt = [ + 'parser' => false, + 'format' => 'sql', + 'db_type_from' => $type_from, + ]; + + # SQL_PRE + $i = 0; foreach ((array)$this->method('schema.pre') as $s) { + if (($i++) == 0) echo "\n-- SQL.PRE\n"; + echo rtrim($s,';').";\n"; + } + + if ($type_from == 'mysql') $views = []; # Mysql store sql create view in mysql format wich only works with mysql + echo "\n-- SQL\n"; + foreach (array_merge($tables,$views) as $t) { + + # DROP / CREATE + $create = rtrim($t->create(false),';'); + $create = str_replace(';CREATE',";\nCREATE",$create); + + if (!($drop = $this->method('sql.drop'))) $drop = + 'DROP '.strtoupper($t->type).' IF EXISTS '.$t->sql_name() + ; + + $t->sql_create = $drop.';'.NB_EOL + .$create.';'.NB_EOL + ; + + if ($insert) $t->sql_create = + "\n-- ".strtoupper($t->type).": ".$t->name."\n".$t->sql_create + ; + echo $t->sql_create; + + # INSERT + if ($insert and $t->type == 'table') { $o = $row_opt; - $t->rows($o); - } + $t->rows($o); + } - } + } - $i = 0; foreach ((array)$this->method('schema.post') as $s) { - if (($i++) == 0) echo "\n-- SQL.POST\n"; - echo rtrim($s,';').";\n"; - } + $i = 0; foreach ((array)$this->method('schema.post') as $s) { + if (($i++) == 0) echo "\n-- SQL.POST\n"; + echo rtrim($s,';').";\n"; + } - return true; - } + return true; + } - public function status() { + public function status() { - $status = $new = []; + $status = $new = []; #debug(array_keys($this->tables())); - $new = [] - +[ - 'id' => (empty($this->id) ? '' : $this->id), - 'name' => $this->name, - 'type' => $this->type, - 'host' => $this->host, - 'tables' => count($this->tables()), - ] - +($this->conf_type('use_path') ? [] : [ - 'port' => $this->port, - 'user' => $this->user, - ]) - +[ - 'title' => $this->title, - 'default_table' => $this->default_table, - ] - +$new; - - if (($sqls=$this->conf_type('status'))) { - - foreach ($sqls as $sql => $fct) { - - try { - $sth = $this->conn->prepare($sql); - $sth->execute(); - } catch(PDOException $e){ - continue; - } - - $rows = $sth->fetchAll(PDO::FETCH_BOTH); - foreach ($rows as $i=>$r) { - if ($v = $fct($r)) $new += $v; - } - #$sqls = $new; - #debug($rows); - } - - } # << type.status - - if (($call=$this->conf_type('status_callback'))) { - $call($new); - } - - #debug($new); - foreach ($new as $k=>$v) { - $status[] = [ - 'name' => $k, - 'value' => $v, - ]; - } - - return $status; - } - - public function fields($st) { - # See: http://php.net/manual/en/pdostatement.getcolumnmeta.php - $fields = []; - #debug($st->columnCount()); - #debug($st->getColumnMeta(0)); - - for ($i = 0; $i < $st->columnCount(); $i++) { - $col = $st->getColumnMeta($i); - - $f = new Field(); - $col['type'] = $f->pdo2type($col['pdo_type']); - unset($col['pdo_type']); - - if (!empty($col['flags'])) { - $col['null'] = in_array('not_null',$col['flags']) ? false : true; - $col['key'] = in_array('primary_key',$col['flags']) ? true : false; - } - unset($col['flags']); - - unset($col['len']); # never right ! - unset($col['precision']); # ??? - - $f->__construct($col); - $fields[] = $f; - } - - return $fields; - } - - public function sql_pre() { - $return = []; - - foreach ((array)$this->conf_type('sql_pre') as $s) { - if (!empty($s)) $return[] = $s; - } - - if (!empty($this->sql_pre)) { - foreach ((array)$this->sql_pre as $s) { - if (!empty($s)) $return[] = $s; - } - } - - return $return; - } - - public function sql_post() { - $return = []; - - foreach ((array)$this->conf_type('sql_post') as $s) { - if (!empty($s)) $return[] = $s; - } - - if (!empty($this->sql_post)) { - foreach ((array)$this->sql_post as $s) { - if (!empty($s)) $return[] = $s; - } - } + $new = [] + +[ + 'id' => (empty($this->id) ? '' : $this->id), + 'name' => $this->name, + 'type' => $this->type, + 'host' => $this->host, + 'tables' => count($this->tables()), + ] + +($this->conf_type('use_path') ? [] : [ + 'port' => $this->port, + 'user' => $this->user, + ]) + +[ + 'title' => $this->title, + 'default_table' => $this->default_table, + ] + +$new; + + if (($sqls=$this->conf_type('status'))) { + + foreach ($sqls as $sql => $fct) { + + try { + $sth = $this->conn->prepare($sql); + $sth->execute(); + } catch(PDOException $e){ + continue; + } + + $rows = $sth->fetchAll(PDO::FETCH_BOTH); + foreach ($rows as $i=>$r) { + if ($v = $fct($r)) $new += $v; + } + #$sqls = $new; + #debug($rows); + } - return $return; - } + } # << type.status - public function databases() { + if (($call=$this->conf_type('status_callback'))) { + $call($new); + } - if (!isset($this->databases)) { + #debug($new); + foreach ($new as $k=>$v) { + $status[] = [ + 'name' => $k, + 'value' => $v, + ]; + } - $this->databases = []; - $name = self::p('name',''); + return $status; + } - if ($sql = $this->conf_type('databases') and !empty($this->conn)) { - $fct = ''; - if (is_array($sql)) list($sql,$fct) = count($sql)>1 ? $sql : [$sql[0],'']; + public function fields($st) { + # See: http://php.net/manual/en/pdostatement.getcolumnmeta.php + $fields = []; + #debug($st->columnCount()); + #debug($st->getColumnMeta(0)); - $st = $this->conn->prepare($sql); - $st->execute(); - $this->databases = []; + for ($i = 0; $i < $st->columnCount(); $i++) { + $col = $st->getColumnMeta($i); - while ($row = $st->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT)) { - if ($fct) $fct($row,$this); - if ($row) $this->databases[] = $row; - } + $f = new Field(); + $col['type'] = $f->pdo2type($col['pdo_type']); + unset($col['pdo_type']); - } + if (!empty($col['flags'])) { + $col['null'] = in_array('not_null',$col['flags']) ? false : true; + $col['key'] = in_array('primary_key',$col['flags']) ? true : false; + } + unset($col['flags']); - } + unset($col['len']); # never right ! + unset($col['precision']); # ??? - return $this->databases; - } + $f->__construct($col); + $fields[] = $f; + } - public static function pinit(&$changed=[]) { - if (!empty(self::$paliases)) self::paliases(self::$paliases,$changed); + return $fields; + } - if ($action=self::p('action') and !empty(self::$action_aliases)) { - foreach (self::$action_aliases as $src => $dest) { - if ($action === $src) self::pset('action',$dest); - } - } + public function sql_pre() { + $return = []; - # Param - Extract dbname from table + foreach ((array)$this->conf_type('sql_pre') as $s) { + if (!empty($s)) $return[] = $s; + } + + if (!empty($this->sql_pre)) { + foreach ((array)$this->sql_pre as $s) { + if (!empty($s)) $return[] = $s; + } + } + + return $return; + } + + public function sql_post() { + $return = []; + + foreach ((array)$this->conf_type('sql_post') as $s) { + if (!empty($s)) $return[] = $s; + } + + if (!empty($this->sql_post)) { + foreach ((array)$this->sql_post as $s) { + if (!empty($s)) $return[] = $s; + } + } + + return $return; + } + + public function databases() { + + if (!isset($this->databases)) { + + $this->databases = []; + $name = self::p('name',''); + + if ($sql = $this->conf_type('databases') and !empty($this->conn)) { + $fct = ''; + if (is_array($sql)) list($sql,$fct) = count($sql)>1 ? $sql : [$sql[0],'']; + + $st = $this->conn->prepare($sql); + $st->execute(); + $this->databases = []; + + while ($row = $st->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT)) { + if ($fct) $fct($row,$this); + if ($row) $this->databases[] = $row; + } + + } + + } + + return $this->databases; + } + + public static function pinit(&$changed=[]) { + if (!empty(self::$paliases)) self::paliases(self::$paliases,$changed); + + if ($action=self::p('action') and !empty(self::$action_aliases)) { + foreach (self::$action_aliases as $src => $dest) { + if ($action === $src) self::pset('action',$dest); + } + } + + # Param - Extract dbname from table # NB 12.11.16 if (false and preg_match('/^(\w+)\.(.*?)$/',self::p('table'),$m)) { # NB 12.11.16 self::pset('db',$m[1]); # NB 12.11.16 self::pset('table',$m[2]); # NB 12.11.16 } - # Select param - if (Db::p('table') and Db::p('select')) { - Db::pset('table','SELECT '.(Db::p('select')).' FROM '.Db::p('table')); - Db::pset('select',''); - } - - } - - public function ls(&$fields=[]) { - - $fields = ['id','name','title','type','host' ]; #,'order']; - $dbs = []; - $name = self::p('name',''); - $type = self::p('type',''); - - if (empty($this->conf)) return null; - - foreach ($this->conf as $id => $attr) { - $attr['id'] = $id; - $d = new Db($attr); - $db = []; - - foreach ($fields as $k) { - $db[$k] = isset($d->$k) ? $d->$k : ''; - } - - if (!empty($name) and !$this->str_match($db['name'],$name)) continue; - if (!empty($type) and !$this->str_match($db['type'],$type)) continue; - - $dbs[] = $db; - } - - return $dbs; - } - - public function table_row_encrypt(&$table,&$row) { - if (!empty($table->update_parse)) { - $fct = $table->update_parse; - $fct($row,$table); - } - - if (0 - or empty($this->encrypt) - or empty($this->encrypt['secret']) - or empty($this->encrypt['tables']) - or empty($this->encrypt['tables'][$table->name]) - ) return $row; - - foreach ($row as $k => $v) { - if (!in_array($k,$this->encrypt['tables'][$table->name])) continue; - $row[$k] = $this->encrypt($this->encrypt['secret'],$v); - } - - return $row; - } - - public function table_row_decrypt(&$table,&$row) { - if (0 - or empty($this->encrypt) - or empty($this->encrypt['secret']) - or empty($this->encrypt['tables']) - or empty($this->encrypt['tables'][$table->name]) - ) return $row; - - foreach ($row as $k => $v) { - if (!in_array($k,$this->encrypt['tables'][$table->name])) continue; - $row[$k] = $this->decrypt($this->encrypt['secret'],$v); - } - - return $row; - } - - public static function content_type2format($content_type=null) { - if (empty($content_type)) $content_type = self::client_content_type(); - switch (mime::ext($content_type)) { - case "html": - return 'table'; - default: - return 'csv'; - } - } - - public function page($opt=[]) { - require_once(NB_ROOT.'/lib/php/page.php'); - return new Page(array_merge([ - 'title' => ($this->title ? $this->title : this::prettyText($this->name)), - 'css' => [ - 'css/*.css', - '/*.css', - ], - 'js' => [ - 'js/*.js', - '/*.js', - ], - 'content_type' => Page::content_type_and_set_format(), - 'nav' => [ - [ (!empty($this) and !empty($this->title)) ? $this->title : 'Home', '/'], - ( (!empty($this->table()) and !empty($this->table()->name)) ? [Page::prettyText($this->table()->name),Page::path().'?table='.urlencode($this->table()->name)] : '' ), - ( Page::p('action') ? Page::prettyText(preg_replace('/^\w+\./','',Page::p('action'))) : '' ), - ], - ],$opt)); - } - - public function ssha512_password($password='',$salt='') { - if (empty($password)) return $password; - if ($salt === '') $salt = substr(str_shuffle(str_repeat('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',4)),0,4); - $password = '{SSHA512}' . base64_encode(hash('sha512', $password . $salt). $salt); - return $password; - } - - public function ssha_password($password='') { - if (empty($password)) return $password; - $salt = substr(str_shuffle(str_repeat('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',4)),0,4); - $password = '{SSHA}' . base64_encode(sha1( $password.$salt, TRUE ). $salt); - return $password; - } - - public function cast_text($str) { - if ($fct = $this->conf_type('cast_text')) $str = $fct($str); + # Select param + if (Db::p('table') and Db::p('select')) { + Db::pset('table','SELECT '.(Db::p('select')).' FROM '.Db::p('table')); + Db::pset('select',''); + } + + } + + public function ls(&$fields=[]) { + + $fields = ['id','name','title','type','host' ]; #,'order']; + $dbs = []; + $name = self::p('name',''); + $type = self::p('type',''); + + if (empty($this->conf)) return null; + + foreach ($this->conf as $id => $attr) { + $attr['id'] = $id; + $d = new Db($attr); + $db = []; + + foreach ($fields as $k) { + $db[$k] = isset($d->$k) ? $d->$k : ''; + } + + if (!empty($name) and !$this->str_match($db['name'],$name)) continue; + if (!empty($type) and !$this->str_match($db['type'],$type)) continue; + + $dbs[] = $db; + } + + return $dbs; + } + + public function table_row_encrypt(&$table,&$row) { + if (!empty($table->update_parse)) { + $fct = $table->update_parse; + $fct($row,$table); + } + + if (0 + or empty($this->encrypt) + or empty($this->encrypt['secret']) + or empty($this->encrypt['tables']) + or empty($this->encrypt['tables'][$table->name]) + ) return $row; + + foreach ($row as $k => $v) { + if (!in_array($k,$this->encrypt['tables'][$table->name])) continue; + $row[$k] = $this->encrypt($this->encrypt['secret'],$v); + } + + return $row; + } + + public function table_row_decrypt(&$table,&$row) { + if (0 + or empty($this->encrypt) + or empty($this->encrypt['secret']) + or empty($this->encrypt['tables']) + or empty($this->encrypt['tables'][$table->name]) + ) return $row; + + foreach ($row as $k => $v) { + if (!in_array($k,$this->encrypt['tables'][$table->name])) continue; + $row[$k] = $this->decrypt($this->encrypt['secret'],$v); + } + + return $row; + } + + public static function content_type2format($content_type=null) { + if (empty($content_type)) $content_type = self::client_content_type(); + switch (mime::ext($content_type)) { + case "html": + return 'table'; + default: + return 'csv'; + } + } + + public function page($opt=[]) { + require_once(NB_ROOT.'/lib/php/page.php'); + return new Page(array_merge([ + 'title' => ($this->title ? $this->title : this::prettyText($this->name)), + 'css' => [ + 'css/*.css', + '/*.css', + ], + 'js' => [ + 'js/*.js', + '/*.js', + ], + 'content_type' => Page::content_type_and_set_format(), + 'nav' => [ + [ (!empty($this) and !empty($this->title)) ? $this->title : 'Home', '/'], + ( (!empty($this->table()) and !empty($this->table()->name)) ? [Page::prettyText($this->table()->name),Page::path().'?table='.urlencode($this->table()->name)] : '' ), + ( Page::p('action') ? Page::prettyText(preg_replace('/^\w+\./','',Page::p('action'))) : '' ), + ], + ],$opt)); + } + + public function ssha512_password($password='',$salt='') { + if (empty($password)) return $password; + if ($salt === '') $salt = substr(str_shuffle(str_repeat('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',4)),0,4); + $password = '{SSHA512}' . base64_encode(hash('sha512', $password . $salt). $salt); + return $password; + } + + public function ssha_password($password='') { + if (empty($password)) return $password; + $salt = substr(str_shuffle(str_repeat('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',4)),0,4); + $password = '{SSHA}' . base64_encode(sha1( $password.$salt, TRUE ). $salt); + return $password; + } + + public function cast_text($str) { + if ($fct = $this->conf_type('cast_text')) $str = $fct($str); return $str; - } + } - public function like_nocase() { - if ($v = $this->conf_type('like_nocase')) return $v; + public function like_nocase() { + if ($v = $this->conf_type('like_nocase')) return $v; return 'LIKE'; - } + } } # < Class diff --git a/lib/php/db/table.php b/lib/php/db/table.php index 0866b7db..f2632ae1 100644 --- a/lib/php/db/table.php +++ b/lib/php/db/table.php @@ -3,1698 +3,1680 @@ require_once(realpath(dirname(__FILE__).'/../db.php')); require_once(realpath(NB_ROOT.'/lib/php/db/field.php')); require_once(realpath(NB_ROOT.'/lib/php/out.php')); $DB_TABLE_QUERY_ID = 0; -function __table_define() { - define('TABLE_INDENT',NB_EOL ? "\t" : ""); - define('TABLE_CSV_SEP',Table::p('sep',"\t")); - if (!defined('TABLE_TEMPLATE')) define('TABLE_TEMPLATE',dirname(__FILE__).'/../../../share/templates'); +// >> Define +define('TABLE_INDENT',NB_EOL ? "\t" : ""); +define('TABLE_CSV_SEP',Table::p('sep',"\t")); - if (!defined('DB_HTML_EDIT')) define('DB_HTML_EDIT','Edit'); - if (!defined('DB_HTML_DELETE')) define('DB_HTML_DELETE','Delete'); +if (!defined('TABLE_TEMPLATE')) define('TABLE_TEMPLATE',dirname(__FILE__).'/../../../share/templates'); - # Create a temporary table when table is a SELECT - #if (!defined('DB_TABLE_QUERY_NAME')) - define('DB_TABLE_QUERY_NAME','_query_'); -} +if (!defined('DB_HTML_EDIT')) define('DB_HTML_EDIT','Edit'); +if (!defined('DB_HTML_DELETE')) define('DB_HTML_DELETE','Delete'); +// << Define + +# Create a temporary table when table is a SELECT +#if (!defined('DB_TABLE_QUERY_NAME')) +define('DB_TABLE_QUERY_NAME','_query_'); Class Table extends nb { - public $name; - public $type; # table, view, sql - public $sql; - public $replace = []; # to be process by by javascript (id="db-table-replace") - public $extras = []; - public $rows = []; # array inserted into temporary table - public $row_parse_pre; # Function to call in rows() - public $row_parse_post; # Function to call in rows() - public $update_parse; # Function to call in update, replace, insert - public $count; - public $engine; - public $created; - public static $is_admin = true; - public $key_preff = '_key_'; + public $name; + public $type; # table, view, sql + public $sql; + public $replace = []; # to be process by by javascript (id="db-table-replace") + public $extras = []; + public $rows = []; # array inserted into temporary table + public $row_parse_pre; # Function to call in rows() + public $row_parse_post; # Function to call in rows() + public $update_parse; # Function to call in update, replace, insert + public $count; + public $engine; + public $created; + public static $is_admin = true; + public $key_preff = '_key_'; # NB 19.10.17 TODO - public $field_preff = ''; - - public $fields = []; - public $fields_only = []; - public $indexes = []; - - public $idtemplate; - - # hidden, sort, ... fields - public $show_hidden_params = true; - public $show_buttons = true; - public $show_url_sort = true; - public $show_header = true; - public static $params = [ - 'db', 'table', 'limit', 'debug', 'action', - 'page', 'paged', # wordpress - ]; - - function __construct($name,$opt=[]) { - - if (!is_scalar($name)) { - $opt = $name; - #$name = $opt['name']; - $name = isset($opt['name']) ? $opt['name'] : ''; - - } - - if(!empty($name)) $opt['name'] = $this->name = $name; - #debug($opt); - - #unset($opt['db']); bye($opt); - - // Type - if (isset($opt['sql'])) { - $this->type = 'sql'; unset($opt['type']); - $this->sql = $opt['sql']; unset($opt['sql']); - } - - // Params - if (isset($opt['params'])) { - self::$params = $opt['params']; unset($opt['params']); - } - - // Db / Connection - if (isset($opt['db'])) { - $this->db(is_object($opt['db']) ? $opt['db'] : new Db($opt['db'])); - unset($opt['db']); - - } elseif(isset($GLOBALS['Db'])) { - $this->db($GLOBALS['Db']); - - } else { - $this->db(new Db()); - - } - - // Extras - if (isset($opt['extras'])) { - $this->add_extras($opt['extras']); - unset($opt['extras']); - } - - // Add others - foreach ($opt as $k => $v) { $this->$k = $v; } - - if (empty($this->db()->limit)) { - if ($this->p('paged')) { - $this->db()->limit = ($this->db()->limit * $this->p('paged')).','.$this->db()->limit; - } elseif ($this->db()->limit=$this->p('limit')) { - } - } - - if (isset($_GET['rows.header'])) $this->show_header = $_GET['rows.header']; - if (isset($_GET['rows.fields'])) $this->fields_only = explode(',',$_GET['rows.fields']); - - } - - public function create_temporary_rows() { - // For static rows - if(empty($this->rows)) return null; - if(!empty($this->rows) and empty($this->type)) $this->type = 'rows'; - - $fields = array_keys($this->rows[0]); - $sql_names = $this->sql_names($fields); - - $this->db()->conn->query("CREATE ".$this->sql_temporary()." TABLE $this->name (" - .join(',',$this->ar_map('"$a text"',$sql_names)) - .')'); - $sql = 'INSERT INTO '. $this->sql_name("$this->name") - . ' (' . join(',',array_values($sql_names)).')' - .' VALUES (' . join(',',$this->ar_map('":$a"',$fields)) . ')' - ; - - #debug($sql); - if (!($query = $this->db()->conn->prepare($sql))) { - $this->err_sql($sql); - return false; - } - - $this->fields = []; - foreach ($fields as $name) { - $this->fields[$name] = new Field([ - 'name' => $name, - 'table' => $this, - ]); - } - $this->_fields = 1; - - foreach ($this->rows as $row) { - - foreach ($row as $k=>$v) { - $field = $this->field($k); - $field->bindParam($query,$v,":$k"); - } - - if (!($execute = $query->execute())) { - $this->err_sql($sql); - return false; - } - - } - - return true; - } - - private function sql_temporary() { - if ($this->db()->type == 'sqlite') return 'TEMP'; - return 'TEMPORARY'; - } - - /* - * Function create_temporary - * - * Create temporary if needed - * - */ - public function create_temporary() { - if (!empty($this->_create_temporary)) return; - $this->_create_temporary = true; - - $this->create_temporary_rows(); - - // Name, could be a select - if (DB_TABLE_QUERY_NAME and stripos($this->name,'SELECT ')===0) { - $this->db()->conn->query("CREATE ".$this->sql_temporary()." TABLE ".DB_TABLE_QUERY_NAME." AS $this->name"); - $this->name = DB_TABLE_QUERY_NAME; - - // Virtual Table - } elseif (DB_TABLE_QUERY_NAME and !empty($this->sql)) { + public $field_preff = ''; + + public $fields = []; + public $fields_only = []; + public $indexes = []; + + public $idtemplate; + + # hidden, sort, ... fields + public $show_hidden_params = true; + public $show_buttons = true; + public $show_url_sort = true; + public $show_header = true; + public static $params = [ + 'db', 'table', 'limit', 'debug', 'action', + 'page', 'paged', # wordpress + ]; + + function __construct($name,$opt=[]) { + + if (!is_scalar($name)) { + $opt = $name; + #$name = $opt['name']; + $name = isset($opt['name']) ? $opt['name'] : ''; + + } + + if(!empty($name)) $opt['name'] = $this->name = $name; + #debug($opt); + + #unset($opt['db']); bye($opt); + + // Type + if (isset($opt['sql'])) { + $this->type = 'sql'; unset($opt['type']); + $this->sql = $opt['sql']; unset($opt['sql']); + } + + // Params + if (isset($opt['params'])) { + self::$params = $opt['params']; unset($opt['params']); + } + + // Db / Connection + if (isset($opt['db'])) { + $this->db(is_object($opt['db']) ? $opt['db'] : new Db($opt['db'])); + unset($opt['db']); + + } elseif(isset($GLOBALS['Db'])) { + $this->db($GLOBALS['Db']); + + } else { + $this->db(new Db()); + + } + + // Extras + if (isset($opt['extras'])) { + $this->add_extras($opt['extras']); + unset($opt['extras']); + } + + // Add others + foreach ($opt as $k => $v) { $this->$k = $v; } + + if (empty($this->db()->limit)) { + if ($this->p('paged')) { + $this->db()->limit = ($this->db()->limit * $this->p('paged')).','.$this->db()->limit; + } elseif ($this->db()->limit=$this->p('limit')) { + } + } + + if (isset($_GET['rows.header'])) $this->show_header = $_GET['rows.header']; + if (isset($_GET['rows.fields'])) $this->fields_only = explode(',',$_GET['rows.fields']); + + } + + public function create_temporary_rows() { + // For static rows + if(empty($this->rows)) return null; + if(!empty($this->rows) and empty($this->type)) $this->type = 'rows'; + + $fields = array_keys($this->rows[0]); + $sql_names = $this->sql_names($fields); + + $this->db()->conn->query("CREATE ".$this->sql_temporary()." TABLE $this->name (" + .join(',',$this->ar_map('"$a text"',$sql_names)) + .')'); + $sql = 'INSERT INTO '. $this->sql_name("$this->name") + . ' (' . join(',',array_values($sql_names)).')' + .' VALUES (' . join(',',$this->ar_map('":$a"',$fields)) . ')' + ; + + #debug($sql); + if (!($query = $this->db()->conn->prepare($sql))) { + $this->err_sql($sql); + return false; + } + + $this->fields = []; + foreach ($fields as $name) { + $this->fields[$name] = new Field([ + 'name' => $name, + 'table' => $this, + ]); + } + $this->_fields = 1; + + foreach ($this->rows as $row) { + + foreach ($row as $k=>$v) { + $field = $this->field($k); + $field->bindParam($query,$v,":$k"); + } + + if (!($execute = $query->execute())) { + $this->err_sql($sql); + return false; + } + + } + + return true; + } + + private function sql_temporary() { + if ($this->db()->type == 'sqlite') return 'TEMP'; + return 'TEMPORARY'; + } + + /* + * Function create_temporary + * + * Create temporary if needed + * + */ + public function create_temporary() { + if (!empty($this->_create_temporary)) return; + $this->_create_temporary = true; + + $this->create_temporary_rows(); + + // Name, could be a select + if (DB_TABLE_QUERY_NAME and stripos($this->name,'SELECT ')===0) { + $this->db()->conn->query("CREATE ".$this->sql_temporary()." TABLE ".DB_TABLE_QUERY_NAME." AS $this->name"); + $this->name = DB_TABLE_QUERY_NAME; + + // Virtual Table + } elseif (DB_TABLE_QUERY_NAME and !empty($this->sql)) { # NB 29.12.16 table already exists !!! if ($this->name) $this->name = DB_TABLE_QUERY_NAME; - $this->db()->conn->query("CREATE ".$this->sql_temporary()." TABLE $this->name AS $this->sql"); - - } elseif (preg_match('/\b(\.import|LOAD DATA|COPY|INSERT|REPLACE|DELETE|TRUNCATE|CREATE|DROP|ALERT)\b/',$this->name)) { - bye("Query not Allowed !"); - - } else { - return false; - - } - - return true; - } - - /* - * Function db - * - * return the db object or init it - * - */ - public function db($set=null) { - static $db = null; - #if ($set !== null) debug($set->name); - if ($set !== null) $db = $set; - return $db; - } - - /* - * Function create - * - * return the sql to create the table build internaly - * - */ - public function create($from_engine=true,$db_type='') { - - // String replace function - $sql_replace_fct = $this->db()->conf_type('table.sql.create'); - $db_sql_replace_fct = empty($this->db()->sql_replace) ? '' : $this->db()->sql_replace; - $sql_replace = function($sql) use ($sql_replace_fct,$db_sql_replace_fct) { - if ($db_sql_replace_fct) $sql = $db_sql_replace_fct($sql); - return $sql_replace_fct ? $sql_replace_fct($sql,$this) : $sql; - }; - - if ($from_engine) return $sql_replace($this->sql()); - - if ($this->type() == 'view') { - return $sql_replace('CREATE VIEW '.$this->sql_name().' AS '.preg_replace('/^CREATE\s+.*?\s+AS\s+.*?SELECT/i','SELECT',$this->sql())); - } - - $indexes = []; - foreach ($this->indexes() as $i) { - if (!empty($i['unique']) or !empty($i['key'])) continue; - $indexes[] = 'CREATE INDEX '.$i['name'].' ON '.$this->sql_name().' ('.$i['field'].')'; - } - - # Get all fields - $fields = []; - foreach ($this->fields() as $f) { - if (!empty($f->extras)) continue; - $fields[] = $f; - } - - $type = $this->db()->type; - if (!empty($db_type)) $this->db()->type = $db_type; - - // Specific function for fields if return something use it instead of default - $_create_fct = $this->db()->conf_type('field.create',false); - $_create = function(&$field) use ($_create_fct) { - if ($_create_fct and ($sql=$_create_fct($field))) return $sql; - - // Default - return $field->sql_name().' '.$field->type - .($field->null ? '' : ' NOT NULL') - .($field->default !== null ? ' DEFAULT '.$field->quote($field->default,true) : '') - .($field->key ? ' PRIMARY KEY' : '') - .($field->uniq ? ' UNIQUE' : '') - ; - }; - - $sql = 'CREATE '.strtoupper($this->type()).' '.$this->sql_name() - .' (' - .join(",",array_map(function($f) use ($_create) {return $_create($f);},$fields)) - # done at the end for primary keys .')' - ; - - // Handle multiple primary keys syntaxe - if (substr_count(strtoupper($sql),'PRIMARY KEY')>1) { - $sql = str_ireplace(' PRIMARY KEY','',$sql) - .', PRIMARY KEY ('.join(',',array_map(function($f){return $f->sql_name();},$this->fields_keys())).')' - ; - } - - $this->db()->type = $type; - return $sql_replace($sql.')'.($indexes ? ';'.join(';',$indexes) : '')); - } - - /* - * Function indexes - * - * return indexes - * - */ - public function indexes() { - if (!isset($this->indexes)) { - $sql = $this->db()->conf_type('table.sql.index'); - $fct = ''; - - if (is_array($sql)) list($sql,$fct) = (count($sql)==1 ? [$sql[0],null] : $sql); - if (!$sql) return []; - - $sql = str_replace('',$this->name,$sql); - $sql = str_replace('',$this->db()->name,$sql); - $st = $this->db()->conn->prepare($sql); - $st->execute(); - $this->indexes = []; - while ($row = $st->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT)) { - - if (!$fct) $this->indexes[] = $row; - elseif ($r = $fct($row)) $this->indexes[] = $r; - - } - } - return $this->indexes; - } - - /* - * Function sql - * - * return the sql used create the table - * - */ - public function sql() { - if (isset($this->sql)) return $this->sql; - - if (!preg_match('/^[\w_-]+$/',$this->name) ) { - $this->sql = $this->name; - return $this->sql; - } - - #$sql = str_replace('',$this->name,$this->db()->conf_type('table.sql',true)); - $sql = $this->unvar($this->db()->conf_type('table.sql',true)); - - # Noise before CREATE like MySql - $this->sql = explode('\0',$this->db()->row($sql,'\0')); - if (count($this->sql) > 1) { - $this->sql = $this->sql[1]; - } else { - $this->sql = $this->sql[0]; - } - - # Remove comments - $this->sql = join(' ',preg_grep('/^ *--/',explode("\n",$this->sql),true)); - - # Delete new line and trim for line output - $this->sql = trim(preg_replace('/\s\s+/',' ',$this->sql)); - - if (self::p('ansi')) { - $this->sql = preg_replace("/\s*COLLATE NOCASE/i",'',$this->sql); - } - - #bye($this->sql); - return $this->sql; - } - - public function field($name) { return $this->fields($name); } -# NB 14.12.17 public function field_del($name) { unset($this->fields[$name]); } + $this->db()->conn->query("CREATE ".$this->sql_temporary()." TABLE $this->name AS $this->sql"); + + } elseif (preg_match('/\b(\.import|LOAD DATA|COPY|INSERT|REPLACE|DELETE|TRUNCATE|CREATE|DROP|ALERT)\b/',$this->name)) { + bye("Query not Allowed !"); + + } else { + return false; + + } + + return true; + } + + /* + * Function db + * + * return the db object or init it + * + */ + public function db($set=null) { + static $db = null; + #if ($set !== null) debug($set->name); + if ($set !== null) $db = $set; + return $db; + } + + /* + * Function create + * + * return the sql to create the table build internaly + * + */ + public function create($from_engine=true,$db_type='') { + + // String replace function + $sql_replace_fct = $this->db()->conf_type('table.sql.create'); + $db_sql_replace_fct = empty($this->db()->sql_replace) ? '' : $this->db()->sql_replace; + $sql_replace = function($sql) use ($sql_replace_fct,$db_sql_replace_fct) { + if ($db_sql_replace_fct) $sql = $db_sql_replace_fct($sql); + return $sql_replace_fct ? $sql_replace_fct($sql,$this) : $sql; + }; + + if ($from_engine) return $sql_replace($this->sql()); + + if ($this->type() == 'view') { + return $sql_replace('CREATE VIEW '.$this->sql_name().' AS '.preg_replace('/^CREATE\s+.*?\s+AS\s+.*?SELECT/i','SELECT',$this->sql())); + } + + $indexes = []; + foreach ($this->indexes() as $i) { + if (!empty($i['unique']) or !empty($i['key'])) continue; + $indexes[] = 'CREATE INDEX '.$i['name'].' ON '.$this->sql_name().' ('.$i['field'].')'; + } + + # Get all fields + $fields = []; + foreach ($this->fields() as $f) { + if (!empty($f->extras)) continue; + $fields[] = $f; + } + + $type = $this->db()->type; + if (!empty($db_type)) $this->db()->type = $db_type; + + // Specific function for fields if return something use it instead of default + $_create_fct = $this->db()->conf_type('field.create',false); + $_create = function(&$field) use ($_create_fct) { + if ($_create_fct and ($sql=$_create_fct($field))) return $sql; + + // Default + return $field->sql_name().' '.$field->type + .($field->null ? '' : ' NOT NULL') + .($field->default !== null ? ' DEFAULT '.$field->quote($field->default,true) : '') + .($field->key ? ' PRIMARY KEY' : '') + .($field->uniq ? ' UNIQUE' : '') + ; + }; + + $sql = 'CREATE '.strtoupper($this->type()).' '.$this->sql_name() + .' (' + .join(",",array_map(function($f) use ($_create) {return $_create($f);},$fields)) + # done at the end for primary keys .')' + ; + + // Handle multiple primary keys syntaxe + if (substr_count(strtoupper($sql),'PRIMARY KEY')>1) { + $sql = str_ireplace(' PRIMARY KEY','',$sql) + .', PRIMARY KEY ('.join(',',array_map(function($f){return $f->sql_name();},$this->fields_keys())).')' + ; + } + + $this->db()->type = $type; + return $sql_replace($sql.')'.($indexes ? ';'.join(';',$indexes) : '')); + } + + /* + * Function indexes + * + * return indexes + * + */ + public function indexes() { + if (!isset($this->indexes)) { + $sql = $this->db()->conf_type('table.sql.index'); + $fct = ''; + + if (is_array($sql)) list($sql,$fct) = (count($sql)==1 ? [$sql[0],null] : $sql); + if (!$sql) return []; + + $sql = str_replace('',$this->name,$sql); + $sql = str_replace('',$this->db()->name,$sql); + $st = $this->db()->conn->prepare($sql); + $st->execute(); + $this->indexes = []; + while ($row = $st->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT)) { + + if (!$fct) $this->indexes[] = $row; + elseif ($r = $fct($row)) $this->indexes[] = $r; - /* - * Function db.fields - * - * return all or one fields from a table - * - * @name (string) name of the field to return. Default: null - * @return (array) return null where name does not exsts - */ - public function fields($name=null) { + } + } + return $this->indexes; + } - $this->create_temporary(); + /* + * Function sql + * + * return the sql used create the table + * + */ + public function sql() { + if (isset($this->sql)) return $this->sql; + + if (!preg_match('/^[\w_-]+$/',$this->name) ) { + $this->sql = $this->name; + return $this->sql; + } - if (!isset($this->_fields)) { - $this->_fields = true; + #$sql = str_replace('',$this->name,$this->db()->conf_type('table.sql',true)); + $sql = $this->unvar($this->db()->conf_type('table.sql',true)); - # Extras fields at the end - $save_fields = $this->fields; - $this->fields = []; + # Noise before CREATE like MySql + $this->sql = explode('\0',$this->db()->row($sql,'\0')); + if (count($this->sql) > 1) { + $this->sql = $this->sql[1]; + } else { + $this->sql = $this->sql[0]; + } + + # Remove comments + $this->sql = join(' ',preg_grep('/^ *--/',explode("\n",$this->sql),true)); + + # Delete new line and trim for line output + $this->sql = trim(preg_replace('/\s\s+/',' ',$this->sql)); + + if (self::p('ansi')) { + $this->sql = preg_replace("/\s*COLLATE NOCASE/i",'',$this->sql); + } + + #bye($this->sql); + return $this->sql; + } - $conf = $this->unvar($this->db()->conf_type('table.fields',true)); - if (is_scalar($conf)) $conf = ['sql'=>$conf]; - # NB 25.09.17: dirty fixed for sqlite4 attache db - $conf['sql'] = preg_replace("/^PRAGMA table_info\('([^'\.]+)\./","PRAGMA ".'$1'.".table_info('",$conf['sql']); - $rows = $this->db()->conn->query($conf['sql']); + public function field($name) { return $this->fields($name); } +# NB 14.12.17 public function field_del($name) { unset($this->fields[$name]); } - if (!is_object($rows)) { - $this->bye("Can't get fields from table $this->name "); - } + /* + * Function db.fields + * + * return all or one fields from a table + * + * @name (string) name of the field to return. Default: null + * @return (array) return null where name does not exsts + */ + public function fields($name=null) { + + $this->create_temporary(); + + if (!isset($this->_fields)) { + $this->_fields = true; + + # Extras fields at the end + $save_fields = $this->fields; + $this->fields = []; + + $conf = $this->unvar($this->db()->conf_type('table.fields',true)); + if (is_scalar($conf)) $conf = ['sql'=>$conf]; + # NB 25.09.17: dirty fixed for sqlite4 attache db + $conf['sql'] = preg_replace("/^PRAGMA table_info\('([^'\.]+)\./","PRAGMA ".'$1'.".table_info('",$conf['sql']); + $rows = $this->db()->conn->query($conf['sql']); + + if (!is_object($rows)) { + $this->bye("Can't get fields from table $this->name "); + } - $rows->setFetchMode(PDO::FETCH_ASSOC); + $rows->setFetchMode(PDO::FETCH_ASSOC); - // Get other indexes - $indexes = []; - foreach ($this->indexes() as $i) { - if (empty($i['unique']) and empty($i['key'])) $indexes[$i['field']] = 1; - } + // Get other indexes + $indexes = []; + foreach ($this->indexes() as $i) { + if (empty($i['unique']) and empty($i['key'])) $indexes[$i['field']] = 1; + } - $count = 0; - foreach ($rows as $row) { + $count = 0; + foreach ($rows as $row) { - $count++; - $row = array_change_key_case($row,CASE_LOWER); + $count++; + $row = array_change_key_case($row,CASE_LOWER); - // From config - $row['this'] = $this; # for use - if (isset($conf['map'])) { + // From config + $row['this'] = $this; # for use + if (isset($conf['map'])) { - foreach ($conf['map'] as $from => $to) { - if (!isset($row[$from])) continue; + foreach ($conf['map'] as $from => $to) { + if (!isset($row[$from])) continue; - $row[$to] = $row[$from]; - unset ($row[$from]); - } + $row[$to] = $row[$from]; + unset ($row[$from]); + } - } + } - if (isset($conf['fct'])) $conf['fct']($row); + if (isset($conf['fct'])) $conf['fct']($row); - $field = [ - 'table' => $this, - 'name' => $row['name'], - 'type' => strtolower($row['type']), - 'key' => (preg_match('/^(f.*|no|0)?\s*$/i',$row['key']) ? 0 : 1), - 'index' => (empty($indexes[$row['name']]) ? 0 : $indexes[$row['name']]), - 'null' => (preg_match('/^(f.*|no|0)?\s*$/i',$row['null']) ? 0 : 1), - 'extra' => (isset($row['extra']) ? $row['extra'] : null), # !!! nothing todo with array $extra, this info from the sql server - 'autoincrement' => (isset($row['autoincrement']) ? $row['autoincrement'] : 0), - ]; + $field = [ + 'table' => $this, + 'name' => $row['name'], + 'type' => strtolower($row['type']), + 'key' => (preg_match('/^(f.*|no|0)?\s*$/i',$row['key']) ? 0 : 1), + 'index' => (empty($indexes[$row['name']]) ? 0 : $indexes[$row['name']]), + 'null' => (preg_match('/^(f.*|no|0)?\s*$/i',$row['null']) ? 0 : 1), + 'extra' => (isset($row['extra']) ? $row['extra'] : null), # !!! nothing todo with array $extra, this info from the sql server + 'autoincrement' => (isset($row['autoincrement']) ? $row['autoincrement'] : 0), + ]; - if (isset($row['uniq'])) $field['uniq'] = $row['uniq']; - if (isset($row['default'])) $field['default'] = $row['default']; + if (isset($row['uniq'])) $field['uniq'] = $row['uniq']; + if (isset($row['default'])) $field['default'] = $row['default']; - $this->fields[$field['name']] = new Field($field); - $this->fields[$field['name']]->size = $this->fields[$field['name']]->size(); + $this->fields[$field['name']] = new Field($field); + $this->fields[$field['name']]->size = $this->fields[$field['name']]->size(); - } + } - # Extras fields at the end - $this->fields = array_merge($this->fields,$save_fields); - #if (empty($this->fields)) bye("Table `".$this->name."` does not exists"); + # Extras fields at the end + $this->fields = array_merge($this->fields,$save_fields); + #if (empty($this->fields)) bye("Table `".$this->name."` does not exists"); - } # < $this->fields + } # < $this->fields #bye($this->fields); - if ($name !== null ) { - if (!isset($this->fields[$name])) return null; - return $this->fields[$name]; - } - - return $this->fields; - } - - public function url_keys($values=null,$params=[],$preff='?',$sep='&') { - if ($values === null) $values = $this->p(); - $url = is_array($params) ? $params : [$params]; - - $keys = $this->fields_keys($others); - if (empty($keys)) $keys = $others; - - foreach ($keys as $name => $field) { - if (isset($values[$name])) - $url[] = $this->field_preff.$name . '=' .urlencode($values[$name]) - ; - } - - foreach (self::$params as $p) if ($v=self::p($p)) $url[] = $p.'='.urlencode($v); - return $url ? $preff.join($sep,$url) : ''; - } - - public function fields_keys_values($values) { - $keys = $this->fields_keys(); - if (empty($keys)) $keys = $this->fields(); - - $ret = []; - foreach ($keys as $name => $field) { - if (isset($values[$name])) - $ret[] = $values[$name]; - ; - } - return $ret; - } - - public function fields_keys(&$others=[]) { - - $fields_keys = []; - - foreach ($this->fields() as $name => $f) { - if ($f->key) { - $fields_keys[$name] = $f; - } else { - $others[$name] = $f; - } - } - - return $fields_keys; - - } - - public static function params2hash($keys) { - $params = []; - foreach ($keys as $k) { - $params[$k] = self::p($k); - if (!isset($params[$k]) or (string)$params[$k] === '') unset($params[$k]); - } - return $params; - } - - public static function form_hidden($ignore=[],$params=null) { - $h = ''; - if (!isset($params)) { - $params = self::params2hash(self::$params); - } + if ($name !== null ) { + if (!isset($this->fields[$name])) return null; + return $this->fields[$name]; + } + + return $this->fields; + } + + public function url_keys($values=null,$params=[],$preff='?',$sep='&') { + if ($values === null) $values = $this->p(); + $url = is_array($params) ? $params : [$params]; + + $keys = $this->fields_keys($others); + if (empty($keys)) $keys = $others; + + foreach ($keys as $name => $field) { + if (isset($values[$name])) + $url[] = $this->field_preff.$name . '=' .urlencode($values[$name]) + ; + } + + foreach (self::$params as $p) if ($v=self::p($p)) $url[] = $p.'='.urlencode($v); + return $url ? $preff.join($sep,$url) : ''; + } + + public function fields_keys_values($values) { + $keys = $this->fields_keys(); + if (empty($keys)) $keys = $this->fields(); + + $ret = []; + foreach ($keys as $name => $field) { + if (isset($values[$name])) + $ret[] = $values[$name]; + ; + } + return $ret; + } + + public function fields_keys(&$others=[]) { + + $fields_keys = []; + + foreach ($this->fields() as $name => $f) { + if ($f->key) { + $fields_keys[$name] = $f; + } else { + $others[$name] = $f; + } + } + + return $fields_keys; + + } + + public static function params2hash($keys) { + $params = []; + foreach ($keys as $k) { + $params[$k] = self::p($k); + if (!isset($params[$k]) or (string)$params[$k] === '') unset($params[$k]); + } + return $params; + } + + public static function form_hidden($ignore=[],$params=null) { + $h = ''; + if (!isset($params)) { + $params = self::params2hash(self::$params); + } #debug([$params,array_diff($params,$ignore)]); # NB 07.01.18 foreach (array_diff($params,$ignore) as $k=>$v) { - foreach ($params as $k=>$v) { + foreach ($params as $k=>$v) { if (!empty($ignore) and in_array($k,$ignore)) continue; - if (isset($v) or $k=='action') { - if (self::p('debug')) $h .= ""; - $h .= ''.NB_EOL; - } - } - - return $h; - } - - public function html_add($values = null,$form_action='?') { - return html_edit($values,$form_action,true); - } - - public function sql_edit($values = null,&$add=false) { - $where = $this->where($this->fields(),$values); - if (empty($where)) { - $where = ' WHERE 1=0'; - $add = true; - } else { - $where .= " LIMIT 1"; - } - - $sql = "SELECT *" . $this->select_extras(); - $sql .= " FROM ".$this->sql_name().$where; - if ($this->type == 'sql' and !empty($this->sql)) $sql = $this->sql.$where; - $this->debug(preg_replace('/(,|FROM|WHERE|HAVING|GROUP|ORDER)/i',"\n\\1",$sql),1); - - return $sql; - } - - public function html_edit($values = null,$form_action='?',$add=false) { - if ($values === null) $values = $this->p(); - if (!is_array($values)) $values = [$values]; + if (isset($v) or $k=='action') { + if (self::p('debug')) $h .= ""; + $h .= ''.NB_EOL; + } + } + + return $h; + } + + public function html_add($values = null,$form_action='?') { + return html_edit($values,$form_action,true); + } + + public function sql_edit($values = null,&$add=false) { + $where = $this->where($this->fields(),$values); + if (empty($where)) { + $where = ' WHERE 1=0'; + $add = true; + } else { + $where .= " LIMIT 1"; + } + + $sql = "SELECT *" . $this->select_extras(); + $sql .= " FROM ".$this->sql_name().$where; + if ($this->type == 'sql' and !empty($this->sql)) $sql = $this->sql.$where; + $this->debug(preg_replace('/(,|FROM|WHERE|HAVING|GROUP|ORDER)/i',"\n\\1",$sql),1); + + return $sql; + } + + public function html_edit($values = null,$form_action='?',$add=false) { + if ($values === null) $values = $this->p(); + if (!is_array($values)) $values = [$values]; # NB 23.11.17 $fields = $this->fields(); # NB 23.11.17 $keys = $this->fields_keys(); - $sql = $this->sql_edit($values,$add); - - $st = $this->db()->conn->prepare($sql); - $st->execute(); - - // Params - $form_hidden = ''; - $url_params = [ - 'referer' => (!empty($_SERVER['HTTP_REFERER']) ? urlencode($_SERVER['HTTP_REFERER']) : ''), - ]; - if ($this->show_hidden_params and !empty(self::$params)) { - $ignore = ['limit']; - - $form_hidden = '' - .self::form_hidden($ignore,array_merge($this->params2hash(self::$params),[ - 'action' => ($add ? 'insert' : 'update'), - 'referer' => (!empty($_SERVER['HTTP_REFERER']) ? urlencode($_SERVER['HTTP_REFERER']) : ''), - ])) - ; - - foreach (array_diff(self::$params,$ignore) as $p) { - if (!($v = self::p($p))) continue; - $url_params[$p] = $v; - } - - $url_params['action'] = ($add ? 'insert' : 'update'); - - } else { - $form_hidden = (!empty($_SERVER['HTTP_REFERER']) ? '' : ''); - - } - - #debug($form_hidden); - if ($url_params) { - $flat = []; - foreach ($url_params as $k=>$v) { - if ((string)$v === '') continue; - $flat[] = $k . '=' . urlencode($v); - } - if (NB_P_GET) { - $form_action .= ( strpos('?',$form_action) === false ? '?' : '' ) . join('&',$flat); - $form_hidden = ''; - } - } - - // Form - echo '
'.NB_EOL; - echo '
'.NB_EOL; - $count = 0; - if ( $add or ($row = $st->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT))) { - - if (!empty($row)) $this->db()->table_row_decrypt($this,$row); - $count ++; - - foreach ($this->fields() as $name => $field) { + $sql = $this->sql_edit($values,$add); + + $st = $this->db()->conn->prepare($sql); + $st->execute(); + + // Params + $form_hidden = ''; + $url_params = [ + 'referer' => (!empty($_SERVER['HTTP_REFERER']) ? urlencode($_SERVER['HTTP_REFERER']) : ''), + ]; + if ($this->show_hidden_params and !empty(self::$params)) { + $ignore = ['limit']; + + $form_hidden = '' + .self::form_hidden($ignore,array_merge($this->params2hash(self::$params),[ + 'action' => ($add ? 'insert' : 'update'), + 'referer' => (!empty($_SERVER['HTTP_REFERER']) ? urlencode($_SERVER['HTTP_REFERER']) : ''), + ])) + ; + + foreach (array_diff(self::$params,$ignore) as $p) { + if (!($v = self::p($p))) continue; + $url_params[$p] = $v; + } + + $url_params['action'] = ($add ? 'insert' : 'update'); + + } else { + $form_hidden = (!empty($_SERVER['HTTP_REFERER']) ? '' : ''); + + } + + #debug($form_hidden); + if ($url_params) { + $flat = []; + foreach ($url_params as $k=>$v) { + if ((string)$v === '') continue; + $flat[] = $k . '=' . urlencode($v); + } + if (NB_P_GET) { + $form_action .= ( strpos('?',$form_action) === false ? '?' : '' ) . join('&',$flat); + $form_hidden = ''; + } + } + + // Form + echo ''.NB_EOL; + echo '
'.NB_EOL; + $count = 0; + if ( $add or ($row = $st->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT))) { + + if (!empty($row)) $this->db()->table_row_decrypt($this,$row); + $count ++; + + foreach ($this->fields() as $name => $field) { # NB 08.01.18 if ($add and !preg_match('/^(null|.*\(.*)?$/',strtolower($field->default))) { # NB 08.01.18 $row[$name] = $field->default; if ($add) { - $row[$name] = $field->default2str($field->default); + $row[$name] = $field->default2str($field->default); - } elseif(!isset($row[$name])) { - $row[$name] = ''; + } elseif(!isset($row[$name])) { + $row[$name] = ''; - } + } - if (!$add and $field->key) { - echo ''.NB_EOL; - } - echo $field->html_edit($row[$name]); - } + if (!$add and $field->key) { + echo ''.NB_EOL; + } + echo $field->html_edit($row[$name]); + } - } - echo '
'.NB_EOL; # < fields + } + echo '
'.NB_EOL; # < fields - echo '' - .'
' - .( empty($_SERVER['HTTP_REFERER']) ? '' : '') - .'' - .'' - .'
'.NB_EOL - ; + echo '' + .'
' + .( empty($_SERVER['HTTP_REFERER']) ? '' : '') + .'' + .'' + .'
'.NB_EOL + ; - echo $form_hidden.'
'.NB_EOL; + echo $form_hidden.''.NB_EOL; - } + } - public function url_list($k='',$v='') { + public function url_list($k='',$v='') { - $params = []; - $fields = ($this->p('action') == 'delete') ? [] : $this->fields(); + $params = []; + $fields = ($this->p('action') == 'delete') ? [] : $this->fields(); - foreach ( array_diff( array_merge(self::$params,array_keys($fields)), ['action'] ) as $f) { + foreach ( array_diff( array_merge(self::$params,array_keys($fields)), ['action'] ) as $f) { - if (strcmp($this->p($f,''),'')==0) continue; - $params[$f] = $this->p($f); + if (strcmp($this->p($f,''),'')==0) continue; + $params[$f] = $this->p($f); - } + } - if ($k) { + if ($k) { - if (strcmp($v,'')==0) { - unset($params[$k]); - } else { - $params[$k] = $v; - } + if (strcmp($v,'')==0) { + unset($params[$k]); + } else { + $params[$k] = $v; + } - } + } - $flat = []; - foreach ($params as $k=>$v) { $flat[] = $k.'='.urlencode($v); } - return $flat ? '?'. join('&',$flat) : ''; + $flat = []; + foreach ($params as $k=>$v) { $flat[] = $k.'='.urlencode($v); } + return $flat ? '?'. join('&',$flat) : ''; - } + } - public function url_sort($name) { + public function url_sort($name) { - if (!$this->show_url_sort or !($f=$this->field($name)) or !empty($f->dyn) or $f->is_encrypt()) return self::prettyText($name); - #debug($f); + if (!$this->show_url_sort or !($f=$this->field($name)) or !empty($f->dyn) or $f->is_encrypt()) return self::prettyText($name); + #debug($f); - # See: http://dev.w3.org/html5/html-author/charref - $html = ''; + # See: http://dev.w3.org/html5/html-author/charref + $html = ''; $title = $this->prettyText($name).': '; - # Asc - $sel = ( $this->p('orderby')=="$name asc") ? " sel" : ""; - $html .= '' - .'' - .''; - #$html .= ' '; + # Asc + $sel = ( $this->p('orderby')=="$name asc") ? " sel" : ""; + $html .= '' + .'' + .''; + #$html .= ' '; - $html .= ''.$this->prettyText($name).''; + $html .= ''.$this->prettyText($name).''; - #$html .= ' '; + #$html .= ' '; - # Desc - $sel = ( $this->p('orderby')=="$name desc") ? " sel" : ""; - $html .= '' - .'' - .''; + # Desc + $sel = ( $this->p('orderby')=="$name desc") ? " sel" : ""; + $html .= '' + .'' + .''; - return $html; + return $html; - } + } - public function nav($count,$tot,$limit) { + public function nav($count,$tot,$limit) { - $html = ''; + $html = ''; - if ($count<$tot) { - list($x,$y) = strpos($limit,',')!==false - ? preg_split('/\s*,\s*/',$limit) - : [0,$limit] - ; + if ($count<$tot) { + list($x,$y) = strpos($limit,',')!==false + ? preg_split('/\s*,\s*/',$limit) + : [0,$limit] + ; - $prev = $x - $y; - $next = $x + $y; + $prev = $x - $y; + $next = $x + $y; - $this->debug("x=$x limit=$y prev=$prev next=$next tot=$tot",1); + $this->debug("x=$x limit=$y prev=$prev next=$next tot=$tot",1); - } else { - $x = 0; - $y = $tot; - $prev = -1; - $next = 999999; - } + } else { + $x = 0; + $y = $tot; + $prev = -1; + $next = 999999; + } - if ($prev>=0) $html .= '<< '; + if ($prev>=0) $html .= '<< '; - $html .= ''.($tot ? ($x+1) : 0).' - '.( $count<($x+$y) ? $count : ($x+$y) ).' / '.$tot.' results'; + $html .= ''.($tot ? ($x+1) : 0).' - '.( $count<($x+$y) ? $count : ($x+$y) ).' / '.$tot.' results'; - if ($next<$tot) $html .= ' >>'; + if ($next<$tot) $html .= ' >>'; - return $html; + return $html; - } + } - public function where($fields,$hvalues,$need_all_values=false) { + public function where($fields,$hvalues,$need_all_values=false) { - // Construct where - $where = []; - foreach ($fields as $k => $field) { - if (!isset($hvalues[$k])) { - if ($need_all_values) return null; - continue; - } - $where[] = $field->sql_name() . '=' . $field->quote($hvalues[$k]); - } + // Construct where + $where = []; + foreach ($fields as $k => $field) { + if (!isset($hvalues[$k])) { + if ($need_all_values) return null; + continue; + } + $where[] = $field->sql_name() . '=' . $field->quote($hvalues[$k]); + } - return empty($where) ? '' : ' WHERE ' . join(' AND ',$where); + return empty($where) ? '' : ' WHERE ' . join(' AND ',$where); - } + } - public function where_criterias($values,$logic='') { - $having = $where = []; - if (empty($logic)) $logic = 'AND'; + public function where_criterias($values,$logic='') { + $having = $where = []; + if (empty($logic)) $logic = 'AND'; - $regexp = $this->db()->conf_type('regexp'); - if (empty($regexp)) $regexp = 'REGEXP'; + $regexp = $this->db()->conf_type('regexp'); + if (empty($regexp)) $regexp = 'REGEXP'; - foreach ($this->fields() as $k => $field) { + foreach ($this->fields() as $k => $field) { - // No empty values - $v = isset($values[$k]) ? $values[$k] : null; - if (strcmp($v,'')==0 or $v=='!' or $v=='~') continue; + // No empty values + $v = isset($values[$k]) ? $values[$k] : null; + if (strcmp($v,'')==0 or $v=='!' or $v=='~') continue; - // Equal / Not Equal - $equal = '='; - $not = strpos($v,'!')===0 ? 1 : 0; - if ($not) $v = substr($v,1); + // Equal / Not Equal + $equal = '='; + $not = strpos($v,'!')===0 ? 1 : 0; + if ($not) $v = substr($v,1); - // Superior / Inferior - if (preg_match('/^(<|>|<=|>=)/',$v,$m)) { - $v = substr($v,strlen($m[1])); - $equal = $m[1]; - } + // Superior / Inferior + if (preg_match('/^(<|>|<=|>=)/',$v,$m)) { + $v = substr($v,strlen($m[1])); + $equal = $m[1]; + } $match = ''; - // Regex - if (strpos($v,'~')===0) { + // Regex + if (strpos($v,'~')===0) { $match = 'regexp'; - $v = substr($v,1); - $v = $this->db()->quote($v); - $equal = ' '.($not ? 'NOT ' : '').$regexp.' '; + $v = substr($v,1); + $v = $this->db()->quote($v); + $equal = ' '.($not ? 'NOT ' : '').$regexp.' '; - } elseif ($field->string()) { + } elseif ($field->string()) { - if (strtolower($v)=='null') $v = ''; + if (strtolower($v)=='null') $v = ''; - // * -> % - $v = str_replace('*','%',$v); + // * -> % + $v = str_replace('*','%',$v); - $v = $this->db()->quote($v); - if (preg_match('/[_%]/',$v)) { + $v = $this->db()->quote($v); + if (preg_match('/[_%]/',$v)) { $match = 'like'; # NB 07.01.18 $equal = ' '.($not ? 'NOT ' : '').'LIKE '; - $equal = ' '.($not ? 'NOT ' : '').$this->db()->like_nocase().' '; - } else { - $equal = ($not ? '<> ' : $equal); - } + $equal = ' '.($not ? 'NOT ' : '').$this->db()->like_nocase().' '; + } else { + $equal = ($not ? '<> ' : $equal); + } - // Others - } else { + // Others + } else { - // Integer - if ($field->numeric()) { - if (strtolower($v)=='null') $v = '0'; - #$k = "COLAESCE($k,0)"; + // Integer + if ($field->numeric()) { + if (strtolower($v)=='null') $v = '0'; + #$k = "COLAESCE($k,0)"; - // Date, Time according to field->string() behavior - } else { - $v = $this->db()->quote($v); + // Date, Time according to field->string() behavior + } else { + $v = $this->db()->quote($v); - } - $equal = $not ? '<>' : $equal; + } + $equal = $not ? '<>' : $equal; - } + } $name = $field->sql_name(true); # NB 12.01.18 if (!$field->text()) $name = $field->sql_name_cast_text(); - if ($field->extras) { - $k = $this->extras[$k]->sql_name(); + if ($field->extras) { + $k = $this->extras[$k]->sql_name(); # NB 04.01.18 } elseif ($field->numeric() and $field->null) { } elseif ($match) { - if ($field->null) $k = 'COALESCE('.$name.','.$this->db()->quote('').")"; + if ($field->null) $k = 'COALESCE('.$name.','.$this->db()->quote('').")"; - } elseif ($field->numeric()) { + } elseif ($field->numeric()) { $name = $field->sql_name(); - if ($field->null) $k = 'COALESCE('.$name.",0)"; + if ($field->null) $k = 'COALESCE('.$name.",0)"; - } elseif (!$field->numeric() and $field->null) { - $k = 'COALESCE('.$name.",'')"; + } elseif (!$field->numeric() and $field->null) { + $k = 'COALESCE('.$name.",'')"; - } else { - $k = $name; + } else { + $k = $name; - } + } - # having, denorm, EMPTY - if ($field->extras) { - $extra_where = (string)$this->db()->conf_type('extra_where'); - #if ($_SERVER['REMOTE_USER'] == 'nico') debug($sql); - $k = $field->extras; + # having, denorm, EMPTY + if ($field->extras) { + $extra_where = (string)$this->db()->conf_type('extra_where'); + #if ($_SERVER['REMOTE_USER'] == 'nico') debug($sql); + $k = $field->extras; - if ($extra_where == 'having') { - $having[] = "$k$equal$v"; - } else { - $where[] = "$k$equal$v"; - } + if ($extra_where == 'having') { + $having[] = "$k$equal$v"; + } else { + $where[] = "$k$equal$v"; + } - } else { - $where[] = "$k$equal$v"; + } else { + $where[] = "$k$equal$v"; - } + } - } #< foreach + } #< foreach - $sql = ''; - if ($where) $sql .= ' WHERE '.join(" $logic ",$where); - if ($having) $sql .= ' HAVING '.join(" $logic ",$having); - return $sql; + $sql = ''; + if ($where) $sql .= ' WHERE '.join(" $logic ",$where); + if ($having) $sql .= ' HAVING '.join(" $logic ",$having); + return $sql; - } + } - public function add_extras($extras) { - if ($this->p('extras') === '0') return false; + public function add_extras($extras) { + if ($this->p('extras') === '0') return false; - foreach ($extras as $k => $v) { + foreach ($extras as $k => $v) { - if ($v === false or $v === null) { - if (isset($this->fields[$k])) unset($this->fields[$k]); - #if (isset($this->extras[$k])) unset($this->extras[$k]); - $this->_rows_fields = true; - continue; - } + if ($v === false or $v === null) { + if (isset($this->fields[$k])) unset($this->fields[$k]); + #if (isset($this->extras[$k])) unset($this->extras[$k]); + $this->_rows_fields = true; + continue; + } - $v = new Field( ( is_array($v) ? $v : [] ) + [ - 'name' => $k, - 'type' => 'text', - 'extras' => $v, - 'table' => $this, - ]); + $v = new Field( ( is_array($v) ? $v : [] ) + [ + 'name' => $k, + 'type' => 'text', + 'extras' => $v, + 'table' => $this, + ]); - $this->fields[$k] = $v; - $this->extras[$k] = $v; + $this->fields[$k] = $v; + $this->extras[$k] = $v; - } + } - } + } - public function select_extras() { + public function select_extras() { - if (empty($this->extras)) return ''; + if (empty($this->extras)) return ''; - $select = []; foreach ($this->extras as $name => $field) { - $select[] = $field->extras." AS ".$field->sql_name(); - } + $select = []; foreach ($this->extras as $name => $field) { + $select[] = $field->extras." AS ".$field->sql_name(); + } - if (!$select) return ''; - return ','.join(',',$select); - } + if (!$select) return ''; + return ','.join(',',$select); + } - public function rows_count() { + public function rows_count() { $opt = [ 'count' => 1 ]; - return $this->db()->row($this->rows_sql($opt)); + return $this->db()->row($this->rows_sql($opt)); } - public function rows_sql(&$opt=[]) { + public function rows_sql(&$opt=[]) { - if (isset($this->orderby)) self::pdef('orderby',$this->orderby); - if (self::p('order')) self::pset('orderby',self::p('orderby').' '.self::p('order')); # from Wordpress + if (isset($this->orderby)) self::pdef('orderby',$this->orderby); + if (self::p('order')) self::pset('orderby',self::p('orderby').' '.self::p('order')); # from Wordpress $count = empty($opt['count']) ? 0 : 1; - // - // Select - // - if (stripos($this->name,' ') !== false) { - $sql = $this->name; - $limit = $where = ''; + // + // Select + // + if (stripos($this->name,' ') !== false) { + $sql = $this->name; + $limit = $where = ''; if ($count) $sql = "SELECT count(*) FROM ".$this->sql_name(); - } else { + } else { - $where = $this->where_criterias($this->p(),$this->p('op')); - $select_count = ( $where ? $this->db()->conf_type('select_count') : null ); - if (empty($select_count)) $select_count = ['','']; + $where = $this->where_criterias($this->p(),$this->p('op')); + $select_count = ( $where ? $this->db()->conf_type('select_count') : null ); + if (empty($select_count)) $select_count = ['','']; - if (!empty($this->_rows_fields)) { - foreach ($this->fields() as $f) { - if (empty($f->extra)) $select_fields[] = $f->sql_name(); - } + if (!empty($this->_rows_fields)) { + foreach ($this->fields() as $f) { + if (empty($f->extra)) $select_fields[] = $f->sql_name(); + } - } else { - $select_fields = ['*']; + } else { + $select_fields = ['*']; - } + } - $sql = $count ? "SELECT count(*)" : "SELECT ".trim( $select_count[0].' '.join(',',$select_fields) ). $this->select_extras(); - $sql .= " FROM ".$this->sql_name(); - $sql .= $where; + $sql = $count ? "SELECT count(*)" : "SELECT ".trim( $select_count[0].' '.join(',',$select_fields) ). $this->select_extras(); + $sql .= " FROM ".$this->sql_name(); + $sql .= $where; - if ($this->p('orderby') and !$count) $sql .= ' ORDER BY '.$this->p('orderby'); + if ($this->p('orderby') and !$count) $sql .= ' ORDER BY '.$this->p('orderby'); - if ($limit = $this->db()->limit) { - $limit = str_replace(',',' OFFSET ',$limit); - $sql .= ' LIMIT '.$limit; - } else { - $limit = ''; - } + if ($limit = $this->db()->limit) { + $limit = str_replace(',',' OFFSET ',$limit); + $sql .= ' LIMIT '.$limit; + } else { + $limit = ''; + } - } + } if ($count) return $sql; - // - // Get results - // - $this->debug(preg_replace('/[\r\n]+[ ]*/',' ',$sql),1); + // + // Get results + // + $this->debug(preg_replace('/[\r\n]+[ ]*/',' ',$sql),1); # NB 03.09.16 $this->debug(preg_replace('/(,|FROM|WHERE|HAVING|GROUP|ORDER)/i',"\n\\1",$sql),1); - return [$sql,$where,$limit,$select_count]; - } - - public function buttons() { - if (!$this->show_buttons or empty(self::$params)) return false; - if (!preg_match('/(table|view)/',$this->type())) return false; - return true; - } - - private function rows_parsers(&$row,&$opt=[]) { - $parser = isset($opt['parser']) ? $opt['parser'] : true; - $call = null; - - // - // Decrypt - // - if ($parser) $this->db()->table_row_decrypt($this,$row); - - // - // Pre - // - if ($parser and !empty($this->db()->row_parse_pre)) { - $call = $this->db()->row_parse_pre; $call($row,$this,$opt); - } - - if ($parser and !empty($this->row_parse_pre)) { - $call = $this->row_parse_pre; $call($row,$this,$opt); - } - - # Passed param on rows() - if ($parser and !empty($opt['row_parse_pre'])) { - $call = $opt['row_parse_pre']; $call($row,$this,$opt); - } - - // - // Format - // - if ($opt['is_html'] and !$opt['use_out']) { - foreach ($row as $k=>$v) { - if (!isset($this->extras[$k])) $row[$k] = $this->db()->out->format($v); - } - - } - - // - // Post - // - if ($parser and !empty($this->row_parse_post)) { - $call = $this->row_parse_post; $call($row,$this,$opt); - } - - if ($parser and !empty($this->db()->row_parse_post)) { - $call = $this->db()->row_parse_post; $call($row,$this,$opt); - } - - # Passed param on rows() - if ($parser and !empty($opt['row_parse_post'])) { - $call = $opt['row_parse_post']; $call($row,$this,$opt); - } - - return $call; - } - - - public function fields_add_missing(&$fields,$row) { - $new = []; - foreach (array_keys($row) as $name) { - - #debug($name); - $new[$name] = isset($fields[$name]) - ? $fields[$name] - : new Field([ - 'name' => $name, - 'dyn' => true, - 'table' => $this, - 'preffix' => $this->field_preff, - ]) - ; - - } - - $fields = $new; - return $fields; - } - - public function rows(&$opt=[],$opt_by_val=null) { - - # - # Db type change - # - $db_type = $this->db()->type; - if (!empty($opt['db_type_from'])) { - $this->db()->type = $opt['db_type_from']; - } - - # - # Fields - # - if (!DB_TABLE_QUERY_NAME) { - $fields = []; - foreach ($this->db()->fields() as $f) { $fields[$f->name] = $f; } - $this->fields = $fields; - } - - # - # Fields filter - # - $fields = $this->fields(); - $fields_filter = []; - if ($this->fields_only) { - $fields_filter = $this->fields_only; - $new_fields = []; - foreach ($fields_filter as $k) { - $new_fields[$k] = $fields[$k]; - } - $fields = $new_fields; - unset($new_fields); - } - - # - # Build query - # - $this->create_temporary(); - - if ($opt_by_val !== null) $opt = $opt_by_val; - - if (isset($opt['format']) and $opt['format']==='') { - $format = ''; - } else { - - $format = empty($opt['format']) ? $this->p('format') : $opt['format']; - if (!$format and $this->db()->format) $format = $this->db()->format; - if (!$format) $this->bye("Parameter `format` missing!"); - } + return [$sql,$where,$limit,$select_count]; + } + + public function buttons() { + if (!$this->show_buttons or empty(self::$params)) return false; + if (!preg_match('/(table|view)/',$this->type())) return false; + return true; + } + + private function rows_parsers(&$row,&$opt=[]) { + $parser = isset($opt['parser']) ? $opt['parser'] : true; + $call = null; + + // + // Decrypt + // + if ($parser) $this->db()->table_row_decrypt($this,$row); + + // + // Pre + // + if ($parser and !empty($this->db()->row_parse_pre)) { + $call = $this->db()->row_parse_pre; $call($row,$this,$opt); + } + + if ($parser and !empty($this->row_parse_pre)) { + $call = $this->row_parse_pre; $call($row,$this,$opt); + } + + # Passed param on rows() + if ($parser and !empty($opt['row_parse_pre'])) { + $call = $opt['row_parse_pre']; $call($row,$this,$opt); + } + + // + // Format + // + if ($opt['is_html'] and !$opt['use_out']) { + foreach ($row as $k=>$v) { + if (!isset($this->extras[$k])) $row[$k] = $this->db()->out->format($v); + } + + } + + // + // Post + // + if ($parser and !empty($this->row_parse_post)) { + $call = $this->row_parse_post; $call($row,$this,$opt); + } + + if ($parser and !empty($this->db()->row_parse_post)) { + $call = $this->db()->row_parse_post; $call($row,$this,$opt); + } + + # Passed param on rows() + if ($parser and !empty($opt['row_parse_post'])) { + $call = $opt['row_parse_post']; $call($row,$this,$opt); + } + + return $call; + } + + + private function fields_add_missing(&$fields,$row) { + $new = []; + foreach (array_keys($row) as $name) { + + #debug($name); + $new[$name] = isset($fields[$name]) + ? $fields[$name] + : new Field([ + 'name' => $name, + 'dyn' => true, + 'table' => $this, + 'preffix' => $this->field_preff, + ]) + ; + + } + + $fields = $new; + return $fields; + } + + public function rows(&$opt=[],$opt_by_val=null) { + + # + # Db type change + # + $db_type = $this->db()->type; + if (!empty($opt['db_type_from'])) { + $this->db()->type = $opt['db_type_from']; + } + + # + # Fields + # + $fields = $this->fields(); + + # + # Build query + # + $this->create_temporary(); + + if ($opt_by_val !== null) $opt = $opt_by_val; + + if (isset($opt['format']) and $opt['format']==='') { + $format = ''; + } else { + + $format = empty($opt['format']) ? $this->p('format') : $opt['format']; + if (!$format and $this->db()->format) $format = $this->db()->format; + if (!$format) $this->bye("Parameter `format` missing!"); + } #debug($opt); - list($sql,$where,$limit,$select_count) = $this->rows_sql($opt); - $st = null; - $cursor = null; - $sql_orig = null; + list($sql,$where,$limit,$select_count) = $this->rows_sql($opt); + $st = null; + $cursor = null; + $sql_orig = null; - $fct = function() { return true; }; - if ($this->db()->type == 'pgsql') { + $fct = function() { return true; }; + if ($this->db()->type == 'pgsql') { $sql_orig = $sql; - $this->db()->conn->beginTransaction(); - $sql = "DECLARE table_rows CURSOR FOR $sql"; - $cursor = $this->db()->conn->prepare($sql); - $cursor->execute(); - $sql = "FETCH 1 FROM table_rows"; - - } else { - $this->db()->conn->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); - - } - - $st = $this->db()->conn->prepare($sql);#,[PDO::ATTR_ERRMODE => PDO::ERRMODE_SILENT]); - if (empty($cursor)) { - $st->execute(); - } else { - $fct = function() use($st) { return $st->execute(); }; - } - if (!empty($opt['query'])) return $st; - - # - # Use the module out when format unknow - # - $out_conf = null; - $opt['use_out'] = false; - - if ($this->p('out') or !preg_match('/^('.join('|', - [ '','template','table','sql','_div','wp' ] # local - ).')$/',$format)) - { - - $opt['use_out'] = true; - if (!($out_conf = $this->db()->out->types($format))) $this->bye("Unknow format `$format`"); - $out_conf = array_merge($opt,$out_conf); - - # Function name should be format - $this->db()->out->type($format); self::$params += array_values($this->db()->out->types()); - - if (empty($out_conf['enclose'])) $out_conf['enclose'] = ['','']; - debug('Using out module!',3); - - } - - # - # Html - # - if (!isset($opt['is_html'])) $opt['is_html'] = preg_match('/^(table|div)$/',$format) - ? ( $this->show_header ) - : false - ; - - if ($opt['is_html'] and !empty(self::$params) and !$this->p('action') and !$this->p('inc')) { - echo $this->html_menu($opt); - } - - if ($opt['is_html']) { - echo '
'.NB_EOL; + $this->db()->conn->beginTransaction(); + $sql = "DECLARE table_rows CURSOR FOR $sql"; + $cursor = $this->db()->conn->prepare($sql); + $cursor->execute(); + $sql = "FETCH 1 FROM table_rows"; + + } else { + $this->db()->conn->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); + + } + + $st = $this->db()->conn->prepare($sql);#,[PDO::ATTR_ERRMODE => PDO::ERRMODE_SILENT]); + if (empty($cursor)) { + $st->execute(); + } else { + $fct = function() use($st) { return $st->execute(); }; + } + if (!empty($opt['query'])) return $st; + + # + # Use the module out when format unknow + # + $out_conf = null; + $opt['use_out'] = false; + + if ($this->p('out') or !preg_match('/^('.join('|', + [ '','template','table','sql','_div','wp' ] # local + ).')$/',$format)) + { + + $opt['use_out'] = true; + if (!($out_conf = $this->db()->out->types($format))) $this->bye("Unknow format `$format`"); + $out_conf = array_merge($opt,$out_conf); + + # Function name should be format + $this->db()->out->type($format); self::$params += array_values($this->db()->out->types()); + + if (empty($out_conf['enclose'])) $out_conf['enclose'] = ['','']; + debug('Using out module!',3); + + } + + # + # Html + # + if (!isset($opt['is_html'])) $opt['is_html'] = preg_match('/^(table|div)$/',$format) + ? ( $this->show_header ) + : false + ; + + if ($opt['is_html'] and !empty(self::$params) and !$this->p('action') and !$this->p('inc')) { + echo $this->html_menu($opt); + } + + if ($opt['is_html']) { + echo '
'.NB_EOL; # NB 07.01.18 if ($this->show_hidden_params and !$this->p('inc')) echo $this->form_hidden(); - } + } - if ($opt['is_html']) $this->db()->out->type('html'); + if ($opt['is_html']) $this->db()->out->type('html'); - # - # Rows - # + # + # Rows + # - # Parser on/off (default: on) - if (!isset($opt['parser'])) $opt['parser'] = true; + # Parser on/off (default: on) + if (!isset($opt['parser'])) $opt['parser'] = true; - if (!empty($opt['db_type_from'])) { - $this->db()->type = $db_type; - } + if (!empty($opt['db_type_from'])) { + $this->db()->type = $db_type; + } - $count = 0; - while ($fct() and $row = $st->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT)) { + $count = 0; + while ($fct() and $row = $st->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT)) { - $count++; - $call = null; + $count++; + $call = null; - $call = $this->rows_parsers($row,$opt); + $call = $this->rows_parsers($row,$opt); - # - # Fields filter - # - if ($fields_filter) { - $new_row = []; - foreach ($fields_filter as $k) { - if (isset($row[$k])) $new_row[$k] = $row[$k]; - } - $row = $new_row; - } + # + # Fields filter + # + if ($this->fields_only) { + $new_row = []; + foreach ($this->fields_only as $k) { + if (isset($row[$k])) $new_row[$k] = $row[$k]; + } + $row = $new_row; + } - # - # Preffix - # - if (!empty($opt['preffix'])) echo $opt['preffix']; + # + # Preffix + # + if (!empty($opt['preffix'])) echo $opt['preffix']; - # - # Head - # - if ($count === 1) { - if ($opt['is_html']) echo $this->html_rows_top(); + # + # Head + # + if ($count === 1) { + if ($opt['is_html']) echo $this->html_rows_top(); - if ($call) { - $this->fields_add_missing($fields,$row); - } + if ($call) { + $this->fields_add_missing($fields,$row); + } - if ($out_conf) { - $this->db()->out->head($out_conf,array_keys($fields),[$row]); + if ($out_conf) { + $this->db()->out->head($out_conf,array_keys($fields),[$row]); - } else { - echo $this->{"rows_begin_$format"}($fields,$opt); + } else { + echo $this->{"rows_begin_$format"}($fields,$opt); - } + } - } + } - # - # Row - # - $count_fields = 0; + # + # Row + # + $count_fields = 0; - foreach ($fields as $f => $field) { + foreach ($fields as $f => $field) { if (!$this->field($f)) continue; - $row[$f] = $field->out(isset($row[$f]) ? $row[$f] : ''); - $count_fields++; - } + $row[$f] = $field->out(isset($row[$f]) ? $row[$f] : ''); + $count_fields++; + } - if ($out_conf) { - $this->db()->out->row($out_conf,$row); + if ($out_conf) { + $this->db()->out->row($out_conf,$row); - } else { - echo $this->{"rows_rec_$format"}($row,$opt); - } + } else { + echo $this->{"rows_rec_$format"}($row,$opt); + } - } # < while rows + } # < while rows - $st->closeCursor(); - if (!empty($cursor)) $cursor->closeCursor(); - if (!$count) return; + $st->closeCursor(); + if (!empty($cursor)) $cursor->closeCursor(); + if (!$count) return; - $this->count = $opt['count'] = $count; - $this->limit = $opt['limit'] = $limit; + $this->count = $opt['count'] = $count; + $this->limit = $opt['limit'] = $limit; - if ($opt['is_html'] or $format=='wp' or !empty($cursor)) { + if ($opt['is_html'] or $format=='wp' or !empty($cursor)) { if (!empty($sql_orig)) $sql = $sql_orig; - // - // Tot - // - if (!$where and !$limit) { - $debug = "Table.rows(): Not using count(*), use $count"; - $query = $this->db()->conn->query("SELECT $count"); - - } elseif ($select_count[1]) { - $debug = "Table.rows(): Using $select_count[1]"; - $query = $this->db()->conn->query($select_count[1]); - - } elseif ($where) { - $sql_count = $sql; - $sql_count = preg_replace('/ (ORDER|LIMIT) .*?$/s','',$sql_count); - $sql_count = preg_replace('/^SELECT .*FROM/s','SELECT count(*) FROM ',$sql_count); - $debug = "Table.rows(): Using $sql_count"; - $query = $this->db()->conn->query($sql_count); - - } else { - $query = $this->db()->conn->query('SELECT count(*) FROM '.$this->sql_name()); - - } - - if (!$query) $this->err_sql($sql); - - $tot = $query->fetch(PDO::FETCH_COLUMN); - $this->tot = $opt['tot'] = $tot; - - } # < is_html - - if ($count === 0 and !$format) { - echo $this->{"rows_begin_$format"}($fields,$opt); - } - - if ($out_conf) { - $this->db()->out->end($out_conf); - - } else { - echo $this->{"rows_end_$format"}(); - - if ($opt['is_html']) { - echo ''.NB_EOL - ; - } - - } # < out - - if ($opt['is_html']) { - echo '
'.NB_EOL; - } - - #return $count; - } - - /*----------------------------------------------------------------- - No Out - -----------------------------------------------------------------*/ - public function rows_begin_($fields,&$o) { - $o['sep'] = ''; - $o['var'] = [ - 'head' => array_keys($fields), - 'rows' => [], - ]; - } - - public function rows_rec_($row,&$o) { - $o['var']['rows'][] = $row; - } - - public function rows_end_() { - } - - /*----------------------------------------------------------------- - Template - -----------------------------------------------------------------*/ - public function rows_begin_template($fields,&$o) { - $id = $this->idtemplate(); - - $id = preg_replace('/[^\w\._-]/','',$id); - - $file = TABLE_TEMPLATE.'/'.$id.'.php'; - if (!is_readable($file)) return false; #$this->bye("Wrong id `$id`"); + // + // Tot + // + if (!$where and !$limit) { + $debug = "Table.rows(): Not using count(*), use $count"; + $query = $this->db()->conn->query("SELECT $count"); + + } elseif ($select_count[1]) { + $debug = "Table.rows(): Using $select_count[1]"; + $query = $this->db()->conn->query($select_count[1]); + + } elseif ($where) { + $sql_count = $sql; + $sql_count = preg_replace('/ (ORDER|LIMIT) .*?$/s','',$sql_count); + $sql_count = preg_replace('/^SELECT .*FROM/s','SELECT count(*) FROM ',$sql_count); + $debug = "Table.rows(): Using $sql_count"; + $query = $this->db()->conn->query($sql_count); + + } else { + $query = $this->db()->conn->query('SELECT count(*) FROM '.$this->sql_name()); + + } + + if (!$query) $this->err_sql($sql); + + $tot = $query->fetch(PDO::FETCH_COLUMN); + $this->tot = $opt['tot'] = $tot; + + } # < is_html + + if ($count === 0 and !$format) { + echo $this->{"rows_begin_$format"}($fields,$opt); + } + + if ($out_conf) { + $this->db()->out->end($out_conf); + + } else { + echo $this->{"rows_end_$format"}(); + + if ($opt['is_html']) { + echo ''.NB_EOL + ; + } + + } # < out + + if ($opt['is_html']) { + echo '
'.NB_EOL; + } + + #return $count; + } + + /*----------------------------------------------------------------- + No Out + -----------------------------------------------------------------*/ + public function rows_begin_($fields,&$o) { + $o['sep'] = ''; + $o['var'] = [ + 'head' => array_keys($fields), + 'rows' => [], + ]; + } + + public function rows_rec_($row,&$o) { + $o['var']['rows'][] = $row; + } + + public function rows_end_() { + } + + /*----------------------------------------------------------------- + Template + -----------------------------------------------------------------*/ + public function rows_begin_template($fields,&$o) { + $id = $this->idtemplate(); + + $id = preg_replace('/[^\w\._-]/','',$id); + + $file = TABLE_TEMPLATE.'/'.$id.'.php'; + if (!is_readable($file)) return false; #$this->bye("Wrong id `$id`"); # NB 02.12.16 $o['file'] = $file; - $this->__file = $file; - $this->__fields = array_keys($fields); + $this->__file = $file; + $this->__fields = array_keys($fields); # NB 02.12.16 $HEAD = array_keys($fields); # NB 02.12.16 $ROWS = []; # NB 02.12.16 $ROW = []; # NB 02.12.16 require $o['file']; - } - - public function rows_rec_template($row,&$o) { - $i = 0; - foreach ($row as $k=>$v) { - $row[$i] = $v; - $i++; - } - $this->__rows[] = $row; + } + + public function rows_rec_template($row,&$o) { + $i = 0; + foreach ($row as $k=>$v) { + $row[$i] = $v; + $i++; + } + $this->__rows[] = $row; # NB 02.12.16 $HEAD = []; # NB 02.12.16 $ROWS = [$row]; # NB 02.12.16 $ROW = $row; - } - - public function rows_end_template() { - $HEAD = &$this->__fields; - $ROWS = &$this->__rows; - $ROW = &$ROWS[0];; - require $this->__file; - unset($this->__file); - unset($this->__fields); - unset($this->__rows); - } - - /*----------------------------------------------------------------- - Wordpress - -----------------------------------------------------------------*/ - public function rows_begin_wp() { - require_once(NB_ROOT.'/lib/php/db/wp.php'); - $this->_html_table = new html_table($this); - return ''; - } - - public function rows_rec_wp(&$row) { - $this->_html_table->items[] = $row; - return ''; - } - - public function rows_end_wp() { - - $limit = preg_replace('/^.*,\s*/','',$this->limit); - - $this->_html_table->set_pagination_args([ - 'total_items' => $this->tot, // total items defined above - 'per_page' => $limit, // per page constant defined at top of method - 'total_pages' => ceil($this->tot / $limit) // calculate pages count - ]); - - #$this->_html_table->display_tablenav('top'); - $this->_html_table->display(); - #$this->_html_table->display_tablenav('bottom'); - unset($this->_html_table); - return ''; - } + } + + public function rows_end_template() { + $HEAD = &$this->__fields; + $ROWS = &$this->__rows; + $ROW = &$ROWS[0];; + require $this->__file; + unset($this->__file); + unset($this->__fields); + unset($this->__rows); + } + + /*----------------------------------------------------------------- + Wordpress + -----------------------------------------------------------------*/ + public function rows_begin_wp() { + require_once(NB_ROOT.'/lib/php/db/wp.php'); + $this->_html_table = new html_table($this); + return ''; + } + + public function rows_rec_wp(&$row) { + $this->_html_table->items[] = $row; + return ''; + } + + public function rows_end_wp() { + + $limit = preg_replace('/^.*,\s*/','',$this->limit); + + $this->_html_table->set_pagination_args([ + 'total_items' => $this->tot, // total items defined above + 'per_page' => $limit, // per page constant defined at top of method + 'total_pages' => ceil($this->tot / $limit) // calculate pages count + ]); + + #$this->_html_table->display_tablenav('top'); + $this->_html_table->display(); + #$this->_html_table->display_tablenav('bottom'); + unset($this->_html_table); + return ''; + } /*----------------------------------------------------------------- - Sql + Sql -----------------------------------------------------------------*/ public function rows_begin_sql() { - return ''; - return "\n-- ".$this->name."\n"; + return ''; + return "\n-- ".$this->name."\n"; } public function rows_rec_sql(&$row,&$opt) { - $keys = $values = []; + $keys = $values = []; - foreach ($row as $k=>$v) { - if (isset($this->extras[$k])) continue; - $f = $this->field($k); + foreach ($row as $k=>$v) { + if (isset($this->extras[$k])) continue; + $f = $this->field($k); - $values[] = $f->quote($v); - $keys[] = $f->sql_name(); - } + $values[] = $f->quote($v); + $keys[] = $f->sql_name(); + } - $fields = $this->fields_only ? ' ('.join(',',$keys).')' : ''; - $sql = "INSERT INTO ".$this->sql_name().$fields." VALUES(".join(',',array_values($values)).");"; + $fields = $this->fields_only ? ' ('.join(',',$keys).')' : ''; + $sql = "INSERT INTO ".$this->sql_name().$fields." VALUES(".join(',',array_values($values)).");"; - $fct = !empty($opt['fct']) ? $opt['fct'] : null; - if ($fct) $sql = $fct($sql,$this); + $fct = !empty($opt['fct']) ? $opt['fct'] : null; + if ($fct) $sql = $fct($sql,$this); - return $sql.NB_EOL; + return $sql.NB_EOL; } public function rows_end_sql() { - return ''; - } - - /*----------------------------------------------------------------- - Text - -----------------------------------------------------------------*/ - public function rows_begin_text() { - $this->_row_text = null; - return ''; - } - - public function rows_rec_text(&$row) { - $text = ''; - if ($this->_row_text === null) { - $this->_row_text = true; - } else { - $text .= "\t"; - } - return $text.$row."\n"; - } - - public function rows_end_text() { - unset($this->_row_text); - return ''; - } - - /*----------------------------------------------------------------- - Json - -----------------------------------------------------------------*/ - public function rows_begin_json() { - $this->_row_json = null; - return '['.NB_EOL; - return '' - #."// database: ".$this->db()->name."\n" - #."// table: $this->name\n" - .'['.NB_EOL; - } - - public function rows_rec_json(&$row) { - if ($this->_row_json === null) { - $json = ''; - $this->_row_json = true; - } else { - $json = ','.NB_EOL; - } - return $json . json_encode($row); - } - - public function rows_end_json() { - unset($this->_row_json); - return NB_EOL.']'.NB_EOL; - } - - /*----------------------------------------------------------------- - Xml - -----------------------------------------------------------------*/ - public function rows_begin_xml() { - return '' - .''.NB_EOL #name.'" database="'.$this->db()->name.'" database-type="'.$this->db()->conf_type('type').'">'.NB_EOL - ; - } - - public function rows_rec_xml(&$row) { - $xml = ''; - $xml .= TABLE_INDENT."".NB_EOL; - foreach ($row as $k=>$v) { - if ($v !== '') $xml .= '' - . TABLE_INDENT.TABLE_INDENT."<".$k.">" - .'' - . '' - . NB_EOL; - } - $xml .= TABLE_INDENT."".NB_EOL; - return $xml; - } - - public function rows_end_xml() { - return ''.NB_EOL; - } - - public function zaza() { return [ ['A','B'], ['a','bb'] ]; } - - /*----------------------------------------------------------------- - Csv - -----------------------------------------------------------------*/ - public function rows_begin_csv($fields) { - - if (self::p('rows_head_char')!=='') echo self::p('rows_head_char'); - if (!$this->show_header) return ''; - return join(TABLE_CSV_SEP,array_keys($fields))."\n"; - } - - public function rows_rec_csv(&$row) { - return str_replace("\n",'|',join(TABLE_CSV_SEP,array_values($row)))."\n"; - } - - public function rows_end_csv() { - return ''; - } - - /*----------------------------------------------------------------- - Html Table - -----------------------------------------------------------------*/ - public function rows_begin_table($fields) { - - $html = ''; - - $html .= ''.NB_EOL; - - $this->__rows_table_attr = []; - foreach ($fields as $name => $f) { - $this->__rows_table_attr[$name] = '' - . ' class="' . $name - . ($f->key ? ' key' : '') - . (isset($this->extras[$name]) ? ' extra' : '') - . ' ' . preg_replace('/\W.*$/','',$f->type) - .'"' - ; - } - - if ($this->show_header) { - $html .= ''.NB_EOL; - - // Columns names - $html .= ''.NB_EOL; - if ($this->buttons() and DB_HTML_EDIT) $html .= ''.NB_EOL; - foreach ($fields as $name => $f) { - $html .= '__rows_table_attr[$name].'>'.$this->url_sort($name).''.NB_EOL; - } - if ($this->buttons() and DB_HTML_DELETE) $html .= ''.NB_EOL; - $html .= ''.NB_EOL; - $html .= ''.NB_EOL; - } - - $html .= ''.NB_EOL; - return $html; - } - - public function rows_rec_table(&$row,&$opt) { - - $buttons = $this->html_row_buttons($row); - - $html = ''.NB_EOL; - - if ($this->buttons() and !empty($buttons[0])) $html .= ''.NB_EOL; - - foreach ($row as $k => $v) { - if ( !empty($this) and !empty($this->field($k)) ) { - $v = $this->field($k)->htmlValue($v); - } - $html .= '__rows_table_attr[$k].'>'.$v.''.NB_EOL; - } - - if ($this->buttons() and !empty($buttons[1])) $html .= ''.NB_EOL; - - $html .= ''.NB_EOL; + return ''; + } - return $html; - } + /*----------------------------------------------------------------- + Text + -----------------------------------------------------------------*/ + public function rows_begin_text() { + $this->_row_text = null; + return ''; + } - public function rows_end_table() { - unset($this->__rows_table_attr); - $html = ''; - $html .= ''.NB_EOL; - $html .= '
'.$buttons[0].''.$buttons[1].'
'.NB_EOL; - return $html; - } + public function rows_rec_text(&$row) { + $text = ''; + if ($this->_row_text === null) { + $this->_row_text = true; + } else { + $text .= "\t"; + } + return $text.$row."\n"; + } - /*----------------------------------------------------------------- - Html Div - -----------------------------------------------------------------*/ - public function rows_begin_div() { - return '
'.NB_EOL; - } + public function rows_end_text() { + unset($this->_row_text); + return ''; + } - public function rows_rec_div(&$row) { + /*----------------------------------------------------------------- + Json + -----------------------------------------------------------------*/ + public function rows_begin_json() { + $this->_row_json = null; + return '['.NB_EOL; + return '' + #."// database: ".$this->db()->name."\n" + #."// table: $this->name\n" + .'['.NB_EOL; + } - $html = ''; + public function rows_rec_json(&$row) { + if ($this->_row_json === null) { + $json = ''; + $this->_row_json = true; + } else { + $json = ','.NB_EOL; + } + return $json . json_encode($row); + } - $html .= '
    '.NB_EOL; + public function rows_end_json() { + unset($this->_row_json); + return NB_EOL.']'.NB_EOL; + } - if ($this->buttons()) { - $html .= '
  • '.NB_EOL; - $html .= join('',$this->html_row_buttons($row)); - $html .= '
  • '.NB_EOL; - } + /*----------------------------------------------------------------- + Xml + -----------------------------------------------------------------*/ + public function rows_begin_xml() { + return '' + .''.NB_EOL #name.'" database="'.$this->db()->name.'" database-type="'.$this->db()->conf_type('type').'">'.NB_EOL + ; + } - foreach ($row as $k => $v) { - $html .= '
  • ' - .( $k == '0' ? '' : '') - .''.$v.'' - .'
  • '.NB_EOL; - } + public function rows_rec_xml(&$row) { + $xml = ''; + $xml .= TABLE_INDENT."".NB_EOL; + foreach ($row as $k=>$v) { + if ($v !== '') $xml .= '' + . TABLE_INDENT.TABLE_INDENT."<".$k.">" + .'' + . '' + . NB_EOL; + } + $xml .= TABLE_INDENT."".NB_EOL; + return $xml; + } - $html .= '
'.NB_EOL; + public function rows_end_xml() { + return ''.NB_EOL; + } - return $html; - } + public function zaza() { return [ ['A','B'], ['a','bb'] ]; } - public function rows_end_div() { - return '
'.NB_EOL; - } + /*----------------------------------------------------------------- + Csv + -----------------------------------------------------------------*/ + public function rows_begin_csv($fields) { + + if (self::p('rows_head_char')!=='') echo self::p('rows_head_char'); + if (!$this->show_header) return ''; + return join(TABLE_CSV_SEP,array_keys($fields))."\n"; + } + + public function rows_rec_csv(&$row) { + return str_replace("\n",'|',join(TABLE_CSV_SEP,array_values($row)))."\n"; + } + + public function rows_end_csv() { + return ''; + } + + /*----------------------------------------------------------------- + Html Table + -----------------------------------------------------------------*/ + public function rows_begin_table($fields) { + + $html = ''; + + $html .= ''.NB_EOL; + + $this->__rows_table_attr = []; + foreach ($fields as $name => $f) { + $this->__rows_table_attr[$name] = '' + . ' class="' . $name + . ($f->key ? ' key' : '') + . (isset($this->extras[$name]) ? ' extra' : '') + . ' ' . preg_replace('/\W.*$/','',$f->type) + .'"' + ; + } - public function sql_names($value) { + if ($this->show_header) { + $html .= ''.NB_EOL; - $new = []; - foreach ($value as $k=>$v) { - $new[$k] = $this->sql_name($v); - } - return $new; - } + // Columns names + $html .= ''.NB_EOL; + if ($this->buttons() and DB_HTML_EDIT) $html .= ''.NB_EOL; + foreach ($fields as $name => $f) { + $html .= '__rows_table_attr[$name].'>'.$this->url_sort($name).''.NB_EOL; + } + if ($this->buttons() and DB_HTML_DELETE) $html .= ''.NB_EOL; + $html .= ''.NB_EOL; + $html .= ''.NB_EOL; + } - public function sql_name($value=null) { + $html .= ''.NB_EOL; + return $html; + } - return $this->db()->sql_name($value === null ? $this->name : $value); - } + public function rows_rec_table(&$row,&$opt) { - private function _post2sql($post) { - $keys = []; - $keys_values = []; - $fields = []; - $fields_values = []; - foreach ($this->fields() as $name => $field) { + $buttons = $this->html_row_buttons($row); - if ($field->extras) continue; + $html = ''.NB_EOL; - $value = $post[$this->field_preff.$name]; + if ($this->buttons() and !empty($buttons[0])) $html .= ''.NB_EOL; - if ($field->key) { - $keys[] = $name; + foreach ($row as $k => $v) { + if ( !empty($this) and !empty($this->field($k)) ) { + $v = $this->field($k)->htmlValue($v); + } + $html .= '__rows_table_attr[$k].'>'.$v.''.NB_EOL; + } - if (!isset($post[$this->key_preff.$name])) { - if ($field->key) $this->bye("Missing `$name`!"); - continue; - } + if ($this->buttons() and !empty($buttons[1])) $html .= ''.NB_EOL; - if (isset($post[$this->key_preff.$name])) { - $keys_values[] = $post[$this->key_preff.$name]; + $html .= ''.NB_EOL; - } else { - $keys_values[] = $value; - } + return $html; + } - } else { + public function rows_end_table() { + unset($this->__rows_table_attr); + $html = ''; + $html .= ''.NB_EOL; + $html .= '
'.$buttons[0].''.$buttons[1].'
'.NB_EOL; + return $html; + } - $fields[] = $name; - $fields_values[] = $value; + /*----------------------------------------------------------------- + Html Div + -----------------------------------------------------------------*/ + public function rows_begin_div() { + return '
'.NB_EOL; + } + + public function rows_rec_div(&$row) { + + $html = ''; + + $html .= '
    '.NB_EOL; + + if ($this->buttons()) { + $html .= '
  • '.NB_EOL; + $html .= join('',$this->html_row_buttons($row)); + $html .= '
  • '.NB_EOL; + } - } + foreach ($row as $k => $v) { + $html .= '
  • ' + .( $k == '0' ? '' : '') + .''.$v.'' + .'
  • '.NB_EOL; + } + + $html .= '
'.NB_EOL; + + return $html; + } + + public function rows_end_div() { + return '
'.NB_EOL; + } + + public function sql_names($value) { + + $new = []; + foreach ($value as $k=>$v) { + $new[$k] = $this->sql_name($v); + } + return $new; + } + + public function sql_name($value=null) { + + return $this->db()->sql_name($value === null ? $this->name : $value); + } + + private function _post2sql($post) { + $keys = []; + $keys_values = []; + $fields = []; + $fields_values = []; + foreach ($this->fields() as $name => $field) { + + if ($field->extras) continue; + + $value = $post[$this->field_preff.$name]; + + if ($field->key) { + $keys[] = $name; + + if (!isset($post[$this->key_preff.$name])) { + if ($field->key) $this->bye("Missing `$name`!"); + continue; + } + + if (isset($post[$this->key_preff.$name])) { + $keys_values[] = $post[$this->key_preff.$name]; + + } else { + $keys_values[] = $value; + } + + } else { + + $fields[] = $name; + $fields_values[] = $value; + + } } return [ - 'keys' => $keys, - 'keys_values' => $keys_values, - 'fields' => $fields, - 'fields_values' => $fields_values, - 'all_keys' => array_combine($keys,$keys_values), - 'all_fields' => array_combine($fields,$fields_values), + 'keys' => $keys, + 'keys_values' => $keys_values, + 'fields' => $fields, + 'fields_values' => $fields_values, + 'all_keys' => array_combine($keys,$keys_values), + 'all_fields' => array_combine($fields,$fields_values), ]; - } + } - public function replace($hvalues,&$info=[]) { + public function replace($hvalues,&$info=[]) { # NB 12.12.17: When REPLACE is not supported where call a personalized function to modify $sql $fct = $this->db()->conf_type('replace_insert'); if (!empty($fct)) { $info['fct'] = $fct; return $this->insert($hvalues,$info); } - return $this->insert($hvalues,$info,'REPLACE'); - } + return $this->insert($hvalues,$info,'REPLACE'); + } - public function insert($post,&$info=[],$insert_word='INSERT') { + public function insert($post,&$info=[],$insert_word='INSERT') { - if (empty($info['values'])) $info['values'] = []; - if (empty($post)) $this->bye('insert(): No values'); + if (empty($info['values'])) $info['values'] = []; + if (empty($post)) $this->bye('insert(): No values'); - $sql_names = $fields = $values = []; + $sql_names = $fields = $values = []; - foreach ($this->fields() as $name => $field) { - if ($field->key and $field->autoincrement()) continue; + foreach ($this->fields() as $name => $field) { + if ($field->key and $field->autoincrement()) continue; - if (!isset($post[$this->field_preff.$name])) { + if (!isset($post[$this->field_preff.$name])) { # For postgres and replace mode, we want to update timestamp for example if (!empty($info['fct']) and isset($field->default)) { @@ -1705,100 +1687,100 @@ Class Table extends nb { } - $fields[$name] = $field; - $sql_names[$name] = $field->sql_name(); - $values[] = $post[$this->field_preff.$name]; - } + $fields[$name] = $field; + $sql_names[$name] = $field->sql_name(); + $values[] = $post[$this->field_preff.$name]; + } - if (empty($fields)) $this->bye('insert(): No fields for table'); + if (empty($fields)) $this->bye('insert(): No fields for table'); - $sql = - $insert_word.' INTO '. $this->sql_name() . ' (' . join(',',array_values($sql_names)).')' - .' VALUES (' . join(',',ar_map('":$a"',array_keys($fields))) . ')' - ; + $sql = + $insert_word.' INTO '. $this->sql_name() . ' (' . join(',',array_values($sql_names)).')' + .' VALUES (' . join(',',ar_map('":$a"',array_keys($fields))) . ')' + ; if (!empty($info['fct'])) { $fct = $info['fct']; unset($info['fct']); $fct($sql,$this,$fields); } - $info['sql'] = $sql; + $info['sql'] = $sql; - if (!($query = $this->db()->conn->prepare($sql))) { - $this->err_sql($sql); - return false; - } + if (!($query = $this->db()->conn->prepare($sql))) { + $this->err_sql($sql); + return false; + } - $info['values'] = $post; + $info['values'] = $post; - foreach ($fields as $name => $field) { - $row = [ $name => $post[$name] ]; - $this->db()->table_row_encrypt($this,$row); - #debug($name.': '.$row[$name]); - if (!empty($info['values'][$name])) $info['values'][$name] = $row[$name]; - $field->bindParam($query,$row[$name],":$name"); - } + foreach ($fields as $name => $field) { + $row = [ $name => $post[$name] ]; + $this->db()->table_row_encrypt($this,$row); + #debug($name.': '.$row[$name]); + if (!empty($info['values'][$name])) $info['values'][$name] = $row[$name]; + $field->bindParam($query,$row[$name],":$name"); + } - if (self::p('debug')) { - $this->debug($info,1); - return true; - } + if (self::p('debug')) { + $this->debug($info,1); + return true; + } - if (!($execute = $query->execute())) { - $this->err_sql($sql); - return false; - } + if (!($execute = $query->execute())) { + $this->err_sql($sql); + return false; + } - $info['rowCount'] = $query->rowCount(); - return $query->rowCount(); - } + $info['rowCount'] = $query->rowCount(); + return $query->rowCount(); + } - public function update($post,&$info=[]) { + public function update($post,&$info=[]) { - $keys = []; - $keys_values = []; - $fields = []; - $fields_values = []; + $keys = []; + $keys_values = []; + $fields = []; + $fields_values = []; # NB 14.12.17 $bindParam = false; # NB 12.05.17: Not working ???? - $bindParam = true; # NB 12.05.17: Not working ???? + $bindParam = true; # NB 12.05.17: Not working ???? - foreach ($this->fields() as $name => $field) { + foreach ($this->fields() as $name => $field) { - if ($field->extras) continue; + if ($field->extras) continue; - $value = $post[$this->field_preff.$name]; + $value = $post[$this->field_preff.$name]; - if ($field->key) { - $keys[] = $name; + if ($field->key) { + $keys[] = $name; - if (!isset($post[$this->key_preff.$name])) { - if ($field->key) $this->bye("Missing `$name`!"); - continue; - } + if (!isset($post[$this->key_preff.$name])) { + if ($field->key) $this->bye("Missing `$name`!"); + continue; + } # NB 12.12.17 $_value = isset($post[$this->key_preff.$name]) ? $post[$this->key_preff.$name] : null; - if (isset($post[$this->key_preff.$name])) { - $fields[] = $name; - $fields_values[] = $post[$this->key_preff.$name]; - $keys_values[] = $post[$this->key_preff.$name]; + if (isset($post[$this->key_preff.$name])) { + $fields[] = $name; + $fields_values[] = $post[$this->key_preff.$name]; + $keys_values[] = $post[$this->key_preff.$name]; - } else { - $keys_values[] = $value; - } + } else { + $keys_values[] = $value; + } - } else { + } else { - $fields[] = $name; - $fields_values[] = $value; + $fields[] = $name; + $fields_values[] = $value; - } + } - } + } - $info['keys'] = array_combine($keys,$keys_values); - $info['fields'] = array_combine($fields,$fields_values); - $info['post'] = $post; + $info['keys'] = array_combine($keys,$keys_values); + $info['fields'] = array_combine($fields,$fields_values); + $info['post'] = $post; #bye([$keys,$keys_values]); #debug([$post,$this->fields()]); @@ -1806,245 +1788,245 @@ Class Table extends nb { # $fields = $keys; # $fields_values = $keys_values; # } - if (empty($fields)) $this->bye("Missing fields!"); - - if (empty($keys)) { - $this->bye("Missing keys!"); - $keys = $fields; - $keys_values = $fields_values; - } - - $sql = '' - .'UPDATE ' . $this->sql_name() - .' SET ' . join(',',$this->ar_map('"$a=:$a"',$fields)) - .' WHERE ' . join(' AND ',$this->ar_map('"$a=:key_$a"',$keys)) - ; - #$info['sql'] = $sql; - $info = [ 'sql' => $sql ] + $info; - - if ($bindParam and !($query = $this->db()->conn->prepare($sql))) { - $this->err('PDO::errorInfo(): ' .join(' ', $this->db()->conn->errorInfo()) .NB_EOL); - return false; - } - - foreach ($fields as $name) { - #debug("$name: ".$post[$name]); - $row = [ $name => $post[$name] ]; - $this->db()->table_row_encrypt($this,$row); - if ($bindParam) $field->bindParam($query,$row[$name],":$name"); - $sql = str_replace(":$name",$this->field($name)->quote($row[$name]),$sql); - } - - foreach ($info['keys'] as $name => $value) { - #debug("$name: ".$post[$name]); - if ($bindParam) $field->bindParam($query,$value,":key_$name"); - $sql = str_replace(":key_$name",$this->field($name)->quote($value),$sql); - } - - $info['sql'] = $sql; - if (!$bindParam) { - $query = $this->db()->conn->prepare($sql); - } - #return $sql; - if (self::p('debug')) { - $this->debug($info,1); - return false; - } - - if (!($ex = $query->execute())) { - $this->err_sql($sql); - return false; - } - - $info = [ 'rowCount' => $query->rowCount()] + $info; - #debug($info); return 0; - return $info['rowCount']; - - } - - public function delete($post,&$info=[]) { - if (empty($info['values'])) $info['values'] = []; - $info['values'] = $post; - - $keys = $this->fields_keys(); - - // If no primary keys, we use all field - if (empty($keys)) $keys = $this->fields(); - - if (!($where = $this->where($keys,$post,self::$is_admin ? false : true))) { - err('Db.delete(): Missing keys values'); - return null; - } + if (empty($fields)) $this->bye("Missing fields!"); + + if (empty($keys)) { + $this->bye("Missing keys!"); + $keys = $fields; + $keys_values = $fields_values; + } + + $sql = '' + .'UPDATE ' . $this->sql_name() + .' SET ' . join(',',$this->ar_map('"$a=:$a"',$fields)) + .' WHERE ' . join(' AND ',$this->ar_map('"$a=:key_$a"',$keys)) + ; + #$info['sql'] = $sql; + $info = [ 'sql' => $sql ] + $info; + + if ($bindParam and !($query = $this->db()->conn->prepare($sql))) { + $this->err('PDO::errorInfo(): ' .join(' ', $this->db()->conn->errorInfo()) .NB_EOL); + return false; + } + + foreach ($fields as $name) { + #debug("$name: ".$post[$name]); + $row = [ $name => $post[$name] ]; + $this->db()->table_row_encrypt($this,$row); + if ($bindParam) $field->bindParam($query,$row[$name],":$name"); + $sql = str_replace(":$name",$this->field($name)->quote($row[$name]),$sql); + } + + foreach ($info['keys'] as $name => $value) { + #debug("$name: ".$post[$name]); + if ($bindParam) $field->bindParam($query,$value,":key_$name"); + $sql = str_replace(":key_$name",$this->field($name)->quote($value),$sql); + } + + $info['sql'] = $sql; + if (!$bindParam) { + $query = $this->db()->conn->prepare($sql); + } + #return $sql; + if (self::p('debug')) { + $this->debug($info,1); + return false; + } + + if (!($ex = $query->execute())) { + $this->err_sql($sql); + return false; + } + + $info = [ 'rowCount' => $query->rowCount()] + $info; + #debug($info); return 0; + return $info['rowCount']; + + } + + public function delete($post,&$info=[]) { + if (empty($info['values'])) $info['values'] = []; + $info['values'] = $post; + + $keys = $this->fields_keys(); + + // If no primary keys, we use all field + if (empty($keys)) $keys = $this->fields(); + + if (!($where = $this->where($keys,$post,self::$is_admin ? false : true))) { + err('Db.delete(): Missing keys values'); + return null; + } # NB 07.12.17: Add LIMIT 1. If a table as not primary key when want to delete only on record # NB 12.12.17 $sql = 'DELETE FROM ' . $this->sql_name() . $where . ($this->db()->type == 'pgsql' ? '' : ' LIMIT 1'); - $sql = 'DELETE FROM ' . $this->sql_name() . $where . ($this->db()->conf_type('delete_no_limit') ? '' : ' LIMIT 1'); - $info['sql'] = $sql; + $sql = 'DELETE FROM ' . $this->sql_name() . $where . ($this->db()->conf_type('delete_no_limit') ? '' : ' LIMIT 1'); + $info['sql'] = $sql; - if (self::p('debug')) { - $this->debug($info,1); - return false; - } + if (self::p('debug')) { + $this->debug($info,1); + return false; + } - $query = $this->db()->exec($sql); - $info['rowCount'] = $query; + $query = $this->db()->exec($sql); + $info['rowCount'] = $query; - return $info['rowCount']; - } + return $info['rowCount']; + } - public function out($v,$head=[],$conf=[]) { return $this->db()->out($v,$head,$conf); } + public function out($v,$head=[],$conf=[]) { return $this->db()->out($v,$head,$conf); } - public function url_referer($default='') { + public function url_referer($default='') { - if (self::p('referer')) { - return urldecode($this->p('referer')); + if (self::p('referer')) { + return urldecode($this->p('referer')); - } elseif(!empty($default)) { - return $default; + } elseif(!empty($default)) { + return $default; - } else { - return '?table=' . urlencode($this->name) . (self::p('db') ? '&db='.self::p('db') : ''); + } else { + return '?table=' . urlencode($this->name) . (self::p('db') ? '&db='.self::p('db') : ''); - } + } - } + } # NB 12.01.18 public function maxlengths() { # NB 12.01.18 $sql = 'MAX(LENGTH('.$field->sql_name(true).'))'; # NB 12.01.18 } - public function fields_rows() { - $rows = array_values($this->object2array($this->fields())); - - list($sql,$where,$limit,$select_count) = $this->rows_sql(); - foreach ([ - 'maxlen' => 'MAX(LENGTH('.$this->db()->cast_text('').'))', - 'max' => 'MAX()', - ] as $name => $select) { - if (!$this->p($name)) continue; - $sql = ''; + public function fields_rows() { + $rows = array_values($this->object2array($this->fields())); - foreach ($this->fields() as $f) { - $sql .= ($sql == '' ? 'SELECT ' : ', '); - $sql .= str_replace('',$f->sql_name(),$select); - } + list($sql,$where,$limit,$select_count) = $this->rows_sql(); + foreach ([ + 'maxlen' => 'MAX(LENGTH('.$this->db()->cast_text('').'))', + 'max' => 'MAX()', + ] as $name => $select) { + if (!$this->p($name)) continue; + $sql = ''; - $sql .= ' FROM ' . $this->sql_name() . $where . ($limit ? " LIMIT ".$limit : ''); - $len = $this->db()->query($sql)->fetch(PDO::FETCH_NUM); + foreach ($this->fields() as $f) { + $sql .= ($sql == '' ? 'SELECT ' : ', '); + $sql .= str_replace('',$f->sql_name(),$select); + } - $i = 0; - foreach ($rows as $k => $v) { $rows[$k][$name] = $len[$i]; $i++; } + $sql .= ' FROM ' . $this->sql_name() . $where . ($limit ? " LIMIT ".$limit : ''); + $len = $this->db()->query($sql)->fetch(PDO::FETCH_NUM); - } + $i = 0; + foreach ($rows as $k => $v) { $rows[$k][$name] = $len[$i]; $i++; } - return $rows; - } + } - public function action($action=null) { + return $rows; + } - if ($action == 'table.fields') { - $rows = $this->fields_rows(); - return $this->out($rows); + public function action($action=null) { - } elseif ($action == 'table.rows') { - $this->db()->print_header($this->p('format')); - $this->rows(); - return true; + if ($action == 'table.fields') { + $rows = $this->fields_rows(); + return $this->out($rows); - } elseif ($action == 'table.info') { - return $this->out($this->info()); + } elseif ($action == 'table.rows') { + $this->db()->print_header($this->p('format')); + $this->rows(); + return true; - } elseif ($action == 'table.delete') { - if (!$this->delete($_POST,$e) and !isset($e['rowCount'])) bye($e); - $this->db()->print_header('Location',$this->url_referer(str_replace('&','&',$this->url_list()))); - $this->out($e); - return true; + } elseif ($action == 'table.info') { + return $this->out($this->info()); - } elseif ($action == 'table.replace') { - if (!$this->replace($_POST,$e) and !isset($e['rowCount'])) bye($e); - $this->db()->print_header('Location',$this->url_referer()); - $this->out($e); - return true; + } elseif ($action == 'table.delete') { + if (!$this->delete($_POST,$e) and !isset($e['rowCount'])) bye($e); + $this->db()->print_header('Location',$this->url_referer(str_replace('&','&',$this->url_list()))); + $this->out($e); + return true; - } elseif ($action == 'table.insert') { - if (!$this->insert($_POST,$e)) bye(); - $this->db()->print_header('Location',$this->url_referer()); - $this->out($e); - return true; + } elseif ($action == 'table.replace') { + if (!$this->replace($_POST,$e) and !isset($e['rowCount'])) bye($e); + $this->db()->print_header('Location',$this->url_referer()); + $this->out($e); + return true; - } elseif ($action == 'table.update') { - if ($this->update($_POST,$e) === false) bye($e); - $this->db()->print_header('Location',$this->url_referer()); - $this->out($e); - return true; + } elseif ($action == 'table.insert') { + if (!$this->insert($_POST,$e)) bye(); + $this->db()->print_header('Location',$this->url_referer()); + $this->out($e); + return true; - } elseif ($action == 'table.truncate') { - $this->db()->query('TRUNCATE '.$this->sql_name()); - return true; + } elseif ($action == 'table.update') { + if ($this->update($_POST,$e) === false) bye($e); + $this->db()->print_header('Location',$this->url_referer()); + $this->out($e); + return true; - } elseif (self::class_action_out($this,$action) !== null) { - return true; + } elseif ($action == 'table.truncate') { + $this->db()->query('TRUNCATE '.$this->sql_name()); + return true; - } elseif ($this->p('format') and !preg_match('/^(table|div)$/',$this->p('format'))) { + } elseif (self::class_action_out($this,$action) !== null) { + return true; - $opt = ['format' => $this->p('format')]; - $this->rows($opt); - return true; + } elseif ($this->p('format') and !preg_match('/^(table|div)$/',$this->p('format'))) { - } elseif ($action == 'edit') { - return $this->html_edit(); + $opt = ['format' => $this->p('format')]; + $this->rows($opt); + return true; - } elseif ($this->p('table')) { - # NB 17.03.16 } else { - $this->pdef('limit','20'); + } elseif ($action == 'edit') { + return $this->html_edit(); - // Rows - return $this->rows(); + } elseif ($this->p('table')) { + # NB 17.03.16 } else { + $this->pdef('limit','20'); - } + // Rows + return $this->rows(); - return false; - } + } - public function html_row_buttons(&$row) { - if (!$this->show_buttons or empty(self::$params)) return []; - return [ - (!DB_HTML_EDIT ? '' : ''.DB_HTML_EDIT.''.NB_EOL), - (!DB_HTML_DELETE ? '' : ''.DB_HTML_DELETE.''.NB_EOL), - ]; - } + return false; + } + + public function html_row_buttons(&$row) { + if (!$this->show_buttons or empty(self::$params)) return []; + return [ + (!DB_HTML_EDIT ? '' : ''.DB_HTML_EDIT.''.NB_EOL), + (!DB_HTML_DELETE ? '' : ''.DB_HTML_DELETE.''.NB_EOL), + ]; + } - public function html_rows_top() { - if (self::p('replace') === '0') return ''; - $html = ''; + public function html_rows_top() { + if (self::p('replace') === '0') return ''; + $html = ''; - if (!empty($this->replace)) { + if (!empty($this->replace)) { - $replace = []; - foreach ($this->replace as $k=>$v) { $replace[] = "$k.$v"; } - $html .= ''.NB_EOL; + $replace = []; + foreach ($this->replace as $k=>$v) { $replace[] = "$k.$v"; } + $html .= ''.NB_EOL; - } + } - return $html; + return $html; - } + } - public function count() { + public function count() { - if (isset($this->count)) return $this->count; + if (isset($this->count)) return $this->count; - $sql_count = $this->name; + $sql_count = $this->name; - # We could use it instead of query, but wont be cached ! $this->create_temporary(); - if ($this->type == 'sql' and $this->name !== DB_TABLE_QUERY_NAME) { - if (!$this->sql) return; + # We could use it instead of query, but wont be cached ! $this->create_temporary(); + if ($this->type == 'sql' and $this->name !== DB_TABLE_QUERY_NAME) { + if (!$this->sql) return; - $sql_count = "SELECT COUNT(*) FROM ($this->sql) _table_count" ; - #debug([$this->name,$sql_count]); + $sql_count = "SELECT COUNT(*) FROM ($this->sql) _table_count" ; + #debug([$this->name,$sql_count]); # NB 08.08.17 if (preg_match('/SELECT.*SELECT|UNION/i',$this->sql)) { # NB 08.08.17 $sql_count = "SELECT COUNT(*) FROM ($this->sql) _table_count" ; # NB 08.08.17 } else { @@ -2052,313 +2034,312 @@ Class Table extends nb { # NB 08.08.17 bye($sql_count); # NB 08.08.17 } - } elseif (preg_match('/^[\w_-]+$/',$sql_count)) { - $sql_count = "SELECT count(*) FROM ".$this->sql_name($sql_count); - - } else { - $sql_count = preg_replace('/ (ORDER|LIMIT) .*?$/s','',$sql_count); - $sql_count = preg_replace('/^SELECT .*FROM/s','SELECT count(*) FROM ',$sql_count); - - } - - $this->count = (int)$this->db()->row($sql_count); - return $this->count; - - } - - public function err_sql($sql) { - $err = $this->db()->conn->errorInfo(); - $err[] = $sql; - $this->bye(join(' | ',$err)); - } - - public function html_menu($opt=[]) { - - $buttons = ''; - if (!empty($opt['buttons'])) $buttons = $opt['buttons']; - - $r = ''; # < Options + + } + + // + // Criterias + // + $r .= '
'; + foreach ( $this->fields() as $k => $f) { + + if ($f->is_encrypt()) continue; + $v = $this->p($k); + + $r .= '' + .'' + . '' + . '' + .'' + ; + + } + + if ($this->p('options')==='0') $r .= $buttons; + $r .= '
'; # < Criterias + + /// + // Bye + /// + $r .= ''.NB_EOL; + return $r; + } + + public function __sleep() { + return [ + 'name', + 'sql', + 'type', + 'fields', + 'extras', + 'row_parse_pre', + 'row_parse_post', + 'count', + 'engine', + 'created', + ]; + } + + public function serialize() { + $this->fields(); + #$this->count(); + return serialize($this); + } + + public function unserialize() { + $o = unserialize($this->serialize()); + return var_export($o,true); + } + + public function type() { + if (isset($this->type)) return $this->type; + return $this->type = $this->status('type'); + } + + public function unvar($value) { + if (empty($value)) return $value; + if (!is_scalar($value)) { + foreach ($value as $k=>$v) { + if (is_scalar($v)) $value[$k] = $this->unvar($v); + } + return $value; + } + $replace = [ + '' => $this->name, + '' => $this->type, + ]; + return str_replace(array_keys($replace),array_values($replace),$value); + } + + public function status($key=null) { + + if (!isset($this->status)) { + + if ($this->type == 'sql') { + + $this->status = [ + 'type' => $this->type, + 'name' => $this->name, + ]; + + } else { + + $this->create_temporary(); + $sql = $this->db()->method('tables'); + if (!$this->p('count')) $sql .= " LIMIT 0"; + $sql = "SELECT * FROM ($sql) t WHERE name=".$this->db()->quote($this->name); + + $sth = $this->db()->conn->query($sql,PDO::FETCH_ASSOC); + if (!empty($sth)) $this->status = $sth->fetch(); + + } # if ($this->type == 'sql') + + if (empty($this->status)) $this->status = []; + + # Add to status array + foreach ([ + 'name', + 'type', + ] as $k) { + if (!empty($this->$k)) $this->status[$k] = $this->$k; + } + + # Add from status array + foreach ([ + 'engine', + 'created', + ] as $k) { + if (empty($this->$k) and !empty($this->status[$k])) $this->$k = $this->status[$k]; + } + } + + # Params + foreach ([ + 'count', + 'fields', + 'sql', + ] as $k) { + if (isset($this->status[$k])) continue; # NB 08.08.17 if (!empty($this->status[$k])) continue; - if (empty($key)) { - if (!$this->p($k)) continue; + if (empty($key)) { + if (!$this->p($k)) continue; - } elseif(is_array($key)) { - if (!in_array($k,$key)) continue; + } elseif(is_array($key)) { + if (!in_array($k,$key)) continue; - } else { - if ($k!=$key) continue; - } + } else { + if ($k!=$key) continue; + } - $this->status[$k] = $this->$k(); - if (is_array($this->status[$k])) $this->status[$k] = count($this->status[$k]); - } + $this->status[$k] = $this->$k(); + if (is_array($this->status[$k])) $this->status[$k] = count($this->status[$k]); + } - if (!empty($key) and is_scalar($key)) return ( empty($this->status[$key]) ? '' : $this->status[$key] ); - return $this->status; - } + if (!empty($key) and is_scalar($key)) return ( empty($this->status[$key]) ? '' : $this->status[$key] ); + return $this->status; + } - private function idtemplate($id=null) { - if (empty($id) - and !( $id=$this->p('idtemplate') ) - and !( $id = $this->idtemplate ) - ) $this->bye('Wrong parameter!'); - return $id; - } + private function idtemplate($id=null) { + if (empty($id) + and !( $id=$this->p('idtemplate') ) + and !( $id = $this->idtemplate ) + ) $this->bye('Wrong parameter!'); + return $id; + } - public function template($id=null) { - $id = $this->idtemplate($id); + public function template($id=null) { + $id = $this->idtemplate($id); - $id = preg_replace('/[^\w\._-]/','',$id); + $id = preg_replace('/[^\w\._-]/','',$id); - $file = TABLE_TEMPLATE.'/'.$id.'.php'; - if (!is_readable($file)) return false; #$this->bye("Wrong id `$id`"); + $file = TABLE_TEMPLATE.'/'.$id.'.php'; + if (!is_readable($file)) return false; #$this->bye("Wrong id `$id`"); - $opt = [ 'format'=> '' ]; - $this->rows($opt); + $opt = [ 'format'=> '' ]; + $this->rows($opt); - $HEAD = &$opt['var']['head']; - $ROWS = &$opt['var']['rows']; - $ROW = &$opt['var']['rows'][0]; - foreach ($ROWS as $key=>$row) { - $i=0; - foreach ($row as $k=>$v) { - $ROWS[$key][$i] = $v; - $i++; - } - } - #$opt['var']['rows']=[]; + $HEAD = &$opt['var']['head']; + $ROWS = &$opt['var']['rows']; + $ROW = &$opt['var']['rows'][0]; + foreach ($ROWS as $key=>$row) { + $i=0; + foreach ($row as $k=>$v) { + $ROWS[$key][$i] = $v; + $i++; + } + } + #$opt['var']['rows']=[]; - # Protect $_REQUEST ! - $_REQUEST_BAK = $_REQUEST; - $_REQUEST = array_merge($_REQUEST,$ROW); + # Protect $_REQUEST ! + $_REQUEST_BAK = $_REQUEST; + $_REQUEST = array_merge($_REQUEST,$ROW); - $ex = require $file; + $ex = require $file; - $_REQUEST = $_REQUEST_BAK; + $_REQUEST = $_REQUEST_BAK; - #return $ex; - } + #return $ex; + } - public function ssha_password($password) { - return $this->db()->ssha_password($password); - } + public function ssha_password($password) { + return $this->db()->ssha_password($password); + } - static public function _bye($msg = '__bye__', $backtrace_deep = 0) { - die($msg); - } + static public function _bye($msg = '__bye__', $backtrace_deep = 0) { + die($msg); + } } # < Class -__table_define(); ?>