]> git.nbdom.net Git - nb.git/commitdiff
out(), clean html, ...
authorNicolas Boisselier <nicolas.boisselier@gmail.com>
Sun, 28 Feb 2016 05:51:38 +0000 (05:51 +0000)
committerNicolas Boisselier <nicolas.boisselier@gmail.com>
Sun, 28 Feb 2016 05:51:38 +0000 (05:51 +0000)
lib/php/db.php
lib/php/db/table.php
lib/php/nb.php

index 9539aa7a18e0bca5cdd7a3b161aceaab0e983316..52e6467ebc9c043e86509274d5f726494d3e9223 100644 (file)
@@ -8,7 +8,6 @@
 *****************************************************************************/
 require_once(dirname(__FILE__).'/nb.php');
 require_once(dirname(__FILE__).'/db/table.php');
-# NB 29.12.15 define('SQL_NAME_FORCE_QUOTE_EXP','^(range)$');
 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="this.setAttribute(\'name\',\'edit\');this.parentElement.submit()?0:0"/>'
@@ -263,9 +262,9 @@ EOF;
   function print_header($format) {
     if (empty($_SERVER['DOCUMENT_ROOT'])) return null;
 
-    if (!$c=$this->ext2mime($format)) return false;
-    header('Content-type: '.$c);
-    return true;
+    if (!$mime=$this->ext2mime($format)) return false;
+    header('Content-type: '.$mime);
+    return $mime;
   }
 
   function html_menu($table=null) {
@@ -362,41 +361,43 @@ EOF;
   }
 
   function sql_name($value) {
-# NB 29.12.15     if (preg_match('/^\w+$/',$value) and
-# NB 29.12.15       (
-# NB 29.12.15         !SQL_NAME_FORCE_QUOTE_EXP or
-# NB 29.12.15         !preg_match('/'.SQL_NAME_FORCE_QUOTE_EXP.'/',$value)
-# NB 29.12.15       )
-# NB 29.12.15     ) return $value;
     if ($this->type == 'mysql') return '`'.$value.'`';
     return '"'.$value.'"';
   }
 
