]> git.nbdom.net Git - nb.git/commitdiff
db, getexp
authorNicolas Boisselier <nicolas.boisselier@gmail.com>
Sun, 26 Jul 2015 23:55:51 +0000 (00:55 +0100)
committerNicolas Boisselier <nicolas.boisselier@gmail.com>
Sun, 26 Jul 2015 23:55:51 +0000 (00:55 +0100)
etc/profile.d/0default.sh [new file with mode: 0644]
etc/profile.d/nb.sh
lib/css/db.css
lib/js/tools.js
lib/php/db.php
lib/php/db/field.php
lib/php/db/table.php
lib/php/page.php

diff --git a/etc/profile.d/0default.sh b/etc/profile.d/0default.sh
new file mode 100644 (file)
index 0000000..6023b9b
--- /dev/null
@@ -0,0 +1,41 @@
+radio_play() {
+#1 | FranceInter   | http://www.tv-radio.com/station/france_inter_mp3/france_inter_mp3-128k.m3u
+#3 | FranceInfo    | http://players.creacast.com/creacast/france_info/playlist.m3u
+#4 | FranceCulture | http://www.tv-radio.com/station/france_culture_mp3/france_culture_mp3-128k.m3u 
+  local radios="\
+1 | FranceInter   | http://audio.scdn.arkena.com/11008/franceinter-midfi128.mp3
+2 | Indie         | http://107.155.126.42:17160/listen.pls
+3 | FranceInfo    | http://audio.scdn.arkena.com/11006/franceinfo-midfi128.mp3
+4 | FranceCulture | http://audio.scdn.arkena.com/11010/franceculture-midfi128.mp3
+
+Choose one > \
+"
+  if [ -z "$@" ]; then
+    read -p "$radios"
+  else
+    REPLY="$@"
+  fi
+
+  test -z "$REPLY" 2>/dev/null && return
+  echo "$radios" | awk -F '|' '$1 == '$REPLY' {print $3; exit}' | sed 's/^ //' | xargs mplayer 2>/dev/null
+}
+
+_getexp_pcregrep=""
+getexp() {
+  [ -z "$*" -o "$1" == "-h" -o "$1" == "--help" ] && echo "Usage: $FUNCNAME [capture number|default 0] PERL_REGEXP FILES..." && return
+  declare exp num
+  num=0; case "$1" in [0-9]*) num=$1; shift ;; esac
+  exp=$1; shift
+
+  if [ -z "$_getexp_pcregrep" ]; then
+    _getexp_pcregrep=0
+    which pcregrep > /dev/null && _getexp_pcregrep=1
+  fi
+
+  if [ $_getexp_pcregrep = 1 ]; then
+    pcregrep -o${num} "$exp" $@
+  else
+    perl -ne 'BEGIN{$e=shift @ARGV; $n=shift(@ARGV) or 0; $e="($e)" and $n=1 if $n==0} (@_=m{$e}) and ($n<=scalar(@_)) and print ($n==0 ? $_[0] : $_[$n-1].chr(10))' "$exp" "$num" $@
+  fi
+  return
+}
index 20e8b5f83413ccc83ee4449b399f1287c8d1779c..12e13d988d35bc1c423d47ac2678590135f939dc 100644 (file)
@@ -130,26 +130,3 @@ nb_alert() {
 # NB 09.06.15   fi
   eval "$cmd"
 }
-
-radio_play() {
-#1 | FranceInter   | http://www.tv-radio.com/station/france_inter_mp3/france_inter_mp3-128k.m3u
-#3 | FranceInfo    | http://players.creacast.com/creacast/france_info/playlist.m3u
-#4 | FranceCulture | http://www.tv-radio.com/station/france_culture_mp3/france_culture_mp3-128k.m3u 
-  local radios="\
-1 | FranceInter   | http://audio.scdn.arkena.com/11008/franceinter-midfi128.mp3
-2 | Indie         | http://107.155.126.42:17160/listen.pls
-3 | FranceInfo    | http://audio.scdn.arkena.com/11006/franceinfo-midfi128.mp3
-4 | FranceCulture | http://audio.scdn.arkena.com/11010/franceculture-midfi128.mp3
-
-Choose one > \
-"
-  if [ -z "$@" ]; then
-    read -p "$radios"
-  else
-    REPLY="$@"
-  fi
-
-  test -z "$REPLY" 2>/dev/null && return
-  awk -F '|' '$1 == '$REPLY' {print $3; exit}' <<< "$radios" | sed 's/^ //' | xargs mplayer 2>/dev/null
-}
-
index ba3bc96800e775cd7a0cedd58be348a318c32332..adbcb6e073bc628221d0991723d24184df091316 100644 (file)
@@ -7,6 +7,27 @@ border: solid  1px red !important;
 #db {
 }
 
