--- /dev/null
+<?php
+/*****************************************************************************
+
+ Class DB
+ Render different output format ex: html, xml, yaml, csv
+ from any database
+
+*****************************************************************************/
+class db {
+ var $tables = array();
+ var $conn;
+ var $type;
+ var $help_criterias = array(
+ ' * or % for wildcar',
+ ' ! to negate',
+ ' ~ for regex',
+ ' combine criterias with OR/AND',
+ );
+
+ function db($pdo) {
+ $this->conn = new PDO($pdo);
+ $this->type = strtolower(preg_replace('/^([^:]+):.*$/','\1',$pdo));
+
+ if ($this->type == 'sqlite') {
+
+ $this->conn->sqliteCreateFunction('regexp',
+ function ($pattern, $data, $delimiter = '~', $modifiers = 'isuS') {
+ if (isset($pattern, $data) === true) {
+ return (preg_match(sprintf('%1$s%2$s%1$s%3$s', $delimiter, $pattern, $modifiers), $data) > 0);
+ }
+ return null;
+ }
+ );
+
+ $this->conn->sqliteCreateFunction('to_char',
+ function ($value,$format) {
+ $replace = array(
+ 'YYYY' => '%Y',
+ 'MM' => '%m',
+ 'WW' => '%W',
+ 'DD' => '%d',
+ );
+ $format = str_replace(array_keys($replace),array_values($replace),$format);
+ return strftime($format,strtotime($value));
+ }
+ ,2);
+
+ }
+
+ }
+
+/*
+ function database() {
+ $rows = $this->db->query('PRAGMA database_list');
+ }
+*/
+
+ function tables() {
+ if (!$this->tables) {
+
+ if ($this->type == 'sqlite') {
+ $sql = "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name";
+ } elseif ($this->type == 'pgsql') {
+ $sql = "SELECT table_name FROM information_schema.tables WHERE table_type in('BASE TABLE','LOCAL TEMPORARY') AND table_schema NOT IN ('pg_catalog', 'information_schema')";
+ } else {
+ err('db.tables(): Unknow db type: '.$this->type);
+ return array();
+ }
+
+ $rows = $this->conn->query($sql);
+ foreach ($rows as $row) {
+ $this->tables[] = current($row);
+ }
+
+ }
+ return $this->tables;
+
+ }
+
+ function rowCount($st) {
+ if (!$st) return null;
+ if ($this->type != 'sqlite') return $st->rowCount();
+ $sql = $st->queryString;
+ return $this->conn->query("SELECT count(*) FROM ($sql) count",PDO::FETCH_COLUMN,0)->fetch();
+ }
+
+ function help($tables=null) {
+ header('Content-type: text/plain');
+
+ if ($tables === null) $tables = $this->tables();
+ $tables = join('',ar_map('" ".$a."\n"',$tables));
+
+ $criterias = join('',ar_map('" ".$a."\n"',$this->help_criterias));
+
+ return <<<EOF
+Criterias:
+$criterias
+Tables
+$tables
+Extras:
+ - op = [OR|AND] criterias operator
+ - sort = field+DESC
+ - format = [xml|yaml|csv|table|row]
+ - header = [1|0] Print header fields (default: 1)
+
+EOF;
+ }
+
+ function print_header($type) {
+
+ if ($_REQUEST['format']=='csv') {
+ header('Content-type: text/plain');
+
+ } elseif ($_REQUEST['format']=='yaml') {
+ header('Content-type: text/yaml');
+
+ } elseif ($_REQUEST['format']=='xml') {
+ header('Content-type: text/xml');
+
+ } else {
+
+ @$GLOBALS['PAGE']['is_text'] = false;
+ return false;
+ }
+
+ @$GLOBALS['PAGE']['is_text'] = true;
+ return true;
+ }
+
+ function initParams($tables=null) {
+ if (empty($_REQUEST)) $_REQUEST = array();
+ if ($tables === null) $tables = $this->tables();
+
+ #$_REQUEST['table'] = @$_REQUEST['table'] ? preg_replace('/^([\w\d_-]+).*$/','\1',$_REQUEST['table']) : $tables[0];
+ $_REQUEST['table'] = @$_REQUEST['table'] ? $_REQUEST['table'] : ($tables === null ? '' : $tables[0]);
+ if (@$_REQUEST['sql']) $_REQUEST['table'] = $_REQUEST['sql'];
+
+ $_REQUEST['limit'] = @$_REQUEST['limit']
+ ? preg_replace('/^(\d+)(,\d+).*$/','\1\2',$_REQUEST['limit'])
+ : ( preg_match('/^(curl|lynx|lwp)/',@$_SERVER['HTTP_USER_AGENT']) ? 999999 : 50 )
+ ;
+
+ $_REQUEST['format'] = @$_REQUEST['format'] ? $_REQUEST['format'] : 'table';
+
+ #$_REQUEST['op'] = strtoupper(@$_REQUEST['op']) == 'AND' ? 'AND' : 'OR';
+ $_REQUEST['op'] = strtoupper(@$_REQUEST['op']) == 'OR' ? 'OR' : 'AND';
+
+ @$GLOBALS['PAGE']['js_code'] = 'var sem_ui_tables = ['.join(',',ar_map('str_quote($a)',$tables)).']; var sem_ui_table = '.str_quote(@$_REQUEST['table']).';';
+
+ }
+ }
+
+class table {
+
+ var $name;
+ var $db;
+ var $fields = array();
+ var $extras = array();
+ var $params = array(
+ 'table',
+ 'limit',
+ 'debug',
+ );
+
+ function table($name,$opt=array()) {
+
+ // Connection
+ if (@$opt['db']) {
+ $this->db = @$opt['db'];
+ } else {
+ $this->db = new db();
+ }
+
+ // Table could be a select
+ if (stripos($name,'SELECT ')===0) {
+ $this->db->conn->query("CREATE TEMPORARY TABLE _query_ AS $name");
+ $name = '_query_';
+ } elseif (preg_match('/\b(\.import|LOAD DATA|COPY|INSERT|REPLACE|DELETE|TRUNCATE|CREATE|DROP|ALERT)\b/',$name)) {
+ bye("Query not Allowed !");
+ }
+
+ $this->name = $name;
+
+ if (@$opt['extras']) $this->add_extras($opt['extras']);
+
+ return array();
+ }
+
+ function fields() {
+ if (!$this->fields) {
+
+ 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 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";
+
+ } else {
+ err('table.fields(): Unknow db type: '.$this->db->type);
+ return array();
+
+ }
+
+ $rows = $this->db->conn->query($sql);
+
+ $rows->setFetchMode(PDO::FETCH_ASSOC);
+
+ foreach ($rows as $row) {
+
+ $this->fields[$row['name']]['type'] = $row['type'];
+ $this->fields[$row['name']]['null'] = $row['notnull'] == '0' ? 1 : 0;
+ $this->fields[$row['name']]['extra'] = null;
+
+ }
+
+ }
+
+ return $this->fields;
+ }
+
+ function debug($msg,$level=0) {
+ if ($level and $level>DEBUG) return;
+
+ $msg = is_scalar($msg) ? $msg : print_r($msg,true);
+ if (@$GLOBALS['PAGE']['is_text']) {
+ echo "DEBUG: $msg\n";
+ return;
+ }
+ echo '<pre class="debug">'
+ .(@$_SERVER['HTTP_HOST'] ? htmlentities($msg) : $msg)
+ .'</pre>'.PHP_EOL;
+
+ }
+
+ function url_params($k='',$v='') {
+
+ $params = array();
+
+ foreach (array_merge(
+ $this->params,
+ array_keys($this->fields())
+ ) as $f) {
+
+ if (@strcmp($_REQUEST[$f],'')==0) continue;
+ $params[$f] = $_REQUEST[$f];
+
+ }
+
+ if ($k) {
+
+ if (strcmp($v,'')==0) {
+ unset($params[$k]);
+ } else {
+ $params[$k] = $v;
+ }
+
+ }
+
+ $flat = array();
+ foreach ($params as $k=>$v) { $flat[] = $k.'='.urlencode($v); }
+ return $flat ? '?'. join('&',$flat) : '';
+
+ }
+
+ function url_sort($name) {
+
+ $html = '';
+
+ # Asc
+ $sel = ( @$_REQUEST['sort']=="$name asc") ? " sel" : "";
+ $html .= '<a title="First In (asc)" class="sort asc'.$sel.'" href="'.$this->url_params("sort","$name asc").'">'
+ .'<span class="asc">↓</span>'
+ .'</a>';
+ $html .= ' ';
+
+ $html .= $name;
+
+ $html .= ' ';
+
+ # Desc
+ $sel = ( @$_REQUEST['sort']=="$name desc") ? " sel" : "";
+ $html .= '<a title="Last In (desc)" class="sort desc'.$sel.'" href="'.$this->url_params("sort","$name desc").'">'
+ .'<span class="desc">↑</span>'
+ .'</a>';
+
+ return $html;
+
+ }
+
+ function nav($count,$tot,$limit) {
+
+ if ($count<$tot) {
+ list($x,$y) = strpos($limit,',')!==false
+ ? preg_split('/\s*,\s*/',$limit)
+ : array(0,$limit)
+ ;
+
+ $prev = $x - $y;
+ $next = $x + $y;
+
+ $this->debug("x=$x limit=$y prev=$prev next=$next tot=$tot",1);
+ } else {
+ $x = 0;
+ $y = $tot;
+ $prev = -1;
+ $next = 999999;
+ }
+
+ echo '<div class="nav" id="nav_bottom">';
+
+ if ($prev>=0) echo '<span class="prev"><a href="'.$this->url_params('limit',preg_replace('/^0,/','',"$prev,$y")).'"><<</a></span> ';
+
+ echo '<span class="count">'.($tot ? ($x+1) : 0).' - '.($x+$y).' / '.$tot.' results</span>';
+
+ if ($next<$tot) echo ' <span class="prev"><a href="'.$this->url_params('limit',"$next,$y").'">>></a></span>';
+
+ echo '</div>'.PHP_EOL;
+ }
+
+ function form_criterias($opt=array()) {
+
+ echo '<form class="criteria bgcolor border rad inline" method="get" action="">'.PHP_EOL;
+ echo '<div class="small help">Use: '.join(' | ',$this->db->help_criterias).'</div>'.PHP_EOL;
+
+ foreach ($this->params as $k) {
+ $v = @$_REQUEST[$k];
+ if ($k == 'limit') $v = '';
+ echo '<input type="hidden" name="'.$k.'" value="'.$v.'" />'.PHP_EOL;
+ }
+
+ $criteria = array();
+ foreach ( array_keys($this->fields()) as $k ) {
+
+ $v = @$_REQUEST[$k];
+
+ $criteria[] = ''
+ . '<label>'.prettyText($k).':</label>'
+ . '<input type="text" id="'.$k.'" name="'.$k.'" value="'.$v.'" />'
+ ;
+
+ }
+
+ $criteria[] = html_select_array(array(
+ 'AND',
+ 'OR',
+ ),array(
+ 'html' => 'name="op"',
+ 'selected' => @$_REQUEST['op'],
+ ));
+
+ $criteria[] = html_select_array(array(
+ array('','HTML'),
+ array('csv','CSV'),
+ array('xml','XML'),
+ array('yaml','YAML'),
+ ),array(
+ 'html' => 'name="format"',
+ 'selected' => @$_REQUEST['format'],
+ ));
+ $criteria[] = '<input type="submit" class="button" value="GO"/>';
+
+ echo join(''.PHP_EOL,$criteria);
+
+ echo '</form>'.PHP_EOL;
+ }
+
+ function where_criterias() {
+ $having = $where = array();
+
+ foreach ($this->fields() as $k => $spec) {
+
+ // No empty values
+ $v = @$_REQUEST[$k];
+ 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);
+
+ // Regex
+ if (strpos($v,'~')===0) {
+ $v = substr($v,1);
+ $v = $this->db->conn->quote($v);
+ $equal = ' '.($not ? 'NOT ' : '').'REGEXP ';
+
+ // Text
+ } elseif (preg_match('/text|char|blob/',$spec['type'])
+ or !preg_match('/^[\d+\.]$/',$v) # text char in search
+ ) {
+
+ if (strtolower($v)=='null') $v = '';
+ #$k = "COLAESCE($k,'')";
+
+ // * -> %
+ $v = str_replace('*','%',$v);
+
+ $v = $this->db->conn->quote($v);
+ $equal = ' '.($not ? 'NOT ' : '').'LIKE ';
+
+ // Integer
+ } else {
+ if (preg_match('/date|time/',$spec['type'])) $v = $this->db->conn->quote($v);
+ if (strtolower($v)=='null') $v = '0';
+ $equal = $not ? '<>' : '=';
+
+ }
+
+ if (preg_match('/(LIKE|REGEXP) ..$/',"$equal$v")) {
+ $k = "COALESCE($k,".$this->db->conn->quote('').")";
+ }
+
+ if ($this->db->type == 'mysql' and $spec['extra']) {
+ $having[] = "$k$equal$v";
+ } elseif ($this->db->type == 'pgsql' and $spec['extra']) {
+ $where[] = $this->extras[$k]."$equal$v";
+ } else {
+ $where[] = "$k$equal$v";
+ }
+
+ }
+
+ $sql = '';
+ if ($where) $sql .= ' WHERE '.join(' '. @$_REQUEST['op'].' ',$where);
+ if ($having) $sql .= ' HAVING '.join(' '. @$_REQUEST['op'].' ',$having);
+ return $sql;
+
+ }
+
+ function add_extras($extras) {
+ $this->fields();
+
+ foreach ($extras as $k => $v) {
+
+ $this->fields[$k] = array(
+ 'type' => 'text',
+ 'null' => 0,
+ 'extra' => $v,
+ );
+
+ $this->extras[$k] = $v;
+
+ }
+
+ }
+
+ function select_extras() {
+
+ if (!$this->extras) return '';
+
+ $select = array();
+
+ foreach ($this->extras as $k => $v) {
+
+ $select[] = "$v AS ".($this->db->type == 'pgsql'
+ ? '"'.str_replace('"','\"',$k).'"'
+ : $this->db->conn->quote($k)
+ );
+ /*
+ $select[] = "$v AS ".$this->db->conn->quote($k);
+ */
+
+ /*
+ $k = $this->db->conn->quote($k);
+ if ($this->db->type == 'pgsqpl') $k = str_replace(
+ $select[] = "$v AS $k"
+ */
+
+ }
+
+ return ','.join(',',$select);
+ }
+
+ /******************************************************************
+ Html Output
+ ******************************************************************/
+ function rows($opt=array()) {
+
+ //
+ // Select
+ //
+ $sql = "SELECT *" . $this->select_extras();
+ $sql .= " FROM $this->name".$this->where_criterias();
+ #$this->debug($sql);
+ $this->debug($sql,1);
+
+ //
+ // Tot
+ //
+ $query = $this->db->conn->query("SELECT count(*) FROM ($sql) count",PDO::FETCH_COLUMN,0);
+ if (!$query) {
+ $err = $this->db->conn->errorInfo();
+ $err[] = $sql;
+ err(join(' | ',$err));
+ return $err[0];
+ }
+ $tot = $query->fetch();
+ #if (!$tot) return;
+
+ if (isset($_REQUEST['sort'])) $sql .= ' ORDER BY '.$_REQUEST['sort'];
+
+ if (isset($_REQUEST['limit'])) {
+ $limit = $_REQUEST['limit'];
+ $sql .= ' LIMIT '.$limit;
+ }
+
+ //
+ // Get results
+ //
+ $st = $this->db->conn->prepare($sql);
+ $st->execute();
+
+ if (@$GLOBALS['PAGE']['is_html']) echo '<div class="nav" id="nav_top"></div>'.PHP_EOL;
+
+ $format = ''.(isset($opt['format']) ? $opt['format'] : 'table');
+ $escape = preg_match('/^(table|row|xml)$/',$format) ? true : false;
+ if (preg_match('/^(1)?$/',@$_REQUEST['header'])) echo $this->{"rows_begin_$format"}($opt);
+
+ $count = 0;
+ while ($row = $st->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT)) {
+ $count ++;
+
+ foreach ($this->fields() as $f => $spec) {
+
+ if (!$spec['extra']) {
+ if ($escape) $row[$f] = htmlspecialchars($row[$f]);
+ }
+ /* only if in latin1
+ if ($_REQUEST['format'] == 'csv') {
+ $row[$f] = utf8_encode($row[$f]);
+ } elseif ($spec['extra']) {
+ $row[$f] = htmlentities($row[$f]);
+
+ }
+ */
+
+ }
+
+ echo $this->{"rows_rec_$format"}($row);
+
+ }
+
+ echo $this->{"rows_end_$format"}($opt);
+ if (@$GLOBALS['PAGE']['is_html']) echo $this->nav($count,$tot,$limit);
+
+ $st->closeCursor();
+
+ return $count;
+ }
+
+ /*-----------------------------------------------------------------
+ Yaml
+ -----------------------------------------------------------------*/
+ function rows_begin_yaml() {
+ $GLOBALS['yamls'] = array();
+ return '';
+ }
+
+ function rows_rec_yaml($row) {
+ #echo yaml_emit($row);
+ $GLOBALS['yamls'][] = $row;
+ }
+
+ function rows_end_yaml() {
+ return yaml_emit($GLOBALS['yamls']);
+ return '';
+ }
+
+ /*-----------------------------------------------------------------
+ Xml
+ -----------------------------------------------------------------*/
+ function rows_begin_xml() {
+ #return '<'.$this->name.'>'.PHP_EOL;
+ return ''
+ .'<?xml version=“1.0” encoding=“utf-8”?>'.PHP_EOL
+ .'<semantico src="sem_ui" table="'.$this->name.'">'.PHP_EOL
+ ;
+ }
+
+ function rows_rec_xml($row) {
+ echo "\t<".$this->name.">".PHP_EOL;
+ foreach (array_keys($this->fields()) as $f) {
+ if ($row[$f] !== '') echo ''
+ . "\t\t<".$f.'>'
+ .'<![CDATA['.$row[$f].']]>'
+ . '</'.$f.'>'
+ .PHP_EOL;
+ }
+ echo "\t</".$this->name.">".PHP_EOL;
+ }
+
+ function rows_end_xml() {
+ #return '</'.$this->name.'>'.PHP_EOL;
+ return '</semantico>'.PHP_EOL;
+ }
+
+ /*-----------------------------------------------------------------
+ Csv
+ -----------------------------------------------------------------*/
+ function rows_begin_csv() {
+ echo join("\t",array_keys($this->fields()))."\n";
+ }
+
+ function rows_rec_csv($row) {
+ echo join("\t",array_values($row))."\n";
+ }
+
+ function rows_end_csv() {
+ }
+
+ /*-----------------------------------------------------------------
+ Html Table
+ -----------------------------------------------------------------*/
+// NB 14.04.14 function rows_begin_table($opt=array()) {
+ function rows_begin_table() {
+
+ $html = '<table class="'.$this->name.' rows border">'.PHP_EOL;
+
+ $html .= '<tr class="'.$this->name.' row bold">';
+ foreach (array_keys($this->fields()) as $f) {
+ $html .= '<th class="'.$f.'">'.$this->url_sort($f).'</th>';
+ }
+
+ $html .= "</tr>".PHP_EOL;
+ return $html;
+ }
+
+ function rows_rec_table($row) {
+ echo '<tr>';
+
+ foreach ($row as $k => $v) {
+ echo '<td class="'.$k.'">'.$v.'</td>';
+ }
+
+ echo '</tr>'.PHP_EOL;
+ }
+
+ function rows_end_table() {
+ return "</table>".PHP_EOL;
+ }
+
+ /*-----------------------------------------------------------------
+ Html Div
+ -----------------------------------------------------------------*/
+ function rows_begin_div() {
+ return '<div class="'.$this->name.' rows">'.PHP_EOL;
+ }
+
+ function rows_rec_div($row) {
+ echo '<ul class="border rad bgcolor">';
+
+ foreach ($row as $k => $v) {
+ echo '<li>'
+ .'<span class="key">'.$k.'</span>'
+ .': '
+ .'<span class="value">'.$v.'</span>'
+ .'</li>';
+ }
+
+ echo '</ul>'.PHP_EOL;
+ }
+
+ function rows_end_div() {
+ return "</div>".PHP_EOL;
+ }
+
+}
+?>
--- /dev/null
+<?php
+if (
+ !@$_SERVER['DOCUMENT_ROOT'] and (realpath($argv[0]) == __FILE__)
+) {
+$Page = new Page(array(
+ #'title' => 'Test',
+ 'call' => array(
+ 'begin',
+ array('out', 'Hello World !!!'),
+ #array('out', print_r($_SERVER,true)),
+ 'end',
+ ),
+));
+}
+
+class Page {
+
+ var $call = array();
+ var $output = '';
+
+ var $charset = 'utf-8';
+ var $content_type = 'xhtml';
+ var $title = '';
+
+ var $css = array();
+ var $css_code = '';
+
+ var $js = array();
+ var $js_code = '';
+
+ /*
+ Create
+ */
+ function Page($opt = array()) {
+
+ //// opt
+ foreach ($opt as $k => $v) {
+ if ( ! array_key_exists($k,$this) ) die ("Page->new(): unknow param $k = $v");
+ $this->$k = is_array($v) ? $v : trim($v);
+ }
+
+ // Defaults
+ if ( ! array_key_exists('title',$opt) )
+ #$this->title = $GLOBALS['argv'][0]
+ $this->title = $this->filename2title($_SERVER['SCRIPT_NAME']);
+ #$this->title = preg_replace('@^.*?([^/\.]+)[^/]*@','\1',$_SERVER['SCRIPT_NAME']);
+ #die( $this->title);
+ ;
+
+ //// Default
+ #print_r($this);
+
+ //// Call
+ foreach ($this->to_array($this->call) as $v) {
+
+ if ( is_array($v) ) {
+ $k = $v[0]; $v = $v[1];
+ $this->$k($v);
+
+ } else {
+ $this->$v();
+
+ }
+
+ }
+
+ }
+
+ /*
+ Funtions
+ */
+ function out($v) {
+ echo $v;
+ }
+
+ function to_array($v) {
+ return (is_array($v) ? $v : array($v));
+ }
+
+ function filename2title($str) {
+ $str = preg_replace('@^.*?([^/\.]+)(/index)?(\..*?)$@','\1',$_SERVER['SCRIPT_NAME']);
+ $str = preg_replace('@[\'_-]+$@',' ',$str);
+ return mb_strtoupper(mb_substr($str,0,1)).mb_strtolower(mb_substr($str,1,mb_strlen($str)));
+ }
+
+ function ar_map($return,$array) {
+ return array_map(create_function('$a',"return($return);"),$array);
+ }
+
+ function js_quote($str) {
+ return "'".str_replace("'","\'",$str)."'";
+ }
+
+ function ansi2html($v) {
+ $html = array(
+ sprintf('%c[1;',27) => sprintf('<bold>%c[0;',27),
+
+ 'black' => 30,
+ 'red' => 31,
+ 'green' => 32,
+ 'yellow' => 33,
+ 'blue' => 34,
+ 'magenta' => 35,
+ 'cyan' => 36,
+ 'white' => 37,
+ 'default' => 39,
+ sprintf('%c[0;30m',27) => '<span style="color:black">',
+ sprintf('%c[0;31m',27) => '<span style="color:red">',
+ sprintf('%c[0;32m',27) => '<span style="color:green">',
+ sprintf('%c[0;33m',27) => '<span style="color:#E0E000">', # yellow
+ sprintf('%c[0;34m',27) => '<span style="color:blue">',
+ sprintf('%c[0;35m',27) => '<span style="color:magenta">',
+ sprintf('%c[0;36m',27) => '<span style="color:cyan">',
+ sprintf('%c[0;37m',27) => '<span style="color:white">',
+ #sprintf('%c[0;33m',27) => '<span style="color:yellow">', # yellow
+ sprintf('%c[0m',27) => '</span>',
+ );
+ return preg_replace('/<bold>(<span style=")/','\1font-weight:bold;',
+ str_replace(array_keys($html),array_values($html),Page::str2txt($v))
+ );
+ }
+
+ function str2txt($v) {
+ static $replace_flags = null;
+ static $charset = null;
+ if ($replace_flags === null) {
+
+ $charset = strtoupper($this->charset);
+ #$replace_flags = ENT_COMPAT | ENT_DISALLOWED;
+ $replace_flags = ENT_COMPAT;
+
+ if (preg_match('/xhml/',$this->content_type)) {
+ $replace_flags = $replace_flags | ENT_XHTML;
+ } elseif (preg_match('/xml/',$this->content_type)) {
+ $replace_flags = $replace_flags | ENT_XML1;
+ } else {
+ #$replace_flags = $replace_flags | ENT_HTML401;
+ $replace_flags = $replace_flags | ENT_HTML5;
+ }
+
+ }
+
+ return htmlspecialchars($v,$replace_flags,$charset);
+ }
+
+ function tag($content='',$tag,$attrs='') {
+
+ if (!is_array($content)) $content = array($content);
+ $tags = array();
+ foreach ($content as $c) {
+ $tags[] = ''
+ . '<' . $tag
+ . ($attrs ? " $attrs" : "")
+ . '>'
+ . $c
+ . "</$tag>"
+ ;
+ }
+ return join(PHP_EOL,$tags);
+ return ''
+ . '<' . $tag
+ . ($attrs ? " $attrs" : "")
+ . '>'
+ . $content
+ . "</$tag>"
+ ;
+ }
+
+ function debug($debug) {
+
+ if (is_array($debug) or is_object($debug)) $debug = print_r($debug,true);
+ if (preg_match('/ml$/',$this->content_type)) {
+ #echo "<!-- $debug -->";
+ echo "<pre class=\"ui-state-highlight debug\">".htmlentities($debug)."</pre>".PHP_EOL;
+
+ } else {
+ echo "DEBUG: $debug\n";
+
+ }
+
+ }
+
+ /*
+ Output
+ */
+ function begin() {
+
+ $this->headers();
+ echo $this->doctype();
+
+ if (preg_match('/html$/',$this->content_type)) {
+ echo '<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">'.PHP_EOL;
+ }
+
+ echo $this->head();
+
+ if (preg_match('/ml$/',$this->content_type)) {
+
+ echo '<body>' . PHP_EOL;
+ if ($this->title) echo $this->tag($this->title,'h1').PHP_EOL;
+ }
+
+ }
+
+ function end() {
+
+ if (preg_match('/ml$/',$this->content_type)) {
+ echo '</body>' . PHP_EOL;
+ echo '</html>' . PHP_EOL;
+ }
+
+ }
+
+ function headers() {
+
+ header('Content-type: ' . $this->content_type);
+
+ return true;
+ }
+
+ function doctype($content_type = null) {
+ if (!$content_type) $content_type = $this->content_type;
+ $doctype = '';
+
+ if (preg_match('/frame/',$content_type)) {
+ $doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">'.PHP_EOL;
+ } else if (preg_match('/xhtml/',$content_type)) {
+ $doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'.PHP_EOL;
+ } else {
+ $doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'.PHP_EOL;
+ }
+
+ return $doctype;
+ }
+
+ function head() {
+ $head = '';
+
+ if (preg_match('/ml$/',$this->content_type)) {
+ $head .= '<head>'.PHP_EOL;
+ #$head .= '</head>'.PHP_EOL; return $head;
+
+ if ($this->title) $head .= $this->tag($this->title,'title') . PHP_EOL;
+ if ($this->charset) $head .= '<meta http-equiv="Content-Type" content="text/html; charset='.$this->charset.'" />'.PHP_EOL;
+ if (preg_match('/tml$/',$this->content_type)) {
+
+ foreach ($this->to_array($this->css) as $v) {
+ $head .= '<link rel="stylesheet" href="' . $v . '" />'.PHP_EOL;
+ }
+
+ if ($this->css_code) $head .= ''
+ . '<style type="text/css"><!-- ' . PHP_EOL
+ . $this->css_code
+ . ' --></style>' . PHP_EOL
+ ;
+
+ foreach ($this->to_array($this->js) as $v) {
+ $head .= '<script src="' . $v . '" type="text/javascript"></script>' . PHP_EOL;
+ }
+ if ($this->js_code) $head .= ''
+ . '<script type="text/javascript"><!-- ' . PHP_EOL
+ . trim($this->js_code)."\n"
+ . ' --></script>' . PHP_EOL
+ ;
+
+
+ }
+
+ $head .= '</head>'.PHP_EOL;
+ }
+
+ return $head;
+ }
+
+ function is($is) {
+ if ($is == 'xhtml') return preg_match('/xhtml$/',$this->content_type);
+ if ($is == 'html') return preg_match('/html$/',$this->content_type);
+ if ($is == 'xml') return preg_match('/xml$/',$this->content_type);
+ die("Db->is(): unknow value '$is'");
+ }
+}
+return;
+?>