+  function out($v) {
+    $f = $this->p('format','json');
+    #if (preg_match('/yaml|yml/',$f)) bye($this->yaml_encode($this->object2array($this->fields())));
+    $mime = $this->print_header($f);
+
+    #echo $v.PHP_EOL;
+    #bye($f); return true;
+    if ($f == 'json') { echo json_encode($v).PHP_EOL; }
+    elseif (preg_match('/yaml|yml/',$f)) { echo $this->yaml_encode($v); }
+    elseif (preg_match('/php|var_export/',$f)) { echo var_export($v,true); }
+    elseif (preg_match('/var_dump/',$f)) { echo var_dump($v,true); }
+    elseif (is_scalar($v)) { echo($v.PHP_EOL); }
+    //else { echo($v.PHP_EOL); }
+    else{ echo var_export($v,true); }
+
+    return true;
+
+  }
+
   function action($table) {
     if ($this->p('format') == 'table') $this->pset('format','');
     $action = $this->p('action');
 
-    $formated = $this->print_header($this->p('format'));
-    $data = null;
-    
     if ($action == 'tables') {
-      $this->print_header('json');
-      $data = $this->tables();
-      echo json_encode($data);
-      return true;
-
-    } elseif ($action == 'fields') {
-      $this->print_header('json');
-      $data = $table->fields();
-      echo json_encode($data);
-      return true;
+      return $this->out($this->tables());
 
     } elseif ($action == 'html_menu') {
+      $this->print_header($this->p('format','html'));
       echo $this->html_menu();
       return true;
 
     } else {
-      if ($table->action()) return true;
+      if ($r=$table->action()) return $r;
 
     }
 
index 08f6e8a62ebceca0ec08c95e718b857a98ae2556..beb7f9aeef2941593f67ef988a6b3747849e7436 100644 (file)
@@ -16,7 +16,6 @@ if (false and empty($_SERVER['DOCUMENT_ROOT'])) {
 
 if (!defined('DB_HTML_EDIT')) define('DB_HTML_EDIT','Edit');
 if (!defined('DB_HTML_DELETE')) define('DB_HTML_DELETE','Delete');
-if (!defined('DB_HTML_NAV_TOP')) define('DB_HTML_NAV_TOP','<div class="nav" id="nav_top"></div>'.PHP_EOL);
 if (!defined('DB_TABLE_QUERY_NAME')) define('DB_TABLE_QUERY_NAME','_query_');
 
 class table extends nb {
@@ -28,10 +27,11 @@ class table extends nb {
   public $fields_keys = null;
   public $replace = array(); # replace by javascript
   public $extras = array();
-  public $params = array(
+  public $params = array( # hidden, sort, ... fields
     'table',
     'limit',
     'debug',
+    'action',
   );
   public $order_by = null;
 
@@ -60,7 +60,10 @@ class table extends nb {
     $this->name = $name;
 
     // Extras
-    if (isset($opt['extras'])) {
+    if ($this->p('extras')==='0') {
+      $this->extras = array();
+
+    } else if (isset($opt['extras'])) {
       $this->add_extras($opt['extras']);
 
     } elseif (
@@ -89,12 +92,64 @@ class table extends nb {
    */
   function sql() {
     if (isset($this->sql)) return $this->sql;
+
+    if (!preg_match('/^[\w_-]+$/',$this->name) ) {
+      $this->sql = $this->name;
+      return $this->sql;
+    }
+
     if ($this->db->type == 'sqlite') {
       $sql = "SELECT sql FROM sqlite_master WHERE name='$this->name'";
     } elseif ($this->db->type == 'mysql') {
       $sql = "SHOW CREATE TABLE `$this->name`";
     } elseif ($this->db->type == 'pgsql') {
       $sql = "SELECT show_create_table('$this->name')";
+      $sql = "
+SELECT
+  'CREATE TABLE '||sql.table||'('
+    ||array_to_string(array_agg(sql),', ')
+  ||')' as sql
+FROM (
+  (
+    SELECT -- FIELDS
+      c.oid AS id
+      ,c.relname as table
+      ,9 as prio
+      ,''
+        || f.attname
+        || ' ' || pg_catalog.format_type(f.atttypid,f.atttypmod)
+        ||CASE WHEN f.attnotnull THEN ' NOT NULL' ELSE '' END
+        ||CASE WHEN f.atthasdef = 't' AND d.adsrc !=''THEN ' DEFAULT '||d.adsrc ELSE '' END
+      AS sql
+    FROM pg_attribute f
+        JOIN pg_class c ON c.oid = f.attrelid
+        LEFT JOIN pg_attrdef d ON d.adrelid = c.oid AND d.adnum = f.attnum
+    WHERE c.relkind = 'r'::char
+        AND f.attnum > 0
+    ORDER BY f.attnum
+  )  UNION (
+    SELECT -- CONSTRAINTS
+        c.oid as id
+        ,c.relname as table
+        ,0 as prio
+        ,CASE
+          WHEN p.contype = 'p' THEN 'PRIMARY KEY'
+          WHEN p.contype = 'u' THEN 'UNIQ'
+          ELSE '' END
+        ||'('||array_to_string(array_agg(f.attname),', ')||')' AS sql
+    FROM pg_attribute f
+        JOIN pg_class c ON c.oid = f.attrelid
+        LEFT JOIN pg_constraint p ON p.conrelid = c.oid AND f.attnum = ANY (p.conkey)
+    WHERE c.relkind = 'r'::char
+        AND f.attnum > 0
+        AND p.contype IN ('u','p')
+    GROUP BY c.oid,p.contype,f.attrelid,c.relname
+    ORDER BY c.oid,f.attrelid
+  )
+ORDER BY prio DESC) sql
+WHERE sql.table='$this->name'
+GROUP BY sql.id,sql.table
+";
     } else {
       err('table.sql(): Unknow db type: '.$this->db->type);
     }
@@ -153,7 +208,7 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
 #bye($row);
         $field = array(
           'name'          => $row['name'],
-          'extra'         => null,
+          'extra'         => null, # !!! nothing todo with class variable $extras
           'type'          => strtolower($row['type']),
           'default'       => null,
           'key'           => null,
@@ -389,24 +444,12 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
       $next = 999999;
     }
 
-    #$html .= '<div id="nav_bottom">';
-
     if ($prev>=0) $html .= '<span class="prev"><a href="'.$this->url_list('limit',preg_replace('/^0,/','',"$prev,$y")).'">&lt;&lt;</a></span>&nbsp;';
 
     $html .= '<span class="count">'.($tot ? ($x+1) : 0).' - '.( $count<($x+$y) ? $count : ($x+$y) ).' / '.$tot.' results</span>';
 
     if ($next<$tot) $html .= '&nbsp;<span class="prev"><a href="'.$this->url_list('limit',"$next,$y").'">&gt;&gt;</a></span>';
 
-    #$html .= '</div>'.PHP_EOL;
-    static $js = null;
-    if ($js === null) {
-      $html .= '<script type="text/javascript"><!-- '.PHP_EOL
-        ."var rb = document.getElementById('nav_bottom'); var rt = document.getElementById('nav_top'); if (rb && rt) rt.innerHTML = rb.innerHTML;\n"
-      . ' --></script>'.PHP_EOL
-      ;
-      $js = '1';
-    }
-
     return $html;
 
   }
@@ -578,7 +621,8 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
     if (!$this->extras) return '';
 
     $select = array(); foreach ($this->extras as $k => $v) {
-      $select[] = $v->extra." AS ".$v->quote($k,true);
+# NB 27.02.16       $select[] = $v->extra." AS ".$v->quote($k,true);
+      $select[] = $v->extra." AS ".$this->sql_name($k);
     }
 
     return ','.join(',',$select);
@@ -597,8 +641,7 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
 
     $sql = "SELECT$select_count *" . $this->select_extras();
     $sql .= " FROM ".$this->sql_name();
-
-    $this->sql = $sql = $sql . $where;
+    $sql .= $where;
 
     if ($this->p('sort')) $sql .= ' ORDER BY '.$this->p('sort');
 
@@ -612,15 +655,20 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
     //
     // Get results
     //
+    $this->sql = $sql;
     $this->debug($sql,1);
     $st = $this->db->conn->prepare($sql);
     $st->execute();
 
     $format = ( $this->p('format') ? $this->p('format') : 'table' );
 
-    if (!isset($opt['is_html'])) $opt['is_html'] = preg_match('/^(table|div)$/',$format) ? true : false;
+    if (!isset($opt['is_html'])) $opt['is_html'] = preg_match('/^(table|div)$/',$format)
+      ? ( $this->p('header')!=="0" and $this->p('inc')!=="1")
+      : false
+    ;
 
-    if (preg_match('/^(1)?$/',$this->p('header'))) echo $this->{"rows_begin_$format"}($this->fields());
+    if ($opt['is_html']) echo $this->html_nav_top();
+    echo $this->{"rows_begin_$format"}($this->fields());
 
     $count = 0;
     while ($row = $st->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT)) {
@@ -668,7 +716,8 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
     $opt['count'] = $count;
     $opt['limit'] = $limit;
     echo $this->{"rows_end_$format"}($opt);
-    if ($opt['is_html']) echo '<div id="nav_bottom" class="nav bottom">'
+
+    if ($opt['is_html']) echo '<div class="nav bottom">'
       .$this->nav($opt['count'],$opt['tot'],$opt['limit'])
      .'</div>'
      .PHP_EOL;
@@ -706,6 +755,7 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
   -----------------------------------------------------------------*/
   function rows_begin_json() {
     $this->_row_json = null;
+    return '['.PHP_EOL;
     return ''
       ."// database: ".$this->db->name."\n"
       ."// table: $this->name\n"
@@ -713,18 +763,18 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
   }
 
   function rows_rec_json(&$row) {
-    $json = '';
     if ($this->_row_json === null) {
+      $json = '';
       $this->_row_json = true;
     } else {
-      $json .= ',';
+      $json = ','.PHP_EOL;
     }
-    return $json . json_encode($row).PHP_EOL;
+    return $json . json_encode($row);
   }
 
   function rows_end_json() {
     unset($this->_row_json);
-    return ']'.PHP_EOL;
+    return PHP_EOL.']'.PHP_EOL;
   }
 
   /*-----------------------------------------------------------------
@@ -779,6 +829,8 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
     Csv
   -----------------------------------------------------------------*/
   function rows_begin_csv($fields) {
+
+    if ($this->p('header')==="0") return '';
     return join("\t",array_keys($fields))."\n";
   }
 
@@ -795,35 +847,48 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
   -----------------------------------------------------------------*/
   function rows_begin_table($fields) {
 
-    $html = $this->html_nav_top();
+    $html = '';
+
     #$html .= '<table data-role="table" class="ui-responsive rows '.$this->name.'">'.PHP_EOL;
     $html .= '<table class="rows '.$this->name.'">'.PHP_EOL;
     #if (!empty($opt)) $html .= '<caption>' . $this->nav($opt['count'],$opt['tot'],$opt['limit']) . '</caption>' .PHP_EOL;
 
-    $html .= '<thead><tr class="head">';
+    if ($this->p('header')!=="0") {
+      $html .= '<thead>'.PHP_EOL.'<tr class="head">'.PHP_EOL;
 
-    if (DB_HTML_EDIT) $html .= '<th class="edit"></th>';
+      if ($this->p('buttons')!=='0' and DB_HTML_EDIT) $html .= '<th class="edit"></th>'.PHP_EOL;
 
-    foreach (array_keys($fields) as $f) {
-      $html .= '<th class="'.$f.'">'.$this->url_sort($f).'</th>';
+      foreach (array_keys($fields) as $f) {
+        #$html .= '<th class="'.$f.'">'.($this->p('buttons')==='0' ? $f : $this->url_sort($f)).'</th>'.PHP_EOL;
+        $html .= '<th class="'.$f.'">'.($this->p('buttons')==='0' ? $this->prettyText($f) : $this->url_sort($f)).'</th>'.PHP_EOL;
+      }
+      if ($this->p('buttons')!=='0' and DB_HTML_DELETE) $html .= '<th class="delete"></th>'.PHP_EOL;
+      $html .= '</tr>'.PHP_EOL.'</thead>'.PHP_EOL;
     }
-    if (DB_HTML_DELETE) $html .= '<th class="delete"></th>';
-    $html .= '</tr></thead><tbody>'.PHP_EOL;
 
+    $html .= '<tbody>'.PHP_EOL;
     return $html;
   }
 
   function rows_rec_table(&$row) {
 
-    $html = '<tr class="row">';
+    $html = '<tr class="row">'.PHP_EOL;
 
-    $html .= '<td class="action"><a class="edit button" href="'.$this->url_keys($row,'action=edit').'">'.DB_HTML_EDIT.'</a></td>';
+    if ($this->p('buttons')!=='0') $html .=
+      '<td class="action"><a class="edit button" href="'
+        .$this->url_keys($row,'action=edit')
+      .'">'.DB_HTML_EDIT.'</a></td>'.PHP_EOL;
 
     foreach ($row as $k => $v) {
-      $html .= '<td class="'.$k.'">'.$v.'</td>';
+      if (isset($this->extras[$k])) $k .= " extra";
+      $html .= '<td class="'.$k.'">'.$v.'</td>'.PHP_EOL;
     }
 
-    $html .= '<td class="action"><a class="delete button" href="'.$this->url_keys($row,'action=delete').'">'.DB_HTML_DELETE.'</a></td>';
+    if ($this->p('buttons')!=='0') $html .=
+      '<td class="action"><a class="delete button" href="'
+        .$this->url_keys($row,'action=delete')
+      .'">'.DB_HTML_DELETE.'</a></td>'.PHP_EOL;
+
     $html .= '</tr>'.PHP_EOL;
 
     return $html;
@@ -840,7 +905,7 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
     Html Div
   -----------------------------------------------------------------*/
   function rows_begin_div() {
-    return '<div class="rows '.$this->name.'">'.PHP_EOL.$this->html_nav_top();
+    return '<div class="rows '.$this->name.'">';
   }
 
   function rows_rec_div(&$row) {
@@ -849,10 +914,12 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
 
     $html .= '<ul class="row">';
 
-    $html .= '<li class="buttons">';
-    $html .= '<a class="edit button" href="'.$this->url_keys($row,'action=edit').'">'.DB_HTML_EDIT.'</a>';
-    $html .= '<a class="delete button" href="'.$this->url_keys($row,'action=delete').'">'.DB_HTML_DELETE.'</a>';
-    $html .= '</li>';
+    if ($this->p('buttons')!=='0') {
+      $html .= '<li class="buttons">';
+      $html .= '<a class="edit button" href="'.$this->url_keys($row,'action=edit').'">'.DB_HTML_EDIT.'</a>';
+      $html .= '<a class="delete button" href="'.$this->url_keys($row,'action=delete').'">'.DB_HTML_DELETE.'</a>';
+      $html .= '</li>';
+    }
 
     foreach ($row as $k => $v) {
       $html .= '<li>'
@@ -863,20 +930,14 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
 
     $html .= '</ul>'.PHP_EOL;
 
-// NB 03.08.15     $html .= '<div class="buttons">';
-// NB 03.08.15     $html .= '<a class="edit button" href="'.$this->url_keys($row,'action=edit').'">'.DB_HTML_EDIT.'</a>';
-// NB 03.08.15     $html .= '<a class="delete button" href="'.$this->url_keys($row,'action=delete').'">'.DB_HTML_DELETE.'</a>';
-// NB 03.08.15     $html .= '</div>';
-
-
     return $html;
   }
 
   function rows_end_div($opt=array()) {
   }
 
-  function sql_name() {
-    return $this->db->sql_name($this->name);
+  function sql_name($value=null) {
+    return $this->db->sql_name($value === null ? $this->name : $value);
   }
 
   function insert($hvalues) {
@@ -993,14 +1054,28 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
     return $this->db->exec($sql);
   }
 
+  function out($v) { return $this->db->out($v); }
+
   function action() {
     $action = $this->p('action');
 
     if ($action == 'fields') {
-      $this->db->print_header('json');
-      $data = $this->fields();
-      echo json_encode($data);
-      return true;
+      return $this->out($this->object2array($this->fields()));
+
+    } elseif ($action == 'sql') { return $this->out($this->sql());
+    } elseif ($action == 'count') { return $this->out($this->count());
+
+    } elseif ($action == 'rows') {
+      #if ($this->p('page')==='0') $this->pset('inc',1);
+      return $this->rows();
+
+    } elseif ($action == 'table') {
+      return $this->out(array(
+        #"count" => $this->count(),
+        "sql_name" => $this->sql_name(),
+        "sql" => $this->sql(),
+        "fields" => $this->object2array($this->fields()),
+      ));
 
     } elseif ($action == 'delete') {
       if (!$this->delete($this->p(),$e)) bye($e);
@@ -1040,13 +1115,36 @@ FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.
   }
 
   function html_nav_top() {
-    $html = DB_HTML_NAV_TOP;
+    if ($this->p('header')==="0") return '';
+    $html = '';
+
     if (!empty($this->replace)) {
+
       $replace = array();
       foreach ($this->replace as $k=>$v) { $replace[] = "$k.$v"; }
-      $html .= '<span id="db-table-replace" style="display:none">'.join(' ',$replace).'</span>';
+      $html .= '<span id="db-table-replace" style="display:none">'.join(' ',$replace).'</span>'.PHP_EOL;
+
     }
+
     return $html;
+
+  }
+
+  function count() {
+    
+    if (isset($this->count)) return $this->count;
+      $sql_count = $this->name;
+      if (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;
   }
 
 }
index 5a62f15856011e7801e39fcba3d4421425851688..77292b91258710debaa29357d8603dea5523aeb5 100644 (file)
@@ -4,6 +4,10 @@ require_once(dirname(__FILE__).'/functions.php');
 class nb {
 
   # Sql: elect type,ext from mime_type where ext in ('json','csv','txt','yaml','xml','html','doc','xls');
+  public static $content_types_aliases = array(
+    'text' => 'txt',
+  );
+
   public static $content_types = array(
     'json' => 'application/json',
     'doc'  => 'application/msword',
@@ -69,9 +73,14 @@ class nb {
    * Does what it says
    */
   static function ext2mime($ext) {
+
     foreach (self::$content_types as $e => $c) {
       if ($ext == $e) return $c;
     }
+
+    // Aliases
+    if (isset(self::$content_types_aliases[$ext])) return self::ext2mime(self::$content_types_aliases[$ext]);
+
   }
 
   /*
@@ -162,6 +171,25 @@ class nb {
     $_benchmark[$function] = microtime(true);
   }
 
+  /*
+   * Function: object2array
+   */
+  static function object2array($o) { return $array = json_decode(json_encode($o), true); }
+
+  /*
+   * Function: yaml_encode
+   */
+  static function yaml_encode($row) {
+    #$yaml = yaml_emit(self::object2array($row));
+    $yaml = yaml_emit($row);
+    $yaml = preg_replace('/^---\n/','',$yaml);
+    $yaml = preg_replace('/\n\.\.\.$/','',$yaml);
+    return "--- \n".trim($yaml)."\n";
+    return trim($yaml)."\n";
+    $yaml = preg_replace('/^/m','  ',$yaml);
+    return '- '.trim($yaml)."\n";
+  }
+
 }
 #die(nb::ext2mime('csv'));
 ?>