+/*
+  All
+*/
+form .button,
+form input,
+form select,
+form label
+{
+  margin: 0.3em 0.3em 0.3em 0;
+}
+
+form label {
+  display: inline-block;
+  width: 4em;
+  text-align: right;
+}
+
+form label:after {
+  content: ": ";
+}
+
 /*
   List
 */
@@ -35,45 +56,15 @@ td.phone {
   margin: 0 auto;
   padding: 0.8em 0.8em 0.8em 0.5em;
   padding: 0.5em 0.8em;
-  /*
   display: table;
-  */
 }
 
-.db.menu hr {
-  clear: both;
-  margin: 0;
-  padding: 0.5px 0;
-  border: none;
-  background-color: #f4f4f4;
-}
-
-.db.menu .button,
-.db.menu input,
-.db.menu select,
-.db.menu label
-{
-  margin: 0.3em 0.3em 0.3em 0;
-}
-
-.db.menu span.i,
-.db.menu span.i label {
-  float: left;
-}
-.db.menu span.i label {
-  display: inline-block;
-  width: 4em;
-  text-align: right;
-}
-
-.db.menu label:after {
-  content: ": ";
+div.criterias {
+  border-top: solid 1px #f4f4f4;
+  padding-top: 0.1em;
 }
 
 ul.db.menu {
-  /*
-  margin: -4em 0.4em 0 -7em;
-  */
   max-width: 7em;
 }
 
@@ -92,34 +83,28 @@ li.tables li {
 /*
   Edit
 */
-form.db.edit label
-,form.db.edit input
-{
-  float: left;
-}
 
-div.Zdb.edit {
-  width: 100%;
+form.db.edit {
+  max-width: 50em;
+  margin: 0 auto;
 }
 
 form.db.edit label {
-  clear: left;
   width: 20%;
   margin-bottom: 0.3em;
 }
 
 form.db.edit input {
-  width: 75%;
+  width: 70%;
 }
 
 form.db.edit .buttons {
-  margin: 0 auto;
+  margin: 0.5em auto 0 auto;
   text-align: center;
   clear: both;
 }
 
 form.db.edit .buttons input {
-border: solid 1px red;
   width: auto;
   float: none;
 }
index b63eb722a257764869c5f751116a866973306084..f92a24741110f02b70f6e96e700a9ee9de3d385b 100644 (file)
@@ -5,6 +5,42 @@
  */
 function NB() {
 
+  this.form_submit_clean = function(f) {
+    var i = 0;
+    var msg = '';
+    var url = '';
+    msg += f.action + '\n';
+
+    for(i=0;i<f.length;i++) {
+      var p = f[i];
+      if (!p.name) continue;
+      if (p.value=='') continue;
+      if (p.value=='undefined') continue;
+      msg += p.name + '=' + p.value + '\n';
+  // NB 02.09.13               url += (url ? '&' : '?') + escape(p.name) + '=' + escape(p.value);
+      url += (url ? '&' : '?') + encodeURI(p.name) + '=' + encodeURI(p.value);
+    }
+
+    url = f.action + url;
+
+    //document.location = url;
+
+  /*
+  if (izi_opt['test_version']) {
+    html_msg(''
+      + '<a href="#" onclick="window.location=\''+(url)+'\'; return false;">'
+      + (url)
+      + '</a>'
+    );
+    return false;
+  }
+  */
+
+    //if (url == window.location) return false;
+    window.location = url;
+    return false;
+  }
+
   this.form_clear = function(form) {
     var e;
     for(i=0;i<form.length;i++) {
index 9546c7f63d752f4df5709f293329e2f8d2b09825..ba2e264c5481a454be8fdc8a0eaf3af644f7af0e 100644 (file)
@@ -10,7 +10,8 @@ require_once(dirname(__FILE__).'/functions.php');
 require_once(dirname(__FILE__).'/db/table.php');
 require_once(dirname(__FILE__).'/db/field.php');
 if (!defined('DB_HTML_FORM_BUTTONS')) define('DB_HTML_FORM_BUTTONS',''
-  .'<input type="button" class="button" value="Add" onclick="this.setAttribute(\'type\',\'submit\');this.setAttribute(\'name\',\'edit\')?1:1"/>'
+  .'<input type="button" class="button" value="Add" onclick="window.location = \'?action=edit&amp;table=\'+this.parentElement.elements[\'table\'].value"/>'
+  #.'<input type="button" class="button" value="Add" onclick="this.setAttribute(\'type\',\'submit\');this.setAttribute(\'name\',\'edit\')?1:1"/>'
   #.'<input type="button" class="button" value="Add" onclick="this.setAttribute(\'name\',\'edit\');this.parentElement.submit()?0:0"/>'
   #.'<input type="button" class="button" onclick="return nb.form_clear(this.parentElement)" value="X"/>'
   .'<a class="button" href="#" onclick="nb.form_clear(this.parentElement)?0:0">X</a>'
@@ -97,10 +98,37 @@ class db {
   function database() {
     $rows = $this->db->query('PRAGMA database_list');
   }
+
+  function execParams($sql,$params) {
+
+    try {
+      $r = $this->conn->execParams($sql, $params);
+    } catch (PDOException $e) {
+      err(join(': ',array($e->getMessage(),"Db.execParam()",$sql)));
+      $r = null;
+    }
+
+    return $r;
+  }
 */
 
-  function exec($sql) {
-    return $this->conn->exec($sql);
+  function exec($sql,$params=null) {
+
+    try {
+      $r = $this->conn->exec($sql,$params);
+      /*
+      if ($params === null) {
+        $r = $this->conn->exec($sql,$params);
+      } else {
+        $r = $this->conn->exec($sql);
+      }
+      */
+    } catch (PDOException $e) {
+      err(join(': ',array($e->getMessage(),"Db.exec()",$sql)));
+      $r = null;
+    }
+
+    return $r;
   }
 
   function query($sql) {
@@ -109,7 +137,7 @@ class db {
     try {
       $r = $this->conn->query($sql);
     } catch (PDOException $e) {
-      err(array("Db.query()",$e->getMessage(),$sql));
+      err(join(': ',array($e->getMessage(),"Db.query()",$sql)));
       $r = null;
     }
 
@@ -126,6 +154,7 @@ class db {
     return join($sep,$query->fetch(PDO::FETCH_NUM));
   }
 
+  /*
   function query2a($sql) {
     $r = $this->conn->query($sql,PDO::FETCH_COLUMN);
     return $r ? $r->fetch() : $r;
@@ -144,6 +173,7 @@ class db {
     return $this->conn->query($sql,PDO::FETCH_ASSOC);
   }
 
+  */
   function quote($v) {
     return $this->conn->quote($v);
   }
@@ -233,29 +263,11 @@ EOF;
   function html_menu($table=null) {
 
     $html = ' onchange="this.parentElement.submit()"';
-    $r = '<form class="db menu" method="get" action="">'.PHP_EOL;
-
-    if (!empty($table)) {
-      foreach ( array_keys($table->fields()) as $k ) {
+    $r = '<form class="db menu" method="get" action="" onsubmit="return nb.form_submit_clean(this)">'.PHP_EOL;
 
-        $v = $this->p($k);
-
-        $r .= ''
-          .'<span class="i">'
-          . '<label>'.prettyText($k)
-          .'</label>'
-          . '<input type="text" id="'.$k.'" name="'.$k.'" value="'.$v.'" />'
-          .'</span>'
-        ;
-
-      }
-      #$r .= '<span class=""></span>';
-      $r .= '<hr/>';
-    }
-
-    /// Tables
+    // Tables
     $r .= '<label>Tables</label>'.html_select_array($this->tables(),array(
-      'html'       => 'class="tables" name="table"'.$html,
+      'html'       => 'class="tables" name="table"'.preg_replace('/"/','"nb.form_clear(this.parentElement);',$html,1),
       'selected'   => $this->p('table'),
       'prettyText' => true,
     ));
@@ -278,8 +290,30 @@ EOF;
       'prettyText' => true,
     ));
 
-    // Bye
+    // Buttons
     $r .= DB_HTML_FORM_BUTTONS;
+
+    // Criterias
+    if (!empty($table)) {
+      $r .= '<div class="criterias">';
+      foreach ( array_keys($table->fields()) as $k ) {
+
+        $v = $this->p($k);
+
+        $r .= ''
+          #.'<span class="i">'
+          . '<label>'.prettyText($k)
+          .'</label>'
+          . '<input type="text" id="'.$k.'" name="'.$k.'" value="'.$v.'" />'
+          #.'</span>'
+        ;
+
+      }
+      $r .= '</div>';
+      #$r .= '<span class=""></span>';
+    }
+
+    // Bye
     $r .= '</form>'.PHP_EOL;
     return $r;
   }
@@ -305,6 +339,12 @@ EOF;
     return isset($_REQUEST[$name]) ? $_REQUEST[$name] : $default;
   }
 
+  function sql_name($value) {
+    if (preg_match('/^\w+$/',$value)) return $value;
+    if ($this->db->type == 'mysql') return '`'.$value.'`';
+    return '"'.$value.'"';
+  }
+
 }
 
 ?>
index 0c03d2229703d9916ad7f9eec743aa3ace248303..01826a9c5ca8809172bcbf0eed8be0623273ce74 100644 (file)
@@ -1,47 +1,70 @@
 <?php
-$DB_FIELD_CONN = isset($Db) ? $Db->conn : null;
+/*
+$DB_FIELD_TYPES = array(
+ 'bool' => PDO::PARAM_BOOL,
+ #'null' => PDO::PARAM_NULL,
+ 'int' => PDO::PARAM_INT,
+ 'str' => PDO::PARAM_STR,
+ 'blob' => PDO::PARAM_LOB,
+);
+*/
 class field {
 
   public $name;
   public $type = 'text';
   public $default = null;
+  private $autoincrement = false;
   public $key = false;
-  public $autoinc = false;
+  public $table = null;
 
-  function __construct($name,$attr=array()) {
-    $this->name = $name;
+  function __construct($attr=array()) {
     foreach ($attr as $k => $v) { $this->$k = $v; }
   }
 
-  function is_num() {
-    return preg_match('/int|float|number|currency/',$this->type) ? 1 : 0;
+  function autoincrement() {
+    return $this->autoincrement;
+  }
+
+  function numeric() {
+    return preg_match('/int|float|number|currency/',$this->type) ? true : false;
   }
 
   function html_edit($value) {
 
-    return '<label for="'.$this->name.'">'.htmlspecialchars($this->name).'</label>'
+    return '<label for="'.$this->name.'">'.htmlspecialchars(prettyText($this->name)).'</label>'
     .'<input name="'.$this->name.'" id="'.$this->name.'" value="'.htmlspecialchars($value).'" />'
     .PHP_EOL;
 
   }
 
+  function db() {
+    global $Db;
+    return ( isset($Db) ? $Db : null );
+  }
+
+  function sql_name() {
+    return $this->db()->sql_name($this->name);
+  }
+
   function quote($value,$force_quote=false) {
 
-    if ($DB_FIELD_CONN === null) return "'".str_replace("'","\\'",$value)."'";
-    return $DB_FIELD_CONN->quote($value);
+    if ($force_quote or !$this->numeric()) {
 
-// TODEL - NB 08.07.15
-    if ($force_quote or !$field->is_num()) {
+      if (($db = $this->db()) === null) return "'".preg_replace("/'/","\\'",$value)."'";
+      return $db->quote($value);
+    } else {
 
-      if ($DB_FIELD_CONN === null) return "'".preg_replace("/'/","\\'",$value)."'";
-      return $DB_FIELD_CONN->quote($value);
+      if (strcmp($value,'') == 0) $value = 'NULL';
     }
 
     return $value;
   }
 
-  function where($value) {
+  function size() {
+    return preg_match('/\((\d+)\)/',$this->type,$m) ? $m[1] : null;
+  }
 
+  function where($values) {
     // No empty value
     $v = isset($value) ? $value : null;
     if (strcmp($v,'')==0
@@ -51,7 +74,7 @@ class field {
     ) return null;
 
 // NB 03.07.15       $number = preg_match('/int|float|number|currency/',$this->type) ? 1 : 0;
-    $number = $this->is_num();
+    $number = $this->numeric();
 
     // Equal / Not Equal
     $equal = '=';
@@ -61,14 +84,14 @@ class field {
 
     // Regex
     if (strpos($v,'~')===0) {
-      return $this->name . ($not ? 'NOT ' : '').'REGEXP ' . $DB_FIELD_CONN->quote( substr($v,1) );
+      return $this->name . ($not ? 'NOT ' : '').'REGEXP ' . $this->db()->quote( substr($v,1) );
     }
 
     // Text
     if (!$this->num() or !preg_match('/^\d+(\.\d*)?$/',$v)) { # text criteria value
 
       if (strtolower($v)=='null') $v = '';
-      return $this->name.' '.($not ? 'NOT ' : '').'LIKE '.$DB_FIELD_CONN->quote(str_replace('*','%',$v));
+      return $this->name.' '.($not ? 'NOT ' : '').'LIKE '.$this->db()->quote(str_replace('*','%',$v));
 
     // Others
     } else {
@@ -79,7 +102,7 @@ class field {
 
       // Date, Time
       } else {
-        $v = $DB_FIELD_CONN->quote($v);
+        $v = $this->db()->quote($v);
 
       }
       $equal = $not ? '<>' : '=';
@@ -89,5 +112,19 @@ class field {
     return "$k$equal$v";
   }
 
+  function pdo_type() {
+    if ($this->numeric) return PDO::PARAM_INT;
+    if (strpos($this->type,'bool') !== false ) return PDO::PARAM_BOOL;
+    if (strpos($this->type,'blob') !== false ) return PDO::PARAM_LOB; # not a bug LOB
+    return PDO::PARAM_STR;
+  }
+
+  function bindParam($sth,$value) {
+    # See: http://php.net/manual/en/pdostatement.bindparam.php
+    $sth->bindParam(':'.$this->name, $value, PDO::PARAM_INT);
+    $sth->bindParam(':'.$this->name, $value, PDO::PARAM_STR);
+    $sth->bindParam(':calories', $calories, PDO::PARAM_INT);
+  }
+
 }
 ?>
index 513c0b9b5e93c9b945b55a3579de804379019938..c043cc416fb153a503b4286e8ba32fef1b213d26 100644 (file)
@@ -1,6 +1,7 @@
 <?php
 require_once(dirname(__FILE__).'/../functions.php');
 require_once(dirname(__FILE__).'/../db.php');
+require_once(dirname(__FILE__).'/../db/field.php');
 
 if (false and empty($_SERVER['DOCUMENT_ROOT'])) {
   $_REQUEST['db'] = 'rent'; $name = 'tenant';
@@ -120,45 +121,51 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
 
       foreach ($rows as $row) {
 
-        $this->fields[$row['name']] = array(
+        $field = array(
+          'name'          => null,
           'extra'         => null,
           'type'          => null,
           'default'       => null,
           'key'           => null,
-          'autoincrement' => false,
+          'autoincrement' => null,
         );
 
-        $this->fields[$row['name']]['type'] = strtolower($row['type']);
+        $field['name'] = $row['name'];
+        $field['type'] = strtolower($row['type']);
 
         if (isset($row['notnull'])) {
-          $this->fields[$row['name']]['null'] = $row['notnull'] == '0' ? 1 : 0;
+          $field['null'] = $row['notnull'] == '0' ? 1 : 0;
 
         } else {
-          $this->fields[$row['name']]['null'] = preg_match('/^1|yes|t/i',$row['null']) ? 1 : 0;
+          $field['null'] = preg_match('/^1|yes|t/i',$row['null']) ? true : false;
 
         }
 
-        # sqlite autoincrement
-        if ($this->db->type == 'sqlite' and preg_match('/[\(,]'.$row['name'].' [^\),]+ AUTOINCREMENT/',$this->sql())) {
-          $this->fields[$row['name']]['autoincrement'] = true;
-        }
+        # Autoincrement
 
         # mysql autoincrement
         if (isset($row['Extra']) and $row['Extra'] == 'auto_increment') {
-          $this->fields[$row['name']]['autoincrement'] = true;
+          $field['autoincrement'] = true;
+
+        # sqlite autoincrement
+        } elseif ($this->db->type == 'sqlite'
+          and preg_match('/[\(,]'.$row['name'].' [^\),]+ AUTOINCREMENT/',$this->sql())
+        ) {
+          $field['autoincrement'] = true;
+
         }
 
         # Postgres autoincrement / default
         if (isset($row['pg_default'])) {
 
           if (preg_match('/^nextval\(/',$row['pg_default'])) {
-            $this->fields[$row['name']]['autoincrement'] = true;
+            $field['autoincrement'] = true;
 
           } elseif (preg_match("/^''/",$row['pg_default'])) {
-            $this->fields[$row['name']]['default'] = '';
+            $field['default'] = '';
 
           } else {
-            $this->fields[$row['name']]['default'] = $row['pg_default'];
+            $field['default'] = $row['pg_default'];
 
           }
         }
@@ -166,14 +173,16 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
         # sqlite default
         foreach (array('dflt_value') as $f) {
           if (!isset($row[$f])) continue;
-          $this->fields[$row['name']]['default'] = $row[$f];
+          $field['default'] = $row[$f];
         }
 
         foreach (array('pk','Key') as $f) {
           if (!isset($row[$f])) continue;
-          $this->fields[$row['name']]['key'] = preg_match('/^1|yes|t/i',$row[$f]) ? 1 : 0;
+          $field['key'] = preg_match('/^1|yes|t/i',$row[$f]) ? 1 : 0;
         }
 
+        $this->fields[$row['name']] = new field($field);
+
       }
 
     }
@@ -193,7 +202,7 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
     $keys = $this->fields_keys($others);
     if (empty($keys)) $keys = $others;
 
-    foreach ($keys as $name => $spec) {
+    foreach ($keys as $name => $field) {
       if (isset($values[$name]) and strcmp($values[$name],'')!=0)
         $url[] = $name . '=' .urlencode($values[$name])
       ;
@@ -204,21 +213,17 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
 
   function fields_keys(&$others=array()) {
     
-    #if (!$this->fields_keys) {
-      $this->fields_keys = array();
+    $fields_keys = array();
 
-      foreach ($this->fields() as $name => $f) {
-        #debug($f);
-        if ((int)$f['key'] == 1) {
-          $this->fields_keys[$name] = $f;
-        } else {
-          $others[$name] = $f;
-        }
+    foreach ($this->fields() as $name => $f) {
+      if ($f->key) {
+        $fields_keys[$name] = $f;
+      } else {
+        $others[$name] = $f;
       }
+    }
 
-    #}
-
-    return $this->fields_keys;
+    return $fields_keys;
 
   }
 
@@ -227,37 +232,43 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
     if (!is_array($values)) $values = array($values);
 
     $add = false;
-    $where = str_replace(' LIKE ','=',$this->where_criterias($values));
+    #$where = str_replace(' LIKE ','=',$this->where_criterias($values));
+    $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;
-    $sql .= " LIMIT 1";
     $this->sql = $sql;
 
     $this->debug($sql,1);
     $st = $this->db->conn->prepare($sql);
     $st->execute();
 
-    echo '<form class="db edit" method="post" action="">'.PHP_EOL;
+    echo '<form class="db edit" method="post" action="?">'.PHP_EOL;
+    echo '<div class="fields">'.PHP_EOL;
     $count = 0;
-    if ($row = $st->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT) or $add) {
+    if ( $add or ($row = $st->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT))) {
       $count ++;
 
-      foreach ($this->fields() as $name => $attr) {
-        $field = new field($name,$attr);
-        echo $field->html_edit( (is_array($row) and array_key_exists($name,$row) ) ? $row[$name] : $attr['default']);
-        unset($field);
+      foreach ($this->fields() as $name => $field) {
+        echo $field->html_edit(
+          (! $add and array_key_exists($name,$row) ) ? $row[$name] : $field->default
+        );
       }
+
     }
+    echo '</div>'.PHP_EOL;
 
     echo ''
       .'<div class="db buttons">'
-      .'<input type="submit" name="update"/>'
+      .'<input type="submit"/>'
       .'<input type="hidden" name="table" value="'.$this->db->p('table').'"/>'
+      .'<input type="hidden" name="action" value="'.($add ? 'insert' : 'update').'"/>'
       .'<input type="reset" />'
       .( empty($_SERVER['HTTP_REFERER']) ? '' : '<input type="button" onclick="document.location=document.referrer" value="Cancel" />')
       .'</div>'.PHP_EOL
@@ -413,18 +424,34 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
 
   }
 
+  function where($fields,$hvalues,$need_all_values=false) {
+
+    // Construct where
+    $where = array();
+    foreach ($fields as $k => $field) {
+      if (!isset($hvalues[$k])) {
+        if ($need_all_values) return null;
+        continue;
+      }
+      $where[] = $field->sql_name() . '=' . $field->quote($hvalues[$k]);
+    }
+    #var_dump($where); exit;
+      #.' VALUES (' . join(',',ar_map('":$a"',$fields)).')'
+
+    return empty($where) ? '' : ' WHERE ' . join(' AND ',$where);
+
+  }
+
   function where_criterias($values,$logic='') {
     $having = $where = array();
     if (empty($logic)) $logic = 'AND';
 
-    foreach ($this->fields() as $k => $spec) {
+    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;
-// NB 03.07.15       $number = preg_match('/int|float|number|currency/',$spec['type']) ? 1 : 0;
-      $field = new field($k,$spec);
-      $number = $field->is_num();
+      $number = $field->numeric();
 
       // Equal / Not Equal
       $equal = '=';
@@ -434,11 +461,11 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
       // Regex
       if (strpos($v,'~')===0) {
         $v = substr($v,1);
-        $v = $this->db->conn->quote($v);
+        $v = $this->db->quote($v);
         $equal = ' '.($not ? 'NOT ' : '').'REGEXP ';
 
       // Text
-      } elseif (preg_match('/text|char|blob/',$spec['type'])
+      } elseif (preg_match('/text|char|blob/',$field->type)
         or !preg_match('/^\d+(\.\d*)?$/',$v) # text criteria value
       ) {
 
@@ -448,7 +475,7 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
         // * -> %
         $v = str_replace('*','%',$v);
 
-        $v = $this->db->conn->quote($v);
+        $v = $this->db->quote($v);
         $equal = ' '.($not ? 'NOT ' : '').'LIKE ';
 
       // Others
@@ -460,7 +487,7 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
 
         // Date, Time
         } else {
-          $v = $this->db->conn->quote($v);
+          $v = $this->db->quote($v);
 
         }
         $equal = $not ? '<>' : '=';
@@ -468,20 +495,19 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
       }
 
       if (preg_match('/(LIKE|REGEXP) ..$/',"$equal$v")) {
-        $k = "COALESCE($k,".$this->db->conn->quote('').")";
+        $k = "COALESCE($k,".$this->db->quote('').")";
       }
 
-      if ($this->db->type == 'mysql' and $spec['extra']) {
+      if ($this->db->type == 'mysql' and $field->extra) {
         $having[] = "$k$equal$v";
 
-      } elseif ($this->db->type == 'pgsql' and $spec['extra']) {
+      } elseif ($this->db->type == 'pgsql' and $field->extra) {
         $where[] = $this->extras[$k]."$equal$v";
 
       } else {
         $where[] = "$k$equal$v";
       }
 
-      unset($field);
     } #foreach fields
 
     $sql = '';
@@ -518,14 +544,14 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
 
       $select[] = "$v AS ".($this->db->type == 'pgsql' 
         ? '"'.str_replace('"','\"',$k).'"'
-        : $this->db->conn->quote($k)
+        : $this->db->quote($k)
       );
       /*
-      $select[] = "$v AS ".$this->db->conn->quote($k);
+      $select[] = "$v AS ".$this->db->quote($k);
       */
 
       /*
-      $k = $this->db->conn->quote($k);
+      $k = $this->db->quote($k);
       if ($this->db->type == 'pgsqpl') $k = str_replace(
       $select[] = "$v AS $k"
       */
@@ -546,7 +572,6 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
     $sql = "SELECT *" . $this->select_extras();
     $sql .= " FROM $this->name".$this->where_criterias($this->db->p(),$this->db->p('op'));
     $this->sql = $sql;
-    #$this->debug($sql);
     $this->debug($sql,1);
 
     //
@@ -589,13 +614,13 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
       $count++;
       $count_fields = 0;
 
-      foreach ($this->fields() as $f => $spec) {
+      foreach ($this->fields() as $f => $field) {
 
-        if (!$spec['extra']) {
+        if (!$field->extra) {
           if ($escape) $row[$f] = htmlspecialchars($row[$f]);
         }
 
-        if ($this->db->type == 'sqlite' and preg_match('/^float\((?:\d+,)?(\d+)\)/',$spec['type'],$m)) {
+        if ($this->db->type == 'sqlite' and preg_match('/^float\((?:\d+,)?(\d+)\)/',$field->type,$m)) {
           $row[$f] = sprintf('%.'.$m[1].'f',$row[$f]);
         }
 
@@ -608,8 +633,8 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
       }
 
       if ($opt['is_html']) {
-        array_unshift($row,'<a class="edit button" href="'.$this->url_keys($row,'edit=1').'">'.DB_HTML_EDIT.'</a>');
-        array_push($row,'<a class="delete button" href="'.$this->url_keys($row,'delete=1').'">'.DB_HTML_DELETE.'</a>');
+        array_unshift($row,'<a class="edit button" href="'.$this->url_keys($row,'action=edit').'">'.DB_HTML_EDIT.'</a>');
+        array_push($row,'<a class="delete button" href="'.$this->url_keys($row,'action=delete').'">'.DB_HTML_DELETE.'</a>');
       }
 
       echo $this->{"rows_rec_$format"}($row);
@@ -803,58 +828,105 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
   }
 
   function sql_name() {
-    if ($this->db->type == 'mysql') return '`'.$this->name.'`';
-    return $this->name;
+    return $this->db->sql_name($this->name);
+  }
+
+  function insert($hvalues) {
+    $names = $values = array();
+    #var_dump($hvalues);
+    foreach ($this->fields() as $name => $field) {
+      if (!isset($hvalues[$name])) continue;
+      if ($field->key and $field->autoincrement()) continue;
+      $names[] = $field->sql_name();
+      #$values[] = $field->quote($hvalues[$name]);
+      $values[] = $hvalues[$name];
+    }
+    #bye($values);
+
+    $sql = 
+      'INSERT INTO '. $this->sql_name() . ' (' . join(',',$names).')'
+      #.' VALUES ('  . join(',',$values).')'
+      .' VALUES (' . join(',',ar_map('"?"',$values)) . ')'
+    ;
+    bye(array($sql,$values));
+
+    return $this->db->exec($sql,$values);
+    return $this->db->exec($sql);
   }
 
   function update($hvalues) {
     
-    $keys = $this->fields_keys($values);
-    $values = array_keys($values);
-    $keys = $keys ? array_keys($keys) : $values;
-    $fields = array_keys($this->fields());
-    #bye($keys);
+    $keys = array();
+    $keys_values = array();
+    $fields = array();
+    $fields_values = array();
+    $values = array();
 
-    $sql = 
-      ($this->db->type == 'mysql' ? 'REPLACE' : 'REPLACE')
-      .' INTO '    . $this->sql_name() . ' (' . join(',',$fields).')'
-      .' VALUES (' . join(',',ar_map('":$a"',$fields)).')'
-      #.' WHERE '   . join(' AND ',ar_map('"$a=:$a"',$keys))
-    ;
-    $_sql =  ''
+    foreach ($this->fields() as $name => $field) {
+
+      if (!isset($hvalues[$name])) continue;
+      $value = $hvalues[$name];
+
+      if ($field->key) {
+        $keys[] = $name;
+        $keys_values[] = $name;
+
+      } else {
+        $fields[] = $name;
+        $fields_values[] = $name;
+
+      }
+
+    }
+
+    if (empty($keys)) {
+      $keys = $fields;
+      $keys_values = $fields_values;
+    }
+
+    $sql =  ''
       .'UPDATE ' . $this->sql_name()
-      .' SET '   . join(',',ar_map('"$a=:$a"',$values))
-      .' WHERE ' . join(' AND ',ar_map('"$a=:$a"',$keys))
+      .' SET '   . join(',',ar_map('"$a=:$a"',$fields))
+      .' WHERE ' . join(' AND ',ar_map('"$a=:key_$a"',$keys))
     ;
-    debug($sql);
-    $query = $this->db->conn->prepare($sql);
-    if (!$query) return err('PDO::errorInfo(): ' .join(' ', $this->db->conn->errorInfo()) .PHP_EOL);
+
+    #bye($sql);
+    $this->debug($sql,1);
+
+    if (!($query = $this->db->conn->prepare($sql))) {
+      err('PDO::errorInfo(): ' .join(' ', $this->db->conn->errorInfo()) .PHP_EOL);
+      return false;
+    }
      
-    #print_r(array_keys($this->fields()));
-    #debug($hvalues);
-    foreach (array_keys($this->fields()) as $k) {
-      #echo "== $k=".$hvalues[$k].'</br>'.PHP_EOL;
-      $query->bindParam(":$k", $hvalues[$k]);
+    foreach ($fields as $name) {
+      $query->bindParam(":$name", $hvalues[$name]);
+    }
+    foreach ($keys as $name) {
+      $query->bindParam(":key_$name", $hvalues[$name]);
     }
 
     #return $sql;
-    $execute = $query->execute();
-    if (!$execute) return err('PDO::errorInfo(): ' .join(' ', $this->db->conn->errorInfo()) .PHP_EOL);
-    debug($execute);
+    if (!($execute = $query->execute())) {
+      err('PDO::errorInfo(): ' .join(' ', $this->db->conn->errorInfo()) .PHP_EOL);
+      return false;
+    }
+
+    return $execute;
 
   }
 
-  function delete($hvalues) {
-    $where = str_replace(' LIKE ','=',$this->where_criterias($hvalues));
-    if (!$where) return 0;
-    $sql = 'DELETE FROM ' . $this->sql_name() . $where;
-    debug($sql);
-    try {
-      $this->db->conn->query($sql);
-    } catch (PDOException $e) {
-      return err($e->getMessage(), "Table.delete()");
+  function delete($hvalues,&$e=null) {
+    $keys = $this->fields_keys();
+    // If no primary keys, we use all field
+    if (empty($keys)) $keys = $this->fields();
+
+    if (!($where = $this->where($keys,$hvalues,true))) {
+      err('Db.delete(): Missing keys values');
+      return null;
     }
-    return true;
+
+    $sql = 'DELETE FROM ' . $this->sql_name() . $where;
+    return $this->db->exec($sql);
   }
 
 }
index e21f2fdf66d0a70882a5b2243e7b2575ade272c4..dea7980df0991b46183eec9eff82c9160ad9718e 100644 (file)
@@ -32,6 +32,9 @@ class Page {
   public $js = array();
   public $js_code = '';
 
+  public $body_class;
+  public $body_id;
+
   /*
     Create
   */
@@ -200,7 +203,10 @@ class Page {
 
     if (preg_match('/ml$/',$this->content_type)) {
 
-      echo '<body>' . PHP_EOL;
+      echo '<body'
+        .(empty($this->body_class) ? '' : ' class="'.$this->body_class.'"')
+        .(empty($this->body_id)    ? '' : ' id="'.$this->body_id.'"')
+      .'>' . PHP_EOL;
       if ($this->title) echo $this->tag($this->title,'h1').PHP_EOL;
     }