,
'sqlite' => "SELECT name,type FROM sqlite_master WHERE type IN('table','view') AND name NOT LIKE 'sqlite_%' ORDER BY name",
),
+ 'table.fields' => array(
+ 'pgsql' => "SELECT
+a.attname AS name,
+pg_catalog.format_type(a.atttypid, a.atttypmod) AS type,
+CASE a.attnotnull WHEN 't' then 1 ELSE 0 END AS notnull,
+(SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128) FROM pg_catalog.pg_attrdef d WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef) AS pg_default,
+(SELECT 1 FROM pg_index i WHERE a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey) AND i.indrelid = '<NAME>'::regclass AND i.indisprimary) as pk
+FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relname='<NAME>' AND pg_catalog.pg_table_is_visible(c.oid) ) AND a.attnum > 0 AND NOT a.attisdropped ORDER BY a.attnum",
+ 'mysql' => "SHOW COLUMNS FROM `<NAME>`",
+ 'sqlite' => "PRAGMA table_info('<NAME>')",
+ ),
+ 'table.sql' => array(
+ 'pgsql' => "
+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='<NAME>'
+GROUP BY sql.id,sql.table
+",
+ 'mysql' => "SHOW CREATE TABLE `<NAME>`",
+ 'sqlite' => "SELECT sql FROM sqlite_master WHERE name='<NAME>'",
+ ),
);
#die($DB_TYPES['tables']['mysql']);
}
public function config() {
- #bye($this->types('config'));
- if (!($config = $this->types('config')))
- self::bye("db.config(): Unknow db type: ".$this->type." from ".print_r($GLOBALS['DB_TYPES'],1))
- ;
+
+ $config = $this->type('config',true);
+
$config[1] = str_replace('<NAME>',$this->name,$config[1]);
if (!file_exists($config[0])) return array();
return $return;
}
- public function types($key=false,$die=false) {
+ public function type($key=false,$die=false) {
#if (!isset($DB_TYPES[$key][$this->type])) return;
global $DB_TYPES;
!isset($DB_TYPES[$key])
or !isset($DB_TYPES[$key][$this->type])
or empty($DB_TYPES[$key][$this->type])
- )
- # ??? not working ???
- #self::bye("db.types(): Unknow key `$key` for type `".$this->type."`".print_r($DB_TYPES,1));
- #if ($die) self::bye("db.types(): Unknow key `$key` for type `".$this->type."`");
+ ) {
+ #self::bye("db.type(): Unknow key `$key` for type `".$this->type."`".print_r($DB_TYPES,1));
+ #nb::msg(">>>".$DB_TYPES[$key][$this->type]);
+ if ($die) self::bye("db.type(): Unknow key `$key` for type `".$this->type."`");
return;
- ;
+ }
return $DB_TYPES[$key][$this->type];
}
if (isset($this->_tables) and $this->_tables) return ($return_hash ? $this->tables : $this->_tables);
if (!isset($this->_tables)) $this->_tables = array();
- if (!($sql = $this->types('tables')))
- self::bye("db.types(): Unknow db type: ".$this->type." from ".print_r($GLOBALS['DB_TYPES'],1))
- ;
+ $sql = $this->type('tables',true);
$rows = $this->conn->query($sql,PDO::FETCH_ASSOC);
foreach ($rows as $row) {
public function out2($rows,$head=array()) {
#if (is_scalar($head)) bye(var_dump($head,true));
- if ($this->p('header') === '0' ) $head = false;
- elseif (is_scalar($head)) $head = array($head);
# NB 09.03.16 elseif (count($rows)) {
# NB 09.03.16 $first = self::ar_first($row);
# NB 09.03.16 #if (self::is_hash($first))
echo $this->html_menu();
$return = true;
- } elseif (preg_match('/db\.(\w+)/',$action,$m)) {
+ } elseif (preg_match('/^db\.(\w+)/',$action,$m)) {
$meth = $m[1];
$rows = $this->$meth();
- #$return = $this->out2($rows);
- if ($rows) $return =
- out::rows($this->p('format',out::php_cli() ? 'csv' : 'csv'),$rows)
- ;
+ if ($rows) $return = $this->out2($rows,self::is_hash($rows) ? true : array($meth));
$return = true;
} elseif($table) {
if ($r=$table->action($action)) $return = $r;
+ #if (!is_scalar($return)) $return = $this->out2($return);
}
}
}
- public function dump() {
+ public function sql() {
$this->pset('orderby',null);
+ $r = array();
foreach ($this->tables() as $t) {
$t = $this->table($t);
#$this->pset('format','sql');
- echo preg_replace('/\s+/',' ',$t->sql()).";\n";
- $t->rows();
+ #$r[] = preg_replace('/\s+/',' ',$t->sql()).";";
+ #if (0)
+ #$r[] = preg_replace('/ +/',' ',$t->sql()).";";
+ $r[] = preg_replace('/\s+/',' ',
+ # Filter comment to generate one sql per line
+ join(' ',preg_grep('/^ *--/',explode("\n",$t->sql()),true))
+ ).";";
+ #$t->rows();
}
- return array();
+ return $r;
}
} # < Class
require_once(dirname(__FILE__).'/../config.php');
require_once(dirname(__FILE__).'/../db.php');
-if($format = out::client_type()) Db::pdef('format',$format);
+#bye(out::client_type());
+Db::pdef('format',out::client_type());
+#if($format = out::client_type()) Db::pset('format',$format);
# Param - Extract dbname from table
if (preg_match('/^(\w+)\.(.*?)$/',Db::p('table'),$m)) {
Db::pset('db',$m[1]);
Db::pset('table',$m[2]);
}
+#$conf = Db::conf_dbs(array( Db::$root_dir.'/etc/dbs.yaml','/etc/dbs.yaml' )); Db::init($conf);
Db::init(array( Db::$root_dir.'/etc/dbs.yaml','/etc/dbs.yaml' ));
if( defined('DB_JUST_INIT')) return true;
if (!defined('DB_HTML_DELETE')) define('DB_HTML_DELETE','Delete');
if (!defined('DB_TABLE_QUERY_NAME')) define('DB_TABLE_QUERY_NAME','_query_');
-class Table extends nb {
+Class Table extends nb {
public $name;
public $db;
function __construct($name,$opt=array()) {
+ if (!is_scalar($name)) {
+ $opt = $name;
+ $name = null;
+ }
+
foreach ($opt as $k => $v) { $this->$k = $v; }
#unset($opt['db']); bye($opt);
// Connection
if (isset($opt['db'])) {
- $this->db = $opt['db'];
+ $this->db = is_object($opt['db']) ? $opt['db'] : new Db($opt['db']);
} else {
- $this->db = new db();
+ $this->db = new Db();
}
// Name, could be a select
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);
- }
+ $sql = str_replace('<NAME>',$this->name,$this->db->type('table.sql',true));
$this->sql = $this->db->row($sql);
+ $this->sql = preg_replace("/^\w+\s+(CREATE)/i",'$1',$this->sql); # for mysql
+ #$this->sql = trim($this->sql);
#bye($this->sql);
return $this->sql;
}
if ($this->fields === null) {
$this->fields = array();
-
- if ($this->db->type == 'sqlite') {
- $sql = "PRAGMA table_info('$this->name')";
-
- } elseif ($this->db->type == 'pgsql') {
- $sql = "SELECT
-a.attname AS name,
-pg_catalog.format_type(a.atttypid, a.atttypmod) AS type,
-CASE a.attnotnull WHEN 't' then 1 ELSE 0 END AS notnull,
-(SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128) FROM pg_catalog.pg_attrdef d WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef) AS pg_default,
-(SELECT 1 FROM pg_index i WHERE a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey) AND i.indrelid = '$this->name'::regclass AND i.indisprimary) as pk
-FROM pg_catalog.pg_attribute a WHERE a.attrelid = (SELECT c.oid FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relname='$this->name' AND pg_catalog.pg_table_is_visible(c.oid) ) AND a.attnum > 0 AND NOT a.attisdropped ORDER BY a.attnum";
-
- } elseif ($this->db->type == 'mysql') {
- $sql = "SHOW COLUMNS FROM `$this->name`";
-
- } else {
- err('table.fields(): Unknow db type: '.$this->db->type);
- return array();
-
- }
-
+ $sql = str_replace('<NAME>',$this->name,$this->db->type('table.fields',true));
$rows = $this->db->conn->query($sql);
$rows->setFetchMode(PDO::FETCH_ASSOC);
if (isset($row['extra']) and $row['extra'] == 'auto_increment') {
$field['autoincrement'] = true;
- # sqlite autoincrement
+ # sqlite autoincrement only in sql
} elseif ($this->db->type == 'sqlite'
and preg_match('/[\(,]'.$row['name'].' [^\),]+ AUTOINCREMENT/',$this->sql())
) {
if ($opt['is_html']) echo $this->html_nav_top();
if ($out_conf) {
- out::begin($out_conf,$this->fields(),array($row));
+ out::head($out_conf,$this->fields(),array($row));
} else {
echo $this->{"rows_begin_$format"}($this->fields());
$this->db->print_header($this->p('format'));
$this->rows(); return true;
-# NB 06.03.16 } elseif ($action == 'table') {
-# NB 06.03.16 return $this->out(array(
-# NB 06.03.16 #"count" => $this->count(),
-# NB 06.03.16 "sql_name" => $this->sql_name(),
-# NB 06.03.16 "sql" => $this->sql(),
-# NB 06.03.16 "fields" => $this->object2array($this->fields()),
-# NB 06.03.16 ),true);
+ } elseif ($action == 'table') {
+ return $this->out2(array(
+ #"count" => $this->count(),
+ #"sql_name" => $this->sql_name(),
+ "name" => $this->name,
+ "sql" => $this->sql(),
+ #"fields" => $this->object2array($this->fields()),
+ ));
} elseif ($action == 'table.delete' or $action == 'delete') {
if (!$this->delete($this->p(),$e)) bye($e);
$this->out2($out);
return $r;
+ } elseif (preg_match('/^table\.(\w+)/',$action,$m)) {
+ $meth = $m[1];
+ $rows = $this->$meth();
+ if ($rows) $return = $this->out2($rows,self::is_hash($rows) ? true : array($meth));
+ return true;
+
} elseif ($this->p('format') and !preg_match('/^(table|div)$/',$this->p('format'))) {
$this->rows(array( 'format' => $this->p('format')));
return $r;
}
+ public function unserialize() {
+ $o = unserialize($this->serialize());
+ if (empty($o->db)) {
+ global $Db; $o->db = $Db;
+ }
+ #var_export($o->db);
+ return($o->sql_name());
+ debug($o->sql_name());
+ return var_export($o,true);
+ }
+
+ public function __sleep() {
+ if (1) return array(
+ 'name',
+ 'sql',
+ 'type',
+ 'fields',
+ 'fields_keys',
+ 'replace',
+ 'extras',
+ 'params',
+ 'order_by',
+ );
+
+ $vars = array();
+ #foreach (get_class_vars(get_class($this)) as $k=>$v) { if ($k=!'db') $vars[]=$k; };
+ foreach (get_class_vars(get_class($this)) as $k=>$v) { if ($k=!'db') $vars[]=$k; };
+ #foreach (get_class_vars(__CLASS__) as $k=>$v) { if ($k=!'db') $vars[]=$k; };
+ debug($vars);
+ #$vars = get_object_vars($this);
+ return $vars;
+ }
+
+ public function serialize() {
+ #$o = new self(null,$this);
+ $clone = clone($this);
+ #foreach (get_object_vars($clone) as $k=>$v) { if (is_object($v)) unset($clone->$k); };
+ #var_export($clone->db);
+ #unset($clone->db);
+ #$clone->db = array();
+ #foreach (get_object_vars($this->db) as $k=>$v) { if (!is_object($v)) $clone->db[$k] = $v; };
+ #debug($clone->db);
+ #foreach (get_object_vars($this) as $k=>$v) { unset($this->$k); };
+ return serialize($clone);
+ }
-}
+} # < Class
?>
if ($msg!=='__bye__') err($msg,'bye',( $backtrace_deep !== false ? (1+$backtrace_deep) : $backtrace_deep ));
#if ($msg) err($msg,'bye',1+$backtrace_deep);
exit;
+ #die("Can't exit from BYE!!!");
}
function warn ($msg) {
function __destruct() {
#foreach (get_object_vars($this) as $k=>$v) { echo ("$k: $v\n"); }
#if (is_object($this))
- try {
- foreach (get_object_vars($this) as $k=>$v) { unset($this->$k); };
- } catch(Exception $e) {
- }
+ foreach (get_object_vars($this) as $k=>$v) { unset($this->$k); };
+ #foreach (get_class_vars($this) as $k=>$v) { unset($this->$k); };
+# NB 27.03.16 try {
+# NB 27.03.16 foreach (get_object_vars($this) as $k=>$v) { unset($this->$k); };
+# NB 27.03.16 } catch(Exception $e) {
+# NB 27.03.16 }
}
/*
# NB 07.03.16 define('OUT_BRACE2','}');
# NB 07.03.16 define('OUT_COMA',','.NB_EOL);
-class Out extends Nb {
+Class Out extends Nb {
- public static $types; public static function types() {
+ public static $charset = 'utf-8';
+ public static $types;
+ public static $type;
+ public static function init() {
self::$types = array(
'sql' => array(
),
'rec' => ',',
),
);
+ self::$type = self::client_type();
}
public function __construct($type,&$data,$head=array()) {
if (!empty($type) and !empty($data)) return $this->rows($type,$data,$head);
}
- public static function begin($o,$head,$data=array()) {
+ public static function scalar($v) {
+ if (is_scalar($v)) return $v;
+ #if (is_array($v) and !self::is_hash($v)) return join(', ',$v);
+ #return var_export($v,true);
+ return trim(preg_replace(array(
+ '/^\s*\'(.*?)\' => \'?(.*?)\'?,$/m', # hash
+ '/^\s*(array \(|\),?)$/m', # sub array
+ '/ *\'(.*?)\' =>\s*$\r?\n/m', # sub hash
+ '/\s*\d+ => \'(.*?)\'(,)?\r?\n/m', # aray
+ '/$(\r?\n)+$/m', # blank lines
+ '/,\s*$/m', # last ,
+ ),array(
+ '$1=$2',
+ '',
+ '$1=',
+ '$1$2 ',
+ '',
+ '',
+ ),var_export($v,true)));
+ return var_export($v,true);
+ return is_scalar($v) ? $v : json_encode($v);
+ }
+
+ public static function head($o,$head,$data=array()) {
#if (self::p('header')==="0") return;
if (isset($o['enclose'])) echo $o['enclose'][0];
if (!isset($o['head'])) return;
#var_dump($head); return;
- if ($head === false) return;
- if (empty($head)) {
+ if (empty($head) and $head!== false) {
if (self::is_hash($data[0])) {
$head = array_keys($data[0]);
} else {
}
}
+ if (self::p('header') === '0' ) return;
+ if ($head === false) return;
echo $o['head']($head,$o) . empty($o['eol']) ? '' : $o['eol'];
}
public static function rows_get($type,$data,$head=array()) {
ob_start();
self::rows($type,$data,$head);
+ $contents = ob_get_contents();
+ ob_end_clean();
+ return $contents;
return ob_get_flush();
}
public static function rows($type,&$data,$head=array()) {
# Ex: for action=tables when header=0
+
if (is_scalar($data)) $data = array(array($data));
- #bye($data);
- #if (empty($head)) $head = array_fill(0,count($data[0]),'?');
if (!isset(self::$types[$type])) self::bye("Unknow type: `$type`");
$conf = self::$types[$type];
if (self::is_hash($data)) $data = array($data);
if (is_scalar($data)) $data = array($data);
- if (is_scalar($head) and !is_bool($head)) $head = array($head);
-
$tot = count($data);
$count = 0;
# Function head
- self::begin($conf,$head,$data);
+ #elseif (is_scalar($head)) $head = array($head);
+ if (is_scalar($head) and !is_bool($head)) $head = array($head);
+ self::head($conf,$head,$data);
foreach ($data as $row) {
if ($count>0) out::concat($conf);
public static function client_type() {
foreach (array_keys(self::$types) as $t) {
if (preg_match("@^\w+/$t@",self::client_header('Accept'))) return $t;
- #if (preg_match("@^\w+/$t@",self::client_header('Accept'),$m)) bye( $m );
- #if (self::client_header('Accept',$t)) return $t;
}
return;
}
-} Out::types() ; # < Class
+ public static function escape($v,$type=null) {
+ static $replace_flags = null;
+
+ $is_scalar = is_scalar($v);
+ $v = out::scalar($v);
+
+ if ($replace_flags === null) {
+
+ #$replace_flags = ENT_COMPAT | ENT_DISALLOWED;
+ $replace_flags = ENT_COMPAT;
+
+ if ($type === null) $type = self::$type;
+ if (!$type) {
+ return $v;
+
+ } elseif ($type=='xhtml' or (
+ !empty(self::$types[$type]['is_html'])
+ and !empty(self::$types[$type]['is_xml'])
+ )) {
+ $replace_flags = $replace_flags | ENT_XHTML;
+
+ } elseif ($type=='xml' or !empty(self::$types[$type]['is_xml'])) {
+ $replace_flags = $replace_flags | ENT_XML1;
+
+ } elseif ($type=='html' or !empty(self::$types[$type]['is_html'])) {
+ $replace_flags = $replace_flags | ENT_HTML5;
+
+ } else { # text
+ return $v;
+ return preg_replace('/\n/','',$v);
+
+ }
+
+ }
+
+ $v = htmlspecialchars($v,$replace_flags,strtoupper(self::$charset));
+ if (!$is_scalar) $v = '<pre>'.NB_EOL.$v.NB_EOL.'</pre>';
+ return $v;
+ }
+
+} Out::init() ; # < Class
/****************************************************************************/
function out_yaml(&$row,$o) {
}
function out_csv(&$row,$o) {
+
$values = array();
foreach (array_values($row) as $k=>$v) {
#if (!is_scalar($v)) $v = join('',$v);
- if (!is_scalar($v)) $v = json_encode($v);
- $values[] = $v;
+ $values[] = preg_replace('/zAZA/','',out::scalar($v));
+ #$values[] = preg_replace('/\r?\n/','',out::scalar($v));
}
#echo join($o['sep'],array_values($row));
# Tag = o[tag] or key
if (isset($o['tag'])) {
- $class = ' class="'.$k.'"';
+ $class = is_numeric($k) ? '' : ' class="'.$k.'"';
$k = $o['tag'];
} else {
$class = '';
}
+ $v = out::escape($v);
echo ''
.(NB_EOL ? ' ' : '')
."<$k$class>$v</$k>"
function out_xml(&$row,$o) {
echo (NB_EOL ? ' ' : '')."<row>".NB_EOL;
foreach ($row as $k => $v) {
- echo (NB_EOL ? ' ' : '')."<$k><![CDATA[$v]]></$k>".NB_EOL;
+ echo (NB_EOL ? ' ' : '')."<$k><![CDATA[".out::scalar($v)."]]></$k>".NB_EOL;
}
echo (NB_EOL ? ' ' : '')."</row>".NB_EOL;
}
}
if ($content===null) {
- $this->end_tag($tag);
+ $this->tag_end($tag);
return '<' . $tag . ($attrs ? " $attrs" : "") . '>';
}
}
- function end_tag($tag=null) {
+ function tag_end($tag=null) {
static $tags = array();
if ($tag !== null) return array_unshift($tags,$tag);
foreach ($tags as $t) echo "</$t>".NB_EOL;
$tags = array();
- return false;
+ return $tags;
return join('',self::ar_map('',$tags));
if ($tag === null) return $tags;
array_unshift($tags,$tag);
function end() {
if (preg_match('/ml$/',$this->content_type)) {
- #foreach ($this->end_tag() as $t) echo "</$t>".NB_EOL;
- $this->end_tag();
+ #foreach ($this->tag_end() as $t) echo "</$t>".NB_EOL;
+ $this->tag_end();
echo '</body>' . NB_EOL;
echo '</html>' . NB_EOL;
}
$Page->h1 = join(' / ',$nav);
$Page->title = join(' / ',$title);
+
+ return $Page;
+ }
+
+ public function action() {
+ $action = self::p('action');
+ $format = self::p('format',self::php_cli() ? 'csv' : 'table');
+
+ if ($action == 'page.info') {
+ $out = array('path' => $this->path());
+ foreach (get_object_vars($this) as $k=>$v) { if (!empty($this->$k)) $out[$k] = $this->$k; }
+ $out['p'] = self::p();
+ $out['_SERVER'] = $_SERVER;
+
+ $out = array_map(function($k, $v) { return array("name"=>$k,"value"=>$v); },array_keys($out),$out);
+ out::rows($format,$out);
+ return true;
+ }
+
+ return false;
}
public static function html_embed($iframe,$mime='text/html') {