Add new directory structure. Tags will contain current and past releases, and stable will contain any bug fixes to the current stable release so users won't have to get the potentially broken trunk build to fix a screwup in stable.

Trunk updated to 0.9

git-svn-id: http://kusabax.cultnet.net/svn/repo/stable@176 73d99b7e-4f53-4972-b7b7-2ecd3c4d89ee
This commit is contained in:
Sazpaimon committed 2009-05-27 06:37:50 +00:00
commit 88bacfad9c
316 files changed
+79806

No files matched your search

File diff suppressed because it is too large. Load diff
+52
View File
@@ -0,0 +1,52 @@
<?php
/**
* ADOdb Lite Configuration File
*/
/**
* Set the $dbtype variable to the database designator.
* If this variable is enabled it will override the database designator
* entered in the ADONewConnection( $dbtype ) function. The database
* designator in a DSN string will be overridden but the rest of the DSN
* string will be used.
*
* You can place a DSN entry in the $dbtype variable if you would like to
* auto connect to your database.
*
* Example:
*
* $dbtype = "driver://username:password@hostname/database?options[=value]#modules";
*
* driver = Databasetype Designator listed in the table at the start of this page.
* username = The Username needed to access the database
* password = Optional password for accessing the database
* hostname = localhost or url/ip address IE: http://0.0.0.0 or http://www.dbserver.com
* database = The name of the database you will be accessing
* options = All Drivers - 'persist', 'persistent', 'debug', 'fetchmode'
* Mysql (all) - 'port', 'clientflags'
* Mysqli - 'socket'
* Postgress (all) - 'port'
* modules = The modules that should be loaded. IE: pear, cache, extend, ect.
*
*/
//$dbtype = 'mysql';
/**
* If you want to maintain compatability with the ADOdb ADONewConnection( $dbtype )
* function you should designate the modules you need loaded below. If you designate
* the modules below you do not need to designate them in
* ADONewConnection( $dbtype, $modules ).
*
* If you would like more than one module loaded at the same time concatinate the
* module names using a colon (:).
*
* Example:
* $modules = "pear:transaction:extend";
*
* The above example would load the Pear, Transaction and Extend modules
* automatically.
*/
$modules = 'pear:extend';
?>
+392
View File
@@ -0,0 +1,392 @@
<?php
/**
* ADOdb Lite is a PHP class to encapsulate multiple database APIs and is compatible with
* a subset of the ADODB Command Syntax.
* Currently supports Frontbase, MaxDB, miniSQL, MSSQL, MSSQL Pro, MySQLi, MySQLt, MySQL, PostgresSQL,
* PostgresSQL64, PostgresSQL7, PostgresSQL8, SqLite, SqLite Pro, Sybase and Sybase ASE.
*
*/
if (!defined('_ADODB_LAYER'))
define('_ADODB_LAYER',1);
if (!defined('ADODB_DIR'))
define('ADODB_DIR', dirname(__FILE__));
$ADODB_vers = 'V1.42 ADOdb Lite 11 January 2007 (c) 2005-2007 Mark Dickenson. All rights reserved. Released LGPL.';
define('ADODB_FETCH_DEFAULT',0);
define('ADODB_FETCH_NUM',1);
define('ADODB_FETCH_ASSOC',2);
define('ADODB_FETCH_BOTH',3);
GLOBAL $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_DEFAULT; // DEFAULT, NUM, ASSOC or BOTH. Default follows native driver default...
/**
* Database connection
* Usage: $db = new ADONewConnection('dbtype');
*
* @access public
* @param string $dbtype
*/
function &ADONewConnection( $dbtype = 'mysql', $modules = '' )
{
global $ADODB_FETCH_MODE;
$false = false;
@include( ADODB_DIR . '/adodb.config.php' );
if (strpos($dbtype,'://')) {
$dsn_array = @parse_url(rawurldecode($dbtype));
if (!$dsn_array || !$dsn_array['scheme'])
return $false;
$dbtype = $dsn_array['scheme'];
$modules = (!empty($dsn_array['fragment'])) ? $dsn_array['fragment'] : $modules;
} else $dsn_array = array('scheme'=>'');
$dbtype = strtolower($dbtype);
include_once ADODB_DIR . '/adodbSQL_drivers/' . $dbtype . '/' . $dbtype . '_driver.inc';
$last_module = $dbtype . '_' . 'driver';
if(!empty($modules))
{
$module_list = explode(":", strtolower($modules));
$generic_modules = array();
foreach($module_list as $mod) {
$mod = trim($mod);
if(is_file(ADODB_DIR . '/generic_modules/' . $mod . '_module.inc'))
{
$generic_modules[] = $mod;
}
else
{
include_once ADODB_DIR . '/adodbSQL_drivers/' . $dbtype . '/' . $dbtype . '_' . $mod . '_module.inc';
$last_module = $dbtype . '_' . $mod;
}
}
if(count($generic_modules))
{
foreach($generic_modules as $mod) {
include_once ADODB_DIR . '/generic_modules/' . $mod . '_module.inc';
$last_module = $mod;
}
}
}
$extention = $last_module . '_ADOConnection';
$object = new $extention();
$object->last_module_name = $last_module;
$object->raiseErrorFn = (defined('ADODB_ERROR_HANDLER')) ? ADODB_ERROR_HANDLER : false;
$object->query_count = 0;
$object->query_time_total = 0;
if(!empty($dsn_array['scheme']))
{
if (isset($dsn_array['port'])) $object->port = $dsn_array['port'];
$persistent = false;
$forcenew = false;
if (isset($dsn_array['query'])) {
$option_array = explode('&', $dsn_array['query']);
foreach($option_array as $element => $value) {
$array = explode('=', $value);
$data = isset($array[1]) ? $array[1] : 1;
switch(strtolower($array[0])) {
case 'persist':
case 'persistent':
$persistent = $data;
break;
case 'debug':
$object->debug = (integer) $data;
break;
case 'fetchmode':
$ADODB_FETCH_MODE = constant($data);
break;
case 'clientflags':
$object->clientFlags = $data;
break;
case 'port':
$object->port = $data;
break;
case 'socket':
$object->socket = $data;
break;
case 'forcenew':
$forcenew = $data;
break;
}
}
}
$dsn_array['host'] = isset($dsn_array['host']) ? $dsn_array['host'] : '';
$dsn_array['user'] = isset($dsn_array['user']) ? $dsn_array['user'] : '';
$dsn_array['pass'] = isset($dsn_array['pass']) ? $dsn_array['pass'] : '';
$dsn_array['path'] = isset($dsn_array['path']) ? substr($dsn_array['path'], 1) : '';
$result = $object->_connect($dsn_array['host'], $dsn_array['user'], $dsn_array['pass'], $dsn_array['path'], $persistent, $forcenew);
if (!$result) return $false;
}
return $object;
}
/**
* Alternative Database connection
* Usage: $db = new NewADOConnection('dbtype');
*
* @access public
* @param string $dbtype
*/
function &NewADOConnection($dbtype='', $module = '' )
{
$tmp =& ADONewConnection($dbtype, $module);
return $tmp;
}
function &NewDataDictionary(&$connection, $dbtype=false)
{
if(!$dbtype)
$dbtype = $connection->dbtype;
include_once ADODB_DIR . '/adodb-datadict.inc.php';
include_once ADODB_DIR . '/adodbSQL_drivers/' . $dbtype . '/' . $dbtype . '_datadict.inc';
$class = "ADODB2_$dbtype";
$dict = new $class();
$dict->connection = &$connection;
$dict->upperName = strtoupper($dbtype);
$dict->quote = $connection->nameQuote;
$dict->debug_echo = $connection->debug_echo;
return $dict;
}
/**
* Backwards compatible with ADOdb usage of NewPerfMonitor
* Change to module basis for PerfMon mean we need only return a reference to $connection object.
* Usage: $perf =& NewPerfMonitor($conn); - $perf is a reference to $conn
*
* @access public
* @param ADOConnection $connection
* @param string $dbtype This is an optional parameter with no actual use in ADOdb-Lite; for BC only.
*/
function &NewPerfMonitor(&$connection, $dbtype=false)
{
return $connection;
}
class ADOConnection
{
var $connectionId = false;
var $record_set = false;
var $database;
var $dbtype;
var $dataProvider;
var $host;
var $open;
var $password;
var $username;
var $persistent;
var $debug = false;
var $debug_console = false;
var $debug_echo = true;
var $debug_output;
var $forcenewconnection = false;
var $createdatabase = false;
var $last_module_name;
var $socket = false;
var $port = false;
var $clientFlags = 0;
var $nameQuote = '"';
var $sysDate = false; /// name of function that returns the current date
var $sysTimeStamp = false; /// name of function that returns the current timestamp
var $sql;
var $raiseErrorFn = false;
var $query_count = 0;
var $query_time_total = 0;
var $query_list = array();
var $query_list_time = array();
var $query_list_errors = array();
var $_logsql = false;
function ADOConnection()
{
}
/**
* Returns floating point version number of ADOdb Lite
* Usage: $db->Version();
*
* @access public
*/
function Version()
{
global $ADODB_vers;
return (float) substr($ADODB_vers,1);
}
/**
* Returns true if connected to database
* Usage: $db->IsConnected();
*
* @access public
*/
function IsConnected()
{
if($this->connectionId === false || $this->connectionId == false)
return false;
else return true;
}
/**
* Normal Database connection
* Usage: $result = $db->Connect('host', 'username', 'password', 'database');
*
* @access public
* @param string $database
* @param string $host
* @param string $password
* @param string $username
* @param string $forcenew // private
*/
function Connect( $host = "", $username = "", $password = "", $database = "", $forcenew = false)
{
return $this->_connect($host, $username, $password, $database, false, $forcenew);
}
/**
* Persistent Database connection
* Usage: $result = $db->PConnect('host', 'username', 'password', 'database');
*
* @access public
* @param string $database
* @param string $host
* @param string $password
* @param string $username
*/
function PConnect( $host = "", $username = "", $password = "", $database = "")
{
return $this->_connect($host, $username, $password, $database, true, false);
}
/**
* Force New Database connection
* Usage: $result = $db->NConnect('host', 'username', 'password', 'database');
*
* @access public
* @param string $database
* @param string $host
* @param string $password
* @param string $username
*/
function NConnect( $host = "", $username = "", $password = "", $database = "")
{
return $this->_connect($host, $username, $password, $database, false, true);
}
/**
* Returns SQL query and instantiates sql statement & resultset driver
* Usage: $linkId =& $db->execute( 'SELECT * FROM foo ORDER BY id' );
*
* @access public
* @param string $sql
* @return mixed Resource ID, Array
*/
function &Execute( $sql, $inputarr = false )
{
// adodb_log_sql will time the query execution and log the sql query
// note: the later $this->do_query() should not run since adodb_log_sql() independently executes the query itself.
if($this->_logsql === true)
{
$ret =& adodb_log_sql($this, $sql, $inputarr);
if (isset($ret)) return $ret;
}
$rs =& $this->do_query($sql, -1, -1, $inputarr);
return $rs;
}
/**
* Returns SQL query and instantiates sql statement & resultset driver
* Usage: $linkId =& $db->SelectLimit( 'SELECT * FROM foo ORDER BY id', $nrows, $offset );
* $nrows and $offset are optional
*
* @access public
* @param string $sql
* @param string $nrows
* @param string $offset
* @return mixed Resource ID, Array
*/
function &SelectLimit( $sql, $nrows=-1, $offset=-1, $inputarr=false, $secs2cache=0 )
{
$rs =& $this->do_query( $sql, $offset, $nrows, $inputarr);
return $rs;
}
/**
* Display debug output and database error.
*
* @access private
*/
function outp($text, $newline = true)
{
global $ADODB_OUTP;
$this->debug_output = "<br />\n(" . $this->dbtype . "): ".htmlspecialchars($text)."<br />\n Error (" . $this->ErrorNo() .'): '. $this->ErrorMsg() . "<br />\n";
if(defined('ADODB_OUTP'))
{
$fn = ADODB_OUTP;
} else if(isset($ADODB_OUTP))
{
$fn = $ADODB_OUTP;
}
if(defined('ADODB_OUTP') || isset($ADODB_OUTP))
{
$fn($this->debug_output, $newline);
return;
}
if($this->debug_echo)
echo $this->debug_output;
}
}
/**
* Empty result record set for updates, inserts, ect
*
* @access private
*/
class ADORecordSet_empty
{
var $fields = false;
var $EOF = true;
function MoveNext() {return;}
function RecordCount() {return 0;}
function FieldCount() {return 0;}
function EOF(){return TRUE;}
function Close(){return true;}
}
class ADOFieldObject {
var $name = '';
var $max_length=0;
var $type="";
}
?>
@@ -0,0 +1,112 @@
<?php
/**
V4.65 22 July 2005 (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Modified 28 August, 2005 for use with ADOdb Lite by Mark Dickenson
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class ADODB2_mysql extends ADODB_DataDict {
var $dbtype = 'mysql';
var $alterCol = ' MODIFY COLUMN';
var $alterTableAddIndex = true;
var $dropTable = 'DROP TABLE IF EXISTS %s'; // requires mysql 3.22 or later
var $dropIndex = 'DROP INDEX %s ON %s';
var $renameColumn = 'ALTER TABLE %s CHANGE COLUMN %s %s %s'; // needs column-definition!
function ActualType($meta)
{
switch(strtoupper($meta)) {
case 'C': return 'VARCHAR';
case 'XL':return 'LONGTEXT';
case 'X': return 'TEXT';
case 'C2': return 'VARCHAR';
case 'X2': return 'LONGTEXT';
case 'B': return 'LONGBLOB';
case 'D': return 'DATE';
case 'DT': return 'DATETIME';
case 'T': return 'TIME';
case 'TS': return 'TIMESTAMP';
case 'L': return 'TINYINT';
case 'R':
case 'I4':
case 'I': return 'INTEGER';
case 'I1': return 'TINYINT';
case 'I2': return 'SMALLINT';
case 'I8': return 'BIGINT';
case 'F': return 'DOUBLE';
case 'N': return 'NUMERIC';
default:
return $meta;
}
}
// return string must begin with space
function _CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned)
{
$suffix = '';
if ($funsigned) $suffix .= ' UNSIGNED';
if ($fnotnull) $suffix .= ' NOT NULL';
if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
if ($fautoinc) $suffix .= ' AUTO_INCREMENT';
if ($fconstraint) $suffix .= ' '.$fconstraint;
return $suffix;
}
function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
{
$sql = array();
if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {
if ($this->alterTableAddIndex) $sql[] = "ALTER TABLE $tabname DROP INDEX $idxname";
else $sql[] = sprintf($this->dropIndex, $idxname, $tabname);
if ( isset($idxoptions['DROP']) )
return $sql;
}
if ( empty ($flds) ) {
return $sql;
}
if (isset($idxoptions['FULLTEXT'])) {
$unique = ' FULLTEXT';
} elseif (isset($idxoptions['UNIQUE'])) {
$unique = ' UNIQUE';
} else {
$unique = '';
}
if ( is_array($flds) ) $flds = implode(', ',$flds);
if ($this->alterTableAddIndex) $s = "ALTER TABLE $tabname ADD $unique INDEX $idxname ";
else $s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname;
$s .= ' (' . $flds . ')';
if ( isset($idxoptions[$this->upperName]) )
$s .= $idxoptions[$this->upperName];
$sql[] = $s;
return $sql;
}
}
?>
@@ -0,0 +1,321 @@
<?php
/**
* ADOdb Lite Date Module for Mysql
*
*/
if (!defined('TIMESTAMP_FIRST_YEAR')) define('TIMESTAMP_FIRST_YEAR',100);
@include(ADODB_DIR . '/adodb-time.inc.php');
eval('class mysql_date_EXTENDER extends '. $last_module . '_ADOConnection { }');
class mysql_date_ADOConnection extends mysql_date_EXTENDER
{
var $fmtDate = "'Y-m-d'"; /// used by DBDate() as the default date format used by the database
var $fmtTimeStamp = "'Y-m-d H:i:s'";
var $emptyDate = '&nbsp;';
var $emptyTimeStamp = '&nbsp;';
var $sysDate = 'CURDATE()';
var $sysTimeStamp = 'NOW()';
var $isoDates = true; // accepts dates in ISO format
function Time()
{
$rs =& $this->_Execute("select $this->sysTimeStamp");
if ($rs && !$rs->EOF)
return $this->UnixTimeStamp(reset($rs->fields));
else return false;
}
function OffsetDate($dayFraction, $date=false)
{
if (!$date)
$date = $this->sysDate;
$fraction = $dayFraction * 24 * 3600;
return "from_unixtime(unix_timestamp($date)+$fraction)";
}
function SetDateLocale($locale = 'En')
{
$this->locale = $locale;
switch (strtoupper($locale))
{
case 'EN':
$this->fmtDate="'Y-m-d'";
$this->fmtTimeStamp = "'Y-m-d H:i:s'";
break;
case 'US':
$this->fmtDate = "'m-d-Y'";
$this->fmtTimeStamp = "'m-d-Y H:i:s'";
break;
case 'NL':
case 'FR':
case 'RO':
case 'IT':
$this->fmtDate="'d-m-Y'";
$this->fmtTimeStamp = "'d-m-Y H:i:s'";
break;
case 'GE':
$this->fmtDate="'d.m.Y'";
$this->fmtTimeStamp = "'d.m.Y H:i:s'";
break;
default:
$this->fmtDate="'Y-m-d'";
$this->fmtTimeStamp = "'Y-m-d H:i:s'";
break;
}
}
function DBDate($date)
{
if (empty($date) && $date !== 0)
return 'null';
if (is_string($date) && !is_numeric($date)) {
if ($date === 'null' || strncmp($date, "'", 1) === 0)
return $date;
if ($this->isoDates)
return "'$date'";
$date = $this->UnixDate($date);
}
return adodb_date($this->fmtDate, $date);
}
function DBTimeStamp($timestamp)
{
if (empty($timestamp) && $timestamp !== 0)
return 'null';
# strlen(14) allows YYYYMMDDHHMMSS format
if (!is_string($timestamp) || (is_numeric($timestamp) && strlen($timestamp)<14))
return adodb_date($this->fmtTimeStamp, $timestamp);
if ($timestamp === 'null')
return $timestamp;
if ($this->isoDates && strlen($timestamp) !== 14)
return "'$timestamp'";
return adodb_date($this->fmtTimeStamp, $this->UnixTimeStamp($timestamp));
}
function UnixDate($v)
{
if (is_object($v)) {
// odbtp support
//( [year] => 2004 [month] => 9 [day] => 4 [hour] => 12 [minute] => 44 [second] => 8 [fraction] => 0 )
return adodb_mktime($v->hour, $v->minute, $v->second, $v->month, $v->day, $v->year);
}
if (is_numeric($v) && strlen($v) !== 8)
return $v;
if (!preg_match( "|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})|", ($v), $rr))
return false;
if ($rr[1] <= TIMESTAMP_FIRST_YEAR)
return 0;
// h-m-s-MM-DD-YY
return adodb_mktime(0, 0, 0, $rr[2], $rr[3], $rr[1]);
}
function UnixTimeStamp($v)
{
if (is_object($v)) {
// odbtp support
//( [year] => 2004 [month] => 9 [day] => 4 [hour] => 12 [minute] => 44 [second] => 8 [fraction] => 0 )
return adodb_mktime($v->hour, $v->minute, $v->second, $v->month, $v->day, $v->year);
}
if (!preg_match("|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})[ ,-]*(([0-9]{1,2}):?([0-9]{1,2}):?([0-9\.]{1,4}))?|", ($v), $rr))
return false;
if ($rr[1] <= TIMESTAMP_FIRST_YEAR && $rr[2]<= 1)
return 0;
// h-m-s-MM-DD-YY
if (!isset($rr[5]))
return adodb_mktime(0, 0, 0, $rr[2], $rr[3], $rr[1]);
return adodb_mktime($rr[5], $rr[6], $rr[7], $rr[2], $rr[3], $rr[1]);
}
function UserDate($v, $fmt='Y-m-d', $gmt=false)
{
$tt = $this->UnixDate($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
else if ($tt == 0)
return $this->emptyDate;
else if ($tt == -1) { // pre-TIMESTAMP_FIRST_YEAR
}
return ($gmt) ? adodb_gmdate($fmt, $tt) : adodb_date($fmt, $tt);
}
function UserTimeStamp($v, $fmt='Y-m-d H:i:s', $gmt=false)
{
if (!isset($v))
return $this->emptyTimeStamp;
# strlen(14) allows YYYYMMDDHHMMSS format
if (is_numeric($v) && strlen($v)<14)
return ($gmt) ? adodb_gmdate($fmt, $v) : adodb_date($fmt,$v);
$tt = $this->UnixTimeStamp($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
if ($tt == 0)
return $this->emptyTimeStamp;
return ($gmt) ? adodb_gmdate($fmt, $tt) : adodb_date($fmt, $tt);
}
function SQLDate($fmt, $col=false)
{
if (!$col)
$col = $this->sysTimeStamp;
$s = 'DATE_FORMAT('.$col.",'";
$concat = false;
$len = strlen($fmt);
for ($i=0; $i < $len; $i++) {
$ch = $fmt[$i];
switch($ch) {
default:
if ($ch == '\\') {
$i++;
$ch = substr($fmt, $i, 1);
}
/** FALL THROUGH */
case '-':
case '/':
$s .= $ch;
break;
case 'Y':
case 'y':
$s .= '%Y';
break;
case 'M':
$s .= '%b';
break;
case 'm':
$s .= '%m';
break;
case 'D':
case 'd':
$s .= '%d';
break;
case 'Q':
case 'q':
$s .= "'),Quarter($col)";
if ($len > $i+1)
$s .= ",DATE_FORMAT($col,'";
else $s .= ",('";
$concat = true;
break;
case 'H':
$s .= '%H';
break;
case 'h':
$s .= '%I';
break;
case 'i':
$s .= '%i';
break;
case 's':
$s .= '%s';
break;
case 'a':
case 'A':
$s .= '%p';
break;
case 'w':
$s .= '%w';
break;
case 'l':
$s .= '%W';
break;
}
}
$s.="')";
if ($concat)
$s = "CONCAT($s)";
return $s;
}
}
eval('class mysql_date_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class mysql_date_ResultSet extends mysql_date_resultset_EXTENDER
{
var $emptyTimeStamp = '&nbsp;'; /// what to display when $time==0
var $emptyDate = '&nbsp;'; /// what to display when $time==0
var $datetime = false;
function UserTimeStamp($v, $fmt='Y-m-d H:i:s')
{
if (is_numeric($v) && strlen($v)<14)
return adodb_date($fmt, $v);
$tt = $this->UnixTimeStamp($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
if ($tt === 0)
return $this->emptyTimeStamp;
else return adodb_date($fmt, $tt);
}
function UserDate($v,$fmt='Y-m-d')
{
$tt = $this->UnixDate($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
else if ($tt == 0)
return $this->emptyDate;
else if ($tt == -1) { // pre-TIMESTAMP_FIRST_YEAR
}
return adodb_date($fmt, $tt);
}
function UnixDate($v)
{
return mysql_date_ADOConnection::UnixDate($v);
}
function UnixTimeStamp($v)
{
return mysql_date_ADOConnection::UnixTimeStamp($v);
}
}
?>
@@ -0,0 +1,660 @@
<?php
/**
* ADOdb Lite is a PHP class to encapsulate multiple database APIs and is compatible with
* a subset of the ADODB Command Syntax.
* Currently supports Frontbase, MaxDB, miniSQL, MSSQL, MSSQL Pro, MySQLi, MySQLt, MySQL, PostgresSQL,
* PostgresSQL64, PostgresSQL7, SqLite and Sybase.
*
*/
class mysql_driver_ADOConnection extends ADOConnection
{
var $nameQuote = '`';
var $sysDate = 'CURDATE()';
var $sysTimeStamp = 'NOW()';
function mysql_driver_ADOConnection()
{
$this->dbtype = 'mysql';
$this->dataProvider = 'mysql';
}
/**
* Connection to database server and selected database
*
* @access private
*/
function _connect($host = "", $username = "", $password = "", $database = "", $persistent, $forcenew)
{
if (!function_exists('mysql_connect')) {
echo "ERROR: Function 'mysql_connect' not found! Check if MySQL is properly set up. And that PHP has the MySQL extension installed.";
return false;
}
$this->host = $host;
if (!empty($this->port)) $this->host .= ":" . $this->port;
$this->username = $username;
$this->password = $password;
$this->database = $database;
$this->persistent = $persistent;
$this->forcenewconnection = $forcenew;
if($this->persistent == 1)
{
if (strnatcmp(PHP_VERSION, '4.3.0') >= 0)
$this->connectionId = @mysql_pconnect( $this->host, $this->username, $this->password, $this->clientFlags );
else
$this->connectionId = @mysql_pconnect( $this->host, $this->username, $this->password );
}
else
{
if (strnatcmp(PHP_VERSION, '4.3.0') >= 0)
$this->connectionId = @mysql_connect( $this->host, $this->username, $this->password, $this->forcenewconnection, $this->clientFlags );
else if (strnatcmp(PHP_VERSION, '4.2.0') >= 0)
$this->connectionId = @mysql_connect( $this->host, $this->username, $this->password, $this->forcenewconnection );
else
$this->connectionId = @mysql_connect( $this->host, $this->username, $this->password );
}
if ($this->connectionId === false)
{
if ($fn = $this->raiseErrorFn)
$fn($this->dbtype, 'CONNECT', $this->ErrorNo(), $this->ErrorMsg(), $this->host, $this->database, $this);
return false;
}
if (!empty($this->database))
{
if($this->SelectDB( $this->database ) == false)
{
$this->connectionId = false;
return false;
}
}
return true;
}
/**
* Choose a database to connect.
*
* @param dbname is the name of the database to select
* @return true or false
* @access public
*/
function SelectDB($dbname)
{
$this->database = $dbname;
if ($this->connectionId === false)
{
$this->connectionId = false;
return false;
}
else
{
$result = @mysql_select_db( $this->database, $this->connectionId );
if($result === false)
{
if($this->createdatabase == true)
{
$result = @mysql_query( "CREATE DATABASE IF NOT EXISTS " . $this->database, $this->connectionId );
if ($result === false) { // error handling if query fails
return false;
}
$result = @mysql_select_db( $this->database, $this->connectionId );
if($result === false)
{
return false;
}
}
else
{
return false;
}
}
return true;
}
}
/**
* Return database error message
* Usage: $errormessage =& $db->ErrorMsg();
*
* @access public
*/
function ErrorMsg()
{
if ($this->connectionId === false)
{
return @mysql_error();
}
else
{
return @mysql_error($this->connectionId);
}
}
/**
* Return database error number
* Usage: $errorbo =& $db->ErrorNo();
*
* @access public
*/
function ErrorNo()
{
if ($this->connectionId === false)
{
return @mysql_errno();
}
else
{
return @mysql_errno($this->connectionId);
}
}
/**
* Returns # of affected rows from insert/delete/update query
*
* @access public
* @return integer Affected rows
*/
function Affected_Rows()
{
return @mysql_affected_rows($this->connectionId);
}
/**
* Returns the last record id of an inserted item
* Usage: $db->Insert_ID();
*
* @access public
*/
function Insert_ID()
{
return @mysql_insert_id($this->connectionId);
}
/**
* Correctly quotes a string so that all strings are escape coded.
* An example is $db->qstr("Haven't a clue.");
*
* @param string the string to quote
* @param [magic_quotes] if $s is GET/POST var, set to get_magic_quotes_gpc().
*
* @return single-quoted string IE: 'Haven\'t a clue.'
*/
function qstr($string, $magic_quotes=false)
{
if (!$magic_quotes) {
if (strnatcmp(PHP_VERSION, '4.3.0') >= 0) {
return "'" . mysql_real_escape_string($string, $this->connectionId) . "'";
}
$string = str_replace("'", "\\'" , str_replace('\\', '\\\\', str_replace("\0", "\\\0", $string)));
return "'" . $string . "'";
}
return "'" . str_replace('\\"', '"', $string) . "'";
}
function QMagic($string)
{
return $this->qstr($string, get_magic_quotes_gpc());
}
/**
* Returns concatenated string
* Usage: $db->Concat($str1,$str2);
*
* @return concatenated string
*/
function Concat()
{
$arr = func_get_args();
$list = implode(', ', $arr);
if (strlen($list) > 0) return "CONCAT($list)";
else return '';
}
function IfNull( $field, $ifNull )
{
return " IFNULL($field, $ifNull) ";
}
/**
* Closes database connection
* Usage: $db->close();
*
* @access public
*/
function Close()
{
@mysql_close( $this->connectionId );
$this->connectionId = false;
}
/**
* Returns All Records in an array
*
* Usage: $db->GetAll($sql);
* @access public
*/
function &GetAll($sql, $inputarr = false)
{
$data =& $this->GetArray($sql, $inputarr);
return $data;
}
/**
* Returns All Records in an array
*
* Usage: $db->GetArray($sql);
* @access public
*/
function &GetArray($sql, $inputarr = false)
{
$data = false;
$result =& $this->Execute($sql, $inputarr);
if ($result)
{
$data =& $result->GetArray();
$result->Close();
}
return $data;
}
/**
* Executes SQL query and instantiates resultset methods
*
* @access private
* @return mixed Resultset methods
*/
function &do_query( $sql, $offset, $nrows, $inputarr=false )
{
global $ADODB_FETCH_MODE;
$false = false;
$limit = '';
if ($offset >= 0 || $nrows >= 0)
{
$offset = ($offset >= 0) ? $offset . "," : '';
$nrows = ($nrows >= 0) ? $nrows : '18446744073709551615';
$limit = ' LIMIT ' . $offset . ' ' . $nrows;
}
if ($inputarr && is_array($inputarr)) {
$sqlarr = explode('?', $sql);
if (!is_array(reset($inputarr))) $inputarr = array($inputarr);
foreach($inputarr as $arr) {
$sql = ''; $i = 0;
foreach($arr as $v) {
$sql .= $sqlarr[$i];
switch(gettype($v)){
case 'string':
$sql .= $this->qstr($v);
break;
case 'double':
$sql .= str_replace(',', '.', $v);
break;
case 'boolean':
$sql .= $v ? 1 : 0;
break;
default:
if ($v === null)
$sql .= 'NULL';
else $sql .= $v;
}
$i += 1;
}
$sql .= $sqlarr[$i];
if ($i+1 != sizeof($sqlarr))
return $false;
$this->sql = $sql . $limit;
$time_start = array_sum(explode(' ', microtime()));
$this->query_count++;
$resultId = @mysql_query( $this->sql, $this->connectionId );
$time_total = (array_sum(explode(' ', microtime())) - $time_start);
$this->query_time_total += $time_total;
if($this->debug_console)
{
$this->query_list[] = $this->sql;
$this->query_list_time[] = $time_total;
$this->query_list_errors[] = $this->ErrorMsg();
}
if($this->debug)
{
$this->outp($sql . $limit);
}
if ($resultId === false) { // error handling if query fails
if ($fn = $this->raiseErrorFn)
$fn($this->dbtype, 'EXECUTE', $this->ErrorNo(), $this->ErrorMsg(), $this->sql, $inputarr, $this);
return $false;
}
}
}
else
{
$this->sql = $sql . $limit;
$this->sql = $sql . $limit;
$time_start = array_sum(explode(' ', microtime()));
$this->query_count++;
$resultId = @mysql_query( $this->sql, $this->connectionId );
$time_total = (array_sum(explode(' ', microtime())) - $time_start);
$this->query_time_total += $time_total;
if($this->debug_console)
{
$this->query_list[] = $this->sql;
$this->query_list_time[] = $time_total;
$this->query_list_errors[] = $this->ErrorMsg();
}
if($this->debug)
{
$this->outp($sql . $limit);
}
}
if ($resultId === false) { // error handling if query fails
if ($fn = $this->raiseErrorFn)
$fn($this->dbtype, 'EXECUTE', $this->ErrorNo(), $this->ErrorMsg(), $this->sql, $inputarr, $this);
return $false;
}
if ($resultId === true) { // return simplified recordset for inserts/updates/deletes with lower overhead
$recordset = new ADORecordSet_empty();
return $recordset;
}
$resultset_name = $this->last_module_name . "_ResultSet";
$recordset = new $resultset_name( $resultId, $this->connectionId );
$recordset->_currentRow = 0;
switch ($ADODB_FETCH_MODE)
{
case ADODB_FETCH_NUM: $recordset->fetchMode = MYSQL_NUM; break;
case ADODB_FETCH_ASSOC: $recordset->fetchMode = MYSQL_ASSOC; break;
default:
case ADODB_FETCH_DEFAULT:
case ADODB_FETCH_BOTH: $recordset->fetchMode = MYSQL_BOTH; break;
}
$recordset->_numOfRows = @mysql_num_rows( $resultId );
if( $recordset->_numOfRows == 0)
{
$recordset->EOF = true;
}
$recordset->_numOfFields = @mysql_num_fields( $resultId );
$recordset->_fetch();
return $recordset;
}
}
class mysql_driver_ResultSet
{
var $connectionId;
var $fields;
var $resultId;
var $_currentRow = 0;
var $_numOfRows = -1;
var $_numOfFields = -1;
var $fetchMode;
var $EOF;
/**
* mysqlResultSet Constructor
*
* @access private
* @param string $record
* @param string $resultId
*/
function mysql_driver_ResultSet( $resultId, $connectionId )
{
$this->fields = array();
$this->connectionId = $connectionId;
$this->record = array();
$this->resultId = $resultId;
$this->EOF = false;
}
/**
* Frees resultset
*
* @access public
*/
function Close()
{
@mysql_free_result( $this->resultId );
$this->fields = array();
$this->resultId = false;
}
/**
* Returns field name from select query
*
* @access public
* @param string $field
* @return string Field name
*/
function fields( $field )
{
if(empty($field))
{
return $this->fields;
}
else
{
return $this->fields[$field];
}
}
/**
* Returns numrows from select query
*
* @access public
* @return integer Numrows
*/
function RecordCount()
{
return $this->_numOfRows;
}
/**
* Returns num of fields from select query
*
* @access public
* @return integer numfields
*/
function FieldCount()
{
return $this->_numOfFields;
}
/**
* Returns next record
*
* @access public
*/
function MoveNext()
{
if (@$this->fields = mysql_fetch_array($this->resultId,$this->fetchMode)) {
$this->_currentRow += 1;
return true;
}
if (!$this->EOF) {
$this->_currentRow += 1;
$this->EOF = true;
}
return false;
}
/**
* Move to the first row in the recordset. Many databases do NOT support this.
*
* @return true or false
*/
function MoveFirst()
{
if ($this->_currentRow == 0) return true;
return $this->Move(0);
}
/**
* Returns the Last Record
*
* @access public
*/
function MoveLast()
{
if ($this->EOF) return false;
return $this->Move($this->_numOfRows - 1);
}
/**
* Random access to a specific row in the recordset. Some databases do not support
* access to previous rows in the databases (no scrolling backwards).
*
* @param rowNumber is the row to move to (0-based)
*
* @return true if there still rows available, or false if there are no more rows (EOF).
*/
function Move($rowNumber = 0)
{
if ($rowNumber == $this->_currentRow) return true;
$this->EOF = false;
if ($this->_numOfRows > 0){
if ($rowNumber >= $this->_numOfRows - 1){
$rowNumber = $this->_numOfRows - 1;
}
}
if ($this->_seek($rowNumber)) {
$this->_currentRow = $rowNumber;
if ($this->_fetch()) {
return true;
}
$this->fields = false;
}
$this->EOF = true;
return false;
}
/**
* Perform Seek to specific row
*
* @access private
*/
function _seek($row)
{
if ($this->_numOfRows == 0) return false;
return @mysql_data_seek($this->resultId,$row);
}
/**
* Fills field array with first database element when query initially executed
*
* @access private
*/
function _fetch()
{
$this->fields = @mysql_fetch_array($this->resultId,$this->fetchMode);
return is_array($this->fields);
}
/**
* Check to see if last record reached
*
* @access public
*/
function EOF()
{
if( $this->_currentRow < $this->_numOfRows)
{
return false;
}
else
{
$this->EOF = true;
return true;
}
}
/**
* Returns All Records in an array
*
* @access public
* @param [nRows] is the number of rows to return. -1 means every row.
*/
function &GetArray($nRows = -1)
{
$results = array();
$cnt = 0;
while (!$this->EOF && $nRows != $cnt) {
$results[] = $this->fields;
$this->MoveNext();
$cnt++;
}
return $results;
}
function &GetRows($nRows = -1)
{
$arr =& $this->GetArray($nRows);
return $arr;
}
function &GetAll($nRows = -1)
{
$arr =& $this->GetArray($nRows);
return $arr;
}
/**
* Fetch field information for a table.
*
* @return object containing the name, type and max_length
*/
function FetchField($fieldOffset = -1)
{
if ($fieldOffset != -1) {
$fieldObject = @mysql_fetch_field($this->resultId, $fieldOffset);
$fieldObject->max_length = @mysql_field_len($this->resultId,$fieldOffset);
}
else
{
$fieldObject = @mysql_fetch_field($this->resultId);
$fieldObject->max_length = @mysql_field_len($this->resultId);
}
return $fieldObject;
}
}
?>
@@ -0,0 +1,150 @@
<?php
/**
* ADOdb Lite Extend Module for Mysqlt
*
*/
eval('class mysql_extend_EXTENDER extends '. $last_module . '_ADOConnection { }');
class mysql_extend_ADOConnection extends mysql_extend_EXTENDER
{
function &GetAssoc($sql, $inputarr=false, $force_array = false, $first2cols = false)
{
$data = false;
$result =& $this->Execute($sql, $inputarr);
if ($result) {
$data =& $result->GetAssoc($force_array, $first2cols);
$result->Close();
}
return $data;
}
/**
* Generates a sequence id and stores it in $this->genID;
* GenID is only available if $this->hasGenID = true;
*
* @param seqname name of sequence to use
* @param startID if sequence does not exist, start at this ID
* @return 0 if not supported, otherwise a sequence id
*/
var $genID = 0;
var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);";
var $_genSeqSQL = "create table %s (id int not null)";
var $_genSeq2SQL = "insert into %s values (%s)";
var $_dropSeqSQL = "drop table %s";
function GenID($seqname='adodbseq', $startID=1)
{
$getnext = sprintf($this->_genIDSQL, $seqname);
$holdtransOK = $this->transaction_status;
$result = @$this->Execute($getnext);
if (!$result) {
if ($holdtransOK)
$this->transaction_status = true;
// $u = strtoupper($seqname);
$this->Execute(sprintf($this->_genSeqSQL, $seqname));
$this->Execute(sprintf($this->_genSeq2SQL, $seqname, $startID-1));
$result = $this->Execute($getnext);
}
$this->genID = mysql_insert_id($this->connectionId);
if ($result)
$result->Close();
return $this->genID;
}
function CreateSequence($seqname='adodbseq',$startID=1)
{
$u = strtoupper($seqname);
$ok = $this->Execute(sprintf($this->_genSeqSQL, $seqname));
if (!$ok)
return false;
return $this->Execute(sprintf($this->_genSeq2SQL, $seqname, $startID-1));
}
function DropSequence($seqname='adodbseq')
{
return $this->Execute(sprintf($this->_dropSeqSQL, $seqname));
}
}
eval('class mysql_extend_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class mysql_extend_ResultSet extends mysql_extend_resultset_EXTENDER
{
function &GetAssoc($force_array = false, $first2cols = false)
{
$results = false;
if ($this->_numOfFields > 1) {
$numIndex = isset($this->fields[0]);
$results = array();
if (!$first2cols && ($this->_numOfFields > 2 || $force_array)) {
if ($numIndex) {
while (!$this->EOF) {
$results[trim($this->fields[0])] = array_slice($this->fields, 1);
$this->MoveNext();
}
} else {
while (!$this->EOF) {
$results[trim(reset($this->fields))] = array_slice($this->fields, 1);
$this->MoveNext();
}
}
} else {
if ($numIndex) {
while (!$this->EOF) {
$results[trim(($this->fields[0]))] = $this->fields[1];
$this->MoveNext();
}
} else {
while (!$this->EOF) {
$v1 = trim(reset($this->fields));
$v2 = ''.next($this->fields);
$results[$v1] = $v2;
$this->MoveNext();
}
}
}
}
return $results;
}
function PO_RecordCount($table="", $condition="")
{
$lnumrows = $this->_numOfRows;
if($lnumrows == -1 && $this->connectionId)
{
if($table)
{
if ($condition)
$condition = " WHERE " . $condition;
$resultrows = &$this->connectionId->Execute("SELECT COUNT(*) FROM $table $condition");
if ($resultrows)
$lnumrows = reset($resultrows->fields);
}
}
return $lnumrows;
}
function CurrentRow()
{
return $this->_currentRow;
}
function AbsolutePosition()
{
return $this->_currentRow;
}
function NextRecordSet()
{
return false;
}
}
?>
@@ -0,0 +1,623 @@
<?php
/**
* ADOdb Lite Meta Module for Mysql
*
* Portions of the Meta Coding came from ADOdb
*/
/*
(c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. See License.txt.
*/
eval('class mysql_meta_EXTENDER extends '. $last_module . '_ADOConnection { }');
class mysql_meta_ADOConnection extends mysql_meta_EXTENDER
{
var $metaTablesSQL = "SHOW TABLES";
var $metaColumnsSQL = "SHOW COLUMNS FROM %s";
function MetaError($err=false)
{
include_once(ADODB_DIR."/adodb-error.inc.php");
if ($err === false)
$err = $this->ErrorNo();
return adodb_error($this->dataProvider,$this->databaseType,$err);
}
function MetaErrorMsg($errno)
{
include_once(ADODB_DIR."/adodb-error.inc.php");
return adodb_errormsg($errno);
}
/**
* @returns an array with the primary key columns in it.
*/
function MetaPrimaryKeys($table, $owner=false)
{
// owner not used in base class - see oci8
$p = array();
$objs =& $this->MetaColumns($table);
if ($objs) {
foreach($objs as $v) {
if (!empty($v->primary_key))
$p[] = $v->name;
}
}
if (sizeof($p))
return $p;
if (function_exists('ADODB_VIEW_PRIMARYKEYS'))
return ADODB_VIEW_PRIMARYKEYS($this->databaseType, $this->database, $table, $owner);
return false;
}
/**
* @returns assoc array where keys are tables, and values are foreign keys
*/
function MetaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE )
{
if ( !empty($owner) ) {
$table = "$owner.$table";
}
$a_create_table = $this->getRow(sprintf('SHOW CREATE TABLE %s', $table));
if ($associative) $create_sql = $a_create_table["Create Table"];
else $create_sql = $a_create_table[1];
$matches = array();
if (!preg_match_all("/FOREIGN KEY \(`(.*?)`\) REFERENCES `(.*?)` \(`(.*?)`\)/", $create_sql, $matches)) return false;
$foreign_keys = array();
$num_keys = count($matches[0]);
for ( $i = 0; $i < $num_keys; $i ++ ) {
$my_field = explode('`, `', $matches[1][$i]);
$ref_table = $matches[2][$i];
$ref_field = explode('`, `', $matches[3][$i]);
if ( $upper ) {
$ref_table = strtoupper($ref_table);
}
$foreign_keys[$ref_table] = array();
$num_fields = count($my_field);
for ( $j = 0; $j < $num_fields; $j ++ ) {
if ( $associative ) {
$foreign_keys[$ref_table][$ref_field[$j]] = $my_field[$j];
} else {
$foreign_keys[$ref_table][] = "{$my_field[$j]}={$ref_field[$j]}";
}
}
}
return $foreign_keys;
}
// not the fastest implementation - quick and dirty - jlim
// for best performance, use the actual $rs->MetaType().
function MetaType($t,$len=-1,$fieldobj=false)
{
if (empty($this->_metars)) {
$rsclass = $this->last_module_name . "_ResultSet";
$this->_metars =& new $rsclass(false,$this->fetchMode);
}
return $this->_metars->MetaType($t,$len,$fieldobj);
}
/**
* return the databases that the driver can connect to.
* Some databases will return an empty array.
*
* @return an array of database names.
*/
function &MetaDatabases()
{
$qid = mysql_list_dbs($this->connectionId);
$arr = array();
$i = 0;
$max = mysql_num_rows($qid);
while ($i < $max) {
$db = mysql_tablename($qid,$i);
if ($db != 'mysql') $arr[] = $db;
$i += 1;
}
return $arr;
}
/**
* @param ttype can either be 'VIEW' or 'TABLE' or false.
* If false, both views and tables are returned.
* "VIEW" returns only views
* "TABLE" returns only tables
* @param showSchema returns the schema/user with the table name, eg. USER.TABLE
* @param mask is the input mask - only supported by oci8 and postgresql
*
* @return array of tables for current database.
*/
function &MetaTables($ttype=false,$showSchema=false,$mask=false)
{
$save = $this->metaTablesSQL;
if ($showSchema && is_string($showSchema)) {
$this->metaTablesSQL .= " from $showSchema";
}
if ($mask) {
$mask = $this->qstr($mask);
$this->metaTablesSQL .= " like $mask";
}
$ret =& $this->_MetaTables($ttype,$showSchema);
$this->metaTablesSQL = $save;
return $ret;
}
function &_MetaTables($ttype=false,$showSchema=false,$mask=false)
{
global $ADODB_FETCH_MODE;
$false = false;
if ($mask) {
return $false;
}
if ($this->metaTablesSQL) {
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
$rs = $this->Execute($this->metaTablesSQL);
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
if ($rs === false) return $false;
$arr =& $rs->GetArray();
$arr2 = array();
if ($hast = ($ttype && isset($arr[0][1]))) {
$showt = strncmp($ttype,'T',1);
}
for ($i=0; $i < sizeof($arr); $i++) {
if ($hast) {
if ($showt == 0) {
if (strncmp($arr[$i][1],'T',1) == 0) $arr2[] = trim($arr[$i][0]);
} else {
if (strncmp($arr[$i][1],'V',1) == 0) $arr2[] = trim($arr[$i][0]);
}
} else
$arr2[] = trim($arr[$i][0]);
}
$rs->Close();
return $arr2;
}
return $false;
}
function _findschema(&$table,&$schema)
{
if (!$schema && ($at = strpos($table,'.')) !== false) {
$schema = substr($table,0,$at);
$table = substr($table,$at+1);
}
}
/**
* List columns in a database as an array of ADOFieldObjects.
* See top of file for definition of object.
*
* @param $table table name to query
* @param $normalize makes table name case-insensitive (required by some databases)
* @schema is optional database schema to use - not supported by all databases.
*
* @return array of ADOFieldObjects for current table.
*/
function MetaColumns($table)
{
$this->_findschema($table,$schema);
if ($schema) {
$dbName = $this->database;
$this->connection->SelectDB($schema);
}
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
$rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
if ($schema) {
$this->SelectDB($dbName);
}
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
if (!is_object($rs)) {
$false = false;
return $false;
}
$retarr = array();
while (!$rs->EOF){
$fld = new ADOFieldObject();
$fld->name = $rs->fields[0];
$type = $rs->fields[1];
// split type into type(length):
$fld->scale = null;
if (preg_match("/^(.+)\((\d+),(\d+)/", $type, $query_array)) {
$fld->type = $query_array[1];
$fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
$fld->scale = is_numeric($query_array[3]) ? $query_array[3] : -1;
} elseif (preg_match("/^(.+)\((\d+)/", $type, $query_array)) {
$fld->type = $query_array[1];
$fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
} elseif (preg_match("/^(enum)\((.*)\)$/i", $type, $query_array)) {
$fld->type = $query_array[1];
$arr = explode(",",$query_array[2]);
$fld->enums = $arr;
$zlen = max(array_map("strlen",$arr)) - 2; // PHP >= 4.0.6
$fld->max_length = ($zlen > 0) ? $zlen : 1;
} else {
$fld->type = $type;
$fld->max_length = -1;
}
$fld->not_null = ($rs->fields[2] != 'YES');
$fld->primary_key = ($rs->fields[3] == 'PRI');
$fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false);
$fld->binary = (strpos($type,'blob') !== false);
$fld->unsigned = (strpos($type,'unsigned') !== false);
if (!$fld->binary) {
$d = $rs->fields[4];
if ($d != '' && $d != 'NULL') {
$fld->has_default = true;
$fld->default_value = $d;
} else {
$fld->has_default = false;
}
}
if ($save == ADODB_FETCH_NUM) {
$retarr[] = $fld;
} else {
$retarr[strtoupper($fld->name)] = $fld;
}
$rs->MoveNext();
}
$rs->Close();
return $retarr;
}
/**
* List indexes on a table as an array.
* @param table table name to query
* @param primary true to only show primary keys. Not actually used for most databases
*
* @return array of indexes on current table. Each element represents an index, and is itself an associative array.
Array (
[name_of_index] => Array
(
[unique] => true or false
[columns] => Array
(
[0] => firstname
[1] => lastname
)
)
*/
function MetaIndexes ($table, $primary = FALSE, $owner=false)
{
// save old fetch mode
global $ADODB_FETCH_MODE;
$false = false;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== FALSE) {
$savem = $this->SetFetchMode(FALSE);
}
// get index details
$rs =& $this->Execute(sprintf('SHOW INDEX FROM %s',$table));
// restore fetchmode
if (isset($savem)) {
$this->SetFetchMode($savem);
}
$ADODB_FETCH_MODE = $save;
if (!is_object($rs)) {
return $false;
}
$indexes = array ();
// parse index data into array
while (!$rs->EOF)
{
if ($primary == FALSE AND $rs->fields[2] == 'PRIMARY') {
$rs->MoveNext();
continue;
}
if (!isset($indexes[$rs->fields[2]])) {
$indexes[$rs->fields[2]] = array(
'unique' => ($rs->fields[1] == 0),
'columns' => array()
);
}
$indexes[$rs->fields[2]]['columns'][$rs->fields[3] - 1] = $rs->fields[4];
$rs->MoveNext();
}
// sort columns by order in the index
foreach ( array_keys ($indexes) as $index )
{
ksort ($indexes[$index]['columns']);
}
return $indexes;
}
/**
* List columns names in a table as an array.
* @param table table name to query
*
* @return array of column names for current table.
*/
function &MetaColumnNames($table, $numIndexes=false)
{
$objarr =& $this->MetaColumns($table);
if (!is_array($objarr)) {
$false = false;
return $false;
}
$arr = array();
if ($numIndexes) {
$i = 0;
foreach($objarr as $v) $arr[$i++] = $v->name;
} else
foreach($objarr as $v) $arr[strtoupper($v->name)] = $v->name;
return $arr;
}
function MetaTransaction($mode,$db)
{
$mode = strtoupper($mode);
$mode = str_replace('ISOLATION LEVEL ','',$mode);
switch($mode) {
case 'READ UNCOMMITTED':
switch($db) {
case 'oci8':
case 'oracle':
return 'ISOLATION LEVEL READ COMMITTED';
default:
return 'ISOLATION LEVEL READ UNCOMMITTED';
}
break;
case 'READ COMMITTED':
return 'ISOLATION LEVEL READ COMMITTED';
break;
case 'REPEATABLE READ':
switch($db) {
case 'oci8':
case 'oracle':
return 'ISOLATION LEVEL SERIALIZABLE';
default:
return 'ISOLATION LEVEL REPEATABLE READ';
}
break;
case 'SERIALIZABLE':
return 'ISOLATION LEVEL SERIALIZABLE';
break;
default:
return $mode;
}
}
}
eval('class mysql_meta_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class mysql_meta_ResultSet extends mysql_meta_resultset_EXTENDER
{
/**
* Get the metatype of the column. This is used for formatting. This is because
* many databases use different names for the same type, so we transform the original
* type to our standardised version which uses 1 character codes:
*
* @param t is the type passed in. Normally is ADOFieldObject->type.
* @param len is the maximum length of that field. This is because we treat character
* fields bigger than a certain size as a 'B' (blob).
* @param fieldobj is the field object returned by the database driver. Can hold
* additional info (eg. primary_key for mysql).
*
* @return the general type of the data:
* C for character < 250 chars
* X for teXt (>= 250 chars)
* B for Binary
* N for numeric or floating point
* D for date
* T for timestamp
* L for logical/Boolean
* I for integer
* R for autoincrement counter/integer
*
*
*/
function MetaType($t,$len=-1,$fieldobj=false)
{
if (is_object($t)) {
$fieldobj = $t;
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
$len = -1; // mysql max_length is not accurate
switch (strtoupper($t)) {
case 'STRING':
case 'CHAR':
case 'VARCHAR':
case 'TINYBLOB':
case 'TINYTEXT':
case 'ENUM':
case 'SET':
if ($len <= $this->blobSize) return 'C';
case 'TEXT':
case 'LONGTEXT':
case 'MEDIUMTEXT':
return 'X';
// php_mysql extension always returns 'blob' even if 'text'
// so we have to check whether binary...
case 'IMAGE':
case 'LONGBLOB':
case 'BLOB':
case 'MEDIUMBLOB':
return !empty($fieldobj->binary) ? 'B' : 'X';
case 'YEAR':
case 'DATE': return 'D';
case 'TIME':
case 'DATETIME':
case 'TIMESTAMP': return 'T';
case 'INT':
case 'INTEGER':
case 'BIGINT':
case 'TINYINT':
case 'MEDIUMINT':
case 'SMALLINT':
if (!empty($fieldobj->primary_key)) return 'R';
else return 'I';
default:
static $typeMap = array(
'VARCHAR' => 'C',
'VARCHAR2' => 'C',
'CHAR' => 'C',
'C' => 'C',
'STRING' => 'C',
'NCHAR' => 'C',
'NVARCHAR' => 'C',
'VARYING' => 'C',
'BPCHAR' => 'C',
'CHARACTER' => 'C',
'INTERVAL' => 'C', # Postgres
'MACADDR' => 'C', # postgres
##
'LONGCHAR' => 'X',
'TEXT' => 'X',
'NTEXT' => 'X',
'M' => 'X',
'X' => 'X',
'CLOB' => 'X',
'NCLOB' => 'X',
'LVARCHAR' => 'X',
##
'BLOB' => 'B',
'IMAGE' => 'B',
'BINARY' => 'B',
'VARBINARY' => 'B',
'LONGBINARY' => 'B',
'B' => 'B',
##
'YEAR' => 'D', // mysql
'DATE' => 'D',
'D' => 'D',
##
'UNIQUEIDENTIFIER' => 'C', # MS SQL Server
##
'TIME' => 'T',
'TIMESTAMP' => 'T',
'DATETIME' => 'T',
'TIMESTAMPTZ' => 'T',
'T' => 'T',
'TIMESTAMP WITHOUT TIME ZONE' => 'T', // postgresql
##
'BOOL' => 'L',
'BOOLEAN' => 'L',
'BIT' => 'L',
'L' => 'L',
##
'COUNTER' => 'R',
'R' => 'R',
'SERIAL' => 'R', // ifx
'INT IDENTITY' => 'R',
##
'INT' => 'I',
'INT2' => 'I',
'INT4' => 'I',
'INT8' => 'I',
'INTEGER' => 'I',
'INTEGER UNSIGNED' => 'I',
'SHORT' => 'I',
'TINYINT' => 'I',
'SMALLINT' => 'I',
'I' => 'I',
##
'LONG' => 'N', // interbase is numeric, oci8 is blob
'BIGINT' => 'N', // this is bigger than PHP 32-bit integers
'DECIMAL' => 'N',
'DEC' => 'N',
'REAL' => 'N',
'DOUBLE' => 'N',
'DOUBLE PRECISION' => 'N',
'SMALLFLOAT' => 'N',
'FLOAT' => 'N',
'NUMBER' => 'N',
'NUM' => 'N',
'NUMERIC' => 'N',
'MONEY' => 'N',
## informix 9.2
'SQLINT' => 'I',
'SQLSERIAL' => 'I',
'SQLSMINT' => 'I',
'SQLSMFLOAT' => 'N',
'SQLFLOAT' => 'N',
'SQLMONEY' => 'N',
'SQLDECIMAL' => 'N',
'SQLDATE' => 'D',
'SQLVCHAR' => 'C',
'SQLCHAR' => 'C',
'SQLDTIME' => 'T',
'SQLINTERVAL' => 'N',
'SQLBYTES' => 'B',
'SQLTEXT' => 'X',
## informix 10
"SQLINT8" => 'I8',
"SQLSERIAL8" => 'I8',
"SQLNCHAR" => 'C',
"SQLNVCHAR" => 'C',
"SQLLVARCHAR" => 'X',
"SQLBOOL" => 'L'
);
$tmap = false;
$t = strtoupper($t);
$tmap = (isset($typeMap[$t])) ? $typeMap[$t] : 'N';
return $tmap;
}
}
}
?>
@@ -0,0 +1,426 @@
<?php
/*
V4.65 22 July 2005 (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. See License.txt.
Set tabs to 4 for best viewing.
Library for basic performance monitoring and tuning.
Modified 17 March 2006 for use with ADOdb Lite by Pádraic Brady
Such modifications as listed (c) 2006 Pádraic Brady (maugrimtr@hotmail.com)
Modifications:
- Moved adodb_perf class to $dbtype_perfmon_module.inc as the $dbtype_perfmon_ADOConnection class
- restricted adodb_perf class to tracking table name to use (for BC) - it's an alias for perfmon_parent_ADOConnection::table()
- Added LogSQL() method, and _logsql property
- general formatting changes and replacement of htmlspecialchars() woth htmlentities()
- parent class for specific driver modules added in adodb-perf-module.inc.php
*/
// required to allow a common parent for all perfmon dbtype specific modules to extend
$thisDBType = 'mysql';
require_once(ADODB_DIR . '/adodb-perf.inc.php');
require_once(ADODB_DIR . '/adodb-perf-module.inc.php');
// not really needed, we already know the parent class name?
eval('class mysql_perfmon_EXTENDER extends perfmon_parent_ADOConnection { }');
class mysql_perfmon_ADOConnection extends mysql_perfmon_EXTENDER
{
var $upperCase = 'upper';
var $substr = "substring";
var $tablesSQL = 'show table status';
var $createTableSQL = "CREATE TABLE adodb_logsql (
created datetime NOT NULL,
sql0 varchar(250) NOT NULL,
sql1 text NOT NULL,
params text NOT NULL,
tracer text NOT NULL,
timer decimal(16,6) NOT NULL
)";
var $settings = array(
'Ratios',
'MyISAM cache hit ratio' => array('RATIO',
'=GetKeyHitRatio',
'=WarnCacheRatio'),
'InnoDB cache hit ratio' => array('RATIO',
'=GetInnoDBHitRatio',
'=WarnCacheRatio'),
'data cache hit ratio' => array('HIDE', # only if called
'=FindDBHitRatio',
'=WarnCacheRatio'),
'sql cache hit ratio' => array('RATIO',
'=GetQHitRatio',
''),
'IO',
'data reads' => array('IO',
'=GetReads',
'Number of selects (Key_reads is not accurate)'),
'data writes' => array('IO',
'=GetWrites',
'Number of inserts/updates/deletes * coef (Key_writes is not accurate)'),
'Data Cache',
'MyISAM data cache size' => array('DATAC',
array("show variables", 'key_buffer_size'),
'' ),
'BDB data cache size' => array('DATAC',
array("show variables", 'bdb_cache_size'),
'' ),
'InnoDB data cache size' => array('DATAC',
array("show variables", 'innodb_buffer_pool_size'),
'' ),
'Memory Usage',
'read buffer size' => array('CACHE',
array("show variables", 'read_buffer_size'),
'(per session)'),
'sort buffer size' => array('CACHE',
array("show variables", 'sort_buffer_size'),
'Size of sort buffer (per session)' ),
'table cache' => array('CACHE',
array("show variables", 'table_cache'),
'Number of tables to keep open'),
'Connections',
'current connections' => array('SESS',
array('show status','Threads_connected'),
''),
'max connections' => array( 'SESS',
array("show variables",'max_connections'),
''),
false
);
/**
Get server version info...
@returns An array with 2 elements: $arr['description'] is the description string,
and $arr['version'] is the version (also a string).
*/
function ServerInfo()
{
$arr = array();
$result = $this->do_query('select version()', -1, -1, false);
if (!$result->EOF) $data = $result->fields;
else $data = array();
$arr['version'] = $arr['description'] = $data[0];
//****// Where does $arr come from in ADOdb - doesn't appear global, maybe null? A possible bug?
return $arr;
}
/*
Explain Plan for $sql.
If only a snippet of the $sql is passed in, then $partial will hold the crc32 of the
actual sql.
*/
function Explain($sql,$partial=false)
{
$perf_table = perfmon_parent_ADOConnection::table(); // this was missing in the original ADOdb perf class - bug?
if (strtoupper(substr(trim($sql),0,6)) !== 'SELECT') return '<p>Unable to EXPLAIN a non-select statement</p>';
$save = $this->LogSQL(false);
if ($partial) {
$sqlq = $this->qstr($sql.'%');
$arr = $this->GetArray("select distinct sql1 from $perf_table where sql1 like $sqlq");
if ($arr)
{
foreach($arr as $row)
{
$sql = reset($row);
if (crc32($sql) == $partial) break;
}
}
}
$sql = str_replace('?',"''",$sql);
if ($partial)
{
$sqlq = $this->qstr($sql.'%');
$sql = $this->GetOne("select sql1 from $perf_table where sql1 like $sqlq");
}
$s = '<p><strong>Explain</strong>: '.htmlentities($sql, ENT_QUOTES, 'UTF-8').'</p>';
$rs = $this->Execute('EXPLAIN '.$sql);
$s .= rs2html($rs,false,false,false,false);
$this->LogSQL($save);
$s .= $this->Tracer($sql);
return $s;
}
function Tables()
{
if (!$this->tablesSQL) return false;
$rs = $this->Execute($this->tablesSQL);
if (!$rs) return false;
$html = rs2html($rs,false,false,false,false);
return $html;
}
function CreateLogTable()
{
if (!$this->createTableSQL) return false;
$savelog = $this->LogSQL(false);
$ok = $this->Execute($this->createTableSQL);
$this->LogSQL($savelog);
return ($ok) ? true : false;
}
function GetReads()
{
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$rs = $this->Execute('show status');
$ADODB_FETCH_MODE = $save;
if (!$rs) return 0;
$val = 0;
while (!$rs->EOF)
{
switch($rs->fields[0])
{
case 'Com_select':
$val = $rs->fields[1];
$rs->Close();
return $val;
}
$rs->MoveNext();
}
$rs->Close();
return $val;
}
function GetWrites()
{
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$rs = $this->Execute('show status');
$ADODB_FETCH_MODE = $save;
if (!$rs) return 0;
$val = 0.0;
while (!$rs->EOF)
{
switch($rs->fields[0])
{
case 'Com_insert':
$val += $rs->fields[1];
break;
case 'Com_delete':
$val += $rs->fields[1];
break;
case 'Com_update':
$val += $rs->fields[1]/2;
$rs->Close();
return $val;
}
$rs->MoveNext();
}
$rs->Close();
return $val;
}
function FindDBHitRatio()
{
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$rs = $this->Execute('show table status');
$ADODB_FETCH_MODE = $save;
if (!$rs) return '';
$type = strtoupper($rs->fields[1]);
$rs->Close();
switch($type)
{
case 'MYISAM':
case 'ISAM':
return $this->DBParameter('MyISAM cache hit ratio').' (MyISAM)';
case 'INNODB':
return $this->DBParameter('InnoDB cache hit ratio').' (InnoDB)';
default:
return $type.' not supported';
}
}
function GetQHitRatio()
{
//Total number of queries = Qcache_inserts + Qcache_hits + Qcache_not_cached
$hits = $this->_DBParameter(array("show status","Qcache_hits"));
$total = $this->_DBParameter(array("show status","Qcache_inserts"));
$total += $this->_DBParameter(array("show status","Qcache_not_cached"));
$total += $hits;
if ($total) return round(($hits*100)/$total,2);
return 0;
}
/*
Use session variable to store Hit percentage, because MySQL
does not remember last value of SHOW INNODB STATUS hit ratio
# 1st query to SHOW INNODB STATUS
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 1000 / 1000
# 2nd query to SHOW INNODB STATUS
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
No buffer pool activity since the last printout
*/
function GetInnoDBHitRatio()
{
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$rs = $this->Execute('show innodb status');
;
$ADODB_FETCH_MODE = $save;
if (!$rs || $rs->EOF) return 0;
$stat = $rs->fields[0];
$rs->Close();
$at = strpos($stat,'Buffer pool hit rate');
$stat = substr($stat,$at,200);
if (preg_match('!Buffer pool hit rate\s*([0-9]*) / ([0-9]*)!',$stat,$arr))
{
$val = 100*$arr[1]/$arr[2];
$_SESSION['INNODB_HIT_PCT'] = $val;
return round($val,2);
}
else
{
if (isset($_SESSION['INNODB_HIT_PCT'])) return $_SESSION['INNODB_HIT_PCT'];
return 0;
}
return 0;
}
function GetKeyHitRatio()
{
$hits = $this->_DBParameter(array("show status","Key_read_requests"));
$reqs = $this->_DBParameter(array("show status","Key_reads"));
if ($reqs == 0) return 0;
return round(($hits/($reqs+$hits))*100,2);
}
// start hack
var $optimizeTableLow = 'CHECK TABLE %s FAST QUICK';
var $optimizeTableHigh = 'OPTIMIZE TABLE %s';
/**
* @see adodb_perf#optimizeTable
*/
function optimizeTable( $table, $mode = ADODB_OPT_LOW)
{
if ( !is_string( $table)) return false;
$sql = '';
switch( $mode)
{
case ADODB_OPT_LOW:
$sql = $this->optimizeTableLow;
break;
case ADODB_OPT_HIGH:
$sql = $this->optimizeTableHigh;
break;
default:
{
// May dont use __FUNCTION__ constant for BC (__FUNCTION__ Added in PHP 4.3.0)
trigger_error(sprintf( "<p>%s: '%s' using of undefined mode '%s'</p>", __CLASS__, __FUNCTION__, $mode), E_USER_ERROR);
return false;
}
}
$sql = sprintf( $sql, $table);
return $this->Execute( $sql) !== false;
}
}
eval('class mysql_perfmon_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class mysql_perfmon_ResultSet extends mysql_perfmon_resultset_EXTENDER
{
function MetaType($t,$len=-1,$fieldobj=false)
{
if (is_object($t)) {
$fieldobj = $t;
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
$len = -1; // mysql max_length is not accurate
switch (strtoupper($t)) {
case 'STRING':
case 'CHAR':
case 'VARCHAR':
case 'TINYBLOB':
case 'TINYTEXT':
case 'ENUM':
case 'SET':
if ($len <= $this->blobSize) return 'C';
case 'TEXT':
case 'LONGTEXT':
case 'MEDIUMTEXT':
return 'X';
// php_mysql extension always returns 'blob' even if 'text'
// so we have to check whether binary...
case 'IMAGE':
case 'LONGBLOB':
case 'BLOB':
case 'MEDIUMBLOB':
return !empty($fieldobj->binary) ? 'B' : 'X';
case 'YEAR':
case 'DATE': return 'D';
case 'TIME':
case 'DATETIME':
case 'TIMESTAMP': return 'T';
case 'INT':
case 'INTEGER':
case 'BIGINT':
case 'TINYINT':
case 'MEDIUMINT':
case 'SMALLINT':
if (!empty($fieldobj->primary_key)) return 'R';
else return 'I';
default: return 'N';
}
}
}
?>
@@ -0,0 +1,113 @@
<?php
/**
* ADOdb Lite Transaction Module for Mysql
*
*/
eval('class mysql_transaction_EXTENDER extends '. $last_module . '_ADOConnection { }');
class mysql_transaction_ADOConnection extends mysql_transaction_EXTENDER
{
var $autoCommit = true;
var $transOff = 0;
var $transCnt = 0;
var $transaction_status = true;
function StartTrans($errfn = 'ADODB_TransMonitor')
{
if ($this->transOff > 0) {
$this->transOff += 1;
return;
}
$this->transaction_status = true;
if ($this->debug && $this->transCnt > 0)
ADOConnection::outp("Bad Transaction: StartTrans called within BeginTrans");
$this->BeginTrans();
$this->transOff = 1;
}
function BeginTrans()
{
return false;
}
function CompleteTrans($autoComplete = true)
{
if ($this->transOff > 1) {
$this->transOff -= 1;
return true;
}
$this->transOff = 0;
if ($this->transaction_status && $autoComplete) {
if (!$this->CommitTrans()) {
$this->transaction_status = false;
if ($this->debug)
ADOConnection::outp("Smart Commit failed");
} else
if ($this->debug)
ADOConnection::outp("Smart Commit occurred");
} else {
$this->transaction_status = false;
$this->RollbackTrans();
if ($this->debug)
ADOCOnnection::outp("Smart Rollback occurred");
}
return $this->transaction_status;
}
function CommitTrans($ok=true)
{
return true;
}
function RollbackTrans()
{
return false;
}
function FailTrans()
{
if ($this->debug)
if ($this->transOff == 0) {
ADOConnection::outp("FailTrans outside StartTrans/CompleteTrans");
} else {
ADOConnection::outp("FailTrans was called");
}
$this->transaction_status = false;
}
function HasFailedTrans()
{
if ($this->transOff > 0)
return $this->transaction_status == false;
return false;
}
function RowLock($table,$where)
{
return false;
}
function CommitLock($table)
{
return $this->CommitTrans();
}
function RollbackLock($table)
{
return $this->RollbackTrans();
}
}
eval('class mysql_transaction_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class mysql_transaction_ResultSet extends mysql_transaction_resultset_EXTENDER
{
}
?>
@@ -0,0 +1,112 @@
<?php
/**
V4.65 22 July 2005 (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Modified 28 August, 2005 for use with ADOdb Lite by Mark Dickenson
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class ADODB2_mysqli extends ADODB_DataDict {
var $dbtype = 'mysqli';
var $alterCol = ' MODIFY COLUMN';
var $alterTableAddIndex = true;
var $dropTable = 'DROP TABLE IF EXISTS %s'; // requires mysql 3.22 or later
var $dropIndex = 'DROP INDEX %s ON %s';
var $renameColumn = 'ALTER TABLE %s CHANGE COLUMN %s %s %s'; // needs column-definition!
function ActualType($meta)
{
switch(strtoupper($meta)) {
case 'C': return 'VARCHAR';
case 'XL':return 'LONGTEXT';
case 'X': return 'TEXT';
case 'C2': return 'VARCHAR';
case 'X2': return 'LONGTEXT';
case 'B': return 'LONGBLOB';
case 'D': return 'DATE';
case 'DT': return 'DATETIME';
case 'T': return 'TIME';
case 'TS': return 'TIMESTAMP';
case 'L': return 'TINYINT';
case 'R':
case 'I4':
case 'I': return 'INTEGER';
case 'I1': return 'TINYINT';
case 'I2': return 'SMALLINT';
case 'I8': return 'BIGINT';
case 'F': return 'DOUBLE';
case 'N': return 'NUMERIC';
default:
return $meta;
}
}
// return string must begin with space
function _CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned)
{
$suffix = '';
if ($funsigned) $suffix .= ' UNSIGNED';
if ($fnotnull) $suffix .= ' NOT NULL';
if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
if ($fautoinc) $suffix .= ' AUTO_INCREMENT';
if ($fconstraint) $suffix .= ' '.$fconstraint;
return $suffix;
}
function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
{
$sql = array();
if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {
if ($this->alterTableAddIndex) $sql[] = "ALTER TABLE $tabname DROP INDEX $idxname";
else $sql[] = sprintf($this->dropIndex, $idxname, $tabname);
if ( isset($idxoptions['DROP']) )
return $sql;
}
if ( empty ($flds) ) {
return $sql;
}
if (isset($idxoptions['FULLTEXT'])) {
$unique = ' FULLTEXT';
} elseif (isset($idxoptions['UNIQUE'])) {
$unique = ' UNIQUE';
} else {
$unique = '';
}
if ( is_array($flds) ) $flds = implode(', ',$flds);
if ($this->alterTableAddIndex) $s = "ALTER TABLE $tabname ADD $unique INDEX $idxname ";
else $s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname;
$s .= ' (' . $flds . ')';
if ( isset($idxoptions[$this->upperName]) )
$s .= $idxoptions[$this->upperName];
$sql[] = $s;
return $sql;
}
}
?>
@@ -0,0 +1,321 @@
<?php
/**
* ADOdb Lite Date Module for Mysql
*
*/
if (!defined('TIMESTAMP_FIRST_YEAR')) define('TIMESTAMP_FIRST_YEAR',100);
@include(ADODB_DIR . '/adodb-time.inc.php');
eval('class mysqli_date_EXTENDER extends '. $last_module . '_ADOConnection { }');
class mysqli_date_ADOConnection extends mysqli_date_EXTENDER
{
var $fmtDate = "'Y-m-d'"; /// used by DBDate() as the default date format used by the database
var $fmtTimeStamp = "'Y-m-d H:i:s'";
var $emptyDate = '&nbsp;';
var $emptyTimeStamp = '&nbsp;';
var $sysDate = 'CURDATE()';
var $sysTimeStamp = 'NOW()';
var $isoDates = true; // accepts dates in ISO format
function Time()
{
$rs =& $this->_Execute("select $this->sysTimeStamp");
if ($rs && !$rs->EOF)
return $this->UnixTimeStamp(reset($rs->fields));
else return false;
}
function OffsetDate($dayFraction, $date=false)
{
if (!$date)
$date = $this->sysDate;
$fraction = $dayFraction * 24 * 3600;
return "from_unixtime(unix_timestamp($date)+$fraction)";
}
function SetDateLocale($locale = 'En')
{
$this->locale = $locale;
switch (strtoupper($locale))
{
case 'EN':
$this->fmtDate="'Y-m-d'";
$this->fmtTimeStamp = "'Y-m-d H:i:s'";
break;
case 'US':
$this->fmtDate = "'m-d-Y'";
$this->fmtTimeStamp = "'m-d-Y H:i:s'";
break;
case 'NL':
case 'FR':
case 'RO':
case 'IT':
$this->fmtDate="'d-m-Y'";
$this->fmtTimeStamp = "'d-m-Y H:i:s'";
break;
case 'GE':
$this->fmtDate="'d.m.Y'";
$this->fmtTimeStamp = "'d.m.Y H:i:s'";
break;
default:
$this->fmtDate="'Y-m-d'";
$this->fmtTimeStamp = "'Y-m-d H:i:s'";
break;
}
}
function DBDate($date)
{
if (empty($date) && $date !== 0)
return 'null';
if (is_string($date) && !is_numeric($date)) {
if ($date === 'null' || strncmp($date, "'", 1) === 0)
return $date;
if ($this->isoDates)
return "'$date'";
$date = $this->UnixDate($date);
}
return adodb_date($this->fmtDate, $date);
}
function DBTimeStamp($timestamp)
{
if (empty($timestamp) && $timestamp !== 0)
return 'null';
# strlen(14) allows YYYYMMDDHHMMSS format
if (!is_string($timestamp) || (is_numeric($timestamp) && strlen($timestamp)<14))
return adodb_date($this->fmtTimeStamp, $timestamp);
if ($timestamp === 'null')
return $timestamp;
if ($this->isoDates && strlen($timestamp) !== 14)
return "'$timestamp'";
return adodb_date($this->fmtTimeStamp, $this->UnixTimeStamp($timestamp));
}
function UnixDate($v)
{
if (is_object($v)) {
// odbtp support
//( [year] => 2004 [month] => 9 [day] => 4 [hour] => 12 [minute] => 44 [second] => 8 [fraction] => 0 )
return adodb_mktime($v->hour, $v->minute, $v->second, $v->month, $v->day, $v->year);
}
if (is_numeric($v) && strlen($v) !== 8)
return $v;
if (!preg_match( "|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})|", ($v), $rr))
return false;
if ($rr[1] <= TIMESTAMP_FIRST_YEAR)
return 0;
// h-m-s-MM-DD-YY
return adodb_mktime(0, 0, 0, $rr[2], $rr[3], $rr[1]);
}
function UnixTimeStamp($v)
{
if (is_object($v)) {
// odbtp support
//( [year] => 2004 [month] => 9 [day] => 4 [hour] => 12 [minute] => 44 [second] => 8 [fraction] => 0 )
return adodb_mktime($v->hour, $v->minute, $v->second, $v->month, $v->day, $v->year);
}
if (!preg_match("|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})[ ,-]*(([0-9]{1,2}):?([0-9]{1,2}):?([0-9\.]{1,4}))?|", ($v), $rr))
return false;
if ($rr[1] <= TIMESTAMP_FIRST_YEAR && $rr[2]<= 1)
return 0;
// h-m-s-MM-DD-YY
if (!isset($rr[5]))
return adodb_mktime(0, 0, 0, $rr[2], $rr[3], $rr[1]);
return adodb_mktime($rr[5], $rr[6], $rr[7], $rr[2], $rr[3], $rr[1]);
}
function UserDate($v, $fmt='Y-m-d', $gmt=false)
{
$tt = $this->UnixDate($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
else if ($tt == 0)
return $this->emptyDate;
else if ($tt == -1) { // pre-TIMESTAMP_FIRST_YEAR
}
return ($gmt) ? adodb_gmdate($fmt, $tt) : adodb_date($fmt, $tt);
}
function UserTimeStamp($v, $fmt='Y-m-d H:i:s', $gmt=false)
{
if (!isset($v))
return $this->emptyTimeStamp;
# strlen(14) allows YYYYMMDDHHMMSS format
if (is_numeric($v) && strlen($v)<14)
return ($gmt) ? adodb_gmdate($fmt, $v) : adodb_date($fmt,$v);
$tt = $this->UnixTimeStamp($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
if ($tt == 0)
return $this->emptyTimeStamp;
return ($gmt) ? adodb_gmdate($fmt, $tt) : adodb_date($fmt, $tt);
}
function SQLDate($fmt, $col=false)
{
if (!$col)
$col = $this->sysTimeStamp;
$s = 'DATE_FORMAT('.$col.",'";
$concat = false;
$len = strlen($fmt);
for ($i=0; $i < $len; $i++) {
$ch = $fmt[$i];
switch($ch) {
default:
if ($ch == '\\') {
$i++;
$ch = substr($fmt, $i, 1);
}
/** FALL THROUGH */
case '-':
case '/':
$s .= $ch;
break;
case 'Y':
case 'y':
$s .= '%Y';
break;
case 'M':
$s .= '%b';
break;
case 'm':
$s .= '%m';
break;
case 'D':
case 'd':
$s .= '%d';
break;
case 'Q':
case 'q':
$s .= "'),Quarter($col)";
if ($len > $i+1)
$s .= ",DATE_FORMAT($col,'";
else $s .= ",('";
$concat = true;
break;
case 'H':
$s .= '%H';
break;
case 'h':
$s .= '%I';
break;
case 'i':
$s .= '%i';
break;
case 's':
$s .= '%s';
break;
case 'a':
case 'A':
$s .= '%p';
break;
case 'w':
$s .= '%w';
break;
case 'l':
$s .= '%W';
break;
}
}
$s.="')";
if ($concat)
$s = "CONCAT($s)";
return $s;
}
}
eval('class mysqli_date_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class mysqli_date_ResultSet extends mysqli_date_resultset_EXTENDER
{
var $emptyTimeStamp = '&nbsp;'; /// what to display when $time==0
var $emptyDate = '&nbsp;'; /// what to display when $time==0
var $datetime = false;
function UserTimeStamp($v, $fmt='Y-m-d H:i:s')
{
if (is_numeric($v) && strlen($v)<14)
return adodb_date($fmt, $v);
$tt = $this->UnixTimeStamp($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
if ($tt === 0)
return $this->emptyTimeStamp;
else return adodb_date($fmt, $tt);
}
function UserDate($v,$fmt='Y-m-d')
{
$tt = $this->UnixDate($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
else if ($tt == 0)
return $this->emptyDate;
else if ($tt == -1) { // pre-TIMESTAMP_FIRST_YEAR
}
return adodb_date($fmt, $tt);
}
function UnixDate($v)
{
return mysqli_date_ADOConnection::UnixDate($v);
}
function UnixTimeStamp($v)
{
return mysqli_date_ADOConnection::UnixTimeStamp($v);
}
}
?>
@@ -0,0 +1,641 @@
<?php
/**
* ADOdb Lite is a PHP class to encapsulate multiple database APIs and is compatible with
* a subset of the ADODB Command Syntax.
* Currently supports Frontbase, MaxDB, miniSQL, MSSQL, MSSQL Pro, MySQLi, MySQLt, MySQL, PostgresSQL,
* PostgresSQL64, PostgresSQL7, SqLite and Sybase.
*
*/
class mysqli_driver_ADOConnection extends ADOConnection
{
var $nameQuote = '`';
var $sysDate = 'CURDATE()';
var $sysTimeStamp = 'NOW()';
function mysqli_driver_ADOConnection()
{
$this->dbtype = 'mysqli';
$this->dataProvider = 'mysql';
}
/**
* Connection to database server and selected database
*
* @access private
*/
function _connect($host = "", $username = "", $password = "", $database = "", $persistent, $forcenew)
{
if (!function_exists('mysqli_real_connect')) {
echo "ERROR: Function 'mysqli_real_connect' not found! Check if MySQL is properly set up. And that PHP has the MySQLi extension installed. If MySQLi is not installed, try setting KU_DBTYPE to 'mysql' and try again.";
return false;
}
$this->host = $host;
$this->username = $username;
$this->password = $password;
$this->database = $database;
$this->persistent = $persistent;
$this->forcenewconnection = $forcenew;
$this->connectionId = @mysqli_init();
@mysqli_real_connect( $this->connectionId, $this->host, $this->username, $this->password, $this->database, $this->port, $this->socket, $this->clientFlags );
if (mysqli_connect_errno() != 0)
{
$this->connectionId = false;
}
if ($this->connectionId === false)
{
if ($fn = $this->raiseErrorFn)
$fn($this->dbtype, 'CONNECT', $this->ErrorNo(), $this->ErrorMsg(), $this->host, $this->database, $this);
return false;
}
if (!empty($this->database))
{
if($this->SelectDB( $this->database ) == false)
{
$this->connectionId = false;
return false;
}
}
return true;
}
/**
* Choose a database to connect.
*
* @param dbname is the name of the database to select
* @return true or false
* @access public
*/
function SelectDB($dbname)
{
$this->database = $dbname;
if ($this->connectionId === false)
{
$this->connectionId = false;
return false;
}
else
{
$result = @mysqli_select_db( $this->connectionId, $this->database );
if($result === false)
{
if($this->createdatabase == true)
{
$result = @mysqli_query( $this->connectionId, "CREATE DATABASE IF NOT EXISTS " . $this->database );
if ($result === false) { // error handling if query fails
return false;
}
$result = @mysqli_select_db( $this->connectionId, $this->database );
if($result === false)
{
return false;
}
}
else
{
return false;
}
}
return true;
}
}
/**
* Return database error message
* Usage: $errormessage =& $db->ErrorMsg();
*
* @access public
*/
function ErrorMsg()
{
if ($this->connectionId === false)
{
return @mysqli_connect_error();
}
else
{
return @mysqli_error($this->connectionId);
}
}
/**
* Return database error number
* Usage: $errorbo =& $db->ErrorNo();
*
* @access public
*/
function ErrorNo()
{
if ($this->connectionId === false)
{
return @mysqli_connect_errno();
}
else
{
return @mysqli_errno($this->connectionId);
}
}
/**
* Returns # of affected rows from insert/delete/update query
*
* @access public
* @return integer Affected rows
*/
function Affected_Rows()
{
return @mysqli_affected_rows($this->connectionId);
}
/**
* Returns the last record id of an inserted item
* Usage: $db->Insert_ID();
*
* @access public
*/
function Insert_ID()
{
return @mysqli_insert_id($this->connectionId);
}
/**
* Correctly quotes a string so that all strings are escape coded.
* An example is $db->qstr("Haven't a clue.");
*
* @param string the string to quote
* @param [magic_quotes] if $s is GET/POST var, set to get_magic_quotes_gpc().
*
* @return single-quoted string IE: 'Haven\'t a clue.'
*/
function qstr($string, $magic_quotes=false)
{
if (!$magic_quotes) {
if (strnatcmp(PHP_VERSION, '4.3.0') >= 0 && function_exists('mysqli_real_escape_string')) {
return "'" . mysqli_real_escape_string($this->connectionId, $string) . "'";
}
$string = str_replace("'", "\\'" , str_replace('\\', '\\\\', str_replace("\0", "\\\0", $string)));
return "'" . $string . "'";
}
return "'" . str_replace('\\"', '"', $string) . "'";
}
function QMagic($string)
{
return $this->qstr($string, get_magic_quotes_gpc());
}
/**
* Returns concatenated string
* Usage: $db->Concat($str1,$str2);
*
* @return concatenated string
*/
function Concat()
{
$arr = func_get_args();
$list = implode(', ', $arr);
if (strlen($list) > 0) return "CONCAT($list)";
else return '';
}
function IfNull( $field, $ifNull )
{
return " IFNULL($field, $ifNull) ";
}
/**
* Closes database connection
* Usage: $db->close();
*
* @access public
*/
function Close()
{
@mysqli_close( $this->connectionId );
$this->connectionId = false;
}
/**
* Returns All Records in an array
*
* Usage: $db->GetAll($sql);
* @access public
*/
function &GetAll($sql, $inputarr = false)
{
$data =& $this->GetArray($sql, $inputarr);
return $data;
}
/**
* Returns All Records in an array
*
* Usage: $db->GetArray($sql);
* @access public
*/
function &GetArray($sql, $inputarr = false)
{
$data = false;
$result =& $this->Execute($sql, $inputarr);
if ($result)
{
$data =& $result->GetArray();
$result->Close();
}
return $data;
}
/**
* Executes SQL query and instantiates resultset methods
*
* @access private
* @return mixed Resultset methods
*/
function &do_query( $sql, $offset, $nrows, $inputarr=false )
{
global $ADODB_FETCH_MODE;
$false = false;
$limit = '';
if ($offset >= 0 || $nrows >= 0)
{
$offset = ($offset >= 0) ? $offset . "," : '';
$nrows = ($nrows >= 0) ? $nrows : '18446744073709551615';
$limit = ' LIMIT ' . $offset . ' ' . $nrows;
}
if ($inputarr && is_array($inputarr)) {
$sqlarr = explode('?', $sql);
if (!is_array(reset($inputarr))) $inputarr = array($inputarr);
foreach($inputarr as $arr) {
$sql = ''; $i = 0;
foreach($arr as $v) {
$sql .= $sqlarr[$i];
switch(gettype($v)){
case 'string':
$sql .= $this->qstr($v);
break;
case 'double':
$sql .= str_replace(',', '.', $v);
break;
case 'boolean':
$sql .= $v ? 1 : 0;
break;
default:
if ($v === null)
$sql .= 'NULL';
else $sql .= $v;
}
$i += 1;
}
$sql .= $sqlarr[$i];
if ($i+1 != sizeof($sqlarr))
return $false;
$this->sql = $sql . $limit;
$time_start = array_sum(explode(' ', microtime()));
$this->query_count++;
$resultId = @mysqli_query($this->connectionId, $this->sql );
$time_total = (array_sum(explode(' ', microtime())) - $time_start);
$this->query_time_total += $time_total;
if($this->debug_console)
{
$this->query_list[] = $this->sql;
$this->query_list_time[] = $time_total;
$this->query_list_errors[] = $this->ErrorMsg();
}
if($this->debug)
{
$this->outp($sql . $limit);
}
if ($resultId === false) { // error handling if query fails
if ($fn = $this->raiseErrorFn)
$fn($this->dbtype, 'EXECUTE', $this->ErrorNo(), $this->ErrorMsg(), $this->sql, $inputarr, $this);
return $false;
}
}
}
else
{
$this->sql = $sql . $limit;
$time_start = array_sum(explode(' ', microtime()));
$this->query_count++;
$resultId = @mysqli_query($this->connectionId, $this->sql );
$time_total = (array_sum(explode(' ', microtime())) - $time_start);
$this->query_time_total += $time_total;
if($this->debug_console)
{
$this->query_list[] = $this->sql;
$this->query_list_time[] = $time_total;
$this->query_list_errors[] = $this->ErrorMsg();
}
if($this->debug)
{
$this->outp($sql . $limit);
}
}
if ($resultId === false) { // error handling if query fails
if ($fn = $this->raiseErrorFn)
$fn($this->dbtype, 'EXECUTE', $this->ErrorNo(), $this->ErrorMsg(), $this->sql, $inputarr, $this);
return $false;
}
if ($resultId === true) { // return simplified recordset for inserts/updates/deletes with lower overhead
$recordset = new ADORecordSet_empty();
return $recordset;
}
$resultset_name = $this->last_module_name . "_ResultSet";
$recordset = new $resultset_name( $resultId, $this->connectionId );
$recordset->_currentRow = 0;
switch ($ADODB_FETCH_MODE)
{
case ADODB_FETCH_NUM: $recordset->fetchMode = MYSQLI_NUM; break;
case ADODB_FETCH_ASSOC:$recordset->fetchMode = MYSQLI_ASSOC; break;
default:
case ADODB_FETCH_DEFAULT:
case ADODB_FETCH_BOTH:$recordset->fetchMode = MYSQLI_BOTH; break;
}
$recordset->_numOfRows = @mysqli_num_rows( $resultId );
if( $recordset->_numOfRows == 0)
{
$recordset->EOF = true;
}
$recordset->_numOfFields = @mysqli_num_fields( $resultId );
$recordset->_fetch();
return $recordset;
}
}
class mysqli_driver_ResultSet
{
var $connectionId;
var $fields;
var $resultId;
var $_currentRow = 0;
var $_numOfRows = -1;
var $_numOfFields = -1;
var $fetchMode;
var $EOF;
/**
* mysqlResultSet Constructor
*
* @access private
* @param string $record
* @param string $resultId
*/
function mysqli_driver_ResultSet( $resultId, $connectionId )
{
$this->fields = array();
$this->connectionId = $connectionId;
$this->record = array();
$this->resultId = $resultId;
$this->EOF = false;
}
/**
* Frees resultset
*
* @access public
*/
function Close()
{
@mysqli_free_result( $this->resultId );
$this->fields = array();
$this->resultId = false;
}
/**
* Returns field name from select query
*
* @access public
* @param string $field
* @return string Field name
*/
function fields( $field )
{
if(empty($field))
{
return $this->fields;
}
else
{
return $this->fields[$field];
}
}
/**
* Returns numrows from select query
*
* @access public
* @return integer Numrows
*/
function RecordCount()
{
return $this->_numOfRows;
}
/**
* Returns num of fields from select query
*
* @access public
* @return integer numfields
*/
function FieldCount()
{
return $this->_numOfFields;
}
/**
* Returns next record
*
* @access public
*/
function MoveNext()
{
if (@$this->fields = mysqli_fetch_array($this->resultId,$this->fetchMode)) {
$this->_currentRow += 1;
return true;
}
if (!$this->EOF) {
$this->_currentRow += 1;
$this->EOF = true;
}
return false;
}
/**
* Move to the first row in the recordset. Many databases do NOT support this.
*
* @return true or false
*/
function MoveFirst()
{
if ($this->_currentRow == 0) return true;
return $this->Move(0);
}
/**
* Returns the Last Record
*
* @access public
*/
function MoveLast()
{
if ($this->EOF) return false;
return $this->Move($this->_numOfRows - 1);
}
/**
* Random access to a specific row in the recordset. Some databases do not support
* access to previous rows in the databases (no scrolling backwards).
*
* @param rowNumber is the row to move to (0-based)
*
* @return true if there still rows available, or false if there are no more rows (EOF).
*/
function Move($rowNumber = 0)
{
if ($rowNumber == $this->_currentRow) return true;
$this->EOF = false;
if ($this->_numOfRows > 0){
if ($rowNumber >= $this->_numOfRows - 1){
$rowNumber = $this->_numOfRows - 1;
}
}
if ($this->_seek($rowNumber)) {
$this->_currentRow = $rowNumber;
if ($this->_fetch()) {
return true;
}
$this->fields = false;
}
$this->EOF = true;
return false;
}
/**
* Perform Seek to specific row
*
* @access private
*/
function _seek($row)
{
if ($this->_numOfRows == 0) return false;
return @mysqli_data_seek($this->resultId,$row);
}
/**
* Fills field array with first database element when query initially executed
*
* @access private
*/
function _fetch()
{
$this->fields = @mysqli_fetch_array($this->resultId,$this->fetchMode);
return is_array($this->fields);
}
/**
* Check to see if last record reached
*
* @access public
*/
function EOF()
{
if( $this->_currentRow < $this->_numOfRows)
{
return false;
}
else
{
$this->EOF = true;
return true;
}
}
/**
* Returns All Records in an array
*
* @access public
* @param [nRows] is the number of rows to return. -1 means every row.
*/
function &GetArray($nRows = -1)
{
$results = array();
$cnt = 0;
while (!$this->EOF && $nRows != $cnt) {
$results[] = $this->fields;
$this->MoveNext();
$cnt++;
}
return $results;
}
function &GetRows($nRows = -1)
{
$arr =& $this->GetArray($nRows);
return $arr;
}
function &GetAll($nRows = -1)
{
$arr =& $this->GetArray($nRows);
return $arr;
}
/**
* Fetch field information for a table.
*
* @return object containing the name, type and max_length
*/
function FetchField($fieldOffset = -1)
{
// $fieldOffset not supported by mysqli
$fieldObject = @mysqli_fetch_field($this->resultId);
return $fieldObject;
}
}
?>
@@ -0,0 +1,150 @@
<?php
/**
* ADOdb Lite Extend Module for Mysqlt
*
*/
eval('class mysqli_extend_EXTENDER extends '. $last_module . '_ADOConnection { }');
class mysqli_extend_ADOConnection extends mysqli_extend_EXTENDER
{
function &GetAssoc($sql, $inputarr=false, $force_array = false, $first2cols = false)
{
$data = false;
$result =& $this->Execute($sql, $inputarr);
if ($result) {
$data =& $result->GetAssoc($force_array, $first2cols);
$result->Close();
}
return $data;
}
/**
* Generates a sequence id and stores it in $this->genID;
* GenID is only available if $this->hasGenID = true;
*
* @param seqname name of sequence to use
* @param startID if sequence does not exist, start at this ID
* @return 0 if not supported, otherwise a sequence id
*/
var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);";
var $_genSeqSQL = "create table %s (id int not null)";
var $_genSeq2SQL = "insert into %s values (%s)";
var $_dropSeqSQL = "drop table %s";
var $genID = 0;
function GenID($seqname='adodbseq', $startID=1)
{
$getnext = sprintf($this->_genIDSQL, $seqname);
$holdtransOK = $this->transaction_status;
$result = @$this->Execute($getnext);
if (!$result) {
if ($holdtransOK)
$this->transaction_status = true;
// $u = strtoupper($seqname);
$this->Execute(sprintf($this->_genSeqSQL, $seqname));
$this->Execute(sprintf($this->_genSeq2SQL, $seqname, $startID-1));
$result = $this->Execute($getnext);
}
$this->genID = mysqli_insert_id($this->connectionId);
if ($result)
$result->Close();
return $this->genID;
}
function CreateSequence($seqname='adodbseq',$startID=1)
{
$u = strtoupper($seqname);
$ok = $this->Execute(sprintf($this->_genSeqSQL, $seqname));
if (!$ok)
return false;
return $this->Execute(sprintf($this->_genSeq2SQL, $seqname, $startID-1));
}
function DropSequence($seqname='adodbseq')
{
return $this->Execute(sprintf($this->_dropSeqSQL, $seqname));
}
}
eval('class mysqli_extend_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class mysqli_extend_ResultSet extends mysqli_extend_resultset_EXTENDER
{
function &GetAssoc($force_array = false, $first2cols = false)
{
$results = false;
if ($this->_numOfFields > 1) {
$numIndex = isset($this->fields[0]);
$results = array();
if (!$first2cols && ($this->_numOfFields > 2 || $force_array)) {
if ($numIndex) {
while (!$this->EOF) {
$results[trim($this->fields[0])] = array_slice($this->fields, 1);
$this->MoveNext();
}
} else {
while (!$this->EOF) {
$results[trim(reset($this->fields))] = array_slice($this->fields, 1);
$this->MoveNext();
}
}
} else {
if ($numIndex) {
while (!$this->EOF) {
$results[trim(($this->fields[0]))] = $this->fields[1];
$this->MoveNext();
}
} else {
while (!$this->EOF) {
$v1 = trim(reset($this->fields));
$v2 = ''.next($this->fields);
$results[$v1] = $v2;
$this->MoveNext();
}
}
}
}
return $results;
}
function PO_RecordCount($table="", $condition="")
{
$lnumrows = $this->_numOfRows;
if($lnumrows == -1 && $this->connectionId)
{
if($table)
{
if ($condition)
$condition = " WHERE " . $condition;
$resultrows = &$this->connectionId->Execute("SELECT COUNT(*) FROM $table $condition");
if ($resultrows)
$lnumrows = reset($resultrows->fields);
}
}
return $lnumrows;
}
function CurrentRow()
{
return $this->_currentRow;
}
function AbsolutePosition()
{
return $this->_currentRow;
}
function NextRecordSet()
{
return false;
}
}
?>
@@ -0,0 +1,624 @@
<?php
/**
* ADOdb Lite Meta Module for Mysql
*
* Portions of the Meta Coding came from ADOdb
*/
/*
(c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. See License.txt.
*/
eval('class mysqli_meta_EXTENDER extends '. $last_module . '_ADOConnection { }');
class mysqli_meta_ADOConnection extends mysqli_meta_EXTENDER
{
var $metaTablesSQL = "SHOW TABLES";
var $metaColumnsSQL = "SHOW COLUMNS FROM %s";
function MetaError($err=false)
{
include_once(ADODB_DIR . "/adodb-error.inc.php");
if ($err === false)
$err = $this->ErrorNo();
return adodb_error($this->dataProvider,$this->databaseType,$err);
}
function MetaErrorMsg($errno)
{
include_once(ADODB_DIR . "/adodb-error.inc.php");
return adodb_errormsg($errno);
}
/**
* @returns an array with the primary key columns in it.
*/
function MetaPrimaryKeys($table, $owner=false)
{
// owner not used in base class - see oci8
$p = array();
$objs =& $this->MetaColumns($table);
if ($objs) {
foreach($objs as $v) {
if (!empty($v->primary_key))
$p[] = $v->name;
}
}
if (sizeof($p))
return $p;
if (function_exists('ADODB_VIEW_PRIMARYKEYS'))
return ADODB_VIEW_PRIMARYKEYS($this->databaseType, $this->database, $table, $owner);
return false;
}
/**
* @returns assoc array where keys are tables, and values are foreign keys
*/
function MetaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE )
{
if ( !empty($owner) ) {
$table = "$owner.$table";
}
$a_create_table = $this->getRow(sprintf('SHOW CREATE TABLE %s', $table));
if ($associative) $create_sql = $a_create_table["Create Table"];
else $create_sql = $a_create_table[1];
$matches = array();
if (!preg_match_all("/FOREIGN KEY \(`(.*?)`\) REFERENCES `(.*?)` \(`(.*?)`\)/", $create_sql, $matches)) return false;
$foreign_keys = array();
$num_keys = count($matches[0]);
for ( $i = 0; $i < $num_keys; $i ++ ) {
$my_field = explode('`, `', $matches[1][$i]);
$ref_table = $matches[2][$i];
$ref_field = explode('`, `', $matches[3][$i]);
if ( $upper ) {
$ref_table = strtoupper($ref_table);
}
$foreign_keys[$ref_table] = array();
$num_fields = count($my_field);
for ( $j = 0; $j < $num_fields; $j ++ ) {
if ( $associative ) {
$foreign_keys[$ref_table][$ref_field[$j]] = $my_field[$j];
} else {
$foreign_keys[$ref_table][] = "{$my_field[$j]}={$ref_field[$j]}";
}
}
}
return $foreign_keys;
}
// not the fastest implementation - quick and dirty - jlim
// for best performance, use the actual $rs->MetaType().
function MetaType($t,$len=-1,$fieldobj=false)
{
if (empty($this->_metars)) {
$rsclass = $this->last_module_name . "_ResultSet";
$this->_metars =& new $rsclass(false, $this->fetchMode);
}
return $this->_metars->MetaType($t,$len,$fieldobj);
}
/**
* return the databases that the driver can connect to.
* Some databases will return an empty array.
*
* @return an array of database names.
*/
function &MetaDatabases()
{
$qid = mysql_list_dbs($this->connectionId);
$arr = array();
$i = 0;
$max = mysql_num_rows($qid);
while ($i < $max) {
$db = mysql_tablename($qid,$i);
if ($db != 'mysql') $arr[] = $db;
$i += 1;
}
return $arr;
}
/**
* @param ttype can either be 'VIEW' or 'TABLE' or false.
* If false, both views and tables are returned.
* "VIEW" returns only views
* "TABLE" returns only tables
* @param showSchema returns the schema/user with the table name, eg. USER.TABLE
* @param mask is the input mask - only supported by oci8 and postgresql
*
* @return array of tables for current database.
*/
function &MetaTables($ttype=false,$showSchema=false,$mask=false)
{
$save = $this->metaTablesSQL;
if ($showSchema && is_string($showSchema)) {
$this->metaTablesSQL .= " from $showSchema";
}
if ($mask) {
$mask = $this->qstr($mask);
$this->metaTablesSQL .= " like $mask";
}
$ret =& $this->_MetaTables($ttype,$showSchema);
$this->metaTablesSQL = $save;
return $ret;
}
function &_MetaTables($ttype=false,$showSchema=false,$mask=false)
{
global $ADODB_FETCH_MODE;
$false = false;
if ($mask) {
return $false;
}
if ($this->metaTablesSQL) {
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
$rs = $this->Execute($this->metaTablesSQL);
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
if ($rs === false) return $false;
$arr =& $rs->GetArray();
$arr2 = array();
if ($hast = ($ttype && isset($arr[0][1]))) {
$showt = strncmp($ttype,'T',1);
}
for ($i=0; $i < sizeof($arr); $i++) {
if ($hast) {
if ($showt == 0) {
if (strncmp($arr[$i][1],'T',1) == 0) $arr2[] = trim($arr[$i][0]);
} else {
if (strncmp($arr[$i][1],'V',1) == 0) $arr2[] = trim($arr[$i][0]);
}
} else
$arr2[] = trim($arr[$i][0]);
}
$rs->Close();
return $arr2;
}
return $false;
}
function _findschema(&$table,&$schema)
{
if (!$schema && ($at = strpos($table,'.')) !== false) {
$schema = substr($table,0,$at);
$table = substr($table,$at+1);
}
}
/**
* List columns in a database as an array of ADOFieldObjects.
* See top of file for definition of object.
*
* @param $table table name to query
* @param $normalize makes table name case-insensitive (required by some databases)
* @schema is optional database schema to use - not supported by all databases.
*
* @return array of ADOFieldObjects for current table.
*/
function MetaColumns($table)
{
$this->_findschema($table,$schema);
if ($schema) {
$dbName = $this->database;
$this->connection->SelectDB($schema);
}
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
$rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
if ($schema) {
$this->SelectDB($dbName);
}
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
if (!is_object($rs)) {
$false = false;
return $false;
}
$retarr = array();
while (!$rs->EOF){
$fld = new ADOFieldObject();
$fld->name = $rs->fields[0];
$type = $rs->fields[1];
// split type into type(length):
$fld->scale = null;
if (preg_match("/^(.+)\((\d+),(\d+)/", $type, $query_array)) {
$fld->type = $query_array[1];
$fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
$fld->scale = is_numeric($query_array[3]) ? $query_array[3] : -1;
} elseif (preg_match("/^(.+)\((\d+)/", $type, $query_array)) {
$fld->type = $query_array[1];
$fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
} elseif (preg_match("/^(enum)\((.*)\)$/i", $type, $query_array)) {
$fld->type = $query_array[1];
$arr = explode(",",$query_array[2]);
$fld->enums = $arr;
$zlen = max(array_map("strlen",$arr)) - 2; // PHP >= 4.0.6
$fld->max_length = ($zlen > 0) ? $zlen : 1;
} else {
$fld->type = $type;
$fld->max_length = -1;
}
$fld->not_null = ($rs->fields[2] != 'YES');
$fld->primary_key = ($rs->fields[3] == 'PRI');
$fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false);
$fld->binary = (strpos($type,'blob') !== false);
$fld->unsigned = (strpos($type,'unsigned') !== false);
if (!$fld->binary) {
$d = $rs->fields[4];
if ($d != '' && $d != 'NULL') {
$fld->has_default = true;
$fld->default_value = $d;
} else {
$fld->has_default = false;
}
}
if ($save == ADODB_FETCH_NUM) {
$retarr[] = $fld;
} else {
$retarr[strtoupper($fld->name)] = $fld;
}
$rs->MoveNext();
}
$rs->Close();
return $retarr;
}
/**
* List indexes on a table as an array.
* @param table table name to query
* @param primary true to only show primary keys. Not actually used for most databases
*
* @return array of indexes on current table. Each element represents an index, and is itself an associative array.
Array (
[name_of_index] => Array
(
[unique] => true or false
[columns] => Array
(
[0] => firstname
[1] => lastname
)
)
*/
function MetaIndexes ($table, $primary = FALSE, $owner=false)
{
// save old fetch mode
global $ADODB_FETCH_MODE;
$false = false;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== FALSE) {
$savem = $this->SetFetchMode(FALSE);
}
// get index details
$rs =& $this->Execute(sprintf('SHOW INDEX FROM %s',$table));
// restore fetchmode
if (isset($savem)) {
$this->SetFetchMode($savem);
}
$ADODB_FETCH_MODE = $save;
if (!is_object($rs)) {
return $false;
}
$indexes = array ();
// parse index data into array
while (!$rs->EOF)
{
if ($primary == FALSE AND $rs->fields[2] == 'PRIMARY') {
$rs->MoveNext();
continue;
}
if (!isset($indexes[$rs->fields[2]])) {
$indexes[$rs->fields[2]] = array(
'unique' => ($rs->fields[1] == 0),
'columns' => array()
);
}
$indexes[$rs->fields[2]]['columns'][$rs->fields[3] - 1] = $rs->fields[4];
$rs->MoveNext();
}
// sort columns by order in the index
foreach ( array_keys ($indexes) as $index )
{
ksort ($indexes[$index]['columns']);
}
return $indexes;
}
/**
* List columns names in a table as an array.
* @param table table name to query
*
* @return array of column names for current table.
*/
function &MetaColumnNames($table, $numIndexes=false)
{
$objarr =& $this->MetaColumns($table);
if (!is_array($objarr)) {
$false = false;
return $false;
}
$arr = array();
if ($numIndexes) {
$i = 0;
foreach($objarr as $v) $arr[$i++] = $v->name;
} else
foreach($objarr as $v) $arr[strtoupper($v->name)] = $v->name;
return $arr;
}
function MetaTransaction($mode,$db)
{
$mode = strtoupper($mode);
$mode = str_replace('ISOLATION LEVEL ','',$mode);
switch($mode) {
case 'READ UNCOMMITTED':
switch($db) {
case 'oci8':
case 'oracle':
return 'ISOLATION LEVEL READ COMMITTED';
default:
return 'ISOLATION LEVEL READ UNCOMMITTED';
}
break;
case 'READ COMMITTED':
return 'ISOLATION LEVEL READ COMMITTED';
break;
case 'REPEATABLE READ':
switch($db) {
case 'oci8':
case 'oracle':
return 'ISOLATION LEVEL SERIALIZABLE';
default:
return 'ISOLATION LEVEL REPEATABLE READ';
}
break;
case 'SERIALIZABLE':
return 'ISOLATION LEVEL SERIALIZABLE';
break;
default:
return $mode;
}
}
}
eval('class mysqli_meta_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class mysqli_meta_ResultSet extends mysqli_meta_resultset_EXTENDER
{
/**
* Get the metatype of the column. This is used for formatting. This is because
* many databases use different names for the same type, so we transform the original
* type to our standardised version which uses 1 character codes:
*
* @param t is the type passed in. Normally is ADOFieldObject->type.
* @param len is the maximum length of that field. This is because we treat character
* fields bigger than a certain size as a 'B' (blob).
* @param fieldobj is the field object returned by the database driver. Can hold
* additional info (eg. primary_key for mysql).
*
* @return the general type of the data:
* C for character < 250 chars
* X for teXt (>= 250 chars)
* B for Binary
* N for numeric or floating point
* D for date
* T for timestamp
* L for logical/Boolean
* I for integer
* R for autoincrement counter/integer
*
*
*/
function MetaType($t,$len=-1,$fieldobj=false)
{
if (is_object($t)) {
$fieldobj = $t;
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
$len = -1; // mysql max_length is not accurate
switch (strtoupper($t)) {
case 'STRING':
case 'CHAR':
case 'VARCHAR':
case 'TINYBLOB':
case 'TINYTEXT':
case 'ENUM':
case 'SET':
if ($len <= $this->blobSize) return 'C';
case 'TEXT':
case 'LONGTEXT':
case 'MEDIUMTEXT':
return 'X';
// php_mysql extension always returns 'blob' even if 'text'
// so we have to check whether binary...
case 'IMAGE':
case 'LONGBLOB':
case 'BLOB':
case 'MEDIUMBLOB':
return !empty($fieldobj->binary) ? 'B' : 'X';
case 'YEAR':
case 'DATE': return 'D';
case 'TIME':
case 'DATETIME':
case 'TIMESTAMP': return 'T';
case 'INT':
case 'INTEGER':
case 'BIGINT':
case 'TINYINT':
case 'MEDIUMINT':
case 'SMALLINT':
if (!empty($fieldobj->primary_key)) return 'R';
else return 'I';
default:
static $typeMap = array(
'VARCHAR' => 'C',
'VARCHAR2' => 'C',
'CHAR' => 'C',
'C' => 'C',
'STRING' => 'C',
'NCHAR' => 'C',
'NVARCHAR' => 'C',
'VARYING' => 'C',
'BPCHAR' => 'C',
'CHARACTER' => 'C',
'INTERVAL' => 'C', # Postgres
'MACADDR' => 'C', # postgres
##
'LONGCHAR' => 'X',
'TEXT' => 'X',
'NTEXT' => 'X',
'M' => 'X',
'X' => 'X',
'CLOB' => 'X',
'NCLOB' => 'X',
'LVARCHAR' => 'X',
##
'BLOB' => 'B',
'IMAGE' => 'B',
'BINARY' => 'B',
'VARBINARY' => 'B',
'LONGBINARY' => 'B',
'B' => 'B',
##
'YEAR' => 'D', // mysql
'DATE' => 'D',
'D' => 'D',
##
'UNIQUEIDENTIFIER' => 'C', # MS SQL Server
##
'TIME' => 'T',
'TIMESTAMP' => 'T',
'DATETIME' => 'T',
'TIMESTAMPTZ' => 'T',
'T' => 'T',
'TIMESTAMP WITHOUT TIME ZONE' => 'T', // postgresql
##
'BOOL' => 'L',
'BOOLEAN' => 'L',
'BIT' => 'L',
'L' => 'L',
##
'COUNTER' => 'R',
'R' => 'R',
'SERIAL' => 'R', // ifx
'INT IDENTITY' => 'R',
##
'INT' => 'I',
'INT2' => 'I',
'INT4' => 'I',
'INT8' => 'I',
'INTEGER' => 'I',
'INTEGER UNSIGNED' => 'I',
'SHORT' => 'I',
'TINYINT' => 'I',
'SMALLINT' => 'I',
'I' => 'I',
##
'LONG' => 'N', // interbase is numeric, oci8 is blob
'BIGINT' => 'N', // this is bigger than PHP 32-bit integers
'DECIMAL' => 'N',
'DEC' => 'N',
'REAL' => 'N',
'DOUBLE' => 'N',
'DOUBLE PRECISION' => 'N',
'SMALLFLOAT' => 'N',
'FLOAT' => 'N',
'NUMBER' => 'N',
'NUM' => 'N',
'NUMERIC' => 'N',
'MONEY' => 'N',
## informix 9.2
'SQLINT' => 'I',
'SQLSERIAL' => 'I',
'SQLSMINT' => 'I',
'SQLSMFLOAT' => 'N',
'SQLFLOAT' => 'N',
'SQLMONEY' => 'N',
'SQLDECIMAL' => 'N',
'SQLDATE' => 'D',
'SQLVCHAR' => 'C',
'SQLCHAR' => 'C',
'SQLDTIME' => 'T',
'SQLINTERVAL' => 'N',
'SQLBYTES' => 'B',
'SQLTEXT' => 'X',
## informix 10
"SQLINT8" => 'I8',
"SQLSERIAL8" => 'I8',
"SQLNCHAR" => 'C',
"SQLNVCHAR" => 'C',
"SQLLVARCHAR" => 'X',
"SQLBOOL" => 'L'
);
$tmap = false;
$t = strtoupper($t);
$tmap = (isset($typeMap[$t])) ? $typeMap[$t] : 'N';
if ($t == 'LONG' && $this->dataProvider == 'oci8') return 'B';
return $tmap;
}
}
}
?>
@@ -0,0 +1,468 @@
<?php
/*
V4.65 22 July 2005 (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. See License.txt.
Set tabs to 4 for best viewing.
Library for basic performance monitoring and tuning.
Modified 17 March 2006 for use with ADOdb Lite by Pádraic Brady
Such modifications as listed (c) 2006 Pádraic Brady (maugrimtr@hotmail.com)
Modifications:
- Moved adodb_perf class to $dbtype_perfmon_module.inc as the $dbtype_perfmon_ADOConnection class
- restricted adodb_perf class to tracking table name to use (for BC) - it's an alias for perfmon_parent_ADOConnection::table()
- Added LogSQL() method, and _logsql property
- general formatting changes and replacement of htmlspecialchars() woth htmlentities()
- parent class for specific driver modules added in adodb-perf-module.inc.php
*/
// required to allow a common parent for all perfmon dbtype specific modules to extend
$thisDBType = 'mysqli';
require_once(ADODB_DIR . '/adodb-perf.inc.php');
require_once(ADODB_DIR . '/adodb-perf-module.inc.php');
// not really needed, we already know the parent class name?
eval('class mysqli_perfmon_EXTENDER extends perfmon_parent_ADOConnection { }');
class mysqli_perfmon_ADOConnection extends mysqli_perfmon_EXTENDER
{
var $upperCase = 'upper';
var $substr = "substring";
var $tablesSQL = 'show table status';
var $createTableSQL = "CREATE TABLE adodb_logsql (
created datetime NOT NULL,
sql0 varchar(250) NOT NULL,
sql1 text NOT NULL,
params text NOT NULL,
tracer text NOT NULL,
timer decimal(16,6) NOT NULL
)";
var $settings = array(
'Ratios',
'MyISAM cache hit ratio' => array('RATIO',
'=GetKeyHitRatio',
'=WarnCacheRatio'),
'InnoDB cache hit ratio' => array('RATIO',
'=GetInnoDBHitRatio',
'=WarnCacheRatio'),
'data cache hit ratio' => array('HIDE', # only if called
'=FindDBHitRatio',
'=WarnCacheRatio'),
'sql cache hit ratio' => array('RATIO',
'=GetQHitRatio',
''),
'IO',
'data reads' => array('IO',
'=GetReads',
'Number of selects (Key_reads is not accurate)'),
'data writes' => array('IO',
'=GetWrites',
'Number of inserts/updates/deletes * coef (Key_writes is not accurate)'),
'Data Cache',
'MyISAM data cache size' => array('DATAC',
array("show variables", 'key_buffer_size'),
'' ),
'BDB data cache size' => array('DATAC',
array("show variables", 'bdb_cache_size'),
'' ),
'InnoDB data cache size' => array('DATAC',
array("show variables", 'innodb_buffer_pool_size'),
'' ),
'Memory Usage',
'read buffer size' => array('CACHE',
array("show variables", 'read_buffer_size'),
'(per session)'),
'sort buffer size' => array('CACHE',
array("show variables", 'sort_buffer_size'),
'Size of sort buffer (per session)' ),
'table cache' => array('CACHE',
array("show variables", 'table_cache'),
'Number of tables to keep open'),
'Connections',
'current connections' => array('SESS',
array('show status','Threads_connected'),
''),
'max connections' => array( 'SESS',
array("show variables",'max_connections'),
''),
false
);
/**
Get server version info...
@returns An array with 2 elements: $arr['description'] is the description string,
and $arr['version'] is the version (also a string).
*/
function ServerInfo()
{
$arr = array();
$result = $this->do_query('select version()', -1, -1, false);
if (!$result->EOF) $data = $result->fields;
else $data = array();
$arr['version'] = $arr['description'] = $data[0];
//****// Where does $arr come from in ADOdb - doesn't appear global, maybe null? A possible bug?
return $arr;
}
/*
Explain Plan for $sql.
If only a snippet of the $sql is passed in, then $partial will hold the crc32 of the
actual sql.
*/
function Explain($sql,$partial=false)
{
$perf_table = perfmon_parent_ADOConnection::table(); // this was missing in the original ADOdb perf class - bug?
if (strtoupper(substr(trim($sql),0,6)) !== 'SELECT') return '<p>Unable to EXPLAIN a non-select statement</p>';
$save = $this->LogSQL(false);
if ($partial) {
$sqlq = $this->qstr($sql.'%');
$arr = $this->GetArray("select distinct sql1 from $perf_table where sql1 like $sqlq");
if ($arr)
{
foreach($arr as $row)
{
$sql = reset($row);
if (crc32($sql) == $partial) break;
}
}
}
$sql = str_replace('?',"''",$sql);
if ($partial)
{
$sqlq = $this->qstr($sql.'%');
$sql = $this->GetOne("select sql1 from $perf_table where sql1 like $sqlq");
}
$s = '<p><strong>Explain</strong>: '.htmlentities($sql, ENT_QUOTES, 'UTF-8').'</p>';
$rs = $this->Execute('EXPLAIN '.$sql);
$s .= rs2html($rs,false,false,false,false);
$this->LogSQL($save);
$s .= $this->Tracer($sql);
return $s;
}
function Tables()
{
if (!$this->tablesSQL) return false;
$rs = $this->Execute($this->tablesSQL);
if (!$rs) return false;
$html = rs2html($rs,false,false,false,false);
return $html;
}
function CreateLogTable()
{
if (!$this->createTableSQL) return false;
$savelog = $this->LogSQL(false);
$ok = $this->Execute($this->createTableSQL);
$this->LogSQL($savelog);
return ($ok) ? true : false;
}
function GetReads()
{
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$rs = $this->Execute('show status');
$ADODB_FETCH_MODE = $save;
if (!$rs) return 0;
$val = 0;
while (!$rs->EOF)
{
switch($rs->fields[0])
{
case 'Com_select':
$val = $rs->fields[1];
$rs->Close();
return $val;
}
$rs->MoveNext();
}
$rs->Close();
return $val;
}
function GetWrites()
{
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$rs = $this->Execute('show status');
$ADODB_FETCH_MODE = $save;
if (!$rs) return 0;
$val = 0.0;
while (!$rs->EOF)
{
switch($rs->fields[0])
{
case 'Com_insert':
$val += $rs->fields[1];
break;
case 'Com_delete':
$val += $rs->fields[1];
break;
case 'Com_update':
$val += $rs->fields[1]/2;
$rs->Close();
return $val;
}
$rs->MoveNext();
}
$rs->Close();
return $val;
}
function FindDBHitRatio()
{
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$rs = $this->Execute('show table status');
$ADODB_FETCH_MODE = $save;
if (!$rs) return '';
$type = strtoupper($rs->fields[1]);
$rs->Close();
switch($type)
{
case 'MYISAM':
case 'ISAM':
return $this->DBParameter('MyISAM cache hit ratio').' (MyISAM)';
case 'INNODB':
return $this->DBParameter('InnoDB cache hit ratio').' (InnoDB)';
default:
return $type.' not supported';
}
}
function GetQHitRatio()
{
//Total number of queries = Qcache_inserts + Qcache_hits + Qcache_not_cached
$hits = $this->_DBParameter(array("show status","Qcache_hits"));
$total = $this->_DBParameter(array("show status","Qcache_inserts"));
$total += $this->_DBParameter(array("show status","Qcache_not_cached"));
$total += $hits;
if ($total) return round(($hits*100)/$total,2);
return 0;
}
/*
Use session variable to store Hit percentage, because MySQL
does not remember last value of SHOW INNODB STATUS hit ratio
# 1st query to SHOW INNODB STATUS
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 1000 / 1000
# 2nd query to SHOW INNODB STATUS
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
No buffer pool activity since the last printout
*/
function GetInnoDBHitRatio()
{
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$rs = $this->Execute('show innodb status');
;
$ADODB_FETCH_MODE = $save;
if (!$rs || $rs->EOF) return 0;
$stat = $rs->fields[0];
$rs->Close();
$at = strpos($stat,'Buffer pool hit rate');
$stat = substr($stat,$at,200);
if (preg_match('!Buffer pool hit rate\s*([0-9]*) / ([0-9]*)!',$stat,$arr))
{
$val = 100*$arr[1]/$arr[2];
$_SESSION['INNODB_HIT_PCT'] = $val;
return round($val,2);
}
else
{
if (isset($_SESSION['INNODB_HIT_PCT'])) return $_SESSION['INNODB_HIT_PCT'];
return 0;
}
return 0;
}
function GetKeyHitRatio()
{
$hits = $this->_DBParameter(array("show status","Key_read_requests"));
$reqs = $this->_DBParameter(array("show status","Key_reads"));
if ($reqs == 0) return 0;
return round(($hits/($reqs+$hits))*100,2);
}
// start hack
var $optimizeTableLow = 'CHECK TABLE %s FAST QUICK';
var $optimizeTableHigh = 'OPTIMIZE TABLE %s';
/**
* @see adodb_perf#optimizeTable
*/
function optimizeTable( $table, $mode = ADODB_OPT_LOW)
{
if ( !is_string( $table)) return false;
$sql = '';
switch( $mode)
{
case ADODB_OPT_LOW:
$sql = $this->optimizeTableLow;
break;
case ADODB_OPT_HIGH:
$sql = $this->optimizeTableHigh;
break;
default:
{
// May dont use __FUNCTION__ constant for BC (__FUNCTION__ Added in PHP 4.3.0)
trigger_error(sprintf( "<p>%s: '%s' using of undefined mode '%s'</p>", __CLASS__, __FUNCTION__, $mode), E_USER_ERROR);
return false;
}
}
$sql = sprintf( $sql, $table);
return $this->Execute( $sql) !== false;
}
}
eval('class mysqli_perfmon_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class mysqli_perfmon_ResultSet extends mysqli_perfmon_resultset_EXTENDER
{
function MetaType($t, $len = -1, $fieldobj = false)
{
if (is_object($t)) {
$fieldobj = $t;
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
$len = -1; // mysql max_length is not accurate
switch (strtoupper($t)) {
case 'STRING':
case 'CHAR':
case 'VARCHAR':
case 'TINYBLOB':
case 'TINYTEXT':
case 'ENUM':
case 'SET':
case MYSQLI_TYPE_TINY_BLOB :
case MYSQLI_TYPE_CHAR :
case MYSQLI_TYPE_STRING :
case MYSQLI_TYPE_ENUM :
case MYSQLI_TYPE_SET :
case 253 :
if ($len <= $this->blobSize) return 'C';
case 'TEXT':
case 'LONGTEXT':
case 'MEDIUMTEXT':
return 'X';
// php_mysql extension always returns 'blob' even if 'text'
// so we have to check whether binary...
case 'IMAGE':
case 'LONGBLOB':
case 'BLOB':
case 'MEDIUMBLOB':
case MYSQLI_TYPE_BLOB :
case MYSQLI_TYPE_LONG_BLOB :
case MYSQLI_TYPE_MEDIUM_BLOB :
return !empty($fieldobj->binary) ? 'B' : 'X';
case 'YEAR':
case 'DATE':
case MYSQLI_TYPE_DATE :
case MYSQLI_TYPE_YEAR :
return 'D';
case 'TIME':
case 'DATETIME':
case 'TIMESTAMP':
case MYSQLI_TYPE_DATETIME :
case MYSQLI_TYPE_NEWDATE :
case MYSQLI_TYPE_TIME :
case MYSQLI_TYPE_TIMESTAMP :
return 'T';
case 'INT':
case 'INTEGER':
case 'BIGINT':
case 'TINYINT':
case 'MEDIUMINT':
case 'SMALLINT':
case MYSQLI_TYPE_INT24 :
case MYSQLI_TYPE_LONG :
case MYSQLI_TYPE_LONGLONG :
case MYSQLI_TYPE_SHORT :
case MYSQLI_TYPE_TINY :
if (!empty($fieldobj->primary_key)) return 'R';
return 'I';
// Added floating-point types
// Maybe not necessery.
case 'FLOAT':
case 'DOUBLE':
// case 'DOUBLE PRECISION':
case 'DECIMAL':
case 'DEC':
case 'FIXED':
default:
//if (!is_numeric($t)) echo "<p>--- Error in type matching $t -----</p>";
return 'N';
}
} // function
}
?>
@@ -0,0 +1,138 @@
<?php
/**
* ADOdb Lite Transaction Module for Mysqli
*
*/
eval('class mysqli_transaction_EXTENDER extends '. $last_module . '_ADOConnection { }');
class mysqli_transaction_ADOConnection extends mysqli_transaction_EXTENDER
{
var $autoCommit = true;
var $transOff = 0;
var $transCnt = 0;
var $transaction_status = true;
function StartTrans($errfn = 'ADODB_TransMonitor')
{
if ($this->transOff > 0) {
$this->transOff += 1;
return;
}
$this->transaction_status = true;
if ($this->debug && $this->transCnt > 0)
ADOConnection::outp("Bad Transaction: StartTrans called within BeginTrans");
$this->BeginTrans();
$this->transOff = 1;
}
function BeginTrans()
{
if ($this->transOff)
return true;
$this->transCnt += 1;
$this->Execute('SET AUTOCOMMIT=0');
$this->Execute('BEGIN');
return true;
}
function CompleteTrans($autoComplete = true)
{
if ($this->transOff > 1) {
$this->transOff -= 1;
return true;
}
$this->transOff = 0;
if ($this->transaction_status && $autoComplete) {
if (!$this->CommitTrans()) {
$this->transaction_status = false;
if ($this->debug)
ADOConnection::outp("Smart Commit failed");
} else
if ($this->debug)
ADOConnection::outp("Smart Commit occurred");
} else {
$this->RollbackTrans();
if ($this->debug)
ADOCOnnection::outp("Smart Rollback occurred");
}
return $this->transaction_status;
}
function CommitTrans($ok=true)
{
if ($this->transOff)
return true;
if (!$ok) return
$this->RollbackTrans();
if ($this->transCnt)
$this->transCnt -= 1;
$this->Execute('COMMIT');
$this->Execute('SET AUTOCOMMIT=1');
return true;
}
function RollbackTrans()
{
if ($this->transOff)
return true;
if ($this->transCnt)
$this->transCnt -= 1;
$this->Execute('ROLLBACK');
$this->Execute('SET AUTOCOMMIT=1');
return true;
}
function FailTrans()
{
if ($this->debug)
if ($this->transOff == 0) {
ADOConnection::outp("FailTrans outside StartTrans/CompleteTrans");
} else {
ADOConnection::outp("FailTrans was called");
}
$this->transaction_status = false;
}
function HasFailedTrans()
{
if ($this->transOff > 0)
return $this->transaction_status == false;
return false;
}
function RowLock($tables,$where,$flds='1 as ignore')
{
if ($this->transCnt==0)
$this->BeginTrans();
return $this->GetOne("select $flds from $tables where $where for update");
}
function CommitLock($table)
{
return $this->CommitTrans();
}
function RollbackLock($table)
{
return $this->RollbackTrans();
}
}
eval('class mysqli_transaction_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class mysqli_transaction_ResultSet extends mysqli_transaction_resultset_EXTENDER
{
}
?>
@@ -0,0 +1,211 @@
<?php
/**
V4.65 22 July 2005 (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Modified 28 August, 2005 for use with ADOdb Lite by Mark Dickenson
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class ADODB2_postgres64 extends ADODB_DataDict {
var $dbtype = 'postgres';
var $seqField = false;
var $seqPrefix = 'SEQ_';
var $addCol = ' ADD COLUMN';
var $quote = '"';
var $renameTable = 'ALTER TABLE %s RENAME TO %s'; // at least since 7.1
function ActualType($meta)
{
switch($meta) {
case 'C': return 'VARCHAR';
case 'XL':
case 'X': return 'TEXT';
case 'C2': return 'VARCHAR';
case 'X2': return 'TEXT';
case 'B': return 'BYTEA';
case 'D': return 'DATE';
case 'T': return 'TIMESTAMP';
case 'L': return 'BOOLEAN';
case 'I': return 'INTEGER';
case 'I1': return 'SMALLINT';
case 'I2': return 'INT2';
case 'I4': return 'INT4';
case 'I8': return 'INT8';
case 'F': return 'FLOAT8';
case 'N': return 'NUMERIC';
default:
return $meta;
}
}
function AddColumnSQL($tabname, $flds)
{
$tabname = $this->TableName ($tabname);
$sql = array();
list($lines,$pkey) = $this->_GenFields($flds);
$alter = 'ALTER TABLE ' . $tabname . $this->addCol . ' ';
foreach($lines as $v) {
if (($not_null = preg_match('/NOT NULL/i',$v))) {
$v = preg_replace('/NOT NULL/i','',$v);
}
if (preg_match('/^([^ ]+) .*(DEFAULT [^ ]+)/',$v,$matches)) {
list(,$colname,$default) = $matches;
$sql[] = $alter . str_replace($default,'',$v);
$sql[] = 'ALTER TABLE '.$tabname.' ALTER COLUMN '.$colname.' SET ' . $default;
} else {
$sql[] = $alter . $v;
}
if ($not_null) {
list($colname) = explode(' ',$v);
$sql[] = 'ALTER TABLE '.$tabname.' ALTER COLUMN '.$colname.' SET NOT NULL';
}
}
return $sql;
}
function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
{
if (!$tableflds) {
if ($this->debug) $this->outp("AlterColumnSQL needs a complete table-definiton for PostgreSQL");
return array();
}
return $this->_recreate_copy_table($tabname,False,$tableflds,$tableoptions);
}
function DropColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
{
$has_drop_column = 7.3 <= (float) @$this->serverInfo['version'];
if (!$has_drop_column && !$tableflds) {
if ($this->debug) $this->outp("DropColumnSQL needs complete table-definiton for PostgreSQL < 7.3");
return array();
}
if ($has_drop_column) {
return ADODB_DataDict::DropColumnSQL($tabname, $flds);
}
return $this->_recreate_copy_table($tabname,$flds,$tableflds,$tableoptions);
}
function DropTableSQL($tabname)
{
$sql = ADODB_DataDict::DropTableSQL($tabname);
$drop_seq = $this->_DropAutoIncrement($tabname);
if ($drop_seq) $sql[] = $drop_seq;
return $sql;
}
function _CreateSuffix($fname, &$ftype, $fnotnull,$fdefault,$fautoinc,$fconstraint)
{
if ($fautoinc) {
$ftype = 'SERIAL';
return '';
}
$suffix = '';
if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
if ($fnotnull) $suffix .= ' NOT NULL';
if ($fconstraint) $suffix .= ' '.$fconstraint;
return $suffix;
}
function _DropAutoIncrement($tabname)
{
$tabname = $this->connection->qstr('%'.$tabname.'%');
$seq = $this->connection->GetOne("SELECT relname FROM pg_class WHERE NOT relname ~ 'pg_.*' AND relname LIKE $tabname AND relkind='S'");
// check if a tables depends on the sequenz and it therefor cant and dont need to be droped separatly
if (!$seq || $this->connection->GetOne("SELECT relname FROM pg_class JOIN pg_depend ON pg_class.relfilenode=pg_depend.objid WHERE relname='$seq' AND relkind='S' AND deptype='i'")) {
return False;
}
return "DROP SEQUENCE ".$seq;
}
function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
{
$sql = array();
if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {
$sql[] = sprintf ($this->dropIndex, $idxname, $tabname);
if ( isset($idxoptions['DROP']) )
return $sql;
}
if ( empty ($flds) ) {
return $sql;
}
$unique = isset($idxoptions['UNIQUE']) ? ' UNIQUE' : '';
$s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname . ' ';
if (isset($idxoptions['HASH']))
$s .= 'USING HASH ';
if ( isset($idxoptions[$this->upperName]) )
$s .= $idxoptions[$this->upperName];
if ( is_array($flds) )
$flds = implode(', ',$flds);
$s .= '(' . $flds . ')';
$sql[] = $s;
return $sql;
}
function _recreate_copy_table($tabname,$dropflds,$tableflds,$tableoptions='')
{
if ($dropflds && !is_array($dropflds)) $dropflds = explode(',',$dropflds);
$copyflds = array();
foreach($this->MetaColumns($tabname) as $fld) {
if (!$dropflds || !in_array($fld->name,$dropflds)) {
// we need to explicit convert varchar to a number to be able to do an AlterColumn of a char column to a nummeric one
if (preg_match('/'.$fld->name.' (I|I2|I4|I8|N|F)/i',$tableflds,$matches) &&
in_array($fld->type,array('varchar','char','text','bytea'))) {
$copyflds[] = "to_number($fld->name,'S99D99')";
} else {
$copyflds[] = $fld->name;
}
// identify the sequence name and the fld its on
if ($fld->primary_key && $fld->has_default &&
preg_match("/nextval\('([^']+)'::text\)/",$fld->default_value,$matches)) {
$seq_name = $matches[1];
$seq_fld = $fld->name;
}
}
}
$copyflds = implode(', ',$copyflds);
$tempname = $tabname.'_tmp';
$aSql[] = 'BEGIN'; // we use a transaction, to make sure not to loose the content of the table
$aSql[] = "SELECT * INTO TEMPORARY TABLE $tempname FROM $tabname";
$aSql = array_merge($aSql,$this->DropTableSQL($tabname));
$aSql = array_merge($aSql,$this->CreateTableSQL($tabname,$tableflds,$tableoptions));
$aSql[] = "INSERT INTO $tabname SELECT $copyflds FROM $tempname";
if ($seq_name && $seq_fld) { // if we have a sequence we need to set it again
$seq_name = $tabname.'_'.$seq_fld.'_seq'; // has to be the name of the new implicit sequence
$aSql[] = "SELECT setval('$seq_name',MAX($seq_fld)) FROM $tabname";
}
$aSql[] = "DROP TABLE $tempname";
// recreate the indexes, if they not contain one of the droped columns
foreach($this->MetaIndexes($tabname) as $idx_name => $idx_data)
{
if (substr($idx_name,-5) != '_pkey' && (!$dropflds || !count(array_intersect($dropflds,$idx_data['columns'])))) {
$aSql = array_merge($aSql,$this->CreateIndexSQL($idx_name,$tabname,$idx_data['columns'],
$idx_data['unique'] ? array('UNIQUE') : False));
}
}
$aSql[] = 'COMMIT';
return $aSql;
}
}
?>
@@ -0,0 +1,316 @@
<?php
/**
* ADOdb Lite Date Module for Postgres 64
*
*/
if (!defined('TIMESTAMP_FIRST_YEAR')) define('TIMESTAMP_FIRST_YEAR',100);
@include(ADODB_DIR . '/adodb-time.inc.php');
eval('class postgres64_date_EXTENDER extends '. $last_module . '_ADOConnection { }');
class postgres64_date_ADOConnection extends postgres64_date_EXTENDER
{
var $fmtDate = "'Y-m-d'"; // used by DBDate() as the default date format used by the database
var $fmtTimeStamp = "'Y-m-d H:i:s'"; // used by DBTimeStamp as the default timestamp fmt.
var $emptyDate = '&nbsp;';
var $emptyTimeStamp = '&nbsp;';
var $sysDate = "CURRENT_DATE";
var $sysTimeStamp = "CURRENT_TIMESTAMP";
var $isoDates = true; /// accepts dates in ISO format
function Time()
{
$rs =& $this->_Execute("select $this->sysTimeStamp");
if ($rs && !$rs->EOF)
return $this->UnixTimeStamp(reset($rs->fields));
return false;
}
function OffsetDate($dayFraction, $date=false)
{
if (!$date)
$date = $this->sysDate;
else if (strncmp($date,"'",1) == 0) {
$len = strlen($date);
if (10 <= $len && $len <= 12)
$date = 'date ' . $date;
else $date = 'timestamp ' . $date;
}
return "($date+interval'$dayFraction days')";
}
function SetDateLocale($locale = 'En')
{
$this->locale = $locale;
switch (strtoupper($locale))
{
case 'EN':
$this->fmtDate="'Y-m-d'";
$this->fmtTimeStamp = "'Y-m-d H:i:s'";
break;
case 'US':
$this->fmtDate = "'m-d-Y'";
$this->fmtTimeStamp = "'m-d-Y H:i:s'";
break;
case 'NL':
case 'FR':
case 'RO':
case 'IT':
$this->fmtDate="'d-m-Y'";
$this->fmtTimeStamp = "'d-m-Y H:i:s'";
break;
case 'GE':
$this->fmtDate="'d.m.Y'";
$this->fmtTimeStamp = "'d.m.Y H:i:s'";
break;
default:
$this->fmtDate="'Y-m-d'";
$this->fmtTimeStamp = "'Y-m-d H:i:s'";
break;
}
}
function DBDate($date)
{
if (empty($date) && $date !== 0)
return 'null';
if (is_string($date) && !is_numeric($date)) {
if ($date === 'null' || strncmp($date, "'", 1) === 0)
return $date;
if ($this->isoDates)
return "'$date'";
$date = $this->UnixDate($date);
}
return adodb_date($this->fmtDate,$date);
}
function DBTimeStamp($timestamp)
{
if (empty($timestamp) && $timestamp !== 0)
return 'null';
# strlen(14) allows YYYYMMDDHHMMSS format
if (!is_string($timestamp) || (is_numeric($timestamp) && strlen($timestamp)<14))
return adodb_date($this->fmtTimeStamp, $timestamp);
if ($timestamp === 'null')
return $timestamp;
if ($this->isoDates && strlen($timestamp) !== 14)
return "'$timestamp'";
$timestamp = $this->UnixTimeStamp($timestamp);
return adodb_date($this->fmtTimeStamp, $timestamp);
}
function UnixDate($v)
{
if (is_object($v)) {
// odbtp support
//( [year] => 2004 [month] => 9 [day] => 4 [hour] => 12 [minute] => 44 [second] => 8 [fraction] => 0 )
return adodb_mktime($v->hour, $v->minute, $v->second, $v->month, $v->day, $v->year);
}
if (is_numeric($v) && strlen($v) !== 8)
return $v;
if (!preg_match( "|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})|", ($v), $rr))
return false;
if ($rr[1] <= TIMESTAMP_FIRST_YEAR)
return 0;
// h-m-s-MM-DD-YY
return adodb_mktime(0, 0, 0, $rr[2], $rr[3], $rr[1]);
}
function UnixTimeStamp($v)
{
if (is_object($v)) {
// odbtp support
//( [year] => 2004 [month] => 9 [day] => 4 [hour] => 12 [minute] => 44 [second] => 8 [fraction] => 0 )
return adodb_mktime($v->hour, $v->minute, $v->second, $v->month, $v->day, $v->year);
}
if (!preg_match("|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})[ ,-]*(([0-9]{1,2}):?([0-9]{1,2}):?([0-9\.]{1,4}))?|", ($v), $rr))
return false;
if ($rr[1] <= TIMESTAMP_FIRST_YEAR && $rr[2]<= 1)
return 0;
// h-m-s-MM-DD-YY
if (!isset($rr[5]))
return adodb_mktime(0, 0, 0, $rr[2], $rr[3], $rr[1]);
else return adodb_mktime($rr[5], $rr[6], $rr[7], $rr[2], $rr[3], $rr[1]);
}
function UserDate($v, $fmt='Y-m-d', $gmt=false)
{
$tt = $this->UnixDate($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
else if ($tt == 0)
return $this->emptyDate;
else if ($tt == -1) { // pre-TIMESTAMP_FIRST_YEAR
}
return ($gmt) ? adodb_gmdate($fmt, $tt) : adodb_date($fmt, $tt);
}
function UserTimeStamp($v, $fmt='Y-m-d H:i:s', $gmt=false)
{
if (!isset($v))
return $this->emptyTimeStamp;
# strlen(14) allows YYYYMMDDHHMMSS format
if (is_numeric($v) && strlen($v)<14)
return ($gmt) ? adodb_gmdate($fmt,$v) : adodb_date($fmt,$v);
$tt = $this->UnixTimeStamp($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
if ($tt == 0)
return $this->emptyTimeStamp;
else return ($gmt) ? adodb_gmdate($fmt,$tt) : adodb_date($fmt,$tt);
}
function SQLDate($fmt, $col=false)
{
if (!$col)
$col = $this->sysTimeStamp;
$s = 'TO_CHAR('.$col.",'";
$len = strlen($fmt);
for ($i=0; $i < $len; $i++) {
$ch = $fmt[$i];
switch($ch) {
case 'Y':
case 'y':
$s .= 'YYYY';
break;
case 'Q':
case 'q':
$s .= 'Q';
break;
case 'M':
$s .= 'Mon';
break;
case 'm':
$s .= 'MM';
break;
case 'D':
case 'd':
$s .= 'DD';
break;
case 'H':
$s.= 'HH24';
break;
case 'h':
$s .= 'HH';
break;
case 'i':
$s .= 'MI';
break;
case 's':
$s .= 'SS';
break;
case 'a':
case 'A':
$s .= 'AM';
break;
case 'w':
$s .= 'D';
break;
case 'l':
$s .= 'DAY';
break;
default:
// handle escape characters...
if ($ch == '\\') {
$i++;
$ch = substr($fmt,$i,1);
}
if (strpos('-/.:;, ',$ch) !== false)
$s .= $ch;
else $s .= '"'.$ch.'"';
}
}
return $s. "')";
}
}
eval('class postgres64_date_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class postgres64_date_ResultSet extends postgres64_date_resultset_EXTENDER
{
var $emptyTimeStamp = '&nbsp;'; /// what to display when $time==0
var $emptyDate = '&nbsp;'; /// what to display when $time==0
var $datetime = false;
function UserTimeStamp($v, $fmt='Y-m-d H:i:s')
{
if (is_numeric($v) && strlen($v)<14)
return adodb_date($fmt,$v);
$tt = $this->UnixTimeStamp($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
if ($tt === 0)
return $this->emptyTimeStamp;
else return adodb_date($fmt,$tt);
}
function UserDate($v,$fmt='Y-m-d')
{
$tt = $this->UnixDate($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
else if ($tt == 0)
return $this->emptyDate;
else if ($tt == -1) { // pre-TIMESTAMP_FIRST_YEAR
}
return adodb_date($fmt,$tt);
}
function UnixDate($v)
{
return postgres64_date_ADOConnection::UnixDate($v);
}
function UnixTimeStamp($v)
{
return postgres64_date_ADOConnection::UnixTimeStamp($v);
}
}
?>
@@ -0,0 +1,659 @@
<?php
/**
* ADOdb Lite is a PHP class to encapsulate multiple database APIs and is compatible with
* a subset of the ADODB Command Syntax.
* Currently supports Frontbase, MaxDB, miniSQL, MSSQL, MSSQL Pro, MySQLi, MySQLt, MySQL, PostgresSQL,
* PostgresSQL64, PostgresSQL7, SqLite and Sybase.
*
*/
class postgres64_driver_ADOConnection extends ADOConnection
{
var $connect_string;
var $sysDate = "CURRENT_DATE";
var $sysTimeStamp = "CURRENT_TIMESTAMP";
function postgres64_driver_ADOConnection()
{
$this->dbtype = 'postgres64';
$this->dataProvider = 'postgres';
}
/**
* Connection to database server and selected database
*
* @access private
*/
function _connect($host = "", $username = "", $password = "", $database = "", $persistent, $forcenew)
{
if (!function_exists('pg_connect')) return false;
$this->host = $host;
$this->username = $this->query_addslashes($username);
$this->password = $this->query_addslashes($password);
if (strlen($database) == 0) $database = 'template1';
$this->database = $this->query_addslashes($database);
if ($this->username || $this->password || $this->database) {
$this->connect_string = $this->host;
if ($this->connect_string) {
$host = split(":", $this->connect_string);
if ($host[0]) $this->connect_string = "host=" . $this->query_addslashes($host[0]);
else $this->connect_string = 'host=localhost';
if (isset($host[1])) $this->connect_string .= " port=$host[1]";
else if (!empty($this->port)) $this->connect_string .= " port=" . $this->port;
}
if ($this->username) $this->connect_string .= " user=" . $this->username;
if ($this->password) $this->connect_string .= " password=" . $this->password;
if ($this->database) $this->connect_string .= " dbname=" . $this->database;
}
else
{
$this->connect_string = $this->host;
}
$this->persistent = $persistent;
$this->forcenewconnection = $forcenew;
$this->_makeconnection();
if ($this->connectionId === false)
{
if ($fn = $this->raiseErrorFn)
$fn($this->dbtype, 'CONNECT', $this->ErrorNo(), $this->ErrorMsg(), $this->host, $this->database, $this);
return $this->SelectDB( $this->database );
}
return true;
}
function _makeconnection()
{
if($this->persistent == 1)
{
$this->connectionId = @pg_pconnect( $this->connect_string );
}
else
{
if(!$this->forcenewconnection)
{
$this->connectionId = @pg_connect( $this->connect_string );
}
else
{
$this->connectionId = @pg_connect( $this->connect_string, PGSQL_CONNECT_FORCE_NEW );
}
}
}
function query_addslashes($query)
{
$len = strlen($query);
if ($len == 0)
return "''";
if (strncmp($query,"'",1) === 0 && substr($query,$len-1) == "'")
return $s;
return "'".addslashes($query)."'";
}
/**
* Choose a database to connect.
*
* @param dbname is the name of the database to select
* @return true or false
* @access public
*/
function SelectDB($dbname)
{
$this->database = $dbname;
if ($this->connectionId === false)
{
if($this->createdatabase == true)
{
$this->connectionId = @pg_pconnect( "host=$this->host user=$this->username password=$this->password" );
$result = @pg_query($this->connectionId, "CREATE DATABASE " . $this->database );
if ($result === false) { // error handling if query fails
$this->connectionId = false;
return false;
}
$this->_makeconnection();
if($this->connectionId === false)
{
$this->connectionId = false;
return false;
}
else
{
return true;
}
}
$this->connectionId = false;
return false;
}
else
{
return true;
}
}
/**
* Return database error message
* Usage: $errormessage =& $db->ErrorMsg();
*
* @access public
*/
function ErrorMsg()
{
return @pg_last_error($this->connectionId);
}
/**
* Return database error number
* Usage: $errorbo =& $db->ErrorNo();
*
* @access public
*/
function ErrorNo()
{
$error = @pg_last_error( $this->connectionId );
return strlen($error) ? $error : 0;
}
/**
* Returns # of affected rows from insert/delete/update query
*
* @access public
* @return integer Affected rows
*/
function Affected_Rows()
{
return @pg_affected_rows($this->record_set);
}
/**
* Returns the last record id of an inserted item
* Usage: $db->Insert_ID();
*
* @access public
*/
function Insert_ID()
{
return @pg_getlastoid($this->record_set);
}
/**
* Correctly quotes a string so that all strings are escape coded.
* An example is $db->qstr("Haven't a clue.");
*
* @param string the string to quote
* @param [magic_quotes] if $s is GET/POST var, set to get_magic_quotes_gpc().
*
* @return single-quoted string IE: 'Haven\'t a clue.'
*/
function qstr($string, $magic_quotes=false)
{
// Ugly hack alert! Repalce backticks with some arbitrary character
$string = str_replace('`', "\x1C", $string);
if (!$magic_quotes) {
$string = str_replace("'", "\\'", str_replace('\\', '\\\\', str_replace("\0", "\\\0", $string)));
return "'" . $string . "'";
}
return "'" . str_replace('\\"', '"', $string) . "'";
}
function QMagic($string)
{
return $this->qstr($string, get_magic_quotes_gpc());
}
/**
* Returns concatenated string
* Usage: $db->Concat($str1,$str2);
*
* @return concatenated string
*/
function Concat()
{
$arr = func_get_args();
return implode("||", $arr);
}
function IfNull( $field, $ifNull )
{
return " coalesce($field, $ifNull) ";
}
/**
* Closes database connection
* Usage: $db->close();
*
* @access public
*/
function Close()
{
@pg_close( $this->connectionId );
$this->connectionId = false;
}
/**
* Returns All Records in an array
*
* Usage: $db->GetAll($sql);
* @access public
*/
function &GetAll($sql, $inputarr = false)
{
$data =& $this->GetArray($sql, $inputarr);
return $data;
}
/**
* Returns All Records in an array
*
* Usage: $db->GetArray($sql);
* @access public
*/
function &GetArray($sql, $inputarr = false)
{
$data = false;
$result =& $this->Execute($sql, $inputarr);
if ($result)
{
$data =& $result->GetArray();
$result->Close();
}
return $data;
}
/**
* Executes SQL query and instantiates resultset methods
*
* @access private
* @return mixed Resultset methods
*/
function &do_query( $sql, $offset, $nrows, $inputarr=false )
{
global $ADODB_FETCH_MODE;
$sql = str_replace('`', '"', $sql);
$sql = str_replace("\x1C", "`", $sql);
$sql = str_replace('IS_DELETED', 'is_deleted', $sql);
$sql = str_replace("HIGH_PRIORITY", "", $sql);
$false = false;
// $limit = '';
// if ($offset != -1 || $nrows != -1)
// {
// $offset = ($offset>=0) ? $offset . "," : '';
// $limit = ' LIMIT ' . $offset . ' ' . $nrows;
// }
if ($inputarr && is_array($inputarr)) {
$sqlarr = explode('?', $sql);
if (!is_array(reset($inputarr))) $inputarr = array($inputarr);
foreach($inputarr as $arr) {
$sql = ''; $i = 0;
foreach($arr as $v) {
$sql .= $sqlarr[$i];
switch(gettype($v)){
case 'string':
$sql .= $this->qstr($v);
break;
case 'double':
$sql .= str_replace(',', '.', $v);
break;
case 'boolean':
$sql .= $v ? "'t'" : "'f'";
break;
default:
if ($v === null)
$sql .= 'NULL';
else $sql .= $v;
}
$i += 1;
}
$sql .= $sqlarr[$i];
if ($i+1 != sizeof($sqlarr))
return $false;
$this->sql = $sql;
$time_start = array_sum(explode(' ', microtime()));
$this->query_count++;
$resultId = @pg_query( $this->sql );
$time_total = (array_sum(explode(' ', microtime())) - $time_start);
$this->query_time_total += $time_total;
if($this->debug_console)
{
$this->query_list[] = $this->sql;
$this->query_list_time[] = $time_total;
$this->query_list_errors[] = $this->ErrorMsg();
}
if($this->debug)
{
$this->outp($sql);
}
if ($resultId === false) { // error handling if query fails
if ($fn = $this->raiseErrorFn)
$fn($this->dbtype, 'EXECUTE', $this->ErrorNo(), $this->ErrorMsg(), $this->sql, $inputarr, $this);
return $false;
}
}
}
else
{
$this->sql = $sql;
$time_start = array_sum(explode(' ', microtime()));
$this->query_count++;
$resultId = @pg_query( $this->sql);
$time_total = (array_sum(explode(' ', microtime())) - $time_start);
$this->query_time_total += $time_total;
if($this->debug_console)
{
$this->query_list[] = $this->sql;
$this->query_list_time[] = $time_total;
$this->query_list_errors[] = $this->ErrorMsg();
}
if($this->debug)
{
$this->outp($sql);
}
}
if ($resultId === false) { // error handling if query fails
if ($fn = $this->raiseErrorFn)
$fn($this->dbtype, 'EXECUTE', $this->ErrorNo(), $this->ErrorMsg(), $this->sql, $inputarr, $this);
return $false;
}
if (@pg_numfields( $resultId ) <= 0) { // return simplified recordset for inserts/updates/deletes with lower overhead
$recordset = new ADORecordSet_empty();
$this->record_set = $recordset;
return $recordset;
}
$resultset_name = $this->last_module_name . "_ResultSet";
$recordset = new $resultset_name( $resultId, $this->connectionId );
$this->record_set = $recordset;
$recordset->_currentRow = 0;
switch ($ADODB_FETCH_MODE)
{
case ADODB_FETCH_NUM: $recordset->fetchMode = PGSQL_NUM; break;
case ADODB_FETCH_ASSOC:$recordset->fetchMode = PGSQL_ASSOC; break;
default:
case ADODB_FETCH_DEFAULT:
case ADODB_FETCH_BOTH:$recordset->fetchMode = PGSQL_BOTH; break;
}
$recordset->_numOfRows = @pg_numrows( $resultId );
if( $recordset->_numOfRows == 0)
{
$recordset->EOF = true;
}
$recordset->_numOfFields = @pg_numfields( $resultId );
$recordset->_fetch();
return $recordset;
}
}
class postgres64_driver_ResultSet
{
var $connectionId;
var $fields;
var $resultId;
var $_currentRow = 0;
var $_numOfRows = -1;
var $_numOfFields = -1;
var $fetchMode;
var $EOF;
/**
* pgsqlResultSet Constructor
*
* @access private
* @param string $record
* @param string $resultId
*/
function postgres64_driver_ResultSet( $resultId, $connectionId )
{
$this->fields = array();
$this->connectionId = $connectionId;
$this->record = array();
$this->resultId = $resultId;
$this->EOF = false;
}
/**
* Frees resultset
*
* @access public
*/
function Close()
{
pg_free_result( $this->resultId );
$this->fields = array();
$this->resultId = false;
}
/**
* Returns field name from select query
*
* @access public
* @param string $field
* @return string Field name
*/
function fields( $field )
{
if(empty($field))
{
return $this->fields;
}
else
{
return $this->fields[$field];
}
}
/**
* Returns numrows from select query
*
* @access public
* @return integer Numrows
*/
function RecordCount()
{
return $this->_numOfRows;
}
/**
* Returns num of fields from select query
*
* @access public
* @return integer numfields
*/
function FieldCount()
{
return $this->_numOfFields;
}
/**
* Returns next record
*
* @access public
*/
function MoveNext()
{
if (@$this->fields = pg_fetch_array($this->resultId, NULL, $this->fetchMode)) {
$this->_currentRow += 1;
return true;
}
if (!$this->EOF) {
$this->_currentRow += 1;
$this->EOF = true;
}
return false;
}
/**
* Move to the first row in the recordset. Many databases do NOT support this.
*
* @return true or false
*/
function MoveFirst()
{
if ($this->_currentRow == 0) return true;
return $this->Move(0);
}
/**
* Returns the Last Record
*
* @access public
*/
function MoveLast()
{
if ($this->EOF) return false;
return $this->Move($this->_numOfRows - 1);
}
/**
* Random access to a specific row in the recordset. Some databases do not support
* access to previous rows in the databases (no scrolling backwards).
*
* @param rowNumber is the row to move to (0-based)
*
* @return true if there still rows available, or false if there are no more rows (EOF).
*/
function Move($rowNumber = 0)
{
if ($rowNumber == $this->_currentRow) return true;
$this->EOF = false;
if ($this->_numOfRows > 0){
if ($rowNumber >= $this->_numOfRows - 1){
$rowNumber = $this->_numOfRows - 1;
}
}
if ($this->_seek($rowNumber)) {
$this->_currentRow = $rowNumber;
if ($this->_fetch()) {
return true;
}
$this->fields = false;
}
$this->EOF = true;
return false;
}
/**
* Perform Seek to specific row
*
* @access private
*/
function _seek($row)
{
if ($this->_numOfRows == 0) return false;
return @pg_result_seek($this->resultId,$row);
}
/**
* Fills field array with first database element when query initially executed
*
* @access private
*/
function _fetch()
{
$this->fields = @pg_fetch_array($this->resultId, NULL, $this->fetchMode);
return is_array($this->fields);
}
/**
* Check to see if last record reached
*
* @access public
*/
function EOF()
{
if( $this->_currentRow < $this->_numOfRows)
{
return false;
}
else
{
$this->EOF = true;
return true;
}
}
/**
* Returns All Records in an array
*
* @access public
* @param [nRows] is the number of rows to return. -1 means every row.
*/
function &GetArray($nRows = -1)
{
$results = array();
$cnt = 0;
while (!$this->EOF && $nRows != $cnt) {
$results[] = $this->fields;
$this->MoveNext();
$cnt++;
}
return $results;
}
function &GetRows($nRows = -1)
{
$arr =& $this->GetArray($nRows);
return $arr;
}
function &GetAll($nRows = -1)
{
$arr =& $this->GetArray($nRows);
return $arr;
}
/**
* Fetch field information for a table.
*
* @return object containing the name, type and max_length
*/
function FetchField($fieldOffset = -1)
{
$fieldObject= new ADOFieldObject();
$fieldObject->name = @pg_fieldname($this->resultId, $fieldOffset);
$fieldObject->type = @pg_fieldtype($this->resultId, $fieldOffset);
$fieldObject->max_length = @pg_fieldsize($this->resultId, $fieldOffset);
return $fieldObject;
}
}
?>
@@ -0,0 +1,147 @@
<?php
/**
* ADOdb Lite Extend Module for Mysqlt
*
*/
eval('class postgres64_extend_EXTENDER extends '. $last_module . '_ADOConnection { }');
class postgres64_extend_ADOConnection extends postgres64_extend_EXTENDER
{
function &GetAssoc($sql, $inputarr=false, $force_array = false, $first2cols = false)
{
$data = false;
$result =& $this->Execute($sql, $inputarr);
if ($result) {
$data =& $result->GetAssoc($force_array, $first2cols);
$result->Close();
}
return $data;
}
/**
* Generates a sequence id and stores it in $this->genID;
* GenID is only available if $this->hasGenID = true;
*
* @param seqname name of sequence to use
* @param startID if sequence does not exist, start at this ID
* @return 0 if not supported, otherwise a sequence id
*/
var $_genIDSQL = "SELECT NEXTVAL('%s')";
var $_genSeqSQL = "CREATE SEQUENCE %s START %s";
var $_dropSeqSQL = "DROP SEQUENCE %s";
var $genID = 0;
function GenID($seqname='adodbseq', $startID=1)
{
$getnext = sprintf($this->_genIDSQL, $seqname);
$holdtransOK = $this->transaction_status;
$save_handler = $this->raiseErrorFn;
$this->raiseErrorFn = '';
@($result = $this->Execute($getnext));
$this->raiseErrorFn = $save_handler;
if (!$result) {
$this->transaction_status = $holdtransOK;
$createseq = $this->Execute(sprintf($this->_genSeqSQL, $seqname, $startID));
$result = $this->Execute($getnext);
}
if ($result && !$result->EOF)
$this->genID = reset($result->fields);
else $this->genID = 0;
if ($result)
$result->Close();
return $this->genID;
}
function CreateSequence($seqname='adodbseq', $startID=1)
{
return $this->Execute(sprintf($this->_genSeqSQL, $seqname, $startID));
}
function DropSequence($seqname='adodbseq')
{
return $this->Execute(sprintf($this->_dropSeqSQL, $seqname));
}
}
eval('class postgres64_extend_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class postgres64_extend_ResultSet extends postgres64_extend_resultset_EXTENDER
{
function &GetAssoc($force_array = false, $first2cols = false)
{
$results = false;
if ($this->_numOfFields > 1) {
$numIndex = isset($this->fields[0]);
$results = array();
if (!$first2cols && ($this->_numOfFields > 2 || $force_array)) {
if ($numIndex) {
while (!$this->EOF) {
$results[trim($this->fields[0])] = array_slice($this->fields, 1);
$this->MoveNext();
}
} else {
while (!$this->EOF) {
$results[trim(reset($this->fields))] = array_slice($this->fields, 1);
$this->MoveNext();
}
}
} else {
if ($numIndex) {
while (!$this->EOF) {
$results[trim(($this->fields[0]))] = $this->fields[1];
$this->MoveNext();
}
} else {
while (!$this->EOF) {
$v1 = trim(reset($this->fields));
$v2 = ''.next($this->fields);
$results[$v1] = $v2;
$this->MoveNext();
}
}
}
}
return $results;
}
function PO_RecordCount($table="", $condition="")
{
$lnumrows = $this->_numOfRows;
if($lnumrows == -1 && $this->connectionId)
{
if($table)
{
if ($condition)
$condition = " WHERE " . $condition;
$resultrows = &$this->connectionId->Execute("SELECT COUNT(*) FROM $table $condition");
if ($resultrows)
$lnumrows = reset($resultrows->fields);
}
}
return $lnumrows;
}
function CurrentRow()
{
return $this->_currentRow;
}
function AbsolutePosition()
{
return $this->_currentRow;
}
function NextRecordSet()
{
return false;
}
}
?>
@@ -0,0 +1,684 @@
<?php
/**
* ADOdb Lite Meta Module for Postgres64
*
* Portions of the Meta Coding came from ADOdb
*/
/*
(c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. See License.txt.
*/
eval('class postgres64_meta_EXTENDER extends '. $last_module . '_ADOConnection { }');
class postgres64_meta_ADOConnection extends postgres64_meta_EXTENDER
{
var $metaDatabasesSQL = "select datname from pg_database where datname not in ('template0','template1') order by 1";
var $metaTablesSQL = "select tablename,'T' from pg_tables where tablename not like 'pg\_%'
and tablename not in ('sql_features', 'sql_implementation_info', 'sql_languages',
'sql_packages', 'sql_sizing', 'sql_sizing_profiles')
union
select viewname,'V' from pg_views where viewname not like 'pg\_%'";
var $metaColumnsSQL = "SELECT a.attname,t.typname,a.attlen,a.atttypmod,a.attnotnull,a.atthasdef,a.attnum
FROM pg_class c, pg_attribute a,pg_type t
WHERE relkind in ('r','v') AND (c.relname='%s' or c.relname = lower('%s')) and a.attname not like '....%%'
AND a.attnum > 0 AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum";
// used when schema defined
var $metaColumnsSQL1 = "SELECT a.attname, t.typname, a.attlen, a.atttypmod, a.attnotnull, a.atthasdef, a.attnum
FROM pg_class c, pg_attribute a, pg_type t, pg_namespace n
WHERE relkind in ('r','v') AND (c.relname='%s' or c.relname = lower('%s'))
and c.relnamespace=n.oid and n.nspname='%s'
and a.attname not like '....%%' AND a.attnum > 0
AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum";
// get primary key etc -- from Freek Dijkstra
var $metaKeySQL = "SELECT ic.relname AS index_name, a.attname AS column_name,i.indisunique AS unique_key, i.indisprimary AS primary_key
FROM pg_class bc, pg_class ic, pg_index i, pg_attribute a WHERE bc.oid = i.indrelid AND ic.oid = i.indexrelid AND (i.indkey[0] = a.attnum OR i.indkey[1] = a.attnum OR i.indkey[2] = a.attnum OR i.indkey[3] = a.attnum OR i.indkey[4] = a.attnum OR i.indkey[5] = a.attnum OR i.indkey[6] = a.attnum OR i.indkey[7] = a.attnum) AND a.attrelid = bc.oid AND bc.relname = '%s'";
var $metaDefaultsSQL = "SELECT d.adnum as num, d.adsrc as def from pg_attrdef d, pg_class c where d.adrelid=c.oid and c.relname='%s' order by d.adnum";
function MetaError($err=false)
{
include_once(ADODB_DIR."/adodb-error.inc.php");
if ($err === false)
$err = $this->ErrorNo();
return adodb_error($this->dataProvider,$this->databaseType,$err);
}
function MetaErrorMsg($errno)
{
include_once(ADODB_DIR."/adodb-error.inc.php");
return adodb_errormsg($errno);
}
/**
* @returns an array with the primary key columns in it.
*/
function MetaPrimaryKeys($table, $owner=false)
{
// owner not used in base class - see oci8
$p = array();
$objs =& $this->MetaColumns($table);
if ($objs) {
foreach($objs as $v) {
if (!empty($v->primary_key))
$p[] = $v->name;
}
}
if (sizeof($p)) return $p;
if (function_exists('ADODB_VIEW_PRIMARYKEYS'))
return ADODB_VIEW_PRIMARYKEYS($this->databaseType, $this->database, $table, $owner);
return false;
}
/**
* @returns assoc array where keys are tables, and values are foreign keys
*/
function MetaForeignKeys($table, $owner=false, $upper=false)
{
return false;
}
// not the fastest implementation - quick and dirty - jlim
// for best performance, use the actual $rs->MetaType().
function MetaType($t,$len=-1,$fieldobj=false)
{
if (empty($this->_metars)) {
$rsclass = $this->last_module_name . "_ResultSet";
$this->_metars =& new $rsclass(false,$this->fetchMode);
}
return $this->_metars->MetaType($t,$len,$fieldobj);
}
/**
* return the databases that the driver can connect to.
* Some databases will return an empty array.
*
* @return an array of database names.
*/
function MetaDatabases()
{
global $ADODB_FETCH_MODE;
if ($this->metaDatabasesSQL) {
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
$arr = $this->GetCol($this->metaDatabasesSQL);
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
return $arr;
}
return false;
}
/**
* @param ttype can either be 'VIEW' or 'TABLE' or false.
* If false, both views and tables are returned.
* "VIEW" returns only views
* "TABLE" returns only tables
* @param showSchema returns the schema/user with the table name, eg. USER.TABLE
* @param mask is the input mask - only supported by oci8 and postgresql
*
* @return array of tables for current database.
*/
function &MetaTables($ttype=false,$showSchema=false,$mask=false)
{
$info = $this->ServerInfo();
if ($info['version'] >= 7.3) {
$this->metaTablesSQL = "select tablename,'T' from pg_tables where tablename not like 'pg\_%'
and schemaname not in ( 'pg_catalog','information_schema')
union
select viewname,'V' from pg_views where viewname not like 'pg\_%' and schemaname not in ( 'pg_catalog','information_schema') ";
}
if ($mask) {
$save = $this->metaTablesSQL;
$mask = $this->qstr(strtolower($mask));
if ($info['version']>=7.3)
$this->metaTablesSQL = "
select tablename,'T' from pg_tables where tablename like $mask and schemaname not in ( 'pg_catalog','information_schema')
union
select viewname,'V' from pg_views where viewname like $mask and schemaname not in ( 'pg_catalog','information_schema') ";
else
$this->metaTablesSQL = "
select tablename,'T' from pg_tables where tablename like $mask
union
select viewname,'V' from pg_views where viewname like $mask";
}
$ret =& $this->_MetaTables($ttype,$showSchema);
if ($mask) {
$this->metaTablesSQL = $save;
}
return $ret;
}
function &_MetaTables($ttype=false,$showSchema=false,$mask=false)
{
global $ADODB_FETCH_MODE;
$false = false;
if ($mask) {
return $false;
}
if ($this->metaTablesSQL) {
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
$rs = $this->Execute($this->metaTablesSQL);
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
if ($rs === false) return $false;
$arr =& $rs->GetArray();
$arr2 = array();
if ($hast = ($ttype && isset($arr[0][1]))) {
$showt = strncmp($ttype,'T',1);
}
for ($i=0; $i < sizeof($arr); $i++) {
if ($hast) {
if ($showt == 0) {
if (strncmp($arr[$i][1],'T',1) == 0) $arr2[] = trim($arr[$i][0]);
} else {
if (strncmp($arr[$i][1],'V',1) == 0) $arr2[] = trim($arr[$i][0]);
}
} else
$arr2[] = trim($arr[$i][0]);
}
$rs->Close();
return $arr2;
}
return $false;
}
function _findschema(&$table,&$schema)
{
if (!$schema && ($at = strpos($table,'.')) !== false) {
$schema = substr($table,0,$at);
$table = substr($table,$at+1);
}
}
/**
* List columns in a database as an array of ADOFieldObjects.
* See top of file for definition of object.
*
* @param $table table name to query
* @param $normalize makes table name case-insensitive (required by some databases)
* @schema is optional database schema to use - not supported by all databases.
*
* @return array of ADOFieldObjects for current table.
*/
function &MetaColumns($table,$normalize=true)
{
global $ADODB_FETCH_MODE;
$schema = false;
$false = false;
$this->_findschema($table,$schema);
if ($normalize) $table = strtolower($table);
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
if ($schema) $rs =& $this->Execute(sprintf($this->metaColumnsSQL1,$table,$table,$schema));
else $rs =& $this->Execute(sprintf($this->metaColumnsSQL,$table,$table));
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
if ($rs === false) {
return $false;
}
if (!empty($this->metaKeySQL)) {
// If we want the primary keys, we have to issue a separate query
// Of course, a modified version of the metaColumnsSQL query using a
// LEFT JOIN would have been much more elegant, but postgres does
// not support OUTER JOINS. So here is the clumsy way.
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
$rskey = $this->Execute(sprintf($this->metaKeySQL,($table)));
// fetch all result in once for performance.
$keys =& $rskey->GetArray();
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
$rskey->Close();
unset($rskey);
}
$rsdefa = array();
if (!empty($this->metaDefaultsSQL)) {
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
$sql = sprintf($this->metaDefaultsSQL, ($table));
$rsdef = $this->Execute($sql);
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
if ($rsdef) {
while (!$rsdef->EOF) {
$num = $rsdef->fields['num'];
$s = $rsdef->fields['def'];
if (strpos($s,'::')===false && substr($s, 0, 1) == "'") { /* quoted strings hack... for now... fixme */
$s = substr($s, 1);
$s = substr($s, 0, strlen($s) - 1);
}
$rsdefa[$num] = $s;
$rsdef->MoveNext();
}
} else {
ADOConnection::outp( "==> SQL => " . $sql);
}
unset($rsdef);
}
$retarr = array();
while (!$rs->EOF) {
$fld = new ADOFieldObject();
$fld->name = $rs->fields[0];
$fld->type = $rs->fields[1];
$fld->max_length = $rs->fields[2];
$fld->attnum = $rs->fields[6];
if ($fld->max_length <= 0) $fld->max_length = $rs->fields[3]-4;
if ($fld->max_length <= 0) $fld->max_length = -1;
if ($fld->type == 'numeric') {
$fld->scale = $fld->max_length & 0xFFFF;
$fld->max_length >>= 16;
}
// dannym
// 5 hasdefault; 6 num-of-column
$fld->has_default = ($rs->fields[5] == 't');
if ($fld->has_default) {
$fld->default_value = $rsdefa[$rs->fields[6]];
}
//Freek
$fld->not_null = $rs->fields[4] == 't';
// Freek
if (is_array($keys)) {
foreach($keys as $key) {
if ($fld->name == $key['column_name'] AND $key['primary_key'] == 't')
$fld->primary_key = true;
if ($fld->name == $key['column_name'] AND $key['unique_key'] == 't')
$fld->unique = true; // What name is more compatible?
}
}
if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;
else $retarr[($normalize) ? strtoupper($fld->name) : $fld->name] = $fld;
$rs->MoveNext();
}
$rs->Close();
if (empty($retarr))
return $false;
else
return $retarr;
}
/**
* List indexes on a table as an array.
* @param table table name to query
* @param primary true to only show primary keys. Not actually used for most databases
*
* @return array of indexes on current table. Each element represents an index, and is itself an associative array.
Array (
[name_of_index] => Array
(
[unique] => true or false
[columns] => Array
(
[0] => firstname
[1] => lastname
)
)
*/
function &MetaIndexes ($table, $primary = FALSE)
{
global $ADODB_FETCH_MODE;
$schema = false;
$this->_findschema($table,$schema);
if ($schema) { // requires pgsql 7.3+ - pg_namespace used.
$sql = '
SELECT c.relname as "Name", i.indisunique as "Unique", i.indkey as "Columns"
FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_index i ON i.indexrelid=c.oid
JOIN pg_catalog.pg_class c2 ON c2.oid=i.indrelid
,pg_namespace n
WHERE (c2.relname=\'%s\' or c2.relname=lower(\'%s\')) and c.relnamespace=c2.relnamespace and c.relnamespace=n.oid and n.nspname=\'%s\'';
} else {
$sql = '
SELECT c.relname as "Name", i.indisunique as "Unique", i.indkey as "Columns"
FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_index i ON i.indexrelid=c.oid
JOIN pg_catalog.pg_class c2 ON c2.oid=i.indrelid
WHERE (c2.relname=\'%s\' or c2.relname=lower(\'%s\'))';
}
if ($primary == FALSE) {
$sql .= ' AND i.indisprimary=false;';
}
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== FALSE) {
$savem = $this->SetFetchMode(FALSE);
}
$rs = $this->Execute(sprintf($sql,$table,$table,$schema));
if (isset($savem)) {
$this->SetFetchMode($savem);
}
$ADODB_FETCH_MODE = $save;
if (!is_object($rs)) {
$false = false;
return $false;
}
$col_names = $this->MetaColumnNames($table,true,true);
//3rd param is use attnum,
// see http://sourceforge.net/tracker/index.php?func=detail&aid=1451245&group_id=42718&atid=433976
$indexes = array();
while ($row = $rs->FetchRow()) {
$columns = array();
foreach (explode(' ', $row[2]) as $col) {
$columns[] = $col_names[$col];
}
$indexes[$row[0]] = array(
'unique' => ($row[1] == 't'),
'columns' => $columns
);
}
return $indexes;
}
/**
* List columns names in a table as an array.
* @param table table name to query
*
* @return array of column names for current table.
*/
function &MetaColumnNames($table, $numIndexes=false,$useattnum=false /* only for postgres */)
{
$objarr =& $this->MetaColumns($table);
if (!is_array($objarr)) {
$false = false;
return $false;
}
$arr = array();
if ($numIndexes) {
$i = 0;
if ($useattnum) {
foreach($objarr as $v)
$arr[$v->attnum] = $v->name;
} else
foreach($objarr as $v) $arr[$i++] = $v->name;
} else
foreach($objarr as $v) $arr[strtoupper($v->name)] = $v->name;
return $arr;
}
function MetaTransaction($mode,$db)
{
$mode = strtoupper($mode);
$mode = str_replace('ISOLATION LEVEL ','',$mode);
switch($mode) {
case 'READ UNCOMMITTED':
switch($db) {
case 'oci8':
case 'oracle':
return 'ISOLATION LEVEL READ COMMITTED';
default:
return 'ISOLATION LEVEL READ UNCOMMITTED';
}
break;
case 'READ COMMITTED':
return 'ISOLATION LEVEL READ COMMITTED';
break;
case 'REPEATABLE READ':
switch($db) {
case 'oci8':
case 'oracle':
return 'ISOLATION LEVEL SERIALIZABLE';
default:
return 'ISOLATION LEVEL REPEATABLE READ';
}
break;
case 'SERIALIZABLE':
return 'ISOLATION LEVEL SERIALIZABLE';
break;
default:
return $mode;
}
}
}
eval('class postgres64_meta_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class postgres64_meta_ResultSet extends postgres64_meta_resultset_EXTENDER
{
/**
* Get the metatype of the column. This is used for formatting. This is because
* many databases use different names for the same type, so we transform the original
* type to our standardised version which uses 1 character codes:
*
* @param t is the type passed in. Normally is ADOFieldObject->type.
* @param len is the maximum length of that field. This is because we treat character
* fields bigger than a certain size as a 'B' (blob).
* @param fieldobj is the field object returned by the database driver. Can hold
* additional info (eg. primary_key for mysql).
*
* @return the general type of the data:
* C for character < 250 chars
* X for teXt (>= 250 chars)
* B for Binary
* N for numeric or floating point
* D for date
* T for timestamp
* L for logical/Boolean
* I for integer
* R for autoincrement counter/integer
*
*
*/
function MetaType($t,$len=-1,$fieldobj=false)
{
if (is_object($t)) {
$fieldobj = $t;
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
$is_serial = is_object($fieldobj) && $fieldobj->primary_key && $fieldobj->unique && $fieldobj->has_default && substr($fieldobj->default_value,0,8) == 'nextval(';
switch (strtoupper($t)) {
case 'MONEY': // stupid, postgres expects money to be a string
case 'INTERVAL':
case 'CHAR':
case 'CHARACTER':
case 'VARCHAR':
case 'NAME':
case 'BPCHAR':
case '_VARCHAR':
case 'INET':
case 'MACADDR':
if ($len <= $this->blobSize) return 'C';
case 'TEXT':
return 'X';
case 'IMAGE': // user defined type
case 'BLOB': // user defined type
case 'BIT': // This is a bit string, not a single bit, so don't return 'L'
case 'VARBIT':
case 'BYTEA':
return 'B';
case 'BOOL':
case 'BOOLEAN':
return 'L';
case 'DATE':
return 'D';
case 'TIMESTAMP WITHOUT TIME ZONE':
case 'TIME':
case 'DATETIME':
case 'TIMESTAMP':
case 'TIMESTAMPTZ':
return 'T';
case 'INTEGER': return !$is_serial ? 'I' : 'R';
case 'SMALLINT':
case 'INT2': return !$is_serial ? 'I2' : 'R';
case 'INT4': return !$is_serial ? 'I4' : 'R';
case 'BIGINT':
case 'INT8': return !$is_serial ? 'I8' : 'R';
case 'OID':
case 'SERIAL':
return 'R';
case 'FLOAT4':
case 'FLOAT8':
case 'DOUBLE PRECISION':
case 'REAL':
return 'F';
default:
static $typeMap = array(
'VARCHAR' => 'C',
'VARCHAR2' => 'C',
'CHAR' => 'C',
'C' => 'C',
'STRING' => 'C',
'NCHAR' => 'C',
'NVARCHAR' => 'C',
'VARYING' => 'C',
'BPCHAR' => 'C',
'CHARACTER' => 'C',
'INTERVAL' => 'C', # Postgres
'MACADDR' => 'C', # postgres
##
'LONGCHAR' => 'X',
'TEXT' => 'X',
'NTEXT' => 'X',
'M' => 'X',
'X' => 'X',
'CLOB' => 'X',
'NCLOB' => 'X',
'LVARCHAR' => 'X',
##
'BLOB' => 'B',
'IMAGE' => 'B',
'BINARY' => 'B',
'VARBINARY' => 'B',
'LONGBINARY' => 'B',
'B' => 'B',
##
'YEAR' => 'D', // mysql
'DATE' => 'D',
'D' => 'D',
##
'UNIQUEIDENTIFIER' => 'C', # MS SQL Server
##
'TIME' => 'T',
'TIMESTAMP' => 'T',
'DATETIME' => 'T',
'TIMESTAMPTZ' => 'T',
'T' => 'T',
'TIMESTAMP WITHOUT TIME ZONE' => 'T', // postgresql
##
'BOOL' => 'L',
'BOOLEAN' => 'L',
'BIT' => 'L',
'L' => 'L',
##
'COUNTER' => 'R',
'R' => 'R',
'SERIAL' => 'R', // ifx
'INT IDENTITY' => 'R',
##
'INT' => 'I',
'INT2' => 'I',
'INT4' => 'I',
'INT8' => 'I',
'INTEGER' => 'I',
'INTEGER UNSIGNED' => 'I',
'SHORT' => 'I',
'TINYINT' => 'I',
'SMALLINT' => 'I',
'I' => 'I',
##
'LONG' => 'N', // interbase is numeric, oci8 is blob
'BIGINT' => 'N', // this is bigger than PHP 32-bit integers
'DECIMAL' => 'N',
'DEC' => 'N',
'REAL' => 'N',
'DOUBLE' => 'N',
'DOUBLE PRECISION' => 'N',
'SMALLFLOAT' => 'N',
'FLOAT' => 'N',
'NUMBER' => 'N',
'NUM' => 'N',
'NUMERIC' => 'N',
'MONEY' => 'N',
## informix 9.2
'SQLINT' => 'I',
'SQLSERIAL' => 'I',
'SQLSMINT' => 'I',
'SQLSMFLOAT' => 'N',
'SQLFLOAT' => 'N',
'SQLMONEY' => 'N',
'SQLDECIMAL' => 'N',
'SQLDATE' => 'D',
'SQLVCHAR' => 'C',
'SQLCHAR' => 'C',
'SQLDTIME' => 'T',
'SQLINTERVAL' => 'N',
'SQLBYTES' => 'B',
'SQLTEXT' => 'X',
## informix 10
"SQLINT8" => 'I8',
"SQLSERIAL8" => 'I8',
"SQLNCHAR" => 'C',
"SQLNVCHAR" => 'C',
"SQLLVARCHAR" => 'X',
"SQLBOOL" => 'L'
);
$tmap = false;
$t = strtoupper($t);
$tmap = (isset($typeMap[$t])) ? $typeMap[$t] : 'N';
if ($t == 'LONG' && $this->dataProvider == 'oci8') return 'B';
return $tmap;
}
}
}
?>
@@ -0,0 +1,128 @@
<?php
/**
* ADOdb Lite Transaction Module for Postgres
*
*/
eval('class postgres64_transaction_EXTENDER extends '. $last_module . '_ADOConnection { }');
class postgres64_transaction_ADOConnection extends postgres64_transaction_EXTENDER
{
var $autoCommit = true;
var $transOff = 0;
var $transCnt = 0;
var $transaction_status = true;
function StartTrans($errfn = 'ADODB_TransMonitor')
{
if ($this->transOff > 0) {
$this->transOff += 1;
return;
}
$this->transaction_status = true;
if ($this->debug && $this->transCnt > 0)
ADOConnection::outp("Bad Transaction: StartTrans called within BeginTrans");
$this->BeginTrans();
$this->transOff = 1;
}
function BeginTrans()
{
if ($this->transOff)
return true;
$this->transCnt += 1;
return @pg_Exec($this->connectionId, "begin");
}
function CompleteTrans($autoComplete = true)
{
if ($this->transOff > 1) {
$this->transOff -= 1;
return true;
}
$this->transOff = 0;
if ($this->transaction_status && $autoComplete) {
if (!$this->CommitTrans()) {
$this->transaction_status = false;
if ($this->debug)
ADOConnection::outp("Smart Commit failed");
} else
if ($this->debug)
ADOConnection::outp("Smart Commit occurred");
} else {
$this->RollbackTrans();
if ($this->debug)
ADOCOnnection::outp("Smart Rollback occurred");
}
return $this->transaction_status;
}
function CommitTrans($ok=true)
{
if ($this->transOff)
return true;
if (!$ok)
return $this->RollbackTrans();
$this->transCnt -= 1;
return @pg_Exec($this->connectionId, "commit");
}
function RollbackTrans()
{
if ($this->transOff)
return true;
$this->transCnt -= 1;
return @pg_Exec($this->connectionId, "rollback");
}
function FailTrans()
{
if ($this->debug)
if ($this->transOff == 0) {
ADOConnection::outp("FailTrans outside StartTrans/CompleteTrans");
} else {
ADOConnection::outp("FailTrans was called");
}
$this->transaction_status = false;
}
function HasFailedTrans()
{
if ($this->transOff > 0)
return $this->transaction_status == false;
return false;
}
function RowLock($tables,$where,$flds='1 as ignore')
{
if (!$this->transCnt)
$this->BeginTrans();
return $this->GetOne("select $flds from $tables where $where for update");
}
function CommitLock($table)
{
return $this->CommitTrans();
}
function RollbackLock($table)
{
return $this->RollbackTrans();
}
}
eval('class postgres64_transaction_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class postgres64_transaction_ResultSet extends postgres64_transaction_resultset_EXTENDER
{
}
?>
@@ -0,0 +1,211 @@
<?php
/**
V4.65 22 July 2005 (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Modified 28 August, 2005 for use with ADOdb Lite by Mark Dickenson
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class ADODB2_postgres7 extends ADODB_DataDict {
var $dbtype = 'postgres';
var $seqField = false;
var $seqPrefix = 'SEQ_';
var $addCol = ' ADD COLUMN';
var $quote = '"';
var $renameTable = 'ALTER TABLE %s RENAME TO %s'; // at least since 7.1
function ActualType($meta)
{
switch($meta) {
case 'C': return 'VARCHAR';
case 'XL':
case 'X': return 'TEXT';
case 'C2': return 'VARCHAR';
case 'X2': return 'TEXT';
case 'B': return 'BYTEA';
case 'D': return 'DATE';
case 'T': return 'TIMESTAMP';
case 'L': return 'BOOLEAN';
case 'I': return 'INTEGER';
case 'I1': return 'SMALLINT';
case 'I2': return 'INT2';
case 'I4': return 'INT4';
case 'I8': return 'INT8';
case 'F': return 'FLOAT8';
case 'N': return 'NUMERIC';
default:
return $meta;
}
}
function AddColumnSQL($tabname, $flds)
{
$tabname = $this->TableName ($tabname);
$sql = array();
list($lines,$pkey) = $this->_GenFields($flds);
$alter = 'ALTER TABLE ' . $tabname . $this->addCol . ' ';
foreach($lines as $v) {
if (($not_null = preg_match('/NOT NULL/i',$v))) {
$v = preg_replace('/NOT NULL/i','',$v);
}
if (preg_match('/^([^ ]+) .*(DEFAULT [^ ]+)/',$v,$matches)) {
list(,$colname,$default) = $matches;
$sql[] = $alter . str_replace($default,'',$v);
$sql[] = 'ALTER TABLE '.$tabname.' ALTER COLUMN '.$colname.' SET ' . $default;
} else {
$sql[] = $alter . $v;
}
if ($not_null) {
list($colname) = explode(' ',$v);
$sql[] = 'ALTER TABLE '.$tabname.' ALTER COLUMN '.$colname.' SET NOT NULL';
}
}
return $sql;
}
function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
{
if (!$tableflds) {
if ($this->debug) $this->outp("AlterColumnSQL needs a complete table-definiton for PostgreSQL");
return array();
}
return $this->_recreate_copy_table($tabname,False,$tableflds,$tableoptions);
}
function DropColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
{
$has_drop_column = 7.3 <= (float) @$this->serverInfo['version'];
if (!$has_drop_column && !$tableflds) {
if ($this->debug) $this->outp("DropColumnSQL needs complete table-definiton for PostgreSQL < 7.3");
return array();
}
if ($has_drop_column) {
return ADODB_DataDict::DropColumnSQL($tabname, $flds);
}
return $this->_recreate_copy_table($tabname,$flds,$tableflds,$tableoptions);
}
function DropTableSQL($tabname)
{
$sql = ADODB_DataDict::DropTableSQL($tabname);
$drop_seq = $this->_DropAutoIncrement($tabname);
if ($drop_seq) $sql[] = $drop_seq;
return $sql;
}
function _CreateSuffix($fname, &$ftype, $fnotnull,$fdefault,$fautoinc,$fconstraint)
{
if ($fautoinc) {
$ftype = 'SERIAL';
return '';
}
$suffix = '';
if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
if ($fnotnull) $suffix .= ' NOT NULL';
if ($fconstraint) $suffix .= ' '.$fconstraint;
return $suffix;
}
function _DropAutoIncrement($tabname)
{
$tabname = $this->connection->qstr('%'.$tabname.'%');
$seq = $this->connection->GetOne("SELECT relname FROM pg_class WHERE NOT relname ~ 'pg_.*' AND relname LIKE $tabname AND relkind='S'");
// check if a tables depends on the sequenz and it therefor cant and dont need to be droped separatly
if (!$seq || $this->connection->GetOne("SELECT relname FROM pg_class JOIN pg_depend ON pg_class.relfilenode=pg_depend.objid WHERE relname='$seq' AND relkind='S' AND deptype='i'")) {
return False;
}
return "DROP SEQUENCE ".$seq;
}
function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
{
$sql = array();
if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {
$sql[] = sprintf ($this->dropIndex, $idxname, $tabname);
if ( isset($idxoptions['DROP']) )
return $sql;
}
if ( empty ($flds) ) {
return $sql;
}
$unique = isset($idxoptions['UNIQUE']) ? ' UNIQUE' : '';
$s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname . ' ';
if (isset($idxoptions['HASH']))
$s .= 'USING HASH ';
if ( isset($idxoptions[$this->upperName]) )
$s .= $idxoptions[$this->upperName];
if ( is_array($flds) )
$flds = implode(', ',$flds);
$s .= '(' . $flds . ')';
$sql[] = $s;
return $sql;
}
function _recreate_copy_table($tabname,$dropflds,$tableflds,$tableoptions='')
{
if ($dropflds && !is_array($dropflds)) $dropflds = explode(',',$dropflds);
$copyflds = array();
foreach($this->MetaColumns($tabname) as $fld) {
if (!$dropflds || !in_array($fld->name,$dropflds)) {
// we need to explicit convert varchar to a number to be able to do an AlterColumn of a char column to a nummeric one
if (preg_match('/'.$fld->name.' (I|I2|I4|I8|N|F)/i',$tableflds,$matches) &&
in_array($fld->type,array('varchar','char','text','bytea'))) {
$copyflds[] = "to_number($fld->name,'S99D99')";
} else {
$copyflds[] = $fld->name;
}
// identify the sequence name and the fld its on
if ($fld->primary_key && $fld->has_default &&
preg_match("/nextval\('([^']+)'::text\)/",$fld->default_value,$matches)) {
$seq_name = $matches[1];
$seq_fld = $fld->name;
}
}
}
$copyflds = implode(', ',$copyflds);
$tempname = $tabname.'_tmp';
$aSql[] = 'BEGIN'; // we use a transaction, to make sure not to loose the content of the table
$aSql[] = "SELECT * INTO TEMPORARY TABLE $tempname FROM $tabname";
$aSql = array_merge($aSql,$this->DropTableSQL($tabname));
$aSql = array_merge($aSql,$this->CreateTableSQL($tabname,$tableflds,$tableoptions));
$aSql[] = "INSERT INTO $tabname SELECT $copyflds FROM $tempname";
if ($seq_name && $seq_fld) { // if we have a sequence we need to set it again
$seq_name = $tabname.'_'.$seq_fld.'_seq'; // has to be the name of the new implicit sequence
$aSql[] = "SELECT setval('$seq_name',MAX($seq_fld)) FROM $tabname";
}
$aSql[] = "DROP TABLE $tempname";
// recreate the indexes, if they not contain one of the droped columns
foreach($this->MetaIndexes($tabname) as $idx_name => $idx_data)
{
if (substr($idx_name,-5) != '_pkey' && (!$dropflds || !count(array_intersect($dropflds,$idx_data['columns'])))) {
$aSql = array_merge($aSql,$this->CreateIndexSQL($idx_name,$tabname,$idx_data['columns'],
$idx_data['unique'] ? array('UNIQUE') : False));
}
}
$aSql[] = 'COMMIT';
return $aSql;
}
}
?>
@@ -0,0 +1,316 @@
<?php
/**
* ADOdb Lite Date Module for Postgres 7
*
*/
if (!defined('TIMESTAMP_FIRST_YEAR')) define('TIMESTAMP_FIRST_YEAR',100);
@include(ADODB_DIR . '/adodb-time.inc.php');
eval('class postgres7_date_EXTENDER extends '. $last_module . '_ADOConnection { }');
class postgres7_date_ADOConnection extends postgres7_date_EXTENDER
{
var $fmtDate = "'Y-m-d'"; // used by DBDate() as the default date format used by the database
var $fmtTimeStamp = "'Y-m-d H:i:s'"; // used by DBTimeStamp as the default timestamp fmt.
var $emptyDate = '&nbsp;';
var $emptyTimeStamp = '&nbsp;';
var $sysDate = "CURRENT_DATE";
var $sysTimeStamp = "CURRENT_TIMESTAMP";
var $isoDates = true; /// accepts dates in ISO format
function Time()
{
$rs =& $this->_Execute("select $this->sysTimeStamp");
if ($rs && !$rs->EOF)
return $this->UnixTimeStamp(reset($rs->fields));
return false;
}
function OffsetDate($dayFraction, $date=false)
{
if (!$date)
$date = $this->sysDate;
else if (strncmp($date,"'",1) == 0) {
$len = strlen($date);
if (10 <= $len && $len <= 12)
$date = 'date ' . $date;
else $date = 'timestamp ' . $date;
}
return "($date+interval'$dayFraction days')";
}
function SetDateLocale($locale = 'En')
{
$this->locale = $locale;
switch (strtoupper($locale))
{
case 'EN':
$this->fmtDate="'Y-m-d'";
$this->fmtTimeStamp = "'Y-m-d H:i:s'";
break;
case 'US':
$this->fmtDate = "'m-d-Y'";
$this->fmtTimeStamp = "'m-d-Y H:i:s'";
break;
case 'NL':
case 'FR':
case 'RO':
case 'IT':
$this->fmtDate="'d-m-Y'";
$this->fmtTimeStamp = "'d-m-Y H:i:s'";
break;
case 'GE':
$this->fmtDate="'d.m.Y'";
$this->fmtTimeStamp = "'d.m.Y H:i:s'";
break;
default:
$this->fmtDate="'Y-m-d'";
$this->fmtTimeStamp = "'Y-m-d H:i:s'";
break;
}
}
function DBDate($date)
{
if (empty($date) && $date !== 0)
return 'null';
if (is_string($date) && !is_numeric($date)) {
if ($date === 'null' || strncmp($date, "'", 1) === 0)
return $date;
if ($this->isoDates)
return "'$date'";
$date = $this->UnixDate($date);
}
return adodb_date($this->fmtDate,$date);
}
function DBTimeStamp($timestamp)
{
if (empty($timestamp) && $timestamp !== 0)
return 'null';
# strlen(14) allows YYYYMMDDHHMMSS format
if (!is_string($timestamp) || (is_numeric($timestamp) && strlen($timestamp)<14))
return adodb_date($this->fmtTimeStamp, $timestamp);
if ($timestamp === 'null')
return $timestamp;
if ($this->isoDates && strlen($timestamp) !== 14)
return "'$timestamp'";
$timestamp = $this->UnixTimeStamp($timestamp);
return adodb_date($this->fmtTimeStamp, $timestamp);
}
function UnixDate($v)
{
if (is_object($v)) {
// odbtp support
//( [year] => 2004 [month] => 9 [day] => 4 [hour] => 12 [minute] => 44 [second] => 8 [fraction] => 0 )
return adodb_mktime($v->hour, $v->minute, $v->second, $v->month, $v->day, $v->year);
}
if (is_numeric($v) && strlen($v) !== 8)
return $v;
if (!preg_match( "|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})|", ($v), $rr))
return false;
if ($rr[1] <= TIMESTAMP_FIRST_YEAR)
return 0;
// h-m-s-MM-DD-YY
return adodb_mktime(0, 0, 0, $rr[2], $rr[3], $rr[1]);
}
function UnixTimeStamp($v)
{
if (is_object($v)) {
// odbtp support
//( [year] => 2004 [month] => 9 [day] => 4 [hour] => 12 [minute] => 44 [second] => 8 [fraction] => 0 )
return adodb_mktime($v->hour, $v->minute, $v->second, $v->month, $v->day, $v->year);
}
if (!preg_match("|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})[ ,-]*(([0-9]{1,2}):?([0-9]{1,2}):?([0-9\.]{1,4}))?|", ($v), $rr))
return false;
if ($rr[1] <= TIMESTAMP_FIRST_YEAR && $rr[2]<= 1)
return 0;
// h-m-s-MM-DD-YY
if (!isset($rr[5]))
return adodb_mktime(0, 0, 0, $rr[2], $rr[3], $rr[1]);
else return adodb_mktime($rr[5], $rr[6], $rr[7], $rr[2], $rr[3], $rr[1]);
}
function UserDate($v, $fmt='Y-m-d', $gmt=false)
{
$tt = $this->UnixDate($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
else if ($tt == 0)
return $this->emptyDate;
else if ($tt == -1) { // pre-TIMESTAMP_FIRST_YEAR
}
return ($gmt) ? adodb_gmdate($fmt, $tt) : adodb_date($fmt, $tt);
}
function UserTimeStamp($v, $fmt='Y-m-d H:i:s', $gmt=false)
{
if (!isset($v))
return $this->emptyTimeStamp;
# strlen(14) allows YYYYMMDDHHMMSS format
if (is_numeric($v) && strlen($v)<14)
return ($gmt) ? adodb_gmdate($fmt,$v) : adodb_date($fmt,$v);
$tt = $this->UnixTimeStamp($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
if ($tt == 0)
return $this->emptyTimeStamp;
else return ($gmt) ? adodb_gmdate($fmt,$tt) : adodb_date($fmt,$tt);
}
function SQLDate($fmt, $col=false)
{
if (!$col)
$col = $this->sysTimeStamp;
$s = 'TO_CHAR('.$col.",'";
$len = strlen($fmt);
for ($i=0; $i < $len; $i++) {
$ch = $fmt[$i];
switch($ch) {
case 'Y':
case 'y':
$s .= 'YYYY';
break;
case 'Q':
case 'q':
$s .= 'Q';
break;
case 'M':
$s .= 'Mon';
break;
case 'm':
$s .= 'MM';
break;
case 'D':
case 'd':
$s .= 'DD';
break;
case 'H':
$s.= 'HH24';
break;
case 'h':
$s .= 'HH';
break;
case 'i':
$s .= 'MI';
break;
case 's':
$s .= 'SS';
break;
case 'a':
case 'A':
$s .= 'AM';
break;
case 'w':
$s .= 'D';
break;
case 'l':
$s .= 'DAY';
break;
default:
// handle escape characters...
if ($ch == '\\') {
$i++;
$ch = substr($fmt,$i,1);
}
if (strpos('-/.:;, ',$ch) !== false)
$s .= $ch;
else $s .= '"'.$ch.'"';
}
}
return $s. "')";
}
}
eval('class postgres7_date_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class postgres7_date_ResultSet extends postgres7_date_resultset_EXTENDER
{
var $emptyTimeStamp = '&nbsp;'; /// what to display when $time==0
var $emptyDate = '&nbsp;'; /// what to display when $time==0
var $datetime = false;
function UserTimeStamp($v, $fmt='Y-m-d H:i:s')
{
if (is_numeric($v) && strlen($v)<14)
return adodb_date($fmt,$v);
$tt = $this->UnixTimeStamp($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
if ($tt === 0)
return $this->emptyTimeStamp;
else return adodb_date($fmt,$tt);
}
function UserDate($v,$fmt='Y-m-d')
{
$tt = $this->UnixDate($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
else if ($tt == 0)
return $this->emptyDate;
else if ($tt == -1) { // pre-TIMESTAMP_FIRST_YEAR
}
return adodb_date($fmt,$tt);
}
function UnixDate($v)
{
return postgres7_date_ADOConnection::UnixDate($v);
}
function UnixTimeStamp($v)
{
return postgres7_date_ADOConnection::UnixTimeStamp($v);
}
}
?>
@@ -0,0 +1,680 @@
<?php
/**
* ADOdb Lite is a PHP class to encapsulate multiple database APIs and is compatible with
* a subset of the ADODB Command Syntax.
* Currently supports Frontbase, MaxDB, miniSQL, MSSQL, MSSQL Pro, MySQLi, MySQLt, MySQL, PostgresSQL,
* PostgresSQL64, PostgresSQL7, SqLite and Sybase.
*
*/
class postgres7_driver_ADOConnection extends ADOConnection
{
var $connect_string;
var $sysDate = "CURRENT_DATE";
var $sysTimeStamp = "CURRENT_TIMESTAMP";
var $pg_escape_enable = false;
function postgres7_driver_ADOConnection()
{
$this->dbtype = 'postgres7';
$this->dataProvider = 'postgres';
}
/**
* Connection to database server and selected database
*
* @access private
*/
function _connect($host = "", $username = "", $password = "", $database = "", $persistent, $forcenew)
{
if (!function_exists('pg_connect')) return false;
$this->host = $host;
$this->username = $this->query_addslashes($username);
$this->password = $this->query_addslashes($password);
if (strlen($database) == 0) $database = 'template1';
$this->database = $this->query_addslashes($database);
if ($this->username || $this->password || $this->database) {
$this->connect_string = $this->host;
if ($this->connect_string) {
$host = split(":", $this->connect_string);
if ($host[0]) $this->connect_string = "host=" . $this->query_addslashes($host[0]);
else $this->connect_string = 'host=localhost';
if (isset($host[1])) $this->connect_string .= " port=$host[1]";
else if (!empty($this->port)) $this->connect_string .= " port=" . $this->port;
}
if ($this->username) $this->connect_string .= " user=" . $this->username;
if ($this->password) $this->connect_string .= " password=" . $this->password;
if ($this->database) $this->connect_string .= " dbname=" . $this->database;
}
else
{
$this->connect_string = $this->host;
}
$this->persistent = $persistent;
$this->forcenewconnection = $forcenew;
$this->_makeconnection();
if ($this->connectionId === false)
{
if ($fn = $this->raiseErrorFn)
$fn($this->dbtype, 'CONNECT', $this->ErrorNo(), $this->ErrorMsg(), $this->host, $this->database, $this);
return $this->SelectDB( $this->database );
}
return true;
}
function _makeconnection()
{
if($this->persistent == 1)
{
$this->connectionId = @pg_pconnect( $this->connect_string );
}
else
{
if(!$this->forcenewconnection)
{
$this->connectionId = @pg_connect( $this->connect_string );
}
else
{
$this->connectionId = @pg_connect( $this->connect_string, PGSQL_CONNECT_FORCE_NEW );
}
}
}
function query_addslashes($query)
{
$len = strlen($query);
if ($len == 0)
return "''";
if (strncmp($query,"'",1) === 0 && substr($query,$len-1) == "'")
return $s;
return "'".addslashes($query)."'";
}
/**
* Choose a database to connect.
*
* @param dbname is the name of the database to select
* @return true or false
* @access public
*/
function SelectDB($dbname)
{
$this->database = $dbname;
if ($this->connectionId === false)
{
if($this->createdatabase == true)
{
$this->connectionId = @pg_pconnect( "host=$this->host user=$this->username password=$this->password" );
$result = @pg_query($this->connectionId, "CREATE DATABASE " . $this->database );
if ($result === false) { // error handling if query fails
$this->connectionId = false;
return false;
}
$this->_makeconnection();
if($this->connectionId === false)
{
$this->connectionId = false;
return false;
}
else
{
return true;
}
}
$this->connectionId = false;
return false;
}
else
{
return true;
}
}
/**
* Return database error message
* Usage: $errormessage =& $db->ErrorMsg();
*
* @access public
*/
function ErrorMsg()
{
return @pg_last_error($this->connectionId);
}
/**
* Return database error number
* Usage: $errorbo =& $db->ErrorNo();
*
* @access public
*/
function ErrorNo()
{
$error = @pg_last_error( $this->connectionId );
return strlen($error) ? $error : 0;
}
/**
* Returns # of affected rows from insert/delete/update query
*
* @access public
* @return integer Affected rows
*/
function Affected_Rows()
{
return @pg_affected_rows( $this->record_set );
}
/**
* Returns the last record id of an inserted item
* Usage: $db->Insert_ID();
*
* @access public
*/
function Insert_ID()
{
return @pg_getlastoid($this->record_set);
}
/**
* Correctly quotes a string so that all strings are escape coded.
* An example is $db->qstr("Haven't a clue.");
*
* @param string the string to quote
* @param [magic_quotes] if $s is GET/POST var, set to get_magic_quotes_gpc().
*
* @return single-quoted string IE: 'Haven\'t a clue.'
*/
function qstr($string, $magic_quotes=false)
{
// Ugly hack alert! Repalce backticks with some arbitrary character
$string = str_replace('`', "\x1C", $string);
if (!$magic_quotes) {
if (strnatcmp(PHP_VERSION, '4.2.0') >= 0 && $this->pg_escape_enable) {
return "'" . pg_escape_string($string) . "'";
}
$string = str_replace("'", "\\'", str_replace('\\', '\\\\', str_replace("\0", "\\\0", $string)));
return "'" . $string . "'";
}
return "'" . str_replace('\\"', '"', $string) . "'";
}
function QMagic($string)
{
return $this->qstr($string, get_magic_quotes_gpc());
}
/**
* Returns concatenated string
* Usage: $db->Concat($str1,$str2);
*
* @return concatenated string
*/
function Concat()
{
$arr = func_get_args();
return implode("||", $arr);
}
function IfNull( $field, $ifNull )
{
return " coalesce($field, $ifNull) ";
}
/**
* Closes database connection
* Usage: $db->close();
*
* @access public
*/
function Close()
{
@pg_close( $this->connectionId );
$this->connectionId = false;
}
/**
* Returns All Records in an array
*
* Usage: $db->GetAll($sql);
* @access public
*/
function &GetAll($sql, $inputarr = false)
{
$data =& $this->GetArray($sql, $inputarr);
return $data;
}
/**
* Returns All Records in an array
*
* Usage: $db->GetArray($sql);
* @access public
*/
function &GetArray($sql, $inputarr = false)
{
$data = false;
$result =& $this->Execute($sql, $inputarr);
if ($result)
{
$data =& $result->GetArray();
$result->Close();
}
return $data;
}
/**
* Executes SQL query and instantiates resultset methods
*
* @access private
* @return mixed Resultset methods
*/
function &do_query( $sql, $offset, $nrows, $inputarr=false )
{
global $ADODB_FETCH_MODE;
$sql = str_replace('`', '"', $sql);
$sql = str_replace("\x1C", "`", $sql);
$sql = str_replace('IS_DELETED', 'is_deleted', $sql);
$sql = str_replace("HIGH_PRIORITY", "", $sql);
$false = false;
$offsetStr = '';
$limitStr = '';
if ($offset != -1 || $nrows != -1)
{
$offsetStr = ($offset >= 0) ? " OFFSET " . ((integer)$offset) : '';
$limitStr = ($nrows >= 0) ? " LIMIT " . ((integer)$nrows) : '';
}
if ($inputarr && is_array($inputarr)) {
$sqlarr = explode('?', $sql);
if (!is_array(reset($inputarr))) $inputarr = array($inputarr);
foreach($inputarr as $arr) {
$sql = ''; $i = 0;
foreach($arr as $v) {
$sql .= $sqlarr[$i];
switch(gettype($v)){
case 'string':
$sql .= $this->qstr($v);
break;
case 'double':
$sql .= str_replace(',', '.', $v);
break;
case 'boolean':
$sql .= $v ? "'t'" : "'f'";
break;
default:
if ($v === null)
$sql .= 'NULL';
else $sql .= $v;
}
$i += 1;
}
$sql .= $sqlarr[$i];
if ($i+1 != sizeof($sqlarr))
return $false;
$this->sql = $sql . "$limitStr$offsetStr";
$time_start = array_sum(explode(' ', microtime()));
$this->query_count++;
$resultId = @pg_query( $this->sql);
$time_total = (array_sum(explode(' ', microtime())) - $time_start);
$this->query_time_total += $time_total;
if($this->debug_console)
{
$this->query_list[] = $this->sql;
$this->query_list_time[] = $time_total;
$this->query_list_errors[] = $this->ErrorMsg();
}
if($this->debug)
{
$this->outp($sql . "$limitStr$offsetStr");
}
if ($resultId === false) { // error handling if query fails
if ($fn = $this->raiseErrorFn)
$fn($this->dbtype, 'EXECUTE', $this->ErrorNo(), $this->ErrorMsg(), $this->sql, $inputarr, $this);
return $false;
}
}
}
else
{
$this->sql = $sql . "$limitStr$offsetStr";
$time_start = array_sum(explode(' ', microtime()));
$this->query_count++;
$resultId = @pg_query( $this->sql);
$time_total = (array_sum(explode(' ', microtime())) - $time_start);
$this->query_time_total += $time_total;
if($this->debug_console)
{
$this->query_list[] = $this->sql;
$this->query_list_time[] = $time_total;
$this->query_list_errors[] = $this->ErrorMsg();
}
if($this->debug)
{
$this->outp($sql . "$limitStr$offsetStr");
}
}
if ($resultId === false) { // error handling if query fails
if ($fn = $this->raiseErrorFn)
$fn($this->dbtype, 'EXECUTE', $this->ErrorNo(), $this->ErrorMsg(), $this->sql, $inputarr, $this);
return $false;
}
if (@pg_numfields( $resultId ) <= 0) { // return simplified recordset for inserts/updates/deletes with lower overhead
$recordset = new ADORecordSet_empty();
$this->record_set = $recordset;
return $recordset;
}
$resultset_name = $this->last_module_name . "_ResultSet";
$recordset = new $resultset_name( $resultId, $this->connectionId );
$this->record_set = $recordset;
$recordset->_currentRow = 0;
switch ($ADODB_FETCH_MODE)
{
case ADODB_FETCH_NUM: $recordset->fetchMode = PGSQL_NUM; break;
case ADODB_FETCH_ASSOC:$recordset->fetchMode = PGSQL_ASSOC; break;
default:
case ADODB_FETCH_DEFAULT:
case ADODB_FETCH_BOTH:$recordset->fetchMode = PGSQL_BOTH; break;
}
$recordset->_numOfRows = @pg_numrows( $resultId );
if( $recordset->_numOfRows == 0)
{
$recordset->EOF = true;
}
$recordset->_numOfFields = @pg_numfields( $resultId );
$recordset->_fetch();
return $recordset;
}
}
class postgres7_driver_ResultSet
{
var $connectionId;
var $fields;
var $resultId;
var $_currentRow = 0;
var $_numOfRows = -1;
var $_numOfFields = -1;
var $fetchMode;
var $EOF;
/**
* pgsqlResultSet Constructor
*
* @access private
* @param string $record
* @param string $resultId
*/
function postgres7_driver_ResultSet( $resultId, $connectionId )
{
$this->fields = array();
$this->connectionId = $connectionId;
$this->record = array();
$this->resultId = $resultId;
$this->EOF = false;
}
/**
* Frees resultset
*
* @access public
*/
function Close()
{
pg_free_result( $this->resultId );
$this->fields = array();
$this->resultId = false;
}
/**
* Returns field name from select query
*
* @access public
* @param string $field
* @return string Field name
*/
function fields( $field )
{
if(empty($field))
{
return $this->fields;
}
else
{
return $this->fields[$field];
}
}
/**
* Returns numrows from select query
*
* @access public
* @return integer Numrows
*/
function RecordCount()
{
return $this->_numOfRows;
}
/**
* PEAR DB Compatable Command
*/
function NumRows()
{
return $this->_numOfRows;
}
/**
* Returns num of fields from select query
*
* @access public
* @return integer numfields
*/
function FieldCount()
{
return $this->_numOfFields;
}
/**
* PEAR DB Compatable Command
*/
function NumCols()
{
return $this->_numOfFields;
}
/**
* Returns next record
*
* @access public
*/
function MoveNext()
{
if (@$this->fields = pg_fetch_array($this->resultId, NULL, $this->fetchMode)) {
$this->_currentRow += 1;
return true;
}
if (!$this->EOF) {
$this->_currentRow += 1;
$this->EOF = true;
}
return false;
}
/**
* Move to the first row in the recordset. Many databases do NOT support this.
*
* @return true or false
*/
function MoveFirst()
{
if ($this->_currentRow == 0) return true;
return $this->Move(0);
}
/**
* Returns the Last Record
*
* @access public
*/
function MoveLast()
{
if ($this->EOF) return false;
return $this->Move($this->_numOfRows - 1);
}
/**
* Random access to a specific row in the recordset. Some databases do not support
* access to previous rows in the databases (no scrolling backwards).
*
* @param rowNumber is the row to move to (0-based)
*
* @return true if there still rows available, or false if there are no more rows (EOF).
*/
function Move($rowNumber = 0)
{
if ($rowNumber == $this->_currentRow) return true;
$this->EOF = false;
if ($this->_numOfRows > 0){
if ($rowNumber >= $this->_numOfRows - 1){
$rowNumber = $this->_numOfRows - 1;
}
}
if ($this->_seek($rowNumber)) {
$this->_currentRow = $rowNumber;
if ($this->_fetch()) {
return true;
}
$this->fields = false;
}
$this->EOF = true;
return false;
}
/**
* Perform Seek to specific row
*
* @access private
*/
function _seek($row)
{
if ($this->_numOfRows == 0) return false;
return @pg_result_seek($this->resultId,$row);
}
/**
* Fills field array with first database element when query initially executed
*
* @access private
*/
function _fetch()
{
$this->fields = @pg_fetch_array($this->resultId, NULL, $this->fetchMode);
return is_array($this->fields);
}
/**
* Check to see if last record reached
*
* @access public
*/
function EOF()
{
if( $this->_currentRow < $this->_numOfRows)
{
return false;
}
else
{
$this->EOF = true;
return true;
}
}
/**
* Returns All Records in an array
*
* @access public
* @param [nRows] is the number of rows to return. -1 means every row.
*/
function &GetArray($nRows = -1)
{
$results = array();
$cnt = 0;
while (!$this->EOF && $nRows != $cnt) {
$results[] = $this->fields;
$this->MoveNext();
$cnt++;
}
return $results;
}
function &GetRows($nRows = -1)
{
$arr =& $this->GetArray($nRows);
return $arr;
}
function &GetAll($nRows = -1)
{
$arr =& $this->GetArray($nRows);
return $arr;
}
/**
* Fetch field information for a table.
*
* @return object containing the name, type and max_length
*/
function FetchField($fieldOffset = -1)
{
$fieldObject= new ADOFieldObject();
$fieldObject->name = @pg_fieldname($this->resultId, $fieldOffset);
$fieldObject->type = @pg_fieldtype($this->resultId, $fieldOffset);
$fieldObject->max_length = @pg_fieldsize($this->resultId, $fieldOffset);
return $fieldObject;
}
}
?>
@@ -0,0 +1,147 @@
<?php
/**
* ADOdb Lite Extend Module for Mysqlt
*
*/
eval('class postgres7_extend_EXTENDER extends '. $last_module . '_ADOConnection { }');
class postgres7_extend_ADOConnection extends postgres7_extend_EXTENDER
{
function &GetAssoc($sql, $inputarr=false, $force_array = false, $first2cols = false)
{
$data = false;
$result =& $this->Execute($sql, $inputarr);
if ($result) {
$data =& $result->GetAssoc($force_array, $first2cols);
$result->Close();
}
return $data;
}
/**
* Generates a sequence id and stores it in $this->genID;
* GenID is only available if $this->hasGenID = true;
*
* @param seqname name of sequence to use
* @param startID if sequence does not exist, start at this ID
* @return 0 if not supported, otherwise a sequence id
*/
var $_genIDSQL = "SELECT NEXTVAL('%s')";
var $_genSeqSQL = "CREATE SEQUENCE %s START %s";
var $_dropSeqSQL = "DROP SEQUENCE %s";
var $genID = 0;
function GenID($seqname='adodbseq', $startID=1)
{
$getnext = sprintf($this->_genIDSQL, $seqname);
$holdtransOK = $this->transaction_status;
$save_handler = $this->raiseErrorFn;
$this->raiseErrorFn = '';
@($result = $this->Execute($getnext));
$this->raiseErrorFn = $save_handler;
if (!$result) {
$this->transaction_status = $holdtransOK;
$createseq = $this->Execute(sprintf($this->_genSeqSQL, $seqname, $startID));
$result = $this->Execute($getnext);
}
if ($result && !$result->EOF)
$this->genID = reset($result->fields);
else $this->genID = 0;
if ($result)
$result->Close();
return $this->genID;
}
function CreateSequence($seqname='adodbseq', $startID=1)
{
return $this->Execute(sprintf($this->_genSeqSQL, $seqname, $startID));
}
function DropSequence($seqname='adodbseq')
{
return $this->Execute(sprintf($this->_dropSeqSQL, $seqname));
}
}
eval('class postgres7_extend_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class postgres7_extend_ResultSet extends postgres7_extend_resultset_EXTENDER
{
function &GetAssoc($force_array = false, $first2cols = false)
{
$results = false;
if ($this->_numOfFields > 1) {
$numIndex = isset($this->fields[0]);
$results = array();
if (!$first2cols && ($this->_numOfFields > 2 || $force_array)) {
if ($numIndex) {
while (!$this->EOF) {
$results[trim($this->fields[0])] = array_slice($this->fields, 1);
$this->MoveNext();
}
} else {
while (!$this->EOF) {
$results[trim(reset($this->fields))] = array_slice($this->fields, 1);
$this->MoveNext();
}
}
} else {
if ($numIndex) {
while (!$this->EOF) {
$results[trim(($this->fields[0]))] = $this->fields[1];
$this->MoveNext();
}
} else {
while (!$this->EOF) {
$v1 = trim(reset($this->fields));
$v2 = ''.next($this->fields);
$results[$v1] = $v2;
$this->MoveNext();
}
}
}
}
return $results;
}
function PO_RecordCount($table="", $condition="")
{
$lnumrows = $this->_numOfRows;
if($lnumrows == -1 && $this->connectionId)
{
if($table)
{
if ($condition)
$condition = " WHERE " . $condition;
$resultrows = &$this->connectionId->Execute("SELECT COUNT(*) FROM $table $condition");
if ($resultrows)
$lnumrows = reset($resultrows->fields);
}
}
return $lnumrows;
}
function CurrentRow()
{
return $this->_currentRow;
}
function AbsolutePosition()
{
return $this->_currentRow;
}
function NextRecordSet()
{
return false;
}
}
?>
@@ -0,0 +1,712 @@
<?php
/**
* ADOdb Lite Meta Module for Postgres7
*
* Portions of the Meta Coding came from ADOdb
*/
/*
(c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. See License.txt.
*/
eval('class postgres7_meta_EXTENDER extends '. $last_module . '_ADOConnection { }');
class postgres7_meta_ADOConnection extends postgres7_meta_EXTENDER
{
var $metaDatabasesSQL = "select datname from pg_database where datname not in ('template0','template1') order by 1";
var $metaTablesSQL = "select tablename,'T' from pg_tables where tablename not like 'pg\_%'
and tablename not in ('sql_features', 'sql_implementation_info', 'sql_languages',
'sql_packages', 'sql_sizing', 'sql_sizing_profiles')
union
select viewname,'V' from pg_views where viewname not like 'pg\_%'";
var $metaColumnsSQL = "SELECT a.attname,t.typname,a.attlen,a.atttypmod,a.attnotnull,a.atthasdef,a.attnum
FROM pg_class c, pg_attribute a,pg_type t
WHERE relkind in ('r','v') AND (c.relname='%s' or c.relname = lower('%s')) and a.attname not like '....%%'
AND a.attnum > 0 AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum";
// used when schema defined
var $metaColumnsSQL1 = "SELECT a.attname, t.typname, a.attlen, a.atttypmod, a.attnotnull, a.atthasdef, a.attnum
FROM pg_class c, pg_attribute a, pg_type t, pg_namespace n
WHERE relkind in ('r','v') AND (c.relname='%s' or c.relname = lower('%s'))
and c.relnamespace=n.oid and n.nspname='%s'
and a.attname not like '....%%' AND a.attnum > 0
AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum";
// get primary key etc -- from Freek Dijkstra
var $metaKeySQL = "SELECT ic.relname AS index_name, a.attname AS column_name,i.indisunique AS unique_key, i.indisprimary AS primary_key
FROM pg_class bc, pg_class ic, pg_index i, pg_attribute a WHERE bc.oid = i.indrelid AND ic.oid = i.indexrelid AND (i.indkey[0] = a.attnum OR i.indkey[1] = a.attnum OR i.indkey[2] = a.attnum OR i.indkey[3] = a.attnum OR i.indkey[4] = a.attnum OR i.indkey[5] = a.attnum OR i.indkey[6] = a.attnum OR i.indkey[7] = a.attnum) AND a.attrelid = bc.oid AND bc.relname = '%s'";
var $metaDefaultsSQL = "SELECT d.adnum as num, d.adsrc as def from pg_attrdef d, pg_class c where d.adrelid=c.oid and c.relname='%s' order by d.adnum";
function MetaError($err=false)
{
include_once(ADODB_DIR."/adodb-error.inc.php");
if ($err === false)
$err = $this->ErrorNo();
return adodb_error($this->dataProvider,$this->databaseType,$err);
}
function MetaErrorMsg($errno)
{
include_once(ADODB_DIR."/adodb-error.inc.php");
return adodb_errormsg($errno);
}
/**
* @returns an array with the primary key columns in it.
*/
function MetaPrimaryKeys($table, $owner=false)
{
// owner not used in base class - see oci8
$p = array();
$objs =& $this->MetaColumns($table);
if ($objs) {
foreach($objs as $v) {
if (!empty($v->primary_key))
$p[] = $v->name;
}
}
if (sizeof($p)) return $p;
if (function_exists('ADODB_VIEW_PRIMARYKEYS'))
return ADODB_VIEW_PRIMARYKEYS($this->databaseType, $this->database, $table, $owner);
return false;
}
/**
* @returns assoc array where keys are tables, and values are foreign keys
*/
function MetaForeignKeys($table, $owner=false, $upper=false)
{
$sql = 'SELECT t.tgargs as args
FROM
pg_trigger t,pg_class c,pg_proc p
WHERE
t.tgenabled AND
t.tgrelid = c.oid AND
t.tgfoid = p.oid AND
p.proname = \'RI_FKey_check_ins\' AND
c.relname = \''.strtolower($table).'\'
ORDER BY
t.tgrelid';
$rs =& $this->Execute($sql);
if (!$rs || $rs->EOF) return false;
$arr =& $rs->GetArray();
$a = array();
foreach($arr as $v) {
$data = explode(chr(0), $v['args']);
$size = count($data)-1; //-1 because the last node is empty
for($i = 4; $i < $size; $i++) {
if ($upper)
$a[strtoupper($data[2])][] = strtoupper($data[$i].'='.$data[++$i]);
else
$a[$data[2]][] = $data[$i].'='.$data[++$i];
}
}
return $a;
}
// not the fastest implementation - quick and dirty - jlim
// for best performance, use the actual $rs->MetaType().
function MetaType($t,$len=-1,$fieldobj=false)
{
if (empty($this->_metars)) {
$rsclass = $this->last_module_name . "_ResultSet";
$this->_metars =& new $rsclass(false,$this->fetchMode);
}
return $this->_metars->MetaType($t,$len,$fieldobj);
}
/**
* return the databases that the driver can connect to.
* Some databases will return an empty array.
*
* @return an array of database names.
*/
function MetaDatabases()
{
global $ADODB_FETCH_MODE;
if ($this->metaDatabasesSQL) {
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
$arr = $this->GetCol($this->metaDatabasesSQL);
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
return $arr;
}
return false;
}
/**
* @param ttype can either be 'VIEW' or 'TABLE' or false.
* If false, both views and tables are returned.
* "VIEW" returns only views
* "TABLE" returns only tables
* @param showSchema returns the schema/user with the table name, eg. USER.TABLE
* @param mask is the input mask - only supported by oci8 and postgresql
*
* @return array of tables for current database.
*/
function &MetaTables($ttype=false,$showSchema=false,$mask=false)
{
$info = $this->ServerInfo();
if ($info['version'] >= 7.3) {
$this->metaTablesSQL = "select tablename,'T' from pg_tables where tablename not like 'pg\_%'
and schemaname not in ( 'pg_catalog','information_schema')
union
select viewname,'V' from pg_views where viewname not like 'pg\_%' and schemaname not in ( 'pg_catalog','information_schema') ";
}
if ($mask) {
$save = $this->metaTablesSQL;
$mask = $this->qstr(strtolower($mask));
if ($info['version']>=7.3)
$this->metaTablesSQL = "
select tablename,'T' from pg_tables where tablename like $mask and schemaname not in ( 'pg_catalog','information_schema')
union
select viewname,'V' from pg_views where viewname like $mask and schemaname not in ( 'pg_catalog','information_schema') ";
else
$this->metaTablesSQL = "
select tablename,'T' from pg_tables where tablename like $mask
union
select viewname,'V' from pg_views where viewname like $mask";
}
$ret =& $this->_MetaTables($ttype,$showSchema);
if ($mask) {
$this->metaTablesSQL = $save;
}
return $ret;
}
function &_MetaTables($ttype=false,$showSchema=false,$mask=false)
{
global $ADODB_FETCH_MODE;
$false = false;
if ($mask) {
return $false;
}
if ($this->metaTablesSQL) {
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
$rs = $this->Execute($this->metaTablesSQL);
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
if ($rs === false) return $false;
$arr =& $rs->GetArray();
$arr2 = array();
if ($hast = ($ttype && isset($arr[0][1]))) {
$showt = strncmp($ttype,'T',1);
}
for ($i=0; $i < sizeof($arr); $i++) {
if ($hast) {
if ($showt == 0) {
if (strncmp($arr[$i][1],'T',1) == 0) $arr2[] = trim($arr[$i][0]);
} else {
if (strncmp($arr[$i][1],'V',1) == 0) $arr2[] = trim($arr[$i][0]);
}
} else
$arr2[] = trim($arr[$i][0]);
}
$rs->Close();
return $arr2;
}
return $false;
}
function _findschema(&$table,&$schema)
{
if (!$schema && ($at = strpos($table,'.')) !== false) {
$schema = substr($table,0,$at);
$table = substr($table,$at+1);
}
}
/**
* List columns in a database as an array of ADOFieldObjects.
* See top of file for definition of object.
*
* @param $table table name to query
* @param $normalize makes table name case-insensitive (required by some databases)
* @schema is optional database schema to use - not supported by all databases.
*
* @return array of ADOFieldObjects for current table.
*/
function &MetaColumns($table,$normalize=true)
{
global $ADODB_FETCH_MODE;
$schema = false;
$false = false;
$this->_findschema($table,$schema);
if ($normalize) $table = strtolower($table);
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
if ($schema) $rs =& $this->Execute(sprintf($this->metaColumnsSQL1,$table,$table,$schema));
else $rs =& $this->Execute(sprintf($this->metaColumnsSQL,$table,$table));
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
if ($rs === false) {
return $false;
}
if (!empty($this->metaKeySQL)) {
// If we want the primary keys, we have to issue a separate query
// Of course, a modified version of the metaColumnsSQL query using a
// LEFT JOIN would have been much more elegant, but postgres does
// not support OUTER JOINS. So here is the clumsy way.
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
$rskey = $this->Execute(sprintf($this->metaKeySQL,($table)));
// fetch all result in once for performance.
$keys =& $rskey->GetArray();
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
$rskey->Close();
unset($rskey);
}
$rsdefa = array();
if (!empty($this->metaDefaultsSQL)) {
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
$sql = sprintf($this->metaDefaultsSQL, ($table));
$rsdef = $this->Execute($sql);
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
if ($rsdef) {
while (!$rsdef->EOF) {
$num = $rsdef->fields['num'];
$s = $rsdef->fields['def'];
if (strpos($s,'::')===false && substr($s, 0, 1) == "'") { /* quoted strings hack... for now... fixme */
$s = substr($s, 1);
$s = substr($s, 0, strlen($s) - 1);
}
$rsdefa[$num] = $s;
$rsdef->MoveNext();
}
} else {
ADOConnection::outp( "==> SQL => " . $sql);
}
unset($rsdef);
}
$retarr = array();
while (!$rs->EOF) {
$fld = new ADOFieldObject();
$fld->name = $rs->fields[0];
$fld->type = $rs->fields[1];
$fld->max_length = $rs->fields[2];
$fld->attnum = $rs->fields[6];
if ($fld->max_length <= 0) $fld->max_length = $rs->fields[3]-4;
if ($fld->max_length <= 0) $fld->max_length = -1;
if ($fld->type == 'numeric') {
$fld->scale = $fld->max_length & 0xFFFF;
$fld->max_length >>= 16;
}
// dannym
// 5 hasdefault; 6 num-of-column
$fld->has_default = ($rs->fields[5] == 't');
if ($fld->has_default) {
$fld->default_value = $rsdefa[$rs->fields[6]];
}
//Freek
$fld->not_null = $rs->fields[4] == 't';
// Freek
if (is_array($keys)) {
foreach($keys as $key) {
if ($fld->name == $key['column_name'] AND $key['primary_key'] == 't')
$fld->primary_key = true;
if ($fld->name == $key['column_name'] AND $key['unique_key'] == 't')
$fld->unique = true; // What name is more compatible?
}
}
if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;
else $retarr[($normalize) ? strtoupper($fld->name) : $fld->name] = $fld;
$rs->MoveNext();
}
$rs->Close();
if (empty($retarr))
return $false;
else
return $retarr;
}
/**
* List indexes on a table as an array.
* @param table table name to query
* @param primary true to only show primary keys. Not actually used for most databases
*
* @return array of indexes on current table. Each element represents an index, and is itself an associative array.
Array (
[name_of_index] => Array
(
[unique] => true or false
[columns] => Array
(
[0] => firstname
[1] => lastname
)
)
*/
function &MetaIndexes ($table, $primary = FALSE)
{
global $ADODB_FETCH_MODE;
$schema = false;
$this->_findschema($table,$schema);
if ($schema) { // requires pgsql 7.3+ - pg_namespace used.
$sql = '
SELECT c.relname as "Name", i.indisunique as "Unique", i.indkey as "Columns"
FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_index i ON i.indexrelid=c.oid
JOIN pg_catalog.pg_class c2 ON c2.oid=i.indrelid
,pg_namespace n
WHERE (c2.relname=\'%s\' or c2.relname=lower(\'%s\')) and c.relnamespace=c2.relnamespace and c.relnamespace=n.oid and n.nspname=\'%s\'';
} else {
$sql = '
SELECT c.relname as "Name", i.indisunique as "Unique", i.indkey as "Columns"
FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_index i ON i.indexrelid=c.oid
JOIN pg_catalog.pg_class c2 ON c2.oid=i.indrelid
WHERE (c2.relname=\'%s\' or c2.relname=lower(\'%s\'))';
}
if ($primary == FALSE) {
$sql .= ' AND i.indisprimary=false;';
}
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== FALSE) {
$savem = $this->SetFetchMode(FALSE);
}
$rs = $this->Execute(sprintf($sql,$table,$table,$schema));
if (isset($savem)) {
$this->SetFetchMode($savem);
}
$ADODB_FETCH_MODE = $save;
if (!is_object($rs)) {
$false = false;
return $false;
}
$col_names = $this->MetaColumnNames($table,true,true);
//3rd param is use attnum,
// see http://sourceforge.net/tracker/index.php?func=detail&aid=1451245&group_id=42718&atid=433976
$indexes = array();
while ($row = $rs->FetchRow()) {
$columns = array();
foreach (explode(' ', $row[2]) as $col) {
$columns[] = $col_names[$col];
}
$indexes[$row[0]] = array(
'unique' => ($row[1] == 't'),
'columns' => $columns
);
}
return $indexes;
}
/**
* List columns names in a table as an array.
* @param table table name to query
*
* @return array of column names for current table.
*/
function &MetaColumnNames($table, $numIndexes=false,$useattnum=false /* only for postgres */)
{
$objarr =& $this->MetaColumns($table);
if (!is_array($objarr)) {
$false = false;
return $false;
}
$arr = array();
if ($numIndexes) {
$i = 0;
if ($useattnum) {
foreach($objarr as $v)
$arr[$v->attnum] = $v->name;
} else
foreach($objarr as $v) $arr[$i++] = $v->name;
} else
foreach($objarr as $v) $arr[strtoupper($v->name)] = $v->name;
return $arr;
}
function MetaTransaction($mode,$db)
{
$mode = strtoupper($mode);
$mode = str_replace('ISOLATION LEVEL ','',$mode);
switch($mode) {
case 'READ UNCOMMITTED':
switch($db) {
case 'oci8':
case 'oracle':
return 'ISOLATION LEVEL READ COMMITTED';
default:
return 'ISOLATION LEVEL READ UNCOMMITTED';
}
break;
case 'READ COMMITTED':
return 'ISOLATION LEVEL READ COMMITTED';
break;
case 'REPEATABLE READ':
switch($db) {
case 'oci8':
case 'oracle':
return 'ISOLATION LEVEL SERIALIZABLE';
default:
return 'ISOLATION LEVEL REPEATABLE READ';
}
break;
case 'SERIALIZABLE':
return 'ISOLATION LEVEL SERIALIZABLE';
break;
default:
return $mode;
}
}
}
eval('class postgres7_meta_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class postgres7_meta_ResultSet extends postgres7_meta_resultset_EXTENDER
{
/**
* Get the metatype of the column. This is used for formatting. This is because
* many databases use different names for the same type, so we transform the original
* type to our standardised version which uses 1 character codes:
*
* @param t is the type passed in. Normally is ADOFieldObject->type.
* @param len is the maximum length of that field. This is because we treat character
* fields bigger than a certain size as a 'B' (blob).
* @param fieldobj is the field object returned by the database driver. Can hold
* additional info (eg. primary_key for mysql).
*
* @return the general type of the data:
* C for character < 250 chars
* X for teXt (>= 250 chars)
* B for Binary
* N for numeric or floating point
* D for date
* T for timestamp
* L for logical/Boolean
* I for integer
* R for autoincrement counter/integer
*
*
*/
function MetaType($t,$len=-1,$fieldobj=false)
{
if (is_object($t)) {
$fieldobj = $t;
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
$is_serial = is_object($fieldobj) && $fieldobj->primary_key && $fieldobj->unique && $fieldobj->has_default && substr($fieldobj->default_value,0,8) == 'nextval(';
switch (strtoupper($t)) {
case 'MONEY': // stupid, postgres expects money to be a string
case 'INTERVAL':
case 'CHAR':
case 'CHARACTER':
case 'VARCHAR':
case 'NAME':
case 'BPCHAR':
case '_VARCHAR':
case 'INET':
case 'MACADDR':
if ($len <= $this->blobSize) return 'C';
case 'TEXT':
return 'X';
case 'IMAGE': // user defined type
case 'BLOB': // user defined type
case 'BIT': // This is a bit string, not a single bit, so don't return 'L'
case 'VARBIT':
case 'BYTEA':
return 'B';
case 'BOOL':
case 'BOOLEAN':
return 'L';
case 'DATE':
return 'D';
case 'TIMESTAMP WITHOUT TIME ZONE':
case 'TIME':
case 'DATETIME':
case 'TIMESTAMP':
case 'TIMESTAMPTZ':
return 'T';
case 'INTEGER': return !$is_serial ? 'I' : 'R';
case 'SMALLINT':
case 'INT2': return !$is_serial ? 'I2' : 'R';
case 'INT4': return !$is_serial ? 'I4' : 'R';
case 'BIGINT':
case 'INT8': return !$is_serial ? 'I8' : 'R';
case 'OID':
case 'SERIAL':
return 'R';
case 'FLOAT4':
case 'FLOAT8':
case 'DOUBLE PRECISION':
case 'REAL':
return 'F';
default:
static $typeMap = array(
'VARCHAR' => 'C',
'VARCHAR2' => 'C',
'CHAR' => 'C',
'C' => 'C',
'STRING' => 'C',
'NCHAR' => 'C',
'NVARCHAR' => 'C',
'VARYING' => 'C',
'BPCHAR' => 'C',
'CHARACTER' => 'C',
'INTERVAL' => 'C', # Postgres
'MACADDR' => 'C', # postgres
##
'LONGCHAR' => 'X',
'TEXT' => 'X',
'NTEXT' => 'X',
'M' => 'X',
'X' => 'X',
'CLOB' => 'X',
'NCLOB' => 'X',
'LVARCHAR' => 'X',
##
'BLOB' => 'B',
'IMAGE' => 'B',
'BINARY' => 'B',
'VARBINARY' => 'B',
'LONGBINARY' => 'B',
'B' => 'B',
##
'YEAR' => 'D', // mysql
'DATE' => 'D',
'D' => 'D',
##
'UNIQUEIDENTIFIER' => 'C', # MS SQL Server
##
'TIME' => 'T',
'TIMESTAMP' => 'T',
'DATETIME' => 'T',
'TIMESTAMPTZ' => 'T',
'T' => 'T',
'TIMESTAMP WITHOUT TIME ZONE' => 'T', // postgresql
##
'BOOL' => 'L',
'BOOLEAN' => 'L',
'BIT' => 'L',
'L' => 'L',
##
'COUNTER' => 'R',
'R' => 'R',
'SERIAL' => 'R', // ifx
'INT IDENTITY' => 'R',
##
'INT' => 'I',
'INT2' => 'I',
'INT4' => 'I',
'INT8' => 'I',
'INTEGER' => 'I',
'INTEGER UNSIGNED' => 'I',
'SHORT' => 'I',
'TINYINT' => 'I',
'SMALLINT' => 'I',
'I' => 'I',
##
'LONG' => 'N', // interbase is numeric, oci8 is blob
'BIGINT' => 'N', // this is bigger than PHP 32-bit integers
'DECIMAL' => 'N',
'DEC' => 'N',
'REAL' => 'N',
'DOUBLE' => 'N',
'DOUBLE PRECISION' => 'N',
'SMALLFLOAT' => 'N',
'FLOAT' => 'N',
'NUMBER' => 'N',
'NUM' => 'N',
'NUMERIC' => 'N',
'MONEY' => 'N',
## informix 9.2
'SQLINT' => 'I',
'SQLSERIAL' => 'I',
'SQLSMINT' => 'I',
'SQLSMFLOAT' => 'N',
'SQLFLOAT' => 'N',
'SQLMONEY' => 'N',
'SQLDECIMAL' => 'N',
'SQLDATE' => 'D',
'SQLVCHAR' => 'C',
'SQLCHAR' => 'C',
'SQLDTIME' => 'T',
'SQLINTERVAL' => 'N',
'SQLBYTES' => 'B',
'SQLTEXT' => 'X',
## informix 10
"SQLINT8" => 'I8',
"SQLSERIAL8" => 'I8',
"SQLNCHAR" => 'C',
"SQLNVCHAR" => 'C',
"SQLLVARCHAR" => 'X',
"SQLBOOL" => 'L'
);
$tmap = false;
$t = strtoupper($t);
$tmap = (isset($typeMap[$t])) ? $typeMap[$t] : 'N';
if ($t == 'LONG' && $this->dataProvider == 'oci8') return 'B';
return $tmap;
}
}
}
?>
@@ -0,0 +1,128 @@
<?php
/**
* ADOdb Lite Transaction Module for Postgres
*
*/
eval('class postgres7_transaction_EXTENDER extends '. $last_module . '_ADOConnection { }');
class postgres7_transaction_ADOConnection extends postgres7_transaction_EXTENDER
{
var $autoCommit = true;
var $transOff = 0;
var $transCnt = 0;
var $transaction_status = true;
function StartTrans($errfn = 'ADODB_TransMonitor')
{
if ($this->transOff > 0) {
$this->transOff += 1;
return;
}
$this->transaction_status = true;
if ($this->debug && $this->transCnt > 0)
ADOConnection::outp("Bad Transaction: StartTrans called within BeginTrans");
$this->BeginTrans();
$this->transOff = 1;
}
function BeginTrans()
{
if ($this->transOff)
return true;
$this->transCnt += 1;
return @pg_Exec($this->connectionId, "begin");
}
function CompleteTrans($autoComplete = true)
{
if ($this->transOff > 1) {
$this->transOff -= 1;
return true;
}
$this->transOff = 0;
if ($this->transaction_status && $autoComplete) {
if (!$this->CommitTrans()) {
$this->transaction_status = false;
if ($this->debug)
ADOConnection::outp("Smart Commit failed");
} else
if ($this->debug)
ADOConnection::outp("Smart Commit occurred");
} else {
$this->RollbackTrans();
if ($this->debug)
ADOCOnnection::outp("Smart Rollback occurred");
}
return $this->transaction_status;
}
function CommitTrans($ok=true)
{
if ($this->transOff)
return true;
if (!$ok)
return $this->RollbackTrans();
$this->transCnt -= 1;
return @pg_Exec($this->connectionId, "commit");
}
function RollbackTrans()
{
if ($this->transOff)
return true;
$this->transCnt -= 1;
return @pg_Exec($this->connectionId, "rollback");
}
function FailTrans()
{
if ($this->debug)
if ($this->transOff == 0) {
ADOConnection::outp("FailTrans outside StartTrans/CompleteTrans");
} else {
ADOConnection::outp("FailTrans was called");
}
$this->transaction_status = false;
}
function HasFailedTrans()
{
if ($this->transOff > 0)
return $this->transaction_status == false;
return false;
}
function RowLock($tables,$where,$flds='1 as ignore')
{
if (!$this->transCnt)
$this->BeginTrans();
return $this->GetOne("select $flds from $tables where $where for update");
}
function CommitLock($table)
{
return $this->CommitTrans();
}
function RollbackLock($table)
{
return $this->RollbackTrans();
}
}
eval('class postgres7_transaction_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class postgres7_transaction_ResultSet extends postgres7_transaction_resultset_EXTENDER
{
}
?>
@@ -0,0 +1,211 @@
<?php
/**
V4.65 22 July 2005 (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Modified 28 August, 2005 for use with ADOdb Lite by Mark Dickenson
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class ADODB2_postgres8 extends ADODB_DataDict {
var $dbtype = 'postgres';
var $seqField = false;
var $seqPrefix = 'SEQ_';
var $addCol = ' ADD COLUMN';
var $quote = '"';
var $renameTable = 'ALTER TABLE %s RENAME TO %s'; // at least since 7.1
function ActualType($meta)
{
switch($meta) {
case 'C': return 'VARCHAR';
case 'XL':
case 'X': return 'TEXT';
case 'C2': return 'VARCHAR';
case 'X2': return 'TEXT';
case 'B': return 'BYTEA';
case 'D': return 'DATE';
case 'T': return 'TIMESTAMP';
case 'L': return 'BOOLEAN';
case 'I': return 'INTEGER';
case 'I1': return 'SMALLINT';
case 'I2': return 'INT2';
case 'I4': return 'INT4';
case 'I8': return 'INT8';
case 'F': return 'FLOAT8';
case 'N': return 'NUMERIC';
default:
return $meta;
}
}
function AddColumnSQL($tabname, $flds)
{
$tabname = $this->TableName ($tabname);
$sql = array();
list($lines,$pkey) = $this->_GenFields($flds);
$alter = 'ALTER TABLE ' . $tabname . $this->addCol . ' ';
foreach($lines as $v) {
if (($not_null = preg_match('/NOT NULL/i',$v))) {
$v = preg_replace('/NOT NULL/i','',$v);
}
if (preg_match('/^([^ ]+) .*(DEFAULT [^ ]+)/',$v,$matches)) {
list(,$colname,$default) = $matches;
$sql[] = $alter . str_replace($default,'',$v);
$sql[] = 'ALTER TABLE '.$tabname.' ALTER COLUMN '.$colname.' SET ' . $default;
} else {
$sql[] = $alter . $v;
}
if ($not_null) {
list($colname) = explode(' ',$v);
$sql[] = 'ALTER TABLE '.$tabname.' ALTER COLUMN '.$colname.' SET NOT NULL';
}
}
return $sql;
}
function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
{
if (!$tableflds) {
if ($this->debug) $this->outp("AlterColumnSQL needs a complete table-definiton for PostgreSQL");
return array();
}
return $this->_recreate_copy_table($tabname,False,$tableflds,$tableoptions);
}
function DropColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
{
$has_drop_column = 7.3 <= (float) @$this->serverInfo['version'];
if (!$has_drop_column && !$tableflds) {
if ($this->debug) $this->outp("DropColumnSQL needs complete table-definiton for PostgreSQL < 7.3");
return array();
}
if ($has_drop_column) {
return ADODB_DataDict::DropColumnSQL($tabname, $flds);
}
return $this->_recreate_copy_table($tabname,$flds,$tableflds,$tableoptions);
}
function DropTableSQL($tabname)
{
$sql = ADODB_DataDict::DropTableSQL($tabname);
$drop_seq = $this->_DropAutoIncrement($tabname);
if ($drop_seq) $sql[] = $drop_seq;
return $sql;
}
function _CreateSuffix($fname, &$ftype, $fnotnull,$fdefault,$fautoinc,$fconstraint)
{
if ($fautoinc) {
$ftype = 'SERIAL';
return '';
}
$suffix = '';
if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
if ($fnotnull) $suffix .= ' NOT NULL';
if ($fconstraint) $suffix .= ' '.$fconstraint;
return $suffix;
}
function _DropAutoIncrement($tabname)
{
$tabname = $this->connection->qstr('%'.$tabname.'%');
$seq = $this->connection->GetOne("SELECT relname FROM pg_class WHERE NOT relname ~ 'pg_.*' AND relname LIKE $tabname AND relkind='S'");
// check if a tables depends on the sequenz and it therefor cant and dont need to be droped separatly
if (!$seq || $this->connection->GetOne("SELECT relname FROM pg_class JOIN pg_depend ON pg_class.relfilenode=pg_depend.objid WHERE relname='$seq' AND relkind='S' AND deptype='i'")) {
return False;
}
return "DROP SEQUENCE ".$seq;
}
function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
{
$sql = array();
if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {
$sql[] = sprintf ($this->dropIndex, $idxname, $tabname);
if ( isset($idxoptions['DROP']) )
return $sql;
}
if ( empty ($flds) ) {
return $sql;
}
$unique = isset($idxoptions['UNIQUE']) ? ' UNIQUE' : '';
$s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname . ' ';
if (isset($idxoptions['HASH']))
$s .= 'USING HASH ';
if ( isset($idxoptions[$this->upperName]) )
$s .= $idxoptions[$this->upperName];
if ( is_array($flds) )
$flds = implode(', ',$flds);
$s .= '(' . $flds . ')';
$sql[] = $s;
return $sql;
}
function _recreate_copy_table($tabname,$dropflds,$tableflds,$tableoptions='')
{
if ($dropflds && !is_array($dropflds)) $dropflds = explode(',',$dropflds);
$copyflds = array();
foreach($this->MetaColumns($tabname) as $fld) {
if (!$dropflds || !in_array($fld->name,$dropflds)) {
// we need to explicit convert varchar to a number to be able to do an AlterColumn of a char column to a nummeric one
if (preg_match('/'.$fld->name.' (I|I2|I4|I8|N|F)/i',$tableflds,$matches) &&
in_array($fld->type,array('varchar','char','text','bytea'))) {
$copyflds[] = "to_number($fld->name,'S99D99')";
} else {
$copyflds[] = $fld->name;
}
// identify the sequence name and the fld its on
if ($fld->primary_key && $fld->has_default &&
preg_match("/nextval\('([^']+)'::text\)/",$fld->default_value,$matches)) {
$seq_name = $matches[1];
$seq_fld = $fld->name;
}
}
}
$copyflds = implode(', ',$copyflds);
$tempname = $tabname.'_tmp';
$aSql[] = 'BEGIN'; // we use a transaction, to make sure not to loose the content of the table
$aSql[] = "SELECT * INTO TEMPORARY TABLE $tempname FROM $tabname";
$aSql = array_merge($aSql,$this->DropTableSQL($tabname));
$aSql = array_merge($aSql,$this->CreateTableSQL($tabname,$tableflds,$tableoptions));
$aSql[] = "INSERT INTO $tabname SELECT $copyflds FROM $tempname";
if ($seq_name && $seq_fld) { // if we have a sequence we need to set it again
$seq_name = $tabname.'_'.$seq_fld.'_seq'; // has to be the name of the new implicit sequence
$aSql[] = "SELECT setval('$seq_name',MAX($seq_fld)) FROM $tabname";
}
$aSql[] = "DROP TABLE $tempname";
// recreate the indexes, if they not contain one of the droped columns
foreach($this->MetaIndexes($tabname) as $idx_name => $idx_data)
{
if (substr($idx_name,-5) != '_pkey' && (!$dropflds || !count(array_intersect($dropflds,$idx_data['columns'])))) {
$aSql = array_merge($aSql,$this->CreateIndexSQL($idx_name,$tabname,$idx_data['columns'],
$idx_data['unique'] ? array('UNIQUE') : False));
}
}
$aSql[] = 'COMMIT';
return $aSql;
}
}
?>
@@ -0,0 +1,316 @@
<?php
/**
* ADOdb Lite Date Module for Postgres 8
*
*/
if (!defined('TIMESTAMP_FIRST_YEAR')) define('TIMESTAMP_FIRST_YEAR',100);
@include(ADODB_DIR . '/adodb-time.inc.php');
eval('class postgres8_date_EXTENDER extends '. $last_module . '_ADOConnection { }');
class postgres8_date_ADOConnection extends postgres8_date_EXTENDER
{
var $fmtDate = "'Y-m-d'"; // used by DBDate() as the default date format used by the database
var $fmtTimeStamp = "'Y-m-d H:i:s'"; // used by DBTimeStamp as the default timestamp fmt.
var $emptyDate = '&nbsp;';
var $emptyTimeStamp = '&nbsp;';
var $sysDate = "CURRENT_DATE";
var $sysTimeStamp = "CURRENT_TIMESTAMP";
var $isoDates = true; /// accepts dates in ISO format
function Time()
{
$rs =& $this->_Execute("select $this->sysTimeStamp");
if ($rs && !$rs->EOF)
return $this->UnixTimeStamp(reset($rs->fields));
return false;
}
function OffsetDate($dayFraction, $date=false)
{
if (!$date)
$date = $this->sysDate;
else if (strncmp($date,"'",1) == 0) {
$len = strlen($date);
if (10 <= $len && $len <= 12)
$date = 'date ' . $date;
else $date = 'timestamp ' . $date;
}
return "($date+interval'$dayFraction days')";
}
function SetDateLocale($locale = 'En')
{
$this->locale = $locale;
switch (strtoupper($locale))
{
case 'EN':
$this->fmtDate="'Y-m-d'";
$this->fmtTimeStamp = "'Y-m-d H:i:s'";
break;
case 'US':
$this->fmtDate = "'m-d-Y'";
$this->fmtTimeStamp = "'m-d-Y H:i:s'";
break;
case 'NL':
case 'FR':
case 'RO':
case 'IT':
$this->fmtDate="'d-m-Y'";
$this->fmtTimeStamp = "'d-m-Y H:i:s'";
break;
case 'GE':
$this->fmtDate="'d.m.Y'";
$this->fmtTimeStamp = "'d.m.Y H:i:s'";
break;
default:
$this->fmtDate="'Y-m-d'";
$this->fmtTimeStamp = "'Y-m-d H:i:s'";
break;
}
}
function DBDate($date)
{
if (empty($date) && $date !== 0)
return 'null';
if (is_string($date) && !is_numeric($date)) {
if ($date === 'null' || strncmp($date, "'", 1) === 0)
return $date;
if ($this->isoDates)
return "'$date'";
$date = $this->UnixDate($date);
}
return adodb_date($this->fmtDate,$date);
}
function DBTimeStamp($timestamp)
{
if (empty($timestamp) && $timestamp !== 0)
return 'null';
# strlen(14) allows YYYYMMDDHHMMSS format
if (!is_string($timestamp) || (is_numeric($timestamp) && strlen($timestamp)<14))
return adodb_date($this->fmtTimeStamp, $timestamp);
if ($timestamp === 'null')
return $timestamp;
if ($this->isoDates && strlen($timestamp) !== 14)
return "'$timestamp'";
$timestamp = $this->UnixTimeStamp($timestamp);
return adodb_date($this->fmtTimeStamp, $timestamp);
}
function UnixDate($v)
{
if (is_object($v)) {
// odbtp support
//( [year] => 2004 [month] => 9 [day] => 4 [hour] => 12 [minute] => 44 [second] => 8 [fraction] => 0 )
return adodb_mktime($v->hour, $v->minute, $v->second, $v->month, $v->day, $v->year);
}
if (is_numeric($v) && strlen($v) !== 8)
return $v;
if (!preg_match( "|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})|", ($v), $rr))
return false;
if ($rr[1] <= TIMESTAMP_FIRST_YEAR)
return 0;
// h-m-s-MM-DD-YY
return adodb_mktime(0, 0, 0, $rr[2], $rr[3], $rr[1]);
}
function UnixTimeStamp($v)
{
if (is_object($v)) {
// odbtp support
//( [year] => 2004 [month] => 9 [day] => 4 [hour] => 12 [minute] => 44 [second] => 8 [fraction] => 0 )
return adodb_mktime($v->hour, $v->minute, $v->second, $v->month, $v->day, $v->year);
}
if (!preg_match("|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})[ ,-]*(([0-9]{1,2}):?([0-9]{1,2}):?([0-9\.]{1,4}))?|", ($v), $rr))
return false;
if ($rr[1] <= TIMESTAMP_FIRST_YEAR && $rr[2]<= 1)
return 0;
// h-m-s-MM-DD-YY
if (!isset($rr[5]))
return adodb_mktime(0, 0, 0, $rr[2], $rr[3], $rr[1]);
else return adodb_mktime($rr[5], $rr[6], $rr[7], $rr[2], $rr[3], $rr[1]);
}
function UserDate($v, $fmt='Y-m-d', $gmt=false)
{
$tt = $this->UnixDate($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
else if ($tt == 0)
return $this->emptyDate;
else if ($tt == -1) { // pre-TIMESTAMP_FIRST_YEAR
}
return ($gmt) ? adodb_gmdate($fmt, $tt) : adodb_date($fmt, $tt);
}
function UserTimeStamp($v, $fmt='Y-m-d H:i:s', $gmt=false)
{
if (!isset($v))
return $this->emptyTimeStamp;
# strlen(14) allows YYYYMMDDHHMMSS format
if (is_numeric($v) && strlen($v)<14)
return ($gmt) ? adodb_gmdate($fmt,$v) : adodb_date($fmt,$v);
$tt = $this->UnixTimeStamp($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
if ($tt == 0)
return $this->emptyTimeStamp;
else return ($gmt) ? adodb_gmdate($fmt,$tt) : adodb_date($fmt,$tt);
}
function SQLDate($fmt, $col=false)
{
if (!$col)
$col = $this->sysTimeStamp;
$s = 'TO_CHAR('.$col.",'";
$len = strlen($fmt);
for ($i=0; $i < $len; $i++) {
$ch = $fmt[$i];
switch($ch) {
case 'Y':
case 'y':
$s .= 'YYYY';
break;
case 'Q':
case 'q':
$s .= 'Q';
break;
case 'M':
$s .= 'Mon';
break;
case 'm':
$s .= 'MM';
break;
case 'D':
case 'd':
$s .= 'DD';
break;
case 'H':
$s.= 'HH24';
break;
case 'h':
$s .= 'HH';
break;
case 'i':
$s .= 'MI';
break;
case 's':
$s .= 'SS';
break;
case 'a':
case 'A':
$s .= 'AM';
break;
case 'w':
$s .= 'D';
break;
case 'l':
$s .= 'DAY';
break;
default:
// handle escape characters...
if ($ch == '\\') {
$i++;
$ch = substr($fmt,$i,1);
}
if (strpos('-/.:;, ',$ch) !== false)
$s .= $ch;
else $s .= '"'.$ch.'"';
}
}
return $s. "')";
}
}
eval('class postgres8_date_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class postgres8_date_ResultSet extends postgres8_date_resultset_EXTENDER
{
var $emptyTimeStamp = '&nbsp;'; /// what to display when $time==0
var $emptyDate = '&nbsp;'; /// what to display when $time==0
var $datetime = false;
function UserTimeStamp($v, $fmt='Y-m-d H:i:s')
{
if (is_numeric($v) && strlen($v)<14)
return adodb_date($fmt,$v);
$tt = $this->UnixTimeStamp($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
if ($tt === 0)
return $this->emptyTimeStamp;
else return adodb_date($fmt,$tt);
}
function UserDate($v,$fmt='Y-m-d')
{
$tt = $this->UnixDate($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
else if ($tt == 0)
return $this->emptyDate;
else if ($tt == -1) { // pre-TIMESTAMP_FIRST_YEAR
}
return adodb_date($fmt,$tt);
}
function UnixDate($v)
{
return postgres8_date_ADOConnection::UnixDate($v);
}
function UnixTimeStamp($v)
{
return postgres8_date_ADOConnection::UnixTimeStamp($v);
}
}
?>
@@ -0,0 +1,663 @@
<?php
/**
* ADOdb Lite is a PHP class to encapsulate multiple database APIs and is compatible with
* a subset of the ADODB Command Syntax.
* Currently supports Frontbase, MaxDB, miniSQL, MSSQL, MSSQL Pro, MySQLi, MySQLt, MySQL, PostgresSQL,
* PostgresSQL64, PostgresSQL7, PostgresSQL8, SqLite and Sybase.
*
*/
class postgres8_driver_ADOConnection extends ADOConnection
{
var $connect_string;
var $sysDate = "CURRENT_DATE";
var $sysTimeStamp = "CURRENT_TIMESTAMP";
function postgres8_driver_ADOConnection()
{
$this->dbtype = 'postgres8';
$this->dataProvider = 'postgres';
}
/**
* Connection to database server and selected database
*
* @access private
*/
function _connect($host = "", $username = "", $password = "", $database = "", $persistent, $forcenew)
{
if (!function_exists('pg_connect')) return false;
$this->host = $host;
$this->username = $this->query_addslashes($username);
$this->password = $this->query_addslashes($password);
if (strlen($database) == 0) $database = 'template1';
$this->database = $this->query_addslashes($database);
if ($this->username || $this->password || $this->database) {
$this->connect_string = $this->host;
if ($this->connect_string) {
$host = split(":", $this->connect_string);
if ($host[0]) $this->connect_string = "host=" . $this->query_addslashes($host[0]);
else $this->connect_string = 'host=localhost';
if (isset($host[1])) $this->connect_string .= " port=$host[1]";
else if (!empty($this->port)) $this->connect_string .= " port=" . $this->port;
}
if ($this->username) $this->connect_string .= " user=" . $this->username;
if ($this->password) $this->connect_string .= " password=" . $this->password;
if ($this->database) $this->connect_string .= " dbname=" . $this->database;
}
else
{
$this->connect_string = $this->host;
}
$this->persistent = $persistent;
$this->forcenewconnection = $forcenew;
$this->_makeconnection();
if ($this->connectionId === false)
{
if ($fn = $this->raiseErrorFn)
$fn($this->dbtype, 'CONNECT', $this->ErrorNo(), $this->ErrorMsg(), $this->host, $this->database, $this);
return $this->SelectDB( $this->database );
}
return true;
}
function _makeconnection()
{
if($this->persistent == 1)
{
$this->connectionId = @pg_pconnect( $this->connect_string );
}
else
{
if(!$this->forcenewconnection)
{
$this->connectionId = @pg_connect( $this->connect_string );
}
else
{
$this->connectionId = @pg_connect( $this->connect_string, PGSQL_CONNECT_FORCE_NEW );
}
}
}
function query_addslashes($query)
{
$len = strlen($query);
if ($len == 0)
return "''";
if (strncmp($query,"'",1) === 0 && substr($query,$len-1) == "'")
return $s;
return "'".addslashes($query)."'";
}
/**
* Choose a database to connect.
*
* @param dbname is the name of the database to select
* @return true or false
* @access public
*/
function SelectDB($dbname)
{
$this->database = $dbname;
if ($this->connectionId === false)
{
if($this->createdatabase == true)
{
$this->connectionId = @pg_pconnect( "host=$this->host user=$this->username password=$this->password" );
$result = @pg_query($this->connectionId, "CREATE DATABASE " . $this->database );
if ($result === false) { // error handling if query fails
$this->connectionId = false;
return false;
}
$this->_makeconnection();
if($this->connectionId === false)
{
$this->connectionId = false;
return false;
}
else
{
return true;
}
}
$this->connectionId = false;
return false;
}
else
{
return true;
}
}
/**
* Return database error message
* Usage: $errormessage =& $db->ErrorMsg();
*
* @access public
*/
function ErrorMsg()
{
return @pg_last_error($this->connectionId);
}
/**
* Return database error number
* Usage: $errorbo =& $db->ErrorNo();
*
* @access public
*/
function ErrorNo()
{
$error = @pg_last_error( $this->connectionId );
return strlen($error) ? $error : 0;
}
/**
* Returns # of affected rows from insert/delete/update query
*
* @access public
* @return integer Affected rows
*/
function Affected_Rows()
{
return @pg_affected_rows( $this->record_set );
}
/**
* Returns the last record id of an inserted item
* Usage: $db->Insert_ID();
*
* @access public
*/
function Insert_ID()
{
return @pg_getlastoid($this->record_set);
}
/**
* Correctly quotes a string so that all strings are escape coded.
* An example is $db->qstr("Haven't a clue.");
*
* @param string the string to quote
* @param [magic_quotes] if $s is GET/POST var, set to get_magic_quotes_gpc().
*
* @return single-quoted string IE: 'Haven\'t a clue.'
*/
function qstr($string, $magic_quotes=false)
{
// Ugly hack alert! Repalce backticks with some arbitrary character
$string = str_replace('`', "\x1C", $string);
if (!$magic_quotes) {
if (strnatcmp(PHP_VERSION, '4.2.0') >= 0) {
return "'" . pg_escape_string($string) . "'";
}
$string = str_replace("'", "\\'", str_replace('\\', '\\\\', str_replace("\0", "\\\0", $string)));
return "'" . $string . "'";
}
return "'" . str_replace('\\"', '"', $string) . "'";
}
function QMagic($string)
{
return $this->qstr($string, get_magic_quotes_gpc());
}
/**
* Returns concatenated string
* Usage: $db->Concat($str1,$str2);
*
* @return concatenated string
*/
function Concat()
{
$arr = func_get_args();
return implode("||", $arr);
}
function IfNull( $field, $ifNull )
{
return " coalesce($field, $ifNull) ";
}
/**
* Closes database connection
* Usage: $db->close();
*
* @access public
*/
function Close()
{
@pg_close( $this->connectionId );
$this->connectionId = false;
}
/**
* Returns All Records in an array
*
* Usage: $db->GetAll($sql);
* @access public
*/
function &GetAll($sql, $inputarr = false)
{
$data =& $this->GetArray($sql, $inputarr);
return $data;
}
/**
* Returns All Records in an array
*
* Usage: $db->GetArray($sql);
* @access public
*/
function &GetArray($sql, $inputarr = false)
{
$data = false;
$result =& $this->Execute($sql, $inputarr);
if ($result)
{
$data =& $result->GetArray();
$result->Close();
}
return $data;
}
/**
* Executes SQL query and instantiates resultset methods
*
* @access private
* @return mixed Resultset methods
*/
function &do_query( $sql, $offset, $nrows, $inputarr=false )
{
global $ADODB_FETCH_MODE;
$sql = str_replace('`', '"', $sql);
$sql = str_replace("\x1C", "`", $sql);
$sql = str_replace('IS_DELETED', 'is_deleted', $sql);
$sql = str_replace("HIGH_PRIORITY", "", $sql);
$false = false;
$offsetStr = '';
$limitStr = '';
if ($offset != -1 || $nrows != -1)
{
$offsetStr = ($offset >= 0) ? " OFFSET " . ((integer)$offset) : '';
$limitStr = ($nrows >= 0) ? " LIMIT " . ((integer)$nrows) : '';
}
if ($inputarr && is_array($inputarr)) {
$sqlarr = explode('?', $sql);
if (!is_array(reset($inputarr))) $inputarr = array($inputarr);
foreach($inputarr as $arr) {
$sql = ''; $i = 0;
foreach($arr as $v) {
$sql .= $sqlarr[$i];
switch(gettype($v)){
case 'string':
$sql .= $this->qstr($v);
break;
case 'double':
$sql .= str_replace(',', '.', $v);
break;
case 'boolean':
$sql .= $v ? "'t'" : "'f'";
break;
default:
if ($v === null)
$sql .= 'NULL';
else $sql .= $v;
}
$i += 1;
}
$sql .= $sqlarr[$i];
if ($i+1 != sizeof($sqlarr))
return $false;
$this->sql = $sql . "$limitStr$offsetStr";
$time_start = array_sum(explode(' ', microtime()));
$this->query_count++;
$resultId = @pg_query( $this->sql);
$time_total = (array_sum(explode(' ', microtime())) - $time_start);
$this->query_time_total += $time_total;
if($this->debug_console)
{
$this->query_list[] = $this->sql;
$this->query_list_time[] = $time_total;
$this->query_list_errors[] = $this->ErrorMsg();
}
if($this->debug)
{
$this->outp($sql . "$limitStr$offsetStr");
}
if ($resultId === false) { // error handling if query fails
if ($fn = $this->raiseErrorFn)
$fn($this->dbtype, 'EXECUTE', $this->ErrorNo(), $this->ErrorMsg(), $this->sql, $inputarr, $this);
return $false;
}
}
}
else
{
$this->sql = $sql . "$limitStr$offsetStr";
$time_start = array_sum(explode(' ', microtime()));
$this->query_count++;
$resultId = @pg_query( $this->sql);
$time_total = (array_sum(explode(' ', microtime())) - $time_start);
$this->query_time_total += $time_total;
if($this->debug_console)
{
$this->query_list[] = $this->sql;
$this->query_list_time[] = $time_total;
$this->query_list_errors[] = $this->ErrorMsg();
}
if($this->debug)
{
$this->outp($sql . "$limitStr$offsetStr");
}
}
if ($resultId === false) { // error handling if query fails
if ($fn = $this->raiseErrorFn)
$fn($this->dbtype, 'EXECUTE', $this->ErrorNo(), $this->ErrorMsg(), $this->sql, $inputarr, $this);
return $false;
}
if (@pg_numfields( $resultId ) <= 0) { // return simplified recordset for inserts/updates/deletes with lower overhead
$recordset = new ADORecordSet_empty();
$this->record_set = $recordset;
return $recordset;
}
$resultset_name = $this->last_module_name . "_ResultSet";
$recordset = new $resultset_name( $resultId, $this->connectionId );
$this->record_set = $recordset;
$recordset->_currentRow = 0;
switch ($ADODB_FETCH_MODE)
{
case ADODB_FETCH_NUM: $recordset->fetchMode = PGSQL_NUM; break;
case ADODB_FETCH_ASSOC:$recordset->fetchMode = PGSQL_ASSOC; break;
default:
case ADODB_FETCH_DEFAULT:
case ADODB_FETCH_BOTH:$recordset->fetchMode = PGSQL_BOTH; break;
}
$recordset->_numOfRows = @pg_numrows( $resultId );
if( $recordset->_numOfRows == 0)
{
$recordset->EOF = true;
}
$recordset->_numOfFields = @pg_numfields( $resultId );
$recordset->_fetch();
return $recordset;
}
}
class postgres8_driver_ResultSet
{
var $connectionId;
var $fields;
var $resultId;
var $_currentRow = 0;
var $_numOfRows = -1;
var $_numOfFields = -1;
var $fetchMode;
var $EOF;
/**
* pgsqlResultSet Constructor
*
* @access private
* @param string $record
* @param string $resultId
*/
function postgres8_driver_ResultSet( $resultId, $connectionId )
{
$this->fields = array();
$this->connectionId = $connectionId;
$this->record = array();
$this->resultId = $resultId;
$this->EOF = false;
}
/**
* Frees resultset
*
* @access public
*/
function close()
{
pg_free_result( $this->resultId );
$this->fields = array();
$this->resultId = false;
}
/**
* Returns field name from select query
*
* @access public
* @param string $field
* @return string Field name
*/
function fields( $field )
{
if(empty($field))
{
return $this->fields;
}
else
{
return $this->fields[$field];
}
}
/**
* Returns numrows from select query
*
* @access public
* @return integer Numrows
*/
function RecordCount()
{
return $this->_numOfRows;
}
/**
* Returns num of fields from select query
*
* @access public
* @return integer numfields
*/
function FieldCount()
{
return $this->_numOfFields;
}
/**
* Returns next record
*
* @access public
*/
function MoveNext()
{
if (@$this->fields = pg_fetch_array($this->resultId, NULL, $this->fetchMode)) {
$this->_currentRow += 1;
return true;
}
if (!$this->EOF) {
$this->_currentRow += 1;
$this->EOF = true;
}
return false;
}
/**
* Move to the first row in the recordset. Many databases do NOT support this.
*
* @return true or false
*/
function MoveFirst()
{
if ($this->_currentRow == 0) return true;
return $this->Move(0);
}
/**
* Returns the Last Record
*
* @access public
*/
function MoveLast()
{
if ($this->EOF) return false;
return $this->Move($this->_numOfRows - 1);
}
/**
* Random access to a specific row in the recordset. Some databases do not support
* access to previous rows in the databases (no scrolling backwards).
*
* @param rowNumber is the row to move to (0-based)
*
* @return true if there still rows available, or false if there are no more rows (EOF).
*/
function Move($rowNumber = 0)
{
if ($rowNumber == $this->_currentRow) return true;
$this->EOF = false;
if ($this->_numOfRows > 0){
if ($rowNumber >= $this->_numOfRows - 1){
$rowNumber = $this->_numOfRows - 1;
}
}
if ($this->_seek($rowNumber)) {
$this->_currentRow = $rowNumber;
if ($this->_fetch()) {
return true;
}
$this->fields = false;
}
$this->EOF = true;
return false;
}
/**
* Perform Seek to specific row
*
* @access private
*/
function _seek($row)
{
if ($this->_numOfRows == 0) return false;
return @pg_result_seek($this->resultId,$row);
}
/**
* Fills field array with first database element when query initially executed
*
* @access private
*/
function _fetch()
{
$this->fields = @pg_fetch_array($this->resultId, NULL, $this->fetchMode);
return is_array($this->fields);
}
/**
* Check to see if last record reached
*
* @access public
*/
function EOF()
{
if( $this->_currentRow < $this->_numOfRows)
{
return false;
}
else
{
$this->EOF = true;
return true;
}
}
/**
* Returns All Records in an array
*
* @access public
* @param [nRows] is the number of rows to return. -1 means every row.
*/
function &GetArray($nRows = -1)
{
$results = array();
$cnt = 0;
while (!$this->EOF && $nRows != $cnt) {
$results[] = $this->fields;
$this->MoveNext();
$cnt++;
}
return $results;
}
function &GetRows($nRows = -1)
{
$arr =& $this->GetArray($nRows);
return $arr;
}
function &GetAll($nRows = -1)
{
$arr =& $this->GetArray($nRows);
return $arr;
}
/**
* Fetch field information for a table.
*
* @return object containing the name, type and max_length
*/
function FetchField($fieldOffset = -1)
{
$fieldObject= new ADOFieldObject();
$fieldObject->name = @pg_fieldname($this->resultId, $fieldOffset);
$fieldObject->type = @pg_fieldtype($this->resultId, $fieldOffset);
$fieldObject->max_length = @pg_fieldsize($this->resultId, $fieldOffset);
return $fieldObject;
}
}
?>
@@ -0,0 +1,147 @@
<?php
/**
* ADOdb Lite Extend Module for Mysqlt
*
*/
eval('class postgres8_extend_EXTENDER extends '. $last_module . '_ADOConnection { }');
class postgres8_extend_ADOConnection extends postgres8_extend_EXTENDER
{
function &GetAssoc($sql, $inputarr=false, $force_array = false, $first2cols = false)
{
$data = false;
$result =& $this->Execute($sql, $inputarr);
if ($result) {
$data =& $result->GetAssoc($force_array, $first2cols);
$result->Close();
}
return $data;
}
/**
* Generates a sequence id and stores it in $this->genID;
* GenID is only available if $this->hasGenID = true;
*
* @param seqname name of sequence to use
* @param startID if sequence does not exist, start at this ID
* @return 0 if not supported, otherwise a sequence id
*/
var $_genIDSQL = "SELECT NEXTVAL('%s')";
var $_genSeqSQL = "CREATE SEQUENCE %s START %s";
var $_dropSeqSQL = "DROP SEQUENCE %s";
var $genID = 0;
function GenID($seqname='adodbseq', $startID=1)
{
$getnext = sprintf($this->_genIDSQL, $seqname);
$holdtransOK = $this->transaction_status;
$save_handler = $this->raiseErrorFn;
$this->raiseErrorFn = '';
@($result = $this->Execute($getnext));
$this->raiseErrorFn = $save_handler;
if (!$result) {
$this->transaction_status = $holdtransOK;
$createseq = $this->Execute(sprintf($this->_genSeqSQL, $seqname, $startID));
$result = $this->Execute($getnext);
}
if ($result && !$result->EOF)
$this->genID = reset($result->fields);
else $this->genID = 0;
if ($result)
$result->Close();
return $this->genID;
}
function CreateSequence($seqname='adodbseq', $startID=1)
{
return $this->Execute(sprintf($this->_genSeqSQL, $seqname, $startID));
}
function DropSequence($seqname='adodbseq')
{
return $this->Execute(sprintf($this->_dropSeqSQL, $seqname));
}
}
eval('class postgres8_extend_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class postgres8_extend_ResultSet extends postgres8_extend_resultset_EXTENDER
{
function &GetAssoc($force_array = false, $first2cols = false)
{
$results = false;
if ($this->_numOfFields > 1) {
$numIndex = isset($this->fields[0]);
$results = array();
if (!$first2cols && ($this->_numOfFields > 2 || $force_array)) {
if ($numIndex) {
while (!$this->EOF) {
$results[trim($this->fields[0])] = array_slice($this->fields, 1);
$this->MoveNext();
}
} else {
while (!$this->EOF) {
$results[trim(reset($this->fields))] = array_slice($this->fields, 1);
$this->MoveNext();
}
}
} else {
if ($numIndex) {
while (!$this->EOF) {
$results[trim(($this->fields[0]))] = $this->fields[1];
$this->MoveNext();
}
} else {
while (!$this->EOF) {
$v1 = trim(reset($this->fields));
$v2 = ''.next($this->fields);
$results[$v1] = $v2;
$this->MoveNext();
}
}
}
}
return $results;
}
function PO_RecordCount($table="", $condition="")
{
$lnumrows = $this->_numOfRows;
if($lnumrows == -1 && $this->connectionId)
{
if($table)
{
if ($condition)
$condition = " WHERE " . $condition;
$resultrows = &$this->connectionId->Execute("SELECT COUNT(*) FROM $table $condition");
if ($resultrows)
$lnumrows = reset($resultrows->fields);
}
}
return $lnumrows;
}
function CurrentRow()
{
return $this->_currentRow;
}
function AbsolutePosition()
{
return $this->_currentRow;
}
function NextRecordSet()
{
return false;
}
}
?>
@@ -0,0 +1,712 @@
<?php
/**
* ADOdb Lite Meta Module for Postgres8
*
* Portions of the Meta Coding came from ADOdb
*/
/*
(c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. See License.txt.
*/
eval('class postgres7_meta_EXTENDER extends '. $last_module . '_ADOConnection { }');
class postgres8_meta_ADOConnection extends postgres8_meta_EXTENDER
{
var $metaDatabasesSQL = "select datname from pg_database where datname not in ('template0','template1') order by 1";
var $metaTablesSQL = "select tablename,'T' from pg_tables where tablename not like 'pg\_%'
and tablename not in ('sql_features', 'sql_implementation_info', 'sql_languages',
'sql_packages', 'sql_sizing', 'sql_sizing_profiles')
union
select viewname,'V' from pg_views where viewname not like 'pg\_%'";
var $metaColumnsSQL = "SELECT a.attname,t.typname,a.attlen,a.atttypmod,a.attnotnull,a.atthasdef,a.attnum
FROM pg_class c, pg_attribute a,pg_type t
WHERE relkind in ('r','v') AND (c.relname='%s' or c.relname = lower('%s')) and a.attname not like '....%%'
AND a.attnum > 0 AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum";
// used when schema defined
var $metaColumnsSQL1 = "SELECT a.attname, t.typname, a.attlen, a.atttypmod, a.attnotnull, a.atthasdef, a.attnum
FROM pg_class c, pg_attribute a, pg_type t, pg_namespace n
WHERE relkind in ('r','v') AND (c.relname='%s' or c.relname = lower('%s'))
and c.relnamespace=n.oid and n.nspname='%s'
and a.attname not like '....%%' AND a.attnum > 0
AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum";
// get primary key etc -- from Freek Dijkstra
var $metaKeySQL = "SELECT ic.relname AS index_name, a.attname AS column_name,i.indisunique AS unique_key, i.indisprimary AS primary_key
FROM pg_class bc, pg_class ic, pg_index i, pg_attribute a WHERE bc.oid = i.indrelid AND ic.oid = i.indexrelid AND (i.indkey[0] = a.attnum OR i.indkey[1] = a.attnum OR i.indkey[2] = a.attnum OR i.indkey[3] = a.attnum OR i.indkey[4] = a.attnum OR i.indkey[5] = a.attnum OR i.indkey[6] = a.attnum OR i.indkey[7] = a.attnum) AND a.attrelid = bc.oid AND bc.relname = '%s'";
var $metaDefaultsSQL = "SELECT d.adnum as num, d.adsrc as def from pg_attrdef d, pg_class c where d.adrelid=c.oid and c.relname='%s' order by d.adnum";
function MetaError($err=false)
{
include_once(ADODB_DIR."/adodb-error.inc.php");
if ($err === false)
$err = $this->ErrorNo();
return adodb_error($this->dataProvider,$this->databaseType,$err);
}
function MetaErrorMsg($errno)
{
include_once(ADODB_DIR."/adodb-error.inc.php");
return adodb_errormsg($errno);
}
/**
* @returns an array with the primary key columns in it.
*/
function MetaPrimaryKeys($table, $owner=false)
{
// owner not used in base class - see oci8
$p = array();
$objs =& $this->MetaColumns($table);
if ($objs) {
foreach($objs as $v) {
if (!empty($v->primary_key))
$p[] = $v->name;
}
}
if (sizeof($p)) return $p;
if (function_exists('ADODB_VIEW_PRIMARYKEYS'))
return ADODB_VIEW_PRIMARYKEYS($this->databaseType, $this->database, $table, $owner);
return false;
}
/**
* @returns assoc array where keys are tables, and values are foreign keys
*/
function MetaForeignKeys($table, $owner=false, $upper=false)
{
$sql = 'SELECT t.tgargs as args
FROM
pg_trigger t,pg_class c,pg_proc p
WHERE
t.tgenabled AND
t.tgrelid = c.oid AND
t.tgfoid = p.oid AND
p.proname = \'RI_FKey_check_ins\' AND
c.relname = \''.strtolower($table).'\'
ORDER BY
t.tgrelid';
$rs =& $this->Execute($sql);
if (!$rs || $rs->EOF) return false;
$arr =& $rs->GetArray();
$a = array();
foreach($arr as $v) {
$data = explode(chr(0), $v['args']);
$size = count($data)-1; //-1 because the last node is empty
for($i = 4; $i < $size; $i++) {
if ($upper)
$a[strtoupper($data[2])][] = strtoupper($data[$i].'='.$data[++$i]);
else
$a[$data[2]][] = $data[$i].'='.$data[++$i];
}
}
return $a;
}
// not the fastest implementation - quick and dirty - jlim
// for best performance, use the actual $rs->MetaType().
function MetaType($t,$len=-1,$fieldobj=false)
{
if (empty($this->_metars)) {
$rsclass = $this->last_module_name . "_ResultSet";
$this->_metars =& new $rsclass(false,$this->fetchMode);
}
return $this->_metars->MetaType($t,$len,$fieldobj);
}
/**
* return the databases that the driver can connect to.
* Some databases will return an empty array.
*
* @return an array of database names.
*/
function MetaDatabases()
{
global $ADODB_FETCH_MODE;
if ($this->metaDatabasesSQL) {
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
$arr = $this->GetCol($this->metaDatabasesSQL);
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
return $arr;
}
return false;
}
/**
* @param ttype can either be 'VIEW' or 'TABLE' or false.
* If false, both views and tables are returned.
* "VIEW" returns only views
* "TABLE" returns only tables
* @param showSchema returns the schema/user with the table name, eg. USER.TABLE
* @param mask is the input mask - only supported by oci8 and postgresql
*
* @return array of tables for current database.
*/
function &MetaTables($ttype=false,$showSchema=false,$mask=false)
{
$info = $this->ServerInfo();
if ($info['version'] >= 7.3) {
$this->metaTablesSQL = "select tablename,'T' from pg_tables where tablename not like 'pg\_%'
and schemaname not in ( 'pg_catalog','information_schema')
union
select viewname,'V' from pg_views where viewname not like 'pg\_%' and schemaname not in ( 'pg_catalog','information_schema') ";
}
if ($mask) {
$save = $this->metaTablesSQL;
$mask = $this->qstr(strtolower($mask));
if ($info['version']>=7.3)
$this->metaTablesSQL = "
select tablename,'T' from pg_tables where tablename like $mask and schemaname not in ( 'pg_catalog','information_schema')
union
select viewname,'V' from pg_views where viewname like $mask and schemaname not in ( 'pg_catalog','information_schema') ";
else
$this->metaTablesSQL = "
select tablename,'T' from pg_tables where tablename like $mask
union
select viewname,'V' from pg_views where viewname like $mask";
}
$ret =& $this->_MetaTables($ttype,$showSchema);
if ($mask) {
$this->metaTablesSQL = $save;
}
return $ret;
}
function &_MetaTables($ttype=false,$showSchema=false,$mask=false)
{
global $ADODB_FETCH_MODE;
$false = false;
if ($mask) {
return $false;
}
if ($this->metaTablesSQL) {
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
$rs = $this->Execute($this->metaTablesSQL);
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
if ($rs === false) return $false;
$arr =& $rs->GetArray();
$arr2 = array();
if ($hast = ($ttype && isset($arr[0][1]))) {
$showt = strncmp($ttype,'T',1);
}
for ($i=0; $i < sizeof($arr); $i++) {
if ($hast) {
if ($showt == 0) {
if (strncmp($arr[$i][1],'T',1) == 0) $arr2[] = trim($arr[$i][0]);
} else {
if (strncmp($arr[$i][1],'V',1) == 0) $arr2[] = trim($arr[$i][0]);
}
} else
$arr2[] = trim($arr[$i][0]);
}
$rs->Close();
return $arr2;
}
return $false;
}
function _findschema(&$table,&$schema)
{
if (!$schema && ($at = strpos($table,'.')) !== false) {
$schema = substr($table,0,$at);
$table = substr($table,$at+1);
}
}
/**
* List columns in a database as an array of ADOFieldObjects.
* See top of file for definition of object.
*
* @param $table table name to query
* @param $normalize makes table name case-insensitive (required by some databases)
* @schema is optional database schema to use - not supported by all databases.
*
* @return array of ADOFieldObjects for current table.
*/
function &MetaColumns($table,$normalize=true)
{
global $ADODB_FETCH_MODE;
$schema = false;
$false = false;
$this->_findschema($table,$schema);
if ($normalize) $table = strtolower($table);
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
if ($schema) $rs =& $this->Execute(sprintf($this->metaColumnsSQL1,$table,$table,$schema));
else $rs =& $this->Execute(sprintf($this->metaColumnsSQL,$table,$table));
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
if ($rs === false) {
return $false;
}
if (!empty($this->metaKeySQL)) {
// If we want the primary keys, we have to issue a separate query
// Of course, a modified version of the metaColumnsSQL query using a
// LEFT JOIN would have been much more elegant, but postgres does
// not support OUTER JOINS. So here is the clumsy way.
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
$rskey = $this->Execute(sprintf($this->metaKeySQL,($table)));
// fetch all result in once for performance.
$keys =& $rskey->GetArray();
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
$rskey->Close();
unset($rskey);
}
$rsdefa = array();
if (!empty($this->metaDefaultsSQL)) {
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
$sql = sprintf($this->metaDefaultsSQL, ($table));
$rsdef = $this->Execute($sql);
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
if ($rsdef) {
while (!$rsdef->EOF) {
$num = $rsdef->fields['num'];
$s = $rsdef->fields['def'];
if (strpos($s,'::')===false && substr($s, 0, 1) == "'") { /* quoted strings hack... for now... fixme */
$s = substr($s, 1);
$s = substr($s, 0, strlen($s) - 1);
}
$rsdefa[$num] = $s;
$rsdef->MoveNext();
}
} else {
ADOConnection::outp( "==> SQL => " . $sql);
}
unset($rsdef);
}
$retarr = array();
while (!$rs->EOF) {
$fld = new ADOFieldObject();
$fld->name = $rs->fields[0];
$fld->type = $rs->fields[1];
$fld->max_length = $rs->fields[2];
$fld->attnum = $rs->fields[6];
if ($fld->max_length <= 0) $fld->max_length = $rs->fields[3]-4;
if ($fld->max_length <= 0) $fld->max_length = -1;
if ($fld->type == 'numeric') {
$fld->scale = $fld->max_length & 0xFFFF;
$fld->max_length >>= 16;
}
// dannym
// 5 hasdefault; 6 num-of-column
$fld->has_default = ($rs->fields[5] == 't');
if ($fld->has_default) {
$fld->default_value = $rsdefa[$rs->fields[6]];
}
//Freek
$fld->not_null = $rs->fields[4] == 't';
// Freek
if (is_array($keys)) {
foreach($keys as $key) {
if ($fld->name == $key['column_name'] AND $key['primary_key'] == 't')
$fld->primary_key = true;
if ($fld->name == $key['column_name'] AND $key['unique_key'] == 't')
$fld->unique = true; // What name is more compatible?
}
}
if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;
else $retarr[($normalize) ? strtoupper($fld->name) : $fld->name] = $fld;
$rs->MoveNext();
}
$rs->Close();
if (empty($retarr))
return $false;
else
return $retarr;
}
/**
* List indexes on a table as an array.
* @param table table name to query
* @param primary true to only show primary keys. Not actually used for most databases
*
* @return array of indexes on current table. Each element represents an index, and is itself an associative array.
Array (
[name_of_index] => Array
(
[unique] => true or false
[columns] => Array
(
[0] => firstname
[1] => lastname
)
)
*/
function &MetaIndexes ($table, $primary = FALSE)
{
global $ADODB_FETCH_MODE;
$schema = false;
$this->_findschema($table,$schema);
if ($schema) { // requires pgsql 7.3+ - pg_namespace used.
$sql = '
SELECT c.relname as "Name", i.indisunique as "Unique", i.indkey as "Columns"
FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_index i ON i.indexrelid=c.oid
JOIN pg_catalog.pg_class c2 ON c2.oid=i.indrelid
,pg_namespace n
WHERE (c2.relname=\'%s\' or c2.relname=lower(\'%s\')) and c.relnamespace=c2.relnamespace and c.relnamespace=n.oid and n.nspname=\'%s\'';
} else {
$sql = '
SELECT c.relname as "Name", i.indisunique as "Unique", i.indkey as "Columns"
FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_index i ON i.indexrelid=c.oid
JOIN pg_catalog.pg_class c2 ON c2.oid=i.indrelid
WHERE (c2.relname=\'%s\' or c2.relname=lower(\'%s\'))';
}
if ($primary == FALSE) {
$sql .= ' AND i.indisprimary=false;';
}
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== FALSE) {
$savem = $this->SetFetchMode(FALSE);
}
$rs = $this->Execute(sprintf($sql,$table,$table,$schema));
if (isset($savem)) {
$this->SetFetchMode($savem);
}
$ADODB_FETCH_MODE = $save;
if (!is_object($rs)) {
$false = false;
return $false;
}
$col_names = $this->MetaColumnNames($table,true,true);
//3rd param is use attnum,
// see http://sourceforge.net/tracker/index.php?func=detail&aid=1451245&group_id=42718&atid=433976
$indexes = array();
while ($row = $rs->FetchRow()) {
$columns = array();
foreach (explode(' ', $row[2]) as $col) {
$columns[] = $col_names[$col];
}
$indexes[$row[0]] = array(
'unique' => ($row[1] == 't'),
'columns' => $columns
);
}
return $indexes;
}
/**
* List columns names in a table as an array.
* @param table table name to query
*
* @return array of column names for current table.
*/
function &MetaColumnNames($table, $numIndexes=false,$useattnum=false /* only for postgres */)
{
$objarr =& $this->MetaColumns($table);
if (!is_array($objarr)) {
$false = false;
return $false;
}
$arr = array();
if ($numIndexes) {
$i = 0;
if ($useattnum) {
foreach($objarr as $v)
$arr[$v->attnum] = $v->name;
} else
foreach($objarr as $v) $arr[$i++] = $v->name;
} else
foreach($objarr as $v) $arr[strtoupper($v->name)] = $v->name;
return $arr;
}
function MetaTransaction($mode,$db)
{
$mode = strtoupper($mode);
$mode = str_replace('ISOLATION LEVEL ','',$mode);
switch($mode) {
case 'READ UNCOMMITTED':
switch($db) {
case 'oci8':
case 'oracle':
return 'ISOLATION LEVEL READ COMMITTED';
default:
return 'ISOLATION LEVEL READ UNCOMMITTED';
}
break;
case 'READ COMMITTED':
return 'ISOLATION LEVEL READ COMMITTED';
break;
case 'REPEATABLE READ':
switch($db) {
case 'oci8':
case 'oracle':
return 'ISOLATION LEVEL SERIALIZABLE';
default:
return 'ISOLATION LEVEL REPEATABLE READ';
}
break;
case 'SERIALIZABLE':
return 'ISOLATION LEVEL SERIALIZABLE';
break;
default:
return $mode;
}
}
}
eval('class postgres8_meta_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class postgres8_meta_ResultSet extends postgres8_meta_resultset_EXTENDER
{
/**
* Get the metatype of the column. This is used for formatting. This is because
* many databases use different names for the same type, so we transform the original
* type to our standardised version which uses 1 character codes:
*
* @param t is the type passed in. Normally is ADOFieldObject->type.
* @param len is the maximum length of that field. This is because we treat character
* fields bigger than a certain size as a 'B' (blob).
* @param fieldobj is the field object returned by the database driver. Can hold
* additional info (eg. primary_key for mysql).
*
* @return the general type of the data:
* C for character < 250 chars
* X for teXt (>= 250 chars)
* B for Binary
* N for numeric or floating point
* D for date
* T for timestamp
* L for logical/Boolean
* I for integer
* R for autoincrement counter/integer
*
*
*/
function MetaType($t,$len=-1,$fieldobj=false)
{
if (is_object($t)) {
$fieldobj = $t;
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
$is_serial = is_object($fieldobj) && $fieldobj->primary_key && $fieldobj->unique && $fieldobj->has_default && substr($fieldobj->default_value,0,8) == 'nextval(';
switch (strtoupper($t)) {
case 'MONEY': // stupid, postgres expects money to be a string
case 'INTERVAL':
case 'CHAR':
case 'CHARACTER':
case 'VARCHAR':
case 'NAME':
case 'BPCHAR':
case '_VARCHAR':
case 'INET':
case 'MACADDR':
if ($len <= $this->blobSize) return 'C';
case 'TEXT':
return 'X';
case 'IMAGE': // user defined type
case 'BLOB': // user defined type
case 'BIT': // This is a bit string, not a single bit, so don't return 'L'
case 'VARBIT':
case 'BYTEA':
return 'B';
case 'BOOL':
case 'BOOLEAN':
return 'L';
case 'DATE':
return 'D';
case 'TIMESTAMP WITHOUT TIME ZONE':
case 'TIME':
case 'DATETIME':
case 'TIMESTAMP':
case 'TIMESTAMPTZ':
return 'T';
case 'INTEGER': return !$is_serial ? 'I' : 'R';
case 'SMALLINT':
case 'INT2': return !$is_serial ? 'I2' : 'R';
case 'INT4': return !$is_serial ? 'I4' : 'R';
case 'BIGINT':
case 'INT8': return !$is_serial ? 'I8' : 'R';
case 'OID':
case 'SERIAL':
return 'R';
case 'FLOAT4':
case 'FLOAT8':
case 'DOUBLE PRECISION':
case 'REAL':
return 'F';
default:
static $typeMap = array(
'VARCHAR' => 'C',
'VARCHAR2' => 'C',
'CHAR' => 'C',
'C' => 'C',
'STRING' => 'C',
'NCHAR' => 'C',
'NVARCHAR' => 'C',
'VARYING' => 'C',
'BPCHAR' => 'C',
'CHARACTER' => 'C',
'INTERVAL' => 'C', # Postgres
'MACADDR' => 'C', # postgres
##
'LONGCHAR' => 'X',
'TEXT' => 'X',
'NTEXT' => 'X',
'M' => 'X',
'X' => 'X',
'CLOB' => 'X',
'NCLOB' => 'X',
'LVARCHAR' => 'X',
##
'BLOB' => 'B',
'IMAGE' => 'B',
'BINARY' => 'B',
'VARBINARY' => 'B',
'LONGBINARY' => 'B',
'B' => 'B',
##
'YEAR' => 'D', // mysql
'DATE' => 'D',
'D' => 'D',
##
'UNIQUEIDENTIFIER' => 'C', # MS SQL Server
##
'TIME' => 'T',
'TIMESTAMP' => 'T',
'DATETIME' => 'T',
'TIMESTAMPTZ' => 'T',
'T' => 'T',
'TIMESTAMP WITHOUT TIME ZONE' => 'T', // postgresql
##
'BOOL' => 'L',
'BOOLEAN' => 'L',
'BIT' => 'L',
'L' => 'L',
##
'COUNTER' => 'R',
'R' => 'R',
'SERIAL' => 'R', // ifx
'INT IDENTITY' => 'R',
##
'INT' => 'I',
'INT2' => 'I',
'INT4' => 'I',
'INT8' => 'I',
'INTEGER' => 'I',
'INTEGER UNSIGNED' => 'I',
'SHORT' => 'I',
'TINYINT' => 'I',
'SMALLINT' => 'I',
'I' => 'I',
##
'LONG' => 'N', // interbase is numeric, oci8 is blob
'BIGINT' => 'N', // this is bigger than PHP 32-bit integers
'DECIMAL' => 'N',
'DEC' => 'N',
'REAL' => 'N',
'DOUBLE' => 'N',
'DOUBLE PRECISION' => 'N',
'SMALLFLOAT' => 'N',
'FLOAT' => 'N',
'NUMBER' => 'N',
'NUM' => 'N',
'NUMERIC' => 'N',
'MONEY' => 'N',
## informix 9.2
'SQLINT' => 'I',
'SQLSERIAL' => 'I',
'SQLSMINT' => 'I',
'SQLSMFLOAT' => 'N',
'SQLFLOAT' => 'N',
'SQLMONEY' => 'N',
'SQLDECIMAL' => 'N',
'SQLDATE' => 'D',
'SQLVCHAR' => 'C',
'SQLCHAR' => 'C',
'SQLDTIME' => 'T',
'SQLINTERVAL' => 'N',
'SQLBYTES' => 'B',
'SQLTEXT' => 'X',
## informix 10
"SQLINT8" => 'I8',
"SQLSERIAL8" => 'I8',
"SQLNCHAR" => 'C',
"SQLNVCHAR" => 'C',
"SQLLVARCHAR" => 'X',
"SQLBOOL" => 'L'
);
$tmap = false;
$t = strtoupper($t);
$tmap = (isset($typeMap[$t])) ? $typeMap[$t] : 'N';
if ($t == 'LONG' && $this->dataProvider == 'oci8') return 'B';
return $tmap;
}
}
}
?>
@@ -0,0 +1,128 @@
<?php
/**
* ADOdb Lite Transaction Module for Postgres
*
*/
eval('class postgres8_transaction_EXTENDER extends '. $last_module . '_ADOConnection { }');
class postgres8_transaction_ADOConnection extends postgres8_transaction_EXTENDER
{
var $autoCommit = true;
var $transOff = 0;
var $transCnt = 0;
var $transaction_status = true;
function StartTrans($errfn = 'ADODB_TransMonitor')
{
if ($this->transOff > 0) {
$this->transOff += 1;
return;
}
$this->transaction_status = true;
if ($this->debug && $this->transCnt > 0)
ADOConnection::outp("Bad Transaction: StartTrans called within BeginTrans");
$this->BeginTrans();
$this->transOff = 1;
}
function BeginTrans()
{
if ($this->transOff)
return true;
$this->transCnt += 1;
return @pg_Exec($this->connectionId, "begin");
}
function CompleteTrans($autoComplete = true)
{
if ($this->transOff > 1) {
$this->transOff -= 1;
return true;
}
$this->transOff = 0;
if ($this->transaction_status && $autoComplete) {
if (!$this->CommitTrans()) {
$this->transaction_status = false;
if ($this->debug)
ADOConnection::outp("Smart Commit failed");
} else
if ($this->debug)
ADOConnection::outp("Smart Commit occurred");
} else {
$this->RollbackTrans();
if ($this->debug)
ADOCOnnection::outp("Smart Rollback occurred");
}
return $this->transaction_status;
}
function CommitTrans($ok=true)
{
if ($this->transOff)
return true;
if (!$ok)
return $this->RollbackTrans();
$this->transCnt -= 1;
return @pg_Exec($this->connectionId, "commit");
}
function RollbackTrans()
{
if ($this->transOff)
return true;
$this->transCnt -= 1;
return @pg_Exec($this->connectionId, "rollback");
}
function FailTrans()
{
if ($this->debug)
if ($this->transOff == 0) {
ADOConnection::outp("FailTrans outside StartTrans/CompleteTrans");
} else {
ADOConnection::outp("FailTrans was called");
}
$this->transaction_status = false;
}
function HasFailedTrans()
{
if ($this->transOff > 0)
return $this->transaction_status == false;
return false;
}
function RowLock($tables,$where,$flds='1 as ignore')
{
if (!$this->transCnt)
$this->BeginTrans();
return $this->GetOne("select $flds from $tables where $where for update");
}
function CommitLock($table)
{
return $this->CommitTrans();
}
function RollbackLock($table)
{
return $this->RollbackTrans();
}
}
eval('class postgres8_transaction_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class postgres8_transaction_ResultSet extends postgres8_transaction_resultset_EXTENDER
{
}
?>
@@ -0,0 +1,67 @@
<?php
/**
V4.65 22 July 2005 (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Modified 28 August, 2005 for use with ADOdb Lite by Mark Dickenson
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class ADODB2_sqlite extends ADODB_DataDict {
var $dbtype = 'sqlite';
var $seqField = false;
var $metaTablesSQL = "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name";
function ActualType($meta)
{
switch($meta) {
case 'C': return 'VARCHAR';
case 'XL':
case 'X': return 'VARCHAR(250)';
case 'C2': return 'VARCHAR';
case 'X2': return 'VARCHAR(250)';
case 'B': return 'VARCHAR';
case 'D': return 'DATE';
case 'T': return 'DATE';
case 'L': return 'DECIMAL(1)';
case 'I': return 'DECIMAL(10)';
case 'I1': return 'DECIMAL(3)';
case 'I2': return 'DECIMAL(5)';
case 'I4': return 'DECIMAL(10)';
case 'I8': return 'DECIMAL(20)';
case 'F': return 'DECIMAL(32,8)';
case 'N': return 'DECIMAL';
default:
return $meta;
}
}
function AlterColumnSQL($tabname, $flds)
{
if ($this->debug) $this->outp("AlterColumnSQL not supported");
return array();
}
function DropColumnSQL($tabname, $flds)
{
if ($this->debug) $this->outp("DropColumnSQL not supported");
return array();
}
}
?>
@@ -0,0 +1,241 @@
<?php
/**
* ADOdb Lite Date Module for SQLite
*
*/
if (!defined('TIMESTAMP_FIRST_YEAR')) define('TIMESTAMP_FIRST_YEAR',100);
@include(ADODB_DIR . '/adodb-time.inc.php');
eval('class sqlite_date_EXTENDER extends '. $last_module . '_ADOConnection { }');
class sqlite_date_ADOConnection extends sqlite_date_EXTENDER
{
var $fmtDate = "'Y-m-d'"; /// used by DBDate() as the default date format used by the database
var $fmtTimeStamp = "'Y-m-d H:i:s'";
var $emptyDate = '&nbsp;';
var $emptyTimeStamp = '&nbsp;';
var $sysDate = "adodb_date('Y-m-d')";
var $sysTimeStamp = "adodb_date('Y-m-d H:i:s')";
var $isoDates = false; /// accepts dates in ISO format
function Time()
{
$rs =& $this->_Execute("select $this->sysTimeStamp");
if ($rs && !$rs->EOF)
return $this->UnixTimeStamp(reset($rs->fields));
return false;
}
function OffsetDate($dayFraction, $date=false)
{
if (!$date)
$date = $this->sysDate;
return '('.$date.'+'.$dayFraction.')';
}
function SetDateLocale($locale = 'En')
{
$this->locale = $locale;
switch (strtoupper($locale))
{
case 'EN':
$this->fmtDate="'Y-m-d'";
$this->fmtTimeStamp = "'Y-m-d H:i:s'";
break;
case 'US':
$this->fmtDate = "'m-d-Y'";
$this->fmtTimeStamp = "'m-d-Y H:i:s'";
break;
case 'NL':
case 'FR':
case 'RO':
case 'IT':
$this->fmtDate="'d-m-Y'";
$this->fmtTimeStamp = "'d-m-Y H:i:s'";
break;
case 'GE':
$this->fmtDate="'d.m.Y'";
$this->fmtTimeStamp = "'d.m.Y H:i:s'";
break;
default:
$this->fmtDate="'Y-m-d'";
$this->fmtTimeStamp = "'Y-m-d H:i:s'";
break;
}
}
function DBDate($date)
{
if (empty($date) && $date !== 0)
return 'null';
if (is_string($date) && !is_numeric($date)) {
if ($date === 'null' || strncmp($date, "'", 1) === 0)
return $date;
if ($this->isoDates)
return "'$date'";
$date = $this->UnixDate($date);
}
return adodb_date($this->fmtDate,$date);
}
function DBTimeStamp($timestamp)
{
if (empty($timestamp) && $timestamp !== 0)
return 'null';
# strlen(14) allows YYYYMMDDHHMMSS format
if (!is_string($timestamp) || (is_numeric($timestamp) && strlen($timestamp)<14))
return adodb_date($this->fmtTimeStamp, $timestamp);
if ($timestamp === 'null')
return $timestamp;
if ($this->isoDates && strlen($timestamp) !== 14)
return "'$timestamp'";
$timestamp = $this->UnixTimeStamp($timestamp);
return adodb_date($this->fmtTimeStamp, $timestamp);
}
function UnixDate($v)
{
if (is_object($v)) {
// odbtp support
//( [year] => 2004 [month] => 9 [day] => 4 [hour] => 12 [minute] => 44 [second] => 8 [fraction] => 0 )
return adodb_mktime($v->hour, $v->minute, $v->second, $v->month, $v->day, $v->year);
}
if (is_numeric($v) && strlen($v) !== 8)
return $v;
if (!preg_match( "|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})|", ($v), $rr))
return false;
if ($rr[1] <= TIMESTAMP_FIRST_YEAR)
return 0;
// h-m-s-MM-DD-YY
return adodb_mktime(0, 0, 0, $rr[2], $rr[3], $rr[1]);
}
function UnixTimeStamp($v)
{
if (is_object($v)) {
// odbtp support
//( [year] => 2004 [month] => 9 [day] => 4 [hour] => 12 [minute] => 44 [second] => 8 [fraction] => 0 )
return adodb_mktime($v->hour, $v->minute, $v->second, $v->month, $v->day, $v->year);
}
if (!preg_match("|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})[ ,-]*(([0-9]{1,2}):?([0-9]{1,2}):?([0-9\.]{1,4}))?|", ($v), $rr))
return false;
if ($rr[1] <= TIMESTAMP_FIRST_YEAR && $rr[2]<= 1)
return 0;
// h-m-s-MM-DD-YY
if (!isset($rr[5]))
return adodb_mktime(0, 0, 0, $rr[2], $rr[3], $rr[1]);
else return adodb_mktime($rr[5], $rr[6], $rr[7], $rr[2], $rr[3], $rr[1]);
}
function UserDate($v, $fmt='Y-m-d', $gmt=false)
{
$tt = $this->UnixDate($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
else if ($tt == 0)
return $this->emptyDate;
else if ($tt == -1) { // pre-TIMESTAMP_FIRST_YEAR
}
return ($gmt) ? adodb_gmdate($fmt, $tt) : adodb_date($fmt, $tt);
}
function UserTimeStamp($v, $fmt='Y-m-d H:i:s', $gmt=false)
{
if (!isset($v))
return $this->emptyTimeStamp;
# strlen(14) allows YYYYMMDDHHMMSS format
if (is_numeric($v) && strlen($v)<14)
return ($gmt) ? adodb_gmdate($fmt,$v) : adodb_date($fmt,$v);
$tt = $this->UnixTimeStamp($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
if ($tt == 0)
return $this->emptyTimeStamp;
else return ($gmt) ? adodb_gmdate($fmt,$tt) : adodb_date($fmt,$tt);
}
function SQLDate($fmt, $col=false)
{
$fmt = $this->qstr($fmt);
return ($col) ? "adodb_date2($fmt,$col)" : "adodb_date($fmt)";
}
}
eval('class sqlite_date_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class sqlite_date_ResultSet extends sqlite_date_resultset_EXTENDER
{
var $emptyTimeStamp = '&nbsp;'; /// what to display when $time==0
var $emptyDate = '&nbsp;'; /// what to display when $time==0
var $datetime = false;
function UserTimeStamp($v, $fmt='Y-m-d H:i:s')
{
if (is_numeric($v) && strlen($v)<14)
return adodb_date($fmt,$v);
$tt = $this->UnixTimeStamp($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
if ($tt === 0)
return $this->emptyTimeStamp;
else return adodb_date($fmt,$tt);
}
function UserDate($v,$fmt='Y-m-d')
{
$tt = $this->UnixDate($v);
// $tt == -1 if pre TIMESTAMP_FIRST_YEAR
if (($tt === false || $tt == -1) && $v != false)
return $v;
else if ($tt == 0)
return $this->emptyDate;
else if ($tt == -1) { // pre-TIMESTAMP_FIRST_YEAR
}
return adodb_date($fmt,$tt);
}
function UnixDate($v)
{
return sqlite_date_ADOConnection::UnixDate($v);
}
function UnixTimeStamp($v)
{
return sqlite_date_ADOConnection::UnixTimeStamp($v);
}
}
?>
@@ -0,0 +1,614 @@
<?php
/**
* ADOdb Lite is a PHP class to encapsulate multiple database APIs and is compatible with
* a subset of the ADODB Command Syntax.
* Currently supports Frontbase, MaxDB, miniSQL, MSSQL, MSSQL Pro, MySQLi, MySQLt, MySQL, PostgresSQL,
* PostgresSQL64, PostgresSQL7, SqLite and Sybase.
*
*/
class sqlite_driver_ADOConnection extends ADOConnection
{
var $sysDate = "date('Y-m-d')";
var $sysTimeStamp = "date('Y-m-d H:i:s')";
function sqlite_driver_ADOConnection()
{
$this->dbtype = 'sqlite';
$this->dataProvider = 'sqlite';
}
/**
* Connection to database server and selected database
*
* @access private
*/
function _connect($host = "", $username = "", $password = "", $database = "", $persistent, $forcenew)
{
if (!function_exists('sqlite_factory')) return false;
$this->host = $host;
$this->username = $username;
$this->password = $password;
$this->database = ($database == "") ? $host : $database;
$this->persistent = $persistent;
$this->forcenewconnection = $forcenew;
if($this->persistent == 1)
{
$this->connectionId = @sqlite_popen( $this->database );
}
else
{
$this->connectionId = @sqlite_open( $this->database );
}
if ($this->connectionId === false)
{
if ($fn = $this->raiseErrorFn)
$fn($this->dbtype, 'CONNECT', $this->ErrorNo(), $this->ErrorMsg(), $this->host, $this->database, $this);
return false;
}
return true;
}
/**
* Choose a database to connect.
*
* @param dbname is the name of the database to select
* @return true or false
* @access public
*/
function SelectDB($dbname)
{
$this->database = $dbname;
$this->connectionId = sqlite_close( $this->connectionId );
if($this->persistent == 1)
{
$this->connectionId = @sqlite_popen( $this->database );
}
else
{
$this->connectionId = @sqlite_open( $this->database );
}
if ($this->connectionId === false)
{
if ($fn = $this->raiseErrorFn)
$fn($this->dbtype, 'CONNECT', $this->ErrorNo(), $this->ErrorMsg(), $this->host, $this->database, $this);
return false;
}
return true;
}
/**
* Return database error message
* Usage: $errormessage =& $db->ErrorMsg();
*
* @access public
*/
function ErrorMsg()
{
$errorno = @sqlite_last_error( $this->connectionId );
$error = ($errorno) ? sqlite_error_string($errorno) : '';
return $error;
}
/**
* Return database error number
* Usage: $errorbo =& $db->ErrorNo();
*
* @access public
*/
function ErrorNo()
{
return @sqlite_last_error($this->connectionId);
}
/**
* Returns # of affected rows from insert/delete/update query
*
* @access public
* @return integer Affected rows
*/
function Affected_Rows()
{
return @sqlite_changes( $this->connectionId );
}
/**
* Returns the last record id of an inserted item
* Usage: $db->Insert_ID();
*
* @access public
*/
function Insert_ID()
{
return @sqlite_last_insert_rowid($this->connectionId);
}
/**
* Correctly quotes a string so that all strings are escape coded.
* An example is $db->qstr("Haven't a clue.");
*
* @param string the string to quote
* @param [magic_quotes] if $s is GET/POST var, set to get_magic_quotes_gpc().
*
* @return single-quoted string IE: 'Haven\'t a clue.'
*/
function qstr($string, $magic_quotes=false)
{
// Ugly hack alert! Repalce backticks with some arbitrary character
$string = str_replace('`', "\x1C", $string);
if (!$magic_quotes) {
return "'".str_replace("'", "''", $string)."'";
}
$string = str_replace("\\'", "''", str_replace('\\\\', '\\', str_replace('\\"', '"', $string)));
return "'" . $string . "'";
}
function QMagic($string)
{
return $this->qstr($string, get_magic_quotes_gpc());
}
/**
* Returns concatenated string
* Usage: $db->Concat($str1,$str2);
*
* @return concatenated string
*/
function Concat()
{
$arr = func_get_args();
return implode("||", $arr);
}
function IfNull( $field, $ifNull )
{
return " CASE WHEN $field is null THEN $ifNull ELSE $field END ";
}
/**
* Closes database connection
* Usage: $db->close();
*
* @access public
*/
function Close()
{
@sqlite_close( $this->connectionId );
$this->connectionId = false;
}
/**
* Returns All Records in an array
*
* Usage: $db->GetAll($sql);
* @access public
*/
function &GetAll($sql, $inputarr = false)
{
$data =& $this->GetArray($sql, $inputarr);
return $data;
}
/**
* Returns All Records in an array
*
* Usage: $db->GetArray($sql);
* @access public
*/
function &GetArray($sql, $inputarr = false)
{
$data = false;
$result =& $this->Execute($sql, $inputarr);
if ($result)
{
$data =& $result->GetArray();
$result->Close();
}
return $data;
}
/**
* Executes SQL query and instantiates resultset methods
*
* @access private
* @return mixed Resultset methods
*/
function &do_query( $sql, $offset, $nrows, $inputarr=false )
{
global $ADODB_FETCH_MODE;
$sql = str_replace('`by`', "'by'", $sql);
$sql = str_replace('`order`', '"order"', $sql);
$sql = str_replace('`when`', '"when"', $sql);
$sql = str_replace('`desc`', "'desc'", $sql);
$sql = str_replace('`', '', $sql);
$sql = str_replace("\x1C", "`", $sql);
if (strpos($sql, "(DISTINCT ipmd5)")) {
$sql = str_replace("(DISTINCT ipmd5) FROM " . KU_DBPREFIX . "posts", "(ipmd5) FROM (SELECT DISTINCT ipmd5 FROM " . KU_DBPREFIX . "posts", $sql);
$sql .= ")";
}
$sql = str_replace('IS_DELETED', 'is_deleted', $sql);
$sql = str_replace("HIGH_PRIORITY", "", $sql);
$false = false;
$offsetStr = '';
$limitStr = '';
if ($offset != -1 || $nrows != -1)
{
$offsetStr = ($offset>=0) ? " OFFSET " . $offset . "," : '';
$limitStr = ($nrows >= 0) ? " LIMIT ". $nrows : ($offset >= 0 ? ' LIMIT 999999999' : '');
}
if ($inputarr && is_array($inputarr)) {
$sqlarr = explode('?', $sql);
if (!is_array(reset($inputarr))) $inputarr = array($inputarr);
foreach($inputarr as $arr) {
$sql = ''; $i = 0;
foreach($arr as $v) {
$sql .= $sqlarr[$i];
switch(gettype($v)){
case 'string':
$sql .= $this->qstr($v);
break;
case 'double':
$sql .= str_replace(',', '.', $v);
break;
case 'boolean':
$sql .= $v ? 1 : 0;
break;
default:
if ($v === null)
$sql .= 'NULL';
else $sql .= $v;
}
$i += 1;
}
$sql .= $sqlarr[$i];
if ($i+1 != sizeof($sqlarr))
return $false;
$this->sql = $sql . "$limitStr$offsetStr";
$time_start = array_sum(explode(' ', microtime()));
$this->query_count++;
$resultId = @sqlite_query( $this->sql, $this->connectionId );
$time_total = (array_sum(explode(' ', microtime())) - $time_start);
$this->query_time_total += $time_total;
if($this->debug_console)
{
$this->query_list[] = $this->sql;
$this->query_list_time[] = $time_total;
$this->query_list_errors[] = $this->ErrorMsg();
}
if($this->debug)
{
$this->outp($sql . "$limitStr$offsetStr");
}
if ($resultId === false) { // error handling if query fails
if ($fn = $this->raiseErrorFn)
$fn($this->dbtype, 'EXECUTE', $this->ErrorNo(), $this->ErrorMsg(), $this->sql, $inputarr, $this);
return $false;
}
}
}
else
{
$this->sql = $sql . "$limitStr$offsetStr";
$time_start = array_sum(explode(' ', microtime()));
$this->query_count++;
$resultId = @sqlite_query( $this->sql, $this->connectionId );
$time_total = (array_sum(explode(' ', microtime())) - $time_start);
$this->query_time_total += $time_total;
if($this->debug_console)
{
$this->query_list[] = $this->sql;
$this->query_list_time[] = $time_total;
$this->query_list_errors[] = $this->ErrorMsg();
}
if($this->debug)
{
$this->outp($sql . "$limitStr$offsetStr");
}
}
if ($resultId === false) { // error handling if query fails
if ($fn = $this->raiseErrorFn)
$fn($this->dbtype, 'EXECUTE', $this->ErrorNo(), $this->ErrorMsg(), $this->sql, $inputarr, $this);
return $false;
}
if ($resultId === true) { // return simplified recordset for inserts/updates/deletes with lower overhead
$recordset = new ADORecordSet_empty();
return $recordset;
}
$resultset_name = $this->last_module_name . "_ResultSet";
$recordset = new $resultset_name( $resultId, $this->connectionId );
$recordset->_currentRow = 0;
switch ($ADODB_FETCH_MODE)
{
case ADODB_FETCH_NUM: $recordset->fetchMode = SQLITE_NUM; break;
case ADODB_FETCH_ASSOC:$recordset->fetchMode = SQLITE_ASSOC; break;
default:
case ADODB_FETCH_DEFAULT:
case ADODB_FETCH_BOTH:$recordset->fetchMode = SQLITE_BOTH; break;
}
$recordset->_numOfRows = @sqlite_num_rows( $resultId );
if( $recordset->_numOfRows == 0)
{
$recordset->EOF = true;
}
$recordset->_numOfFields = @sqlite_num_fields( $resultId );
$recordset->_fetch();
return $recordset;
}
}
class sqlite_driver_ResultSet
{
var $connectionId;
var $fields;
var $resultId;
var $_currentRow = 0;
var $_numOfRows = -1;
var $_numOfFields = -1;
var $fetchMode;
var $EOF;
/**
* sqliteResultSet Constructor
*
* @access private
* @param string $record
* @param string $resultId
*/
function sqlite_driver_ResultSet( $resultId, $connectionId )
{
$this->fields = array();
$this->connectionId = $connectionId;
$this->record = array();
$this->resultId = $resultId;
$this->EOF = false;
}
/**
* Frees resultset
*
* @access public
*/
function close()
{
$this->fields = array();
$this->resultId = false;
}
/**
* Returns field name from select query
*
* @access public
* @param string $field
* @return string Field name
*/
function fields( $field )
{
if(empty($field))
{
return $this->fields;
}
else
{
return $this->fields[$field];
}
}
/**
* Returns numrows from select query
*
* @access public
* @return integer Numrows
*/
function RecordCount()
{
return $this->_numOfRows;
}
/**
* Returns num of fields from select query
*
* @access public
* @return integer numfields
*/
function FieldCount()
{
return $this->_numOfFields;
}
/**
* Returns next record
*
* @access public
*/
function MoveNext()
{
if (@$this->fields = sqlite_fetch_array($this->resultId,$this->fetchMode)) {
$this->_currentRow += 1;
return true;
}
if (!$this->EOF) {
$this->_currentRow += 1;
$this->EOF = true;
}
return false;
}
/**
* Move to the first row in the recordset. Many databases do NOT support this.
*
* @return true or false
*/
function MoveFirst()
{
if ($this->_currentRow == 0) return true;
return $this->Move(0);
}
/**
* Returns the Last Record
*
* @access public
*/
function MoveLast()
{
if ($this->EOF) return false;
return $this->Move($this->_numOfRows - 1);
}
/**
* Random access to a specific row in the recordset. Some databases do not support
* access to previous rows in the databases (no scrolling backwards).
*
* @param rowNumber is the row to move to (0-based)
*
* @return true if there still rows available, or false if there are no more rows (EOF).
*/
function Move($rowNumber = 0)
{
if ($rowNumber == $this->_currentRow) return true;
$this->EOF = false;
if ($this->_numOfRows > 0){
if ($rowNumber >= $this->_numOfRows - 1){
$rowNumber = $this->_numOfRows - 1;
}
}
if ($this->_seek($rowNumber)) {
$this->_currentRow = $rowNumber;
if ($this->_fetch()) {
return true;
}
$this->fields = false;
}
$this->EOF = true;
return false;
}
/**
* Perform Seek to specific row
*
* @access private
*/
function _seek($row)
{
if ($this->_numOfRows == 0) return false;
return @sqlite_seek($this->resultId,$row);
}
/**
* Fills field array with first database element when query initially executed
*
* @access private
*/
function _fetch()
{
$this->fields = @sqlite_fetch_array($this->resultId,$this->fetchMode);
return is_array($this->fields);
}
/**
* Check to see if last record reached
*
* @access public
*/
function EOF()
{
if( $this->_currentRow < $this->_numOfRows)
{
return false;
}
else
{
$this->EOF = true;
return true;
}
}
/**
* Returns All Records in an array
*
* @access public
* @param [nRows] is the number of rows to return. -1 means every row.
*/
function &GetArray($nRows = -1)
{
$results = array();
$cnt = 0;
while (!$this->EOF && $nRows != $cnt) {
$results[] = $this->fields;
$this->MoveNext();
$cnt++;
}
return $results;
}
function &GetRows($nRows = -1)
{
$arr =& $this->GetArray($nRows);
return $arr;
}
function &GetAll($nRows = -1)
{
$arr =& $this->GetArray($nRows);
return $arr;
}
/**
* Fetch field information for a table.
*
* @return object containing the name, type and max_length
*/
function FetchField($fieldOffset = -1)
{
$fieldObject = new ADOFieldObject;
$fieldObject->name = sqlite_field_name($this->resultId, $fieldOffset);
$fieldObject->type = 'VARCHAR';
$fieldObject->max_length = -1;
return $fieldObject;
}
}
?>
@@ -0,0 +1,153 @@
<?php
/**
* ADOdb Lite Extend Module for Mysqlt
*
*/
eval('class sqlite_extend_EXTENDER extends '. $last_module . '_ADOConnection { }');
class sqlite_extend_ADOConnection extends sqlite_extend_EXTENDER
{
function &GetAssoc($sql, $inputarr=false, $force_array = false, $first2cols = false)
{
$data = false;
$result =& $this->Execute($sql, $inputarr);
if ($result) {
$data =& $result->GetAssoc($force_array, $first2cols);
$result->Close();
}
return $data;
}
/**
* Generates a sequence id and stores it in $this->genID;
* GenID is only available if $this->hasGenID = true;
*
* @param seqname name of sequence to use
* @param startID if sequence does not exist, start at this ID
* @return 0 if not supported, otherwise a sequence id
*/
var $_genSeqSQL = "create table %s (id integer)";
var $_dropSeqSQL = 'drop table %s';
var $genID = 0;
function GenID($seqname='adodbseq', $startID=1)
{
$MAXLOOPS = 100;
while (--$MAXLOOPS>=0) {
@($num = $this->GetOne("select id from $seq"));
if ($num === false) {
$this->Execute(sprintf($this->_genSeqSQL, $seq));
$start -= 1;
$num = '0';
$result = $this->Execute("insert into $seq values($start)");
if (!$result)
return false;
}
$this->Execute("update $seq set id=id+1 where id=$num");
if ($this->affected_rows() > 0) {
$num += 1;
$this->genID = $num;
return $num;
}
}
if ($fn = $this->raiseErrorFn) {
$fn($this->databaseType, 'GENID',-32000,"Unable to generate unique id after $MAXLOOPS attempts", $seq, $num);
}
return false;
}
function CreateSequence($seqname='adodbseq', $start=1)
{
$ok = $this->Execute(sprintf($this->_genSeqSQL, $seqname));
if (!$ok)
return false;
$start -= 1;
return $this->Execute("insert into $seqname values($start)");
}
function DropSequence($seqname)
{
return $this->Execute(sprintf($this->_dropSeqSQL, $seqname));
}
}
eval('class sqlite_extend_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class sqlite_extend_ResultSet extends sqlite_extend_resultset_EXTENDER
{
function &GetAssoc($force_array = false, $first2cols = false)
{
$results = false;
if ($this->_numOfFields > 1) {
$numIndex = isset($this->fields[0]);
$results = array();
if (!$first2cols && ($this->_numOfFields > 2 || $force_array)) {
if ($numIndex) {
while (!$this->EOF) {
$results[trim($this->fields[0])] = array_slice($this->fields, 1);
$this->MoveNext();
}
} else {
while (!$this->EOF) {
$results[trim(reset($this->fields))] = array_slice($this->fields, 1);
$this->MoveNext();
}
}
} else {
if ($numIndex) {
while (!$this->EOF) {
$results[trim(($this->fields[0]))] = $this->fields[1];
$this->MoveNext();
}
} else {
while (!$this->EOF) {
$v1 = trim(reset($this->fields));
$v2 = ''.next($this->fields);
$results[$v1] = $v2;
$this->MoveNext();
}
}
}
}
return $results;
}
function PO_RecordCount($table="", $condition="")
{
$lnumrows = $this->_numOfRows;
if($lnumrows == -1 && $this->connectionId)
{
if($table)
{
if ($condition)
$condition = " WHERE " . $condition;
$resultrows = &$this->connectionId->Execute("SELECT COUNT(*) FROM $table $condition");
if ($resultrows)
$lnumrows = reset($resultrows->fields);
}
}
return $lnumrows;
}
function CurrentRow()
{
return $this->_currentRow;
}
function AbsolutePosition()
{
return $this->_currentRow;
}
function NextRecordSet()
{
return false;
}
}
?>
@@ -0,0 +1,533 @@
<?php
/**
* ADOdb Lite Meta Module for SQlite
*
* Portions of the Meta Coding came from ADOdb
*/
/*
(c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. See License.txt.
*/
eval('class sqlite_meta_EXTENDER extends '. $last_module . '_ADOConnection { }');
class sqlite_meta_ADOConnection extends sqlite_meta_EXTENDER
{
var $metaTablesSQL = "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name";
var $metaColumnsSQL = "SHOW COLUMNS FROM %s";
function MetaError($err=false)
{
include_once(ADODB_DIR."/adodb-error.inc.php");
if ($err === false)
$err = $this->ErrorNo();
return adodb_error($this->dataProvider,$this->databaseType,$err);
}
function MetaErrorMsg($errno)
{
include_once(ADODB_DIR."/adodb-error.inc.php");
return adodb_errormsg($errno);
}
/**
* @returns an array with the primary key columns in it.
*/
function MetaPrimaryKeys($table, $owner=false)
{
// owner not used in base class - see oci8
$p = array();
$objs =& $this->MetaColumns($table);
if ($objs) {
foreach($objs as $v) {
if (!empty($v->primary_key))
$p[] = $v->name;
}
}
if (sizeof($p)) return $p;
if (function_exists('ADODB_VIEW_PRIMARYKEYS'))
return ADODB_VIEW_PRIMARYKEYS($this->databaseType, $this->database, $table, $owner);
return false;
}
/**
* @returns assoc array where keys are tables, and values are foreign keys
*/
function MetaForeignKeys($table, $owner=false, $upper=false)
{
return false;
}
// not the fastest implementation - quick and dirty - jlim
// for best performance, use the actual $rs->MetaType().
function MetaType($t,$len=-1,$fieldobj=false)
{
if (empty($this->_metars)) {
$rsclass = $this->last_module_name . "_ResultSet";
$this->_metars =& new $rsclass(false,$this->fetchMode);
}
return $this->_metars->MetaType($t,$len,$fieldobj);
}
/**
* return the databases that the driver can connect to.
* Some databases will return an empty array.
*
* @return an array of database names.
*/
function MetaDatabases()
{
global $ADODB_FETCH_MODE;
if ($this->metaDatabasesSQL) {
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
$arr = $this->GetCol($this->metaDatabasesSQL);
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
return $arr;
}
return false;
}
/**
* @param ttype can either be 'VIEW' or 'TABLE' or false.
* If false, both views and tables are returned.
* "VIEW" returns only views
* "TABLE" returns only tables
* @param showSchema returns the schema/user with the table name, eg. USER.TABLE
* @param mask is the input mask - only supported by oci8 and postgresql
*
* @return array of tables for current database.
*/
function &MetaTables($ttype=false,$showSchema=false,$mask=false)
{
global $ADODB_FETCH_MODE;
$false = false;
if ($mask) {
return $false;
}
if ($this->metaTablesSQL) {
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
$rs = $this->Execute($this->metaTablesSQL);
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
if ($rs === false) return $false;
$arr =& $rs->GetArray();
$arr2 = array();
if ($hast = ($ttype && isset($arr[0][1]))) {
$showt = strncmp($ttype,'T',1);
}
for ($i=0; $i < sizeof($arr); $i++) {
if ($hast) {
if ($showt == 0) {
if (strncmp($arr[$i][1],'T',1) == 0) $arr2[] = trim($arr[$i][0]);
} else {
if (strncmp($arr[$i][1],'V',1) == 0) $arr2[] = trim($arr[$i][0]);
}
} else
$arr2[] = trim($arr[$i][0]);
}
$rs->Close();
return $arr2;
}
return $false;
}
function _findschema(&$table,&$schema)
{
if (!$schema && ($at = strpos($table,'.')) !== false) {
$schema = substr($table,0,$at);
$table = substr($table,$at+1);
}
}
/**
* List columns in a database as an array of ADOFieldObjects.
* See top of file for definition of object.
*
* @param $table table name to query
* @param $normalize makes table name case-insensitive (required by some databases)
* @schema is optional database schema to use - not supported by all databases.
*
* @return array of ADOFieldObjects for current table.
*/
function &MetaColumns($tab)
{
global $ADODB_FETCH_MODE;
$false = false;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
$rs = $this->Execute("PRAGMA table_info('$tab')");
if (isset($savem)) $this->SetFetchMode($savem);
if (!$rs) {
$ADODB_FETCH_MODE = $save;
return $false;
}
$arr = array();
while ($r = $rs->FetchRow()) {
$type = explode('(',$r['type']);
$size = '';
if (sizeof($type)==2)
$size = trim($type[1],')');
$fn = strtoupper($r['name']);
$fld = new ADOFieldObject;
$fld->name = $r['name'];
$fld->type = $type[0];
$fld->max_length = $size;
$fld->not_null = $r['notnull'];
$fld->default_value = $r['dflt_value'];
$fld->scale = 0;
if ($save == ADODB_FETCH_NUM) $arr[] = $fld;
else $arr[strtoupper($fld->name)] = $fld;
}
$rs->Close();
$ADODB_FETCH_MODE = $save;
return $arr;
}
/**
* List indexes on a table as an array.
* @param table table name to query
* @param primary true to only show primary keys. Not actually used for most databases
*
* @return array of indexes on current table. Each element represents an index, and is itself an associative array.
Array (
[name_of_index] => Array
(
[unique] => true or false
[columns] => Array
(
[0] => firstname
[1] => lastname
)
)
*/
function &MetaIndexes($table, $primary = FALSE, $owner=false)
{
$false = false;
// save old fetch mode
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== FALSE) {
$savem = $this->SetFetchMode(FALSE);
}
$SQL=sprintf("SELECT name,sql FROM sqlite_master WHERE type='index' AND tbl_name='%s'", strtolower($table));
$rs = $this->Execute($SQL);
if (!is_object($rs)) {
if (isset($savem))
$this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
return $false;
}
$indexes = array ();
while ($row = $rs->FetchRow()) {
if ($primary && preg_match("/primary/i",$row[1]) == 0) continue;
if (!isset($indexes[$row[0]])) {
$indexes[$row[0]] = array(
'unique' => preg_match("/unique/i",$row[1]),
'columns' => array());
}
/**
* There must be a more elegant way of doing this,
* the index elements appear in the SQL statement
* in cols[1] between parentheses
* e.g CREATE UNIQUE INDEX ware_0 ON warehouse (org,warehouse)
*/
$cols = explode("(",$row[1]);
$cols = explode(")",$cols[1]);
array_pop($cols);
$indexes[$row[0]]['columns'] = $cols;
}
if (isset($savem)) {
$this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
}
return $indexes;
}
/**
* List columns names in a table as an array.
* @param table table name to query
*
* @return array of column names for current table.
*/
function &MetaColumnNames($table, $numIndexes=false,$useattnum=false /* only for postgres */)
{
$objarr =& $this->MetaColumns($table);
if (!is_array($objarr)) {
$false = false;
return $false;
}
$arr = array();
if ($numIndexes) {
$i = 0;
if ($useattnum) {
foreach($objarr as $v)
$arr[$v->attnum] = $v->name;
} else
foreach($objarr as $v) $arr[$i++] = $v->name;
} else
foreach($objarr as $v) $arr[strtoupper($v->name)] = $v->name;
return $arr;
}
function MetaTransaction($mode,$db)
{
$mode = strtoupper($mode);
$mode = str_replace('ISOLATION LEVEL ','',$mode);
switch($mode) {
case 'READ UNCOMMITTED':
switch($db) {
case 'oci8':
case 'oracle':
return 'ISOLATION LEVEL READ COMMITTED';
default:
return 'ISOLATION LEVEL READ UNCOMMITTED';
}
break;
case 'READ COMMITTED':
return 'ISOLATION LEVEL READ COMMITTED';
break;
case 'REPEATABLE READ':
switch($db) {
case 'oci8':
case 'oracle':
return 'ISOLATION LEVEL SERIALIZABLE';
default:
return 'ISOLATION LEVEL REPEATABLE READ';
}
break;
case 'SERIALIZABLE':
return 'ISOLATION LEVEL SERIALIZABLE';
break;
default:
return $mode;
}
}
}
eval('class sqlite_meta_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class sqlite_meta_ResultSet extends sqlite_meta_resultset_EXTENDER
{
/**
* Get the metatype of the column. This is used for formatting. This is because
* many databases use different names for the same type, so we transform the original
* type to our standardised version which uses 1 character codes:
*
* @param t is the type passed in. Normally is ADOFieldObject->type.
* @param len is the maximum length of that field. This is because we treat character
* fields bigger than a certain size as a 'B' (blob).
* @param fieldobj is the field object returned by the database driver. Can hold
* additional info (eg. primary_key for mysql).
*
* @return the general type of the data:
* C for character < 250 chars
* X for teXt (>= 250 chars)
* B for Binary
* N for numeric or floating point
* D for date
* T for timestamp
* L for logical/Boolean
* I for integer
* R for autoincrement counter/integer
*
*
*/
function MetaType($t,$len=-1,$fieldobj=false)
{
if (is_object($t)) {
$fieldobj = $t;
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
$len = -1; // mysql max_length is not accurate
switch (strtoupper($t)) {
case 'STRING':
case 'CHAR':
case 'VARCHAR':
case 'TINYBLOB':
case 'TINYTEXT':
case 'ENUM':
case 'SET':
if ($len <= $this->blobSize) return 'C';
case 'TEXT':
case 'LONGTEXT':
case 'MEDIUMTEXT':
return 'X';
// php_mysql extension always returns 'blob' even if 'text'
// so we have to check whether binary...
case 'IMAGE':
case 'LONGBLOB':
case 'BLOB':
case 'MEDIUMBLOB':
return !empty($fieldobj->binary) ? 'B' : 'X';
case 'YEAR':
case 'DATE': return 'D';
case 'TIME':
case 'DATETIME':
case 'TIMESTAMP': return 'T';
case 'INT':
case 'INTEGER':
case 'BIGINT':
case 'TINYINT':
case 'MEDIUMINT':
case 'SMALLINT':
if (!empty($fieldobj->primary_key)) return 'R';
else return 'I';
default:
static $typeMap = array(
'VARCHAR' => 'C',
'VARCHAR2' => 'C',
'CHAR' => 'C',
'C' => 'C',
'STRING' => 'C',
'NCHAR' => 'C',
'NVARCHAR' => 'C',
'VARYING' => 'C',
'BPCHAR' => 'C',
'CHARACTER' => 'C',
'INTERVAL' => 'C', # Postgres
'MACADDR' => 'C', # postgres
##
'LONGCHAR' => 'X',
'TEXT' => 'X',
'NTEXT' => 'X',
'M' => 'X',
'X' => 'X',
'CLOB' => 'X',
'NCLOB' => 'X',
'LVARCHAR' => 'X',
##
'BLOB' => 'B',
'IMAGE' => 'B',
'BINARY' => 'B',
'VARBINARY' => 'B',
'LONGBINARY' => 'B',
'B' => 'B',
##
'YEAR' => 'D', // mysql
'DATE' => 'D',
'D' => 'D',
##
'UNIQUEIDENTIFIER' => 'C', # MS SQL Server
##
'TIME' => 'T',
'TIMESTAMP' => 'T',
'DATETIME' => 'T',
'TIMESTAMPTZ' => 'T',
'T' => 'T',
'TIMESTAMP WITHOUT TIME ZONE' => 'T', // postgresql
##
'BOOL' => 'L',
'BOOLEAN' => 'L',
'BIT' => 'L',
'L' => 'L',
##
'COUNTER' => 'R',
'R' => 'R',
'SERIAL' => 'R', // ifx
'INT IDENTITY' => 'R',
##
'INT' => 'I',
'INT2' => 'I',
'INT4' => 'I',
'INT8' => 'I',
'INTEGER' => 'I',
'INTEGER UNSIGNED' => 'I',
'SHORT' => 'I',
'TINYINT' => 'I',
'SMALLINT' => 'I',
'I' => 'I',
##
'LONG' => 'N', // interbase is numeric, oci8 is blob
'BIGINT' => 'N', // this is bigger than PHP 32-bit integers
'DECIMAL' => 'N',
'DEC' => 'N',
'REAL' => 'N',
'DOUBLE' => 'N',
'DOUBLE PRECISION' => 'N',
'SMALLFLOAT' => 'N',
'FLOAT' => 'N',
'NUMBER' => 'N',
'NUM' => 'N',
'NUMERIC' => 'N',
'MONEY' => 'N',
## informix 9.2
'SQLINT' => 'I',
'SQLSERIAL' => 'I',
'SQLSMINT' => 'I',
'SQLSMFLOAT' => 'N',
'SQLFLOAT' => 'N',
'SQLMONEY' => 'N',
'SQLDECIMAL' => 'N',
'SQLDATE' => 'D',
'SQLVCHAR' => 'C',
'SQLCHAR' => 'C',
'SQLDTIME' => 'T',
'SQLINTERVAL' => 'N',
'SQLBYTES' => 'B',
'SQLTEXT' => 'X',
## informix 10
"SQLINT8" => 'I8',
"SQLSERIAL8" => 'I8',
"SQLNCHAR" => 'C',
"SQLNVCHAR" => 'C',
"SQLLVARCHAR" => 'X',
"SQLBOOL" => 'L'
);
$tmap = false;
$t = strtoupper($t);
$tmap = (isset($typeMap[$t])) ? $typeMap[$t] : 'N';
if ($t == 'LONG' && $this->dataProvider == 'oci8') return 'B';
return $tmap;
}
}
}
?>
@@ -0,0 +1,132 @@
<?php
/**
* ADOdb Lite Transaction Module for Sqlite
*
*/
eval('class sqlite_transaction_EXTENDER extends '. $last_module . '_ADOConnection { }');
class sqlite_transaction_ADOConnection extends sqlite_transaction_EXTENDER
{
var $autoCommit = true;
var $transOff = 0;
var $transCnt = 0;
var $transaction_status = true;
function StartTrans($errfn = 'ADODB_TransMonitor')
{
if ($this->transOff > 0) {
$this->transOff += 1;
return;
}
$this->transaction_status = true;
if ($this->debug && $this->transCnt > 0)
ADOConnection::outp("Bad Transaction: StartTrans called within BeginTrans");
$this->BeginTrans();
$this->transOff = 1;
}
function BeginTrans()
{
if ($this->transOff)
return true;
$ret = $this->Execute("BEGIN TRANSACTION");
$this->transCnt += 1;
return true;
}
function CompleteTrans($autoComplete = true)
{
if ($this->transOff > 1) {
$this->transOff -= 1;
return true;
}
$this->transOff = 0;
if ($this->transaction_status && $autoComplete) {
if (!$this->CommitTrans()) {
$this->transaction_status = false;
if ($this->debug)
ADOConnection::outp("Smart Commit failed");
} else
if ($this->debug)
ADOConnection::outp("Smart Commit occurred");
} else {
$this->RollbackTrans();
if ($this->debug)
ADOCOnnection::outp("Smart Rollback occurred");
}
return $this->transaction_status;
}
function CommitTrans($ok=true)
{
if ($this->transOff)
return true;
if (!$ok)
return $this->RollbackTrans();
$ret = $this->Execute("COMMIT");
if ($this->transCnt>0)
$this->transCnt -= 1;
return !empty($ret);
}
function RollbackTrans()
{
if ($this->transOff)
return true;
$ret = $this->Execute("ROLLBACK");
if ($this->transCnt>0)
$this->transCnt -= 1;
return !empty($ret);
}
function FailTrans()
{
if ($this->debug)
if ($this->transOff == 0) {
ADOConnection::outp("FailTrans outside StartTrans/CompleteTrans");
} else {
ADOConnection::outp("FailTrans was called");
}
$this->transaction_status = false;
}
function HasFailedTrans()
{
if ($this->transOff > 0)
return $this->transaction_status == false;
return false;
}
function RowLock($tables,$where,$flds='1 as ignore')
{
return false;
}
function CommitLock($table)
{
return $this->CommitTrans();
}
function RollbackLock($table)
{
return $this->RollbackTrans();
}
}
eval('class sqlite_transaction_resultset_EXTENDER extends '. $last_module . '_ResultSet { }');
class sqlite_transaction_ResultSet extends sqlite_transaction_resultset_EXTENDER
{
}
?>
@@ -0,0 +1,41 @@
<?php
// Generic adodblite Module
eval('class adodblite_EXTENDER extends ' . $last_module . '_ADOConnection { }');
class adodblite_ADOConnection extends adodblite_EXTENDER
{
function &GetToFieldArray($sql, $inputarr=false, $fieldname = false)
{
$data = false;
$result =& $this->Execute($sql, $inputarr);
if ($result) {
$data =& $result->GetToFieldArray($fieldname);
$result->Close();
}
return $data;
}
}
eval('class adodblite_resultset_EXTENDER extends ' . $last_module . '_ResultSet { }');
class adodblite_ResultSet extends adodblite_resultset_EXTENDER
{
function &GetToFieldArray($fieldname = false)
{
$results = false;
if(!$fieldname)
{
return $results;
}
while (!$this->EOF) {
$results[$this->fields[$fieldname]] = $this->fields;
$this->MoveNext();
}
return $results;
}
}
?>
+226
View File
@@ -0,0 +1,226 @@
<?php
// Generic Menu Module
eval('class menu_EXTENDER extends ' . $last_module . '_ADOConnection { }');
class menu_ADOConnection extends menu_EXTENDER
{
}
eval('class menu_resultset_EXTENDER extends ' . $last_module . '_ResultSet { }');
class menu_ResultSet extends menu_resultset_EXTENDER
{
// Requires $ADODB_FETCH_MODE = ADODB_FETCH_NUM
function GetMenu($name, $defstr='', $blank1stItem=true, $multiple=false, $size=0, $selectAttr='', $compareFields0=true)
{
$hasvalue = false;
if($multiple or is_array($defstr))
{
if($size==0)
$size=5;
$attr = ' multiple size="'.$size.'"';
if(!strpos($name,'[]'))
$name .= '[]';
}
else if($size)
$attr = ' size="'.$size.'"';
else $attr ='';
$s = '<select name="'.$name.'"'.$attr.' '.$selectAttr.'>';
if($blank1stItem)
if(is_string($blank1stItem))
{
$barr = explode(':',$blank1stItem);
if(sizeof($barr) == 1)
$barr[] = '';
$s .= "\n<option value=\"".$barr[0]."\">".$barr[1]."</option>";
} else $s .= "\n<option></option>";
if($this->FieldCount() > 1)
$hasvalue=true;
else $compareFields0 = true;
$value = '';
$optgroup = null;
$firstgroup = true;
$fieldsize = $this->FieldCount();
while(!$this->EOF)
{
$zval = rtrim(reset($this->fields));
if($blank1stItem && $zval=="")
{
$this->MoveNext();
continue;
}
if($fieldsize > 1)
{
if(isset($this->fields[1]))
$zval2 = rtrim($this->fields[1]);
else
$zval2 = rtrim(next($this->fields));
}
$selected = ($compareFields0) ? $zval : $zval2;
$group = '';
if($fieldsize > 2)
{
$group = rtrim($this->fields[2]);
}
if($optgroup != $group)
{
$optgroup = $group;
if($firstgroup)
{
$firstgroup = false;
$s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
}
else
{
$s .="\n</optgroup>";
$s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
}
}
if($hasvalue)
$value = " value='".htmlspecialchars($zval2)."'";
if(is_array($defstr))
{
if(in_array($selected,$defstr))
$s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
else
$s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
}
else
{
if(strcasecmp($selected,$defstr)==0)
$s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
else
$s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
}
$this->MoveNext();
} // while
// closing last optgroup
if($optgroup != null)
{
$s .= "\n</optgroup>";
}
return $s ."\n</select>\n";
}
function GetMenu2($name,$defstr='',$blank1stItem=true,$multiple=false,$size=0, $selectAttr='')
{
return $this->GetMenu($name, $defstr, $blank1stItem, $multiple, $size, $selectAttr, false);
}
function GetMenu3($name, $defstr='', $blank1stItem=true, $multiple=false, $size=0, $selectAttr='')
{
$hasvalue = false;
if($multiple or is_array($defstr))
{
if($size==0)
$size=5;
$attr = ' multiple size="'.$size.'"';
if(!strpos($name,'[]'))
$name .= '[]';
}
else if($size)
$attr = ' size="'.$size.'"';
else $attr ='';
$s = '<select name="'.$name.'"'.$attr.' '.$selectAttr.'>';
if($blank1stItem)
if(is_string($blank1stItem))
{
$barr = explode(':',$blank1stItem);
if(sizeof($barr) == 1)
$barr[] = '';
$s .= "\n<option value=\"".$barr[0]."\">".$barr[1]."</option>";
} else $s .= "\n<option></option>";
if($this->FieldCount() > 1)
$hasvalue=true;
else $compareFields0 = true;
$value = '';
$optgroup = null;
$firstgroup = true;
$fieldsize = sizeof($this->fields);
while(!$this->EOF)
{
$zval = rtrim(reset($this->fields));
if($blank1stItem && $zval=="")
{
$this->MoveNext();
continue;
}
if($fieldsize > 1)
{
if(isset($this->fields[1]))
$zval2 = rtrim($this->fields[1]);
else
$zval2 = rtrim(next($this->fields));
}
$selected = ($compareFields0) ? $zval : $zval2;
$group = '';
if(isset($this->fields[2]))
{
$group = rtrim($this->fields[2]);
}
if($optgroup != $group)
{
$optgroup = $group;
if($firstgroup)
{
$firstgroup = false;
$s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
}
else
{
$s .="\n</optgroup>";
$s .="\n<optgroup label='". htmlspecialchars($group) ."'>";
}
}
if($hasvalue)
$value = " value='".htmlspecialchars($zval2)."'";
if(is_array($defstr))
{
if(in_array($selected,$defstr))
$s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
else
$s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
}
else
{
if(strcasecmp($selected,$defstr)==0)
$s .= "\n<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
else
$s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
}
$this->MoveNext();
} // while
// closing last optgroup
if($optgroup != null)
{
$s .= "\n</optgroup>";
}
return $s ."\n</select>\n";
}
}
?>
@@ -0,0 +1,99 @@
<?php
// Generic Object Module
eval('class object_EXTENDER extends ' . $last_module . '_ADOConnection { }');
class object_ADOConnection extends object_EXTENDER
{
}
class ADOFetchObj
{
}
eval('class object_resultset_EXTENDER extends ' . $last_module . '_ResultSet { }');
class object_ResultSet extends object_resultset_EXTENDER
{
var $_obj;
var $_names;
function &FetchObj()
{
$object =& $this->FetchObject(false);
return $object;
}
function &FetchObject($isupper=true)
{
if (empty($this->_obj))
{
$this->_obj = new ADOFetchObj();
$this->_names = array();
for ($i=0; $i <$this->_numOfFields; $i++)
{
$field = $this->FetchField($i);
$this->_names[] = $field->name;
}
}
$i = 0;
if (PHP_VERSION >= 5)
$object = clone($this->_obj);
else $object = $this->_obj;
for ($i=0; $i <$this->_numOfFields; $i++)
{
$name = $this->_names[$i];
if ($isupper)
$newname = strtoupper($name);
else $newname = $name;
$object->$newname = $this->Fields($name);
}
return $object;
}
function &FetchNextObj()
{
$object =& $this->FetchNextObject(false);
return $object;
}
function &FetchNextObject($isupper=true)
{
$object = false;
if ($this->_numOfRows != 0 && !$this->EOF) {
$object = $this->FetchObject($isupper);
$this->_currentRow++;
if ($this->_fetch())
return $object;
}
$this->EOF = true;
return $object;
}
/* Load a list of database objects
* @param string The field name of a primary key
* @return array If <var>key</var> is empty as sequential list of returned records.
* If <var>key</var> is not empty then the returned array is indexed by the value
* the database key. Returns <var>null</var> if the query fails.
*/
function &loadObjectList( $key='' )
{
$array = array();
while ($row = $this->FetchNextObject(false))
{
if ($key)
{
$array[$row->$key] = $row;
}
else
{
$array[] = $row;
}
}
return $array;
}
}
?>
+192
View File
@@ -0,0 +1,192 @@
<?php
// Generic Pear Module
// This module contains alternative Pear commands.
eval('class pear_EXTENDER extends ' . $last_module . '_ADOConnection { }');
class pear_ADOConnection extends pear_EXTENDER
{
/**
* Set how select queries will retrieve data.
* Usage: $oldmode = $db->SetFetchMode($mode)
*
* @param mode The fetchmode ADODB_FETCH_ASSOC or ADODB_FETCH_NUM
* @returns The previous fetch mode
*/
function SetFetchMode($mode)
{
GLOBAL $ADODB_FETCH_MODE;
$old = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = $mode;
return $old;
}
/**
* Returns the last record id of an inserted item
* Usage: $db->GetCol($sql);
*
* @access public
*/
function GetCol($sql, $inputarr = false, $trim = false)
{
$data = false;
$result =& $this->do_query($sql, -1, -1, $inputarr);
if ($result) {
$data = array();
while (!$result->EOF) {
$data[] = ($trim) ? trim(reset($result->fields)) : reset($result->fields);
$result->MoveNext();
}
$result->Close();
}
return $data;
}
/**
* Return first element of first row of sql statement. Recordset is disposed
* for you.
*
* Usage: $db->GetOne($sql);
* @access public
*/
function &GetOne($sql, $inputarr = false)
{
$data =& $this->GetRow($sql, $inputarr, true);
return $data;
}
/**
* Return one row of sql statement. Recordset is disposed for you.
*
* Usage: $db->GetRow($sql);
* @access public
*/
function &GetRow($sql, $inputarr = false, $getone = false)
{
$data = false;
$result =& $this->do_query($sql, -1, -1, $inputarr);
if ($result) {
if ($getone)
{
if (!$result->EOF) $data = reset($result->fields);
}
else
{
if (!$result->EOF) $data = $result->fields;
else $data = array();
}
$result->Close();
}
return $data;
}
/**
* PEAR DB Compat - do not use internally
*/
function &Query($sql, $inputarr = false)
{
$rs =& $this->do_query($sql, -1, -1, $inputarr);
return $rs;
}
/**
* PEAR DB Compat - do not use internally
*/
function &LimitQuery($sql, $offset, $nrows, $inputarr = false)
{
$rs =& $this->do_query($sql, $nrows, $offset, $inputarr);
return $rs;
}
/**
* PEAR DB Compat - do not use internally
*/
function Disconnect()
{
return $this->Close();
}
/**
* PEAR DB Compat - do not use internally
*/
function ErrorNative()
{
return $this->ErrorNo();
}
/**
* PEAR DB Compat - do not use internally
*/
function Quote($string)
{
return $this->qstr($string, false);
}
}
eval('class pear_resultset_EXTENDER extends ' . $last_module . '_ResultSet { }');
class pear_ResultSet extends pear_resultset_EXTENDER
{
/**
* PEAR DB Compatable Command
*/
function Free()
{
return $this->Close();
}
/**
* PEAR DB Compatable Command
*/
function NumRows()
{
return $this->_numOfRows;
}
/**
* PEAR DB Compatable Command
*/
function NumCols()
{
return $this->_numOfFields;
}
/**
* Fetch a row, returning false if no more rows.
* PEAR DB Compatable Command
*
* @return false or array containing the current record
*/
function FetchRow()
{
if ($this->EOF) {
$false = false;
return $false;
}
$arr = $this->fields;
$this->_currentRow++;
if (!$this->_fetch()) $this->EOF = true;
return $arr;
}
/**
* Fetch a row, returning PEAR_Error if no more rows.
* PEAR DB Compatable Command
*
*/
function FetchInto(&$arr)
{
$false = false;
$true = 1;
if ($this->EOF) return $false;
$arr = $this->fields;
$this->MoveNext();
return $true;
}
}
?>
+144
View File
@@ -0,0 +1,144 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things.
To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others.
Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs.
When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library.
We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances.
For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system.
Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library.
Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library.
You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful.
(For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.)
These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library.
In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices.
Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange.
If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things:
a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place.
e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute.
7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above.
b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License.
11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
+32
View File
@@ -0,0 +1,32 @@
<?php
/*
* This file is part of Trevorchan.
*
* Trevorchan is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* Trevorchan is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* Trevorchan; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* +------------------------------------------------------------------------------+
* Smarty engine initialization and configuration
* +------------------------------------------------------------------------------+
*/
//require_once KU_ROOTDIR . 'lib/smarty/Smarty.class.php';
// Include the main Dwoo class and the Smarty Adapter class
include 'lib/dwoo/Dwoo.compiled.php';
//include 'lib/dwoo/Dwoo/Smarty/Adapter.php';
//$smarty = new Dwoo_Smarty_Adapter();
$dwoo = new Dwoo();
$dwoo_data = new Dwoo_Data();
?>
+1
View File
@@ -0,0 +1 @@
<?php define('DWOO_DIRECTORY', dirname(__FILE__) . DIRECTORY_SEPARATOR); class Dwoo { const VERSION = '1.0.1'; const RELEASE_TAG = 15; const CLASS_PLUGIN = 1; const FUNC_PLUGIN = 2; const NATIVE_PLUGIN = 4; const BLOCK_PLUGIN = 8; const COMPILABLE_PLUGIN = 16; const CUSTOM_PLUGIN = 32; const SMARTY_MODIFIER = 64; const SMARTY_BLOCK = 128; const SMARTY_FUNCTION = 256; const PROXY_PLUGIN = 512; protected $charset = 'utf-8'; protected $globals; protected $compileDir; protected $cacheDir; protected $cacheTime = 0; protected $securityPolicy = null; protected $plugins = array(); protected $filters = array(); protected $resources = array ( 'file' => array ( 'class' => 'Dwoo_Template_File', 'compiler' => null ), 'string' => array ( 'class' => 'Dwoo_Template_String', 'compiler' => null ) ); protected $loader = null; protected $template = null; protected $runtimePlugins; protected $data; protected $scope; protected $scopeTree; protected $stack; protected $curBlock; protected $buffer; protected $pluginProxy; public function __construct($compileDir = KU_CACHEDTEMPLATEDIR, $cacheDir = KU_CACHEDTEMPLATEDIR) { if ($compileDir !== null) { $this->setCompileDir($compileDir); } if ($cacheDir !== null) { $this->setCacheDir($cacheDir); } } public function __clone() { $this->template = null; unset($this->data); } public function output($tpl, $data = array(), Dwoo_ICompiler $compiler = null) { return $this->get($tpl, $data, $compiler, true); } public function get($_tpl, $data = array(), $_compiler = null, $_output = false) { if ($this->template instanceof Dwoo_ITemplate) { $proxy = clone $this; return $proxy->get($_tpl, $data, $_compiler, $_output); } if ($_tpl instanceof Dwoo_ITemplate) { } elseif (is_string($_tpl) && file_exists($_tpl)) { $_tpl = new Dwoo_Template_File($_tpl); } else { throw new Dwoo_Exception('Dwoo->get/Dwoo->output\'s first argument must be a Dwoo_ITemplate (i.e. Dwoo_Template_File) or a valid path to a template file', E_USER_NOTICE); } $this->template = $_tpl; if ($data instanceof Dwoo_IDataProvider) { $this->data = $data->getData(); } elseif (is_array($data)) { $this->data = $data; } else { throw new Dwoo_Exception('Dwoo->get/Dwoo->output\'s data argument must be a Dwoo_IDataProvider object (i.e. Dwoo_Data) or an associative array', E_USER_NOTICE); } $this->initGlobals($_tpl); $this->initRuntimeVars($_tpl); $file = $_tpl->getCachedTemplate($this); $doCache = $file === true; $cacheLoaded = is_string($file); if ($cacheLoaded === true) { if ($_output === true) { include $file; $this->template = null; } else { ob_start(); include $file; $this->template = null; return ob_get_clean(); } } else { if ($doCache === true) { $dynamicId = uniqid(); } $out = include $_tpl->getCompiledTemplate($this, $_compiler); if ($out === false) { $_tpl->forceCompilation(); $out = include $_tpl->getCompiledTemplate($this, $_compiler); } if ($doCache === true) { $out = preg_replace('/(<%|%>|<\?php|<\?|\?>)/', '<?php /*'.$dynamicId.'*/ echo \'$1\'; ?>', $out); if (!class_exists('Dwoo_plugin_dynamic', false)) { $this->getLoader()->loadPlugin('dynamic'); } $out = Dwoo_Plugin_dynamic::unescape($out, $dynamicId); } foreach ($this->filters as $filter) { if (is_array($filter) && $filter[0] instanceof Dwoo_Filter) { $out = call_user_func($filter, $out); } else { $out = call_user_func($filter, $this, $out); } } if ($doCache === true) { $file = $_tpl->cache($this, $out); if ($_output === true) { include $file; $this->template = null; } else { ob_start(); include $file; $this->template = null; return ob_get_clean(); } } else { $this->template = null; if ($_output === true) { echo $out; } else { return $out; } } } } protected function initGlobals(Dwoo_ITemplate $tpl) { $this->globals = array ( 'version' => self::VERSION, 'ad' => '<a href="http://dwoo.org/">Powered by Dwoo</a>', 'now' => $_SERVER['REQUEST_TIME'], 'template' => $tpl->getName(), 'charset' => $this->charset, ); } protected function initRuntimeVars(Dwoo_ITemplate $tpl) { $this->runtimePlugins = array(); $this->scope =& $this->data; $this->scopeTree = array(); $this->stack = array(); $this->curBlock = null; $this->buffer = ''; } public function addPlugin($name, $callback, $compilable = false) { $compilable = $compilable ? self::COMPILABLE_PLUGIN : 0; if (is_array($callback)) { if (is_subclass_of(is_object($callback[0]) ? get_class($callback[0]) : $callback[0], 'Dwoo_Block_Plugin')) { $this->plugins[$name] = array('type'=>self::BLOCK_PLUGIN | $compilable, 'callback'=>$callback, 'class'=>(is_object($callback[0]) ? get_class($callback[0]) : $callback[0])); } else { $this->plugins[$name] = array('type'=>self::CLASS_PLUGIN | $compilable, 'callback'=>$callback, 'class'=>(is_object($callback[0]) ? get_class($callback[0]) : $callback[0]), 'function'=>$callback[1]); } } elseif (class_exists($callback, false)) { if (is_subclass_of($callback, 'Dwoo_Block_Plugin')) { $this->plugins[$name] = array('type'=>self::BLOCK_PLUGIN | $compilable, 'callback'=>$callback, 'class'=>$callback); } else { $this-Line truncated
+38
View File
@@ -0,0 +1,38 @@
<?php
/**
* dwoo compilation exception class
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Compilation_Exception extends Dwoo_Exception
{
protected $compiler;
protected $template;
public function __construct(Dwoo_Compiler $compiler, $message)
{
$this->compiler = $compiler;
$this->template = $compiler->getDwoo()->getTemplate();
parent::__construct('Compilation error at line '.$compiler->getLine().' in "'.$this->template->getResourceName().':'.$this->template->getResourceIdentifier().'" : '.$message);
}
public function getCompiler()
{
return $this->compiler;
}
public function getTemplate()
{
return $this->template;
}
}
File diff suppressed because it is too large. Load diff
+67
View File
@@ -0,0 +1,67 @@
<?php
/**
* Outputs a html &lt;a&gt; tag
* <pre>
* * href : the target URI where the link must point
* * rest : any other attributes you want to add to the tag can be added as named parameters
* </pre>
*
* Example :
*
* <code>
* {* Create a simple link out of an url variable and add a special class attribute: *}
*
* {a $url class="external" /}
*
* {* Mark a link as active depending on some other variable : *}
*
* {a $link.url class=tif($link.active "active"); $link.title /}
*
* {* This is similar to: <a href="{$link.url}" class="{if $link.active}active{/if}">{$link.title}</a> *}
* </code>
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Plugin_a extends Dwoo_Block_Plugin implements Dwoo_ICompilable_Block
{
public function init($href, array $rest=array())
{
}
public static function preProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $type)
{
$p = $compiler->getCompiledParams($params);
$out = Dwoo_Compiler::PHP_OPEN . 'echo \'<a '.self::paramsToAttributes($p);
return $out.'>\';' . Dwoo_Compiler::PHP_CLOSE;
}
public static function postProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $content)
{
$p = $compiler->getCompiledParams($params);
// no content was provided so use the url as display text
if ($content == "") {
// merge </a> into the href if href is a string
if (substr($p['href'], -1) === '"' || substr($p['href'], -1) === '\'') {
return Dwoo_Compiler::PHP_OPEN . 'echo '.substr($p['href'], 0, -1).'</a>'.substr($p['href'], -1).';'.Dwoo_Compiler::PHP_CLOSE;
}
// otherwise append
return Dwoo_Compiler::PHP_OPEN . 'echo '.$p['href'].'.\'</a>\';'.Dwoo_Compiler::PHP_CLOSE;
}
// return content
return $content . '</a>';
}
}
@@ -0,0 +1,61 @@
<?php
/**
* Overrides the compiler auto-escape setting within the block
* <pre>
* * enabled : if set to "on", "enable", true or 1 then the compiler autoescaping is enabled inside this block. set to "off", "disable", false or 0 to disable it
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Plugin_auto_escape extends Dwoo_Block_Plugin implements Dwoo_ICompilable_Block
{
protected static $stack = array();
public function init($enabled)
{
}
public static function preProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $type)
{
$params = $compiler->getCompiledParams($params);
switch(strtolower(trim((string) $params['enabled'], '"\''))) {
case 'on':
case 'true':
case 'enabled':
case 'enable':
case '1':
$enable = true;
break;
case 'off':
case 'false':
case 'disabled':
case 'disable':
case '0':
$enable = false;
break;
default:
throw new Dwoo_Compilation_Exception($compiler, 'Auto_Escape : Invalid parameter ('.$params['enabled'].'), valid parameters are "enable"/true or "disable"/false');
}
self::$stack[] = $compiler->getAutoEscape();
$compiler->setAutoEscape($enable);
return '';
}
public static function postProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $content)
{
$compiler->setAutoEscape(array_pop(self::$stack));
return $content;
}
}
+34
View File
@@ -0,0 +1,34 @@
<?php
/**
* This is used only when rendering a template that has blocks but is not extending anything,
* it doesn't do anything by itself and should not be used outside of template inheritance context,
* see {@link http://wiki.dwoo.org/index.php/TemplateInheritance} to read more about it.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Plugin_block extends Dwoo_Block_Plugin implements Dwoo_ICompilable_Block
{
public function init($name='')
{
}
public static function preProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $type)
{
return '';
}
public static function postProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $content)
{
return $content;
}
}
@@ -0,0 +1,61 @@
<?php
/**
* Captures all the output within this block and saves it into {$.capture.default} by default,
* or {$.capture.name} if you provide another name.
* <pre>
* * name : capture name, used to read the value afterwards
* * assign : if set, the value is also saved in the given variable
* * cat : if true, the value is appended to the previous one (if any) instead of overwriting it
* </pre>
* If the cat parameter is true, the content
* will be appended to the existing content
*
* Example :
*
* <code>
* {capture "foo"}
* Anything in here won't show, it will be saved for later use..
* {/capture}
* Output was : {$.capture.foo}
* </code>
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Plugin_capture extends Dwoo_Block_Plugin implements Dwoo_ICompilable_Block
{
public function init($name = 'default', $assign = null, $cat = false, $trim = false)
{
}
public static function preProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $type)
{
return Dwoo_Compiler::PHP_OPEN.$prepend.'ob_start();'.$append.Dwoo_Compiler::PHP_CLOSE;
}
public static function postProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $content)
{
$params = $compiler->getCompiledParams($params);
$out = $content . Dwoo_Compiler::PHP_OPEN.$prepend."\n".'$tmp = ob_get_clean();';
if ($params['trim'] !== 'false' && $params['trim'] !== 0) {
$out .= "\n".'$tmp = trim($tmp);';
}
if ($params['cat'] === 'true' || $params['cat'] === 1) {
$out .= "\n".'$tmp = $this->readVar(\'dwoo.capture.\'.'.$params['name'].') . $tmp;';
}
if ($params['assign'] !== 'null') {
$out .= "\n".'$this->scope['.$params['assign'].'] = $tmp;';
}
return $out . "\n".'$this->globals[\'capture\']['.$params['name'].'] = $tmp;'.$append.Dwoo_Compiler::PHP_CLOSE;
}
}
@@ -0,0 +1,60 @@
<?php
/**
* Marks the contents of the block as dynamic. Which means that it will not be cached.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Plugin_dynamic extends Dwoo_Block_Plugin implements Dwoo_ICompilable_Block
{
public function init()
{
}
public static function preProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $type)
{
return '';
}
public static function postProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $content)
{
$output = Dwoo_Compiler::PHP_OPEN .
'if($doCache) {'."\n\t".
'echo \'<dwoo:dynamic_\'.$dynamicId.\'>'.
str_replace('\'', '\\\'', $content) .
'</dwoo:dynamic_\'.$dynamicId.\'>\';'.
"\n} else {\n\t";
if(substr($content, 0, strlen(Dwoo_Compiler::PHP_OPEN)) == Dwoo_Compiler::PHP_OPEN) {
$output .= substr($content, strlen(Dwoo_Compiler::PHP_OPEN));
} else {
$output .= Dwoo_Compiler::PHP_CLOSE . $content;
}
if(substr($output, -strlen(Dwoo_Compiler::PHP_CLOSE)) == Dwoo_Compiler::PHP_CLOSE) {
$output = substr($output, 0, -strlen(Dwoo_Compiler::PHP_CLOSE));
} else {
$output .= Dwoo_Compiler::PHP_OPEN;
}
$output .= "\n}". Dwoo_Compiler::PHP_CLOSE;
return $output;
}
public static function unescape($output, $dynamicId)
{
return preg_replace_callback('/<dwoo:dynamic_('.$dynamicId.')>(.+?)<\/dwoo:dynamic_'.$dynamicId.'>/', array('self', 'unescapePhp'), $output);
}
public static function unescapePhp($match)
{
return preg_replace('{<\?php /\*'.$match[1].'\*/ echo \'(.+?)\'; \?>}', '$1', $match[2]);
}
}
+63
View File
@@ -0,0 +1,63 @@
<?php
/**
* Generic else block, it supports all builtin optional-display blocks which are if/for/foreach/loop/with
*
* If any of those block contains an else statement, the content between {else} and {/block} (you do not
* need to close the else block) will be shown if the block's condition has no been met
*
* Example :
*
* <code>
* {foreach $array val}
* $array is not empty so we display it's values : {$val}
* {else}
* if this shows, it means that $array is empty or doesn't exist.
* {/foreach}
* </code>
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Plugin_else extends Dwoo_Block_Plugin implements Dwoo_ICompilable_Block
{
public function init()
{
}
public static function preProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $type)
{
$preContent = '';
while (true) {
$preContent .= $compiler->removeTopBlock();
$block =& $compiler->getCurrentBlock();
$interfaces = class_implements($block['class'], false);
if (in_array('Dwoo_IElseable', $interfaces) !== false) {
break;
}
}
$params['initialized'] = true;
$compiler->injectBlock($type, $params);
return $preContent;
}
public static function postProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $content)
{
if (!isset($params['initialized'])) {
return '';
}
$block =& $compiler->getCurrentBlock();
$block['params']['hasElse'] = Dwoo_Compiler::PHP_OPEN."else {\n".Dwoo_Compiler::PHP_CLOSE . $content . Dwoo_Compiler::PHP_OPEN."\n}".Dwoo_Compiler::PHP_CLOSE;
return '';
}
}
@@ -0,0 +1,60 @@
<?php
/**
* Acts as a php elseif block, allowing you to add one more condition
* if the previous one(s) didn't match. See the {if} plugin for syntax details
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Plugin_elseif extends Dwoo_Plugin_if implements Dwoo_ICompilable_Block, Dwoo_IElseable
{
public function init(array $rest)
{
}
public static function preProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $type)
{
$preContent = '';
while (true) {
$preContent .= $compiler->removeTopBlock();
$block =& $compiler->getCurrentBlock();
$interfaces = class_implements($block['class'], false);
if (in_array('Dwoo_IElseable', $interfaces) !== false) {
break;
}
}
$params['initialized'] = true;
$compiler->injectBlock($type, $params);
return $preContent;
}
public static function postProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $content)
{
if (!isset($params['initialized'])) {
return '';
}
$params = $compiler->getCompiledParams($params);
$pre = Dwoo_Compiler::PHP_OPEN."elseif (".implode(' ', self::replaceKeywords($params['*'], $compiler)).") {\n" . Dwoo_Compiler::PHP_CLOSE;
$post = Dwoo_Compiler::PHP_OPEN."\n}".Dwoo_Compiler::PHP_CLOSE;
if (isset($params['hasElse'])) {
$post .= $params['hasElse'];
}
$block =& $compiler->getCurrentBlock();
$block['params']['hasElse'] = $pre . $content . $post;
return '';
}
}
+123
View File
@@ -0,0 +1,123 @@
<?php
/**
* Similar to the php for block
* <pre>
* * name : for name to access it's iterator variables through {$.for.name.var} see {@link http://wiki.dwoo.org/index.php/IteratorVariables} for details
* * from : array to iterate from (which equals 0) or a number as a start value
* * to : value to stop iterating at (equals count($array) by default if you set an array in from)
* * step : defines the incrementation of the pointer at each iteration
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Plugin_for extends Dwoo_Block_Plugin implements Dwoo_ICompilable_Block, Dwoo_IElseable
{
public static $cnt=0;
public function init($name, $from, $to=null, $step=1, $skip=0)
{
}
public static function preProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $type)
{
// get block params and save the current template pointer to use it in the postProcessing method
$currentBlock =& $compiler->getCurrentBlock();
$currentBlock['params']['tplPointer'] = $compiler->getPointer();
return '';
}
public static function postProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $content)
{
$params = $compiler->getCompiledParams($params);
$tpl = $compiler->getTemplateSource($params['tplPointer']);
// assigns params
$from = $params['from'];
$name = $params['name'];
$step = $params['step'];
$to = $params['to'];
// evaluates which global variables have to be computed
$varName = '$dwoo.for.'.trim($name, '"\'').'.';
$shortVarName = '$.for.'.trim($name, '"\'').'.';
$usesAny = strpos($tpl, $varName) !== false || strpos($tpl, $shortVarName) !== false;
$usesFirst = strpos($tpl, $varName.'first') !== false || strpos($tpl, $shortVarName.'first') !== false;
$usesLast = strpos($tpl, $varName.'last') !== false || strpos($tpl, $shortVarName.'last') !== false;
$usesIndex = strpos($tpl, $varName.'index') !== false || strpos($tpl, $shortVarName.'index') !== false;
$usesIteration = $usesFirst || $usesLast || strpos($tpl, $varName.'iteration') !== false || strpos($tpl, $shortVarName.'iteration') !== false;
$usesShow = strpos($tpl, $varName.'show') !== false || strpos($tpl, $shortVarName.'show') !== false;
$usesTotal = $usesLast || strpos($tpl, $varName.'total') !== false || strpos($tpl, $shortVarName.'total') !== false;
// gets foreach id
$cnt = self::$cnt++;
// builds pre processing output for
$out = Dwoo_Compiler::PHP_OPEN . "\n".'$_for'.$cnt.'_from = '.$from.';'.
"\n".'$_for'.$cnt.'_to = '.$to.';'.
"\n".'$_for'.$cnt.'_step = abs('.$step.');'.
"\n".'if (is_numeric($_for'.$cnt.'_from) && !is_numeric($_for'.$cnt.'_to)) { $this->triggerError(\'For requires the <em>to</em> parameter when using a numerical <em>from</em>\'); }'.
"\n".'$tmp_shows = $this->isArray($_for'.$cnt.'_from, true) || (is_numeric($_for'.$cnt.'_from) && (abs(($_for'.$cnt.'_from - $_for'.$cnt.'_to)/$_for'.$cnt.'_step) !== 0 || $_for'.$cnt.'_from == $_for'.$cnt.'_to));';
// adds foreach properties
if ($usesAny) {
$out .= "\n".'$this->globals["for"]['.$name.'] = array'."\n(";
if ($usesIndex) $out .="\n\t".'"index" => 0,';
if ($usesIteration) $out .="\n\t".'"iteration" => 1,';
if ($usesFirst) $out .="\n\t".'"first" => null,';
if ($usesLast) $out .="\n\t".'"last" => null,';
if ($usesShow) $out .="\n\t".'"show" => $tmp_shows,';
if ($usesTotal) $out .="\n\t".'"total" => $this->isArray($_for'.$cnt.'_from) ? floor(count($_for'.$cnt.'_from) / $_for'.$cnt.'_step) : (is_numeric($_for'.$cnt.'_from) ? abs(($_for'.$cnt.'_to + 1 - $_for'.$cnt.'_from)/$_for'.$cnt.'_step) : 0),';
$out.="\n);\n".'$_for'.$cnt.'_glob =& $this->globals["for"]['.$name.'];';
}
// checks if for must be looped
$out .= "\n".'if ($tmp_shows)'."\n{";
// set from/to to correct values if an array was given
$out .= "\n\t".'if ($this->isArray($_for'.$cnt.'_from, true)) {
$_for'.$cnt.'_to = is_numeric($_for'.$cnt.'_to) ? $_for'.$cnt.'_to - $_for'.$cnt.'_step : count($_for'.$cnt.'_from) - 1;
$_for'.$cnt.'_from = 0;
}';
// reverse from and to if needed
$out .= "\n\t".'if ($_for'.$cnt.'_from > $_for'.$cnt.'_to) {
$tmp = $_for'.$cnt.'_from;
$_for'.$cnt.'_from = $_for'.$cnt.'_to;
$_for'.$cnt.'_to = $tmp;
}
for ($this->scope['.$name.'] = $_for'.$cnt.'_from; $this->scope['.$name.'] <= $_for'.$cnt.'_to; $this->scope['.$name.'] += $_for'.$cnt.'_step)'."\n\t{";
// updates properties
if ($usesIndex) {
$out.="\n\t\t".'$_for'.$cnt.'_glob["index"] = $this->scope['.$name.'];';
}
if ($usesFirst) {
$out .= "\n\t\t".'$_for'.$cnt.'_glob["first"] = (string) ($_for'.$cnt.'_glob["iteration"] === 1);';
}
if ($usesLast) {
$out .= "\n\t\t".'$_for'.$cnt.'_glob["last"] = (string) ($_for'.$cnt.'_glob["iteration"] === $_for'.$cnt.'_glob["total"]);';
}
$out .= "\n/* -- for start output */\n".Dwoo_Compiler::PHP_CLOSE;
// build post processing output and cache it
$postOut = Dwoo_Compiler::PHP_OPEN . '/* -- for end output */';
// update properties
if ($usesIteration) {
$postOut.="\n\t\t".'$_for'.$cnt.'_glob["iteration"]+=1;';
}
// end loop
$postOut .= "\n\t}\n}\n".Dwoo_Compiler::PHP_CLOSE;
if (isset($params['hasElse'])) {
$postOut .= $params['hasElse'];
}
return $out . $content . $postOut;
}
}
+148
View File
@@ -0,0 +1,148 @@
<?php
/**
* Similar to the php foreach block, loops over an array
*
* Note that if you don't provide the item parameter, the key will act as item
* <pre>
* * from : the array that you want to iterate over
* * key : variable name for the key (or for the item if item is not defined)
* * item : variable name for each item
* * name : foreach name to access it's iterator variables through {$.foreach.name.var} see {@link http://wiki.dwoo.org/index.php/IteratorVariables} for details
* </pre>
* Example :
*
* <code>
* {foreach $array val}
* {$val.something}
* {/foreach}
* </code>
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.1
* @date 2008-12-24
* @package Dwoo
*/
class Dwoo_Plugin_foreach extends Dwoo_Block_Plugin implements Dwoo_ICompilable_Block, Dwoo_IElseable
{
public static $cnt=0;
public function init($from, $key=null, $item=null, $name='default', $implode=null)
{
}
public static function preProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $type)
{
// get block params and save the current template pointer to use it in the postProcessing method
$currentBlock =& $compiler->getCurrentBlock();
$currentBlock['params']['tplPointer'] = $compiler->getPointer();
return '';
}
public static function postProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $content)
{
$params = $compiler->getCompiledParams($params);
$tpl = $compiler->getTemplateSource($params['tplPointer']);
// assigns params
$src = $params['from'];
if ($params['item'] !== 'null') {
if ($params['key'] !== 'null') {
$key = $params['key'];
}
$val = $params['item'];
} elseif ($params['key'] !== 'null') {
$val = $params['key'];
} else {
throw new Dwoo_Compilation_Exception($compiler, 'Foreach <em>item</em> parameter missing');
}
$name = $params['name'];
if (substr($val, 0, 1) !== '"' && substr($val, 0, 1) !== '\'') {
throw new Dwoo_Compilation_Exception($compiler, 'Foreach <em>item</em> parameter must be of type string');
}
if (isset($key) && substr($val, 0, 1) !== '"' && substr($val, 0, 1) !== '\'') {
throw new Dwoo_Compilation_Exception($compiler, 'Foreach <em>key</em> parameter must be of type string');
}
// evaluates which global variables have to be computed
$varName = '$dwoo.foreach.'.trim($name, '"\'').'.';
$shortVarName = '$.foreach.'.trim($name, '"\'').'.';
$usesAny = strpos($tpl, $varName) !== false || strpos($tpl, $shortVarName) !== false;
$usesFirst = strpos($tpl, $varName.'first') !== false || strpos($tpl, $shortVarName.'first') !== false;
$usesLast = strpos($tpl, $varName.'last') !== false || strpos($tpl, $shortVarName.'last') !== false;
$usesIndex = $usesFirst || strpos($tpl, $varName.'index') !== false || strpos($tpl, $shortVarName.'index') !== false;
$usesIteration = $usesLast || strpos($tpl, $varName.'iteration') !== false || strpos($tpl, $shortVarName.'iteration') !== false;
$usesShow = strpos($tpl, $varName.'show') !== false || strpos($tpl, $shortVarName.'show') !== false;
$usesTotal = $usesLast || strpos($tpl, $varName.'total') !== false || strpos($tpl, $shortVarName.'total') !== false;
// override globals vars if implode is used
if ($params['implode'] !== 'null') {
$implode = $params['implode'];
$usesAny = true;
$usesLast = true;
$usesIteration = true;
$usesTotal = true;
}
// gets foreach id
$cnt = self::$cnt++;
// build pre content output
$pre = Dwoo_Compiler::PHP_OPEN . "\n".'$_fh'.$cnt.'_data = '.$src.';';
// adds foreach properties
if ($usesAny) {
$pre .= "\n".'$this->globals["foreach"]['.$name.'] = array'."\n(";
if ($usesIndex) $pre .="\n\t".'"index" => 0,';
if ($usesIteration) $pre .="\n\t".'"iteration" => 1,';
if ($usesFirst) $pre .="\n\t".'"first" => null,';
if ($usesLast) $pre .="\n\t".'"last" => null,';
if ($usesShow) $pre .="\n\t".'"show" => $this->isArray($_fh'.$cnt.'_data, true, true),';
if ($usesTotal) $pre .="\n\t".'"total" => $this->isArray($_fh'.$cnt.'_data) ? count($_fh'.$cnt.'_data) : 0,';
$pre.="\n);\n".'$_fh'.$cnt.'_glob =& $this->globals["foreach"]['.$name.'];';
}
// checks if foreach must be looped
$pre .= "\n".'if ($this->isArray($_fh'.$cnt.'_data'.(isset($params['hasElse']) ? ', true, true' : '').') === true)'."\n{";
// iterates over keys
$pre .= "\n\t".'foreach ($_fh'.$cnt.'_data as '.(isset($key)?'$this->scope['.$key.']=>':'').'$this->scope['.$val.'])'."\n\t{";
// updates properties
if ($usesFirst) {
$pre .= "\n\t\t".'$_fh'.$cnt.'_glob["first"] = (string) ($_fh'.$cnt.'_glob["index"] === 0);';
}
if ($usesLast) {
$pre .= "\n\t\t".'$_fh'.$cnt.'_glob["last"] = (string) ($_fh'.$cnt.'_glob["iteration"] === $_fh'.$cnt.'_glob["total"]);';
}
$pre .= "\n/* -- foreach start output */\n".Dwoo_Compiler::PHP_CLOSE;
// build post content output
$post = Dwoo_Compiler::PHP_OPEN . "\n";
if (isset($implode)) {
$post .= '/* -- implode */'."\n".'if (!$_fh'.$cnt.'_glob["last"]) {'.
"\n\t".'echo '.$implode.";\n}\n";
}
$post .= '/* -- foreach end output */';
// update properties
if ($usesIndex) {
$post.="\n\t\t".'$_fh'.$cnt.'_glob["index"]+=1;';
}
if ($usesIteration) {
$post.="\n\t\t".'$_fh'.$cnt.'_glob["iteration"]+=1;';
}
// end loop
$post .= "\n\t}\n}".Dwoo_Compiler::PHP_CLOSE;
if (isset($params['hasElse'])) {
$post .= $params['hasElse'];
}
return $pre . $content . $post;
}
}
@@ -0,0 +1,43 @@
<?php
/**
* This plugin serves as a {else} block specifically for the {foreach} plugin.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Plugin_foreachelse extends Dwoo_Block_Plugin implements Dwoo_ICompilable_Block
{
public function init()
{
}
public static function preProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $type)
{
$with =& $compiler->findBlock('foreach', true);
$params['initialized'] = true;
$compiler->injectBlock($type, $params);
return '';
}
public static function postProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $content)
{
if (!isset($params['initialized'])) {
return '';
}
$block =& $compiler->getCurrentBlock();
$block['params']['hasElse'] = Dwoo_Compiler::PHP_OPEN."else {\n".Dwoo_Compiler::PHP_CLOSE . $content . Dwoo_Compiler::PHP_OPEN."\n}".Dwoo_Compiler::PHP_CLOSE;
return '';
}
}
@@ -0,0 +1,43 @@
<?php
/**
* This plugin serves as a {else} block specifically for the {for} plugin.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Plugin_forelse extends Dwoo_Block_Plugin implements Dwoo_ICompilable_Block
{
public function init()
{
}
public static function preProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $type)
{
$with =& $compiler->findBlock('for', true);
$params['initialized'] = true;
$compiler->injectBlock($type, $params);
return '';
}
public static function postProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $content)
{
if (!isset($params['initialized'])) {
return '';
}
$block =& $compiler->getCurrentBlock();
$block['params']['hasElse'] = Dwoo_Compiler::PHP_OPEN."else {\n".Dwoo_Compiler::PHP_CLOSE . $content . Dwoo_Compiler::PHP_OPEN."\n}".Dwoo_Compiler::PHP_CLOSE;
return '';
}
}
+180
View File
@@ -0,0 +1,180 @@
<?php
/**
* Conditional block, the syntax is very similar to the php one, allowing () || && and
* other php operators. Additional operators && their equivalent php syntax are as follow :
*
* eq -> ==
* neq || ne -> !=
* >= || ge -> >=
* <= || le -> <=
* > -> >
* < -> <
* mod -> %
* not -> !
* X is [not] div by Y -> (X % Y) == 0
* X is [not] even [by Y] -> (X % 2) == 0 || ((X/Y) % 2) == 0
* X is [not] odd [by Y] -> (X % 2) != 0 || ((X/Y) % 2) != 0
*
* This software is provided 'as-is', without any express || implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Plugin_if extends Dwoo_Block_Plugin implements Dwoo_ICompilable_Block, Dwoo_IElseable
{
public function init(array $rest)
{
}
public static function replaceKeywords(array $params, Dwoo_Compiler $compiler)
{
$p = array();
reset($params);
while (list($k,$v) = each($params)) {
$v = (string) $v;
if(substr($v, 0, 1) === '"' || substr($v, 0, 1) === '\'') {
$vmod = strtolower(substr($v, 1, -1));
} else {
$vmod = strtolower($v);
}
switch($vmod) {
case 'and':
$p[] = '&&';
break;
case 'or':
$p[] = '||';
break;
case '==':
case 'eq':
$p[] = '==';
break;
case '<>':
case '!=':
case 'ne':
case 'neq':
$p[] = '!=';
break;
case '>=':
case 'gte':
case 'ge':
$p[] = '>=';
break;
case '<=':
case 'lte':
case 'le':
$p[] = '<=';
break;
case '>':
case 'gt':
$p[] = '>';
break;
case '<':
case 'lt':
$p[] = '<';
break;
case '===':
$p[] = '===';
break;
case '!==':
$p[] = '!==';
break;
case 'is':
if (isset($params[$k+1]) && strtolower(trim($params[$k+1], '"\'')) === 'not') {
$negate = true;
next($params);
} else {
$negate = false;
}
$ptr = 1+(int)$negate;
if (!isset($params[$k+$ptr])) {
$params[$k+$ptr] = '';
} else {
$params[$k+$ptr] = trim($params[$k+$ptr], '"\'');
}
switch($params[$k+$ptr]) {
case 'div':
if (isset($params[$k+$ptr+1]) && strtolower(trim($params[$k+$ptr+1], '"\'')) === 'by') {
$p[] = ' % '.$params[$k+$ptr+2].' '.($negate?'!':'=').'== 0';
next($params);
next($params);
next($params);
} else {
throw new Dwoo_Compilation_Exception($compiler, 'If : Syntax error : syntax should be "if $a is [not] div by $b", found '.$params[$k-1].' is '.($negate?'not ':'').'div '.$params[$k+$ptr+1].' '.$params[$k+$ptr+2]);
}
break;
case 'even':
$a = array_pop($p);
if (isset($params[$k+$ptr+1]) && strtolower(trim($params[$k+$ptr+1], '"\'')) === 'by') {
$b = $params[$k+$ptr+2];
$p[] = '('.$a .' / '.$b.') % 2 '.($negate?'!':'=').'== 0';
next($params);
next($params);
} else {
$p[] = $a.' % 2 '.($negate?'!':'=').'== 0';
}
next($params);
break;
case 'odd':
$a = array_pop($p);
if (isset($params[$k+$ptr+1]) && strtolower(trim($params[$k+$ptr+1], '"\'')) === 'by') {
$b = $params[$k+$ptr+2];
$p[] = '('.$a .' / '.$b.') % 2 '.($negate?'=':'!').'== 0';
next($params);
next($params);
} else {
$p[] = $a.' % 2 '.($negate?'=':'!').'== 0';
}
next($params);
break;
default:
throw new Dwoo_Compilation_Exception($compiler, 'If : Syntax error : syntax should be "if $a is [not] (div|even|odd) [by $b]", found '.$params[$k-1].' is '.$params[$k+$ptr+1]);
}
break;
case '%':
case 'mod':
$p[] = '%';
break;
case '!':
case 'not':
$p[] = '!';
break;
default:
$p[] = $v;
}
}
return $p;
}
public static function preProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $type)
{
return '';
}
public static function postProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $content)
{
$params = $compiler->getCompiledParams($params);
$pre = Dwoo_Compiler::PHP_OPEN.'if ('.implode(' ', self::replaceKeywords($params['*'], $compiler)).") {\n".Dwoo_Compiler::PHP_CLOSE;
$post = Dwoo_Compiler::PHP_OPEN."\n}".Dwoo_Compiler::PHP_CLOSE;
if (isset($params['hasElse'])) {
$post .= $params['hasElse'];
}
return $pre . $content . $post;
}
}
+124
View File
@@ -0,0 +1,124 @@
<?php
/**
* Loops over an array and moves the scope into each value, allowing for shorter loop constructs
*
* Note that to access the array key within a loop block, you have to use the {$_key} variable,
* you can not specify it yourself.
* <pre>
* * from : the array that you want to iterate over
* * name : loop name to access it's iterator variables through {$.loop.name.var} see {@link http://wiki.dwoo.org/index.php/IteratorVariables} for details
* </pre>
* Example :
*
* instead of a foreach block such as :
*
* <code>
* {foreach $variable value}
* {$value.foo} {$value.bar}
* {/foreach}
* </code>
*
* you can do :
*
* <code>
* {loop $variable}
* {$foo} {$bar}
* {/loop}
* </code>
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Plugin_loop extends Dwoo_Block_Plugin implements Dwoo_ICompilable_Block, Dwoo_IElseable
{
public static $cnt=0;
public function init($from, $name='default')
{
}
public static function preProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $type)
{
// get block params and save the current template pointer to use it in the postProcessing method
$currentBlock =& $compiler->getCurrentBlock();
$currentBlock['params']['tplPointer'] = $compiler->getPointer();
return '';
}
public static function postProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $content)
{
$params = $compiler->getCompiledParams($params);
$tpl = $compiler->getTemplateSource($params['tplPointer']);
// assigns params
$src = $params['from'];
$name = $params['name'];
// evaluates which global variables have to be computed
$varName = '$dwoo.loop.'.trim($name, '"\'').'.';
$shortVarName = '$.loop.'.trim($name, '"\'').'.';
$usesAny = strpos($tpl, $varName) !== false || strpos($tpl, $shortVarName) !== false;
$usesFirst = strpos($tpl, $varName.'first') !== false || strpos($tpl, $shortVarName.'first') !== false;
$usesLast = strpos($tpl, $varName.'last') !== false || strpos($tpl, $shortVarName.'last') !== false;
$usesIndex = $usesFirst || strpos($tpl, $varName.'index') !== false || strpos($tpl, $shortVarName.'index') !== false;
$usesIteration = $usesLast || strpos($tpl, $varName.'iteration') !== false || strpos($tpl, $shortVarName.'iteration') !== false;
$usesShow = strpos($tpl, $varName.'show') !== false || strpos($tpl, $shortVarName.'show') !== false;
$usesTotal = $usesLast || strpos($tpl, $varName.'total') !== false || strpos($tpl, $shortVarName.'total') !== false;
// gets foreach id
$cnt = self::$cnt++;
// builds pre processing output
$pre = Dwoo_Compiler::PHP_OPEN . "\n".'$_loop'.$cnt.'_data = '.$src.';';
// adds foreach properties
if ($usesAny) {
$pre .= "\n".'$this->globals["loop"]['.$name.'] = array'."\n(";
if ($usesIndex) $pre .="\n\t".'"index" => 0,';
if ($usesIteration) $pre .="\n\t".'"iteration" => 1,';
if ($usesFirst) $pre .="\n\t".'"first" => null,';
if ($usesLast) $pre .="\n\t".'"last" => null,';
if ($usesShow) $pre .="\n\t".'"show" => $this->isArray($_loop'.$cnt.'_data, true, true),';
if ($usesTotal) $pre .="\n\t".'"total" => $this->isArray($_loop'.$cnt.'_data) ? count($_loop'.$cnt.'_data) : 0,';
$pre.="\n);\n".'$_loop'.$cnt.'_glob =& $this->globals["loop"]['.$name.'];';
}
// checks if the loop must be looped
$pre .= "\n".'if ($this->isArray($_loop'.$cnt.'_data'.(isset($params['hasElse']) ? ', true, true' : '').') === true)'."\n{";
// iterates over keys
$pre .= "\n\t".'foreach ($_loop'.$cnt.'_data as $tmp_key => $this->scope["-loop-"])'."\n\t{";
// updates properties
if ($usesFirst) {
$pre .= "\n\t\t".'$_loop'.$cnt.'_glob["first"] = (string) ($_loop'.$cnt.'_glob["index"] === 0);';
}
if ($usesLast) {
$pre .= "\n\t\t".'$_loop'.$cnt.'_glob["last"] = (string) ($_loop'.$cnt.'_glob["iteration"] === $_loop'.$cnt.'_glob["total"]);';
}
$pre .= "\n\t\t".'$_loop'.$cnt.'_scope = $this->setScope(array("-loop-"));' . "\n/* -- loop start output */\n".Dwoo_Compiler::PHP_CLOSE;
// build post processing output and cache it
$post = Dwoo_Compiler::PHP_OPEN . "\n".'/* -- loop end output */'."\n\t\t".'$this->setScope($_loop'.$cnt.'_scope, true);';
// update properties
if ($usesIndex) {
$post.="\n\t\t".'$_loop'.$cnt.'_glob["index"]+=1;';
}
if ($usesIteration) {
$post.="\n\t\t".'$_loop'.$cnt.'_glob["iteration"]+=1;';
}
// end loop
$post .= "\n\t}\n}\n" . Dwoo_Compiler::PHP_CLOSE;
if (isset($params['hasElse'])) {
$post .= $params['hasElse'];
}
return $pre . $content . $post;
}
}
+131
View File
@@ -0,0 +1,131 @@
<?php
/**
* Compatibility plugin for smarty templates, do not use otherwise, this is deprecated.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Plugin_section extends Dwoo_Block_Plugin implements Dwoo_ICompilable_Block, Dwoo_IElseable
{
public static $cnt=0;
public function init($name, $loop, $start = null, $step = null, $max = null, $show = true)
{
}
public static function preProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $type)
{
return '';
}
public static function postProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $content)
{
$output = Dwoo_Compiler::PHP_OPEN;
$params = $compiler->getCompiledParams($params);
// assigns params
$loop = $params['loop'];
$start = $params['start'];
$max = $params['max'];
$name = $params['name'];
$step = $params['step'];
$show = $params['show'];
// gets unique id
$cnt = self::$cnt++;
$output .= '$this->globals[\'section\']['.$name.'] = array();'."\n".
'$_section'.$cnt.' =& $this->globals[\'section\']['.$name.'];'."\n";
if ($loop !== 'null') {
$output .= '$_section'.$cnt.'[\'loop\'] = is_array($tmp = '.$loop.') ? count($tmp) : max(0, (int) $tmp);'."\n";
} else {
$output .= '$_section'.$cnt.'[\'loop\'] = 1;'."\n";
}
if ($show !== 'null') {
$output .= '$_section'.$cnt.'[\'show\'] = '.$show.";\n";
} else {
$output .= '$_section'.$cnt.'[\'show\'] = true;'."\n";
}
if ($name !== 'null') {
$output .= '$_section'.$cnt.'[\'name\'] = '.$name.";\n";
} else {
$output .= '$_section'.$cnt.'[\'name\'] = true;'."\n";
}
if ($max !== 'null') {
$output .= '$_section'.$cnt.'[\'max\'] = (int)'.$max.";\n".
'if($_section'.$cnt.'[\'max\'] < 0) { $_section'.$cnt.'[\'max\'] = $_section'.$cnt.'[\'loop\']; }'."\n";
} else {
$output .= '$_section'.$cnt.'[\'max\'] = $_section'.$cnt.'[\'loop\'];'."\n";
}
if ($step !== 'null') {
$output .= '$_section'.$cnt.'[\'step\'] = (int)'.$step.' == 0 ? 1 : (int) '.$step.";\n";
} else {
$output .= '$_section'.$cnt.'[\'step\'] = 1;'."\n";
}
if ($start !== 'null') {
$output .= '$_section'.$cnt.'[\'start\'] = (int)'.$start.";\n";
} else {
$output .= '$_section'.$cnt.'[\'start\'] = $_section'.$cnt.'[\'step\'] > 0 ? 0 : $_section'.$cnt.'[\'loop\'] - 1;'."\n".
'if ($_section'.$cnt.'[\'start\'] < 0) { $_section'.$cnt.'[\'start\'] = max($_section'.$cnt.'[\'step\'] > 0 ? 0 : -1, $_section'.$cnt.'[\'loop\'] + $_section'.$cnt.'[\'start\']); } '."\n".
'else { $_section'.$cnt.'[\'start\'] = min($_section'.$cnt.'[\'start\'], $_section'.$cnt.'[\'step\'] > 0 ? $_section'.$cnt.'[\'loop\'] : $_section'.$cnt.'[\'loop\'] -1); }'."\n";
}
/* if ($usesAny) {
$output .= "\n".'$this->globals["section"]['.$name.'] = array'."\n(";
if ($usesIndex) $output .="\n\t".'"index" => 0,';
if ($usesIteration) $output .="\n\t".'"iteration" => 1,';
if ($usesFirst) $output .="\n\t".'"first" => null,';
if ($usesLast) $output .="\n\t".'"last" => null,';
if ($usesShow) $output .="\n\t".'"show" => ($this->isArray($_for'.$cnt.'_from, true)) || (is_numeric($_for'.$cnt.'_from) && $_for'.$cnt.'_from != $_for'.$cnt.'_to),';
if ($usesTotal) $output .="\n\t".'"total" => $this->isArray($_for'.$cnt.'_from) ? count($_for'.$cnt.'_from) - $_for'.$cnt.'_skip : (is_numeric($_for'.$cnt.'_from) ? abs(($_for'.$cnt.'_to + 1 - $_for'.$cnt.'_from)/$_for'.$cnt.'_step) : 0),';
$out.="\n);\n".'$_section'.$cnt.'[\'glob\'] =& $this->globals["section"]['.$name.'];'."\n\n";
}
*/
$output .= 'if ($_section'.$cnt.'[\'show\']) {'."\n";
if ($start === 'null' && $step === 'null' && $max === 'null') {
$output .= ' $_section'.$cnt.'[\'total\'] = $_section'.$cnt.'[\'loop\'];'."\n";
} else {
$output .= ' $_section'.$cnt.'[\'total\'] = min(ceil(($_section'.$cnt.'[\'step\'] > 0 ? $_section'.$cnt.'[\'loop\'] - $_section'.$cnt.'[\'start\'] : $_section'.$cnt.'[\'start\'] + 1) / abs($_section'.$cnt.'[\'step\'])), $_section'.$cnt.'[\'max\']);'."\n";
}
$output .= ' if ($_section'.$cnt.'[\'total\'] == 0) {'."\n".
' $_section'.$cnt.'[\'show\'] = false;'."\n".
' }'."\n".
'} else {'."\n".
' $_section'.$cnt.'[\'total\'] = 0;'."\n}\n";
$output .= 'if ($_section'.$cnt.'[\'show\']) {'."\n";
$output .= "\t".'for ($this->scope['.$name.'] = $_section'.$cnt.'[\'start\'], $_section'.$cnt.'[\'iteration\'] = 1; '.
'$_section'.$cnt.'[\'iteration\'] <= $_section'.$cnt.'[\'total\']; '.
'$this->scope['.$name.'] += $_section'.$cnt.'[\'step\'], $_section'.$cnt.'[\'iteration\']++) {'."\n";
$output .= "\t\t".'$_section'.$cnt.'[\'rownum\'] = $_section'.$cnt.'[\'iteration\'];'."\n";
$output .= "\t\t".'$_section'.$cnt.'[\'index_prev\'] = $this->scope['.$name.'] - $_section'.$cnt.'[\'step\'];'."\n";
$output .= "\t\t".'$_section'.$cnt.'[\'index_next\'] = $this->scope['.$name.'] + $_section'.$cnt.'[\'step\'];'."\n";
$output .= "\t\t".'$_section'.$cnt.'[\'first\'] = ($_section'.$cnt.'[\'iteration\'] == 1);'."\n";
$output .= "\t\t".'$_section'.$cnt.'[\'last\'] = ($_section'.$cnt.'[\'iteration\'] == $_section'.$cnt.'[\'total\']);'."\n";
$output .= Dwoo_Compiler::PHP_CLOSE . $content . Dwoo_Compiler::PHP_OPEN;
$output .= "\n\t}\n} " . Dwoo_Compiler::PHP_CLOSE;
if (isset($params['hasElse'])) {
$output .= $params['hasElse'];
}
return $output;
}
}
@@ -0,0 +1,61 @@
<?php
/**
* Smarty compatibility layer for block plugins, this is used internally and you should not call it
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Plugin_smartyinterface extends Dwoo_Block_Plugin implements Dwoo_ICompilable_Block
{
public function init($__funcname, $__functype, array $rest=array()) {}
public static function preProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $type)
{
$params = $compiler->getCompiledParams($params);
$func = $params['__funcname'];
$pluginType = $params['__functype'];
$paramsOut = '';
if(isset($params['*'])) {
$params = $params['*'];
foreach ($params as $i=>$p) {
$paramsOut .= var_export($i, true).' => '.$p.',';
}
}
if ($pluginType & Dwoo::CUSTOM_PLUGIN) {
$customPlugins = $compiler->getDwoo()->getCustomPlugins();
$callback = $customPlugins[$func]['callback'];
if (is_array($callback)) {
if (is_object($callback[0])) {
$callback = '$this->customPlugins[\''.$func.'\'][0]->'.$callback[1].'(';
} else {
$callback = ''.$callback[0].'::'.$callback[1].'(';
}
} else {
$callback = $callback.'(';
}
} else {
$callback = 'smarty_block_'.$func.'(';
}
$curBlock =& $compiler->getCurrentBlock();
$curBlock['params']['postOut'] = Dwoo_Compiler::PHP_OPEN.' $_block_content = ob_get_clean(); $_block_repeat=false; echo '.$callback.'$_tag_stack[count($_tag_stack)-1], $_block_content, $this, $_block_repeat); } array_pop($_tag_stack);'.Dwoo_Compiler::PHP_CLOSE;
return Dwoo_Compiler::PHP_OPEN.$prepend.' if (!isset($_tag_stack)){ $_tag_stack = array(); } $_tag_stack[] = array('.$paramsOut.'); $_block_repeat=true; '.$callback.'$_tag_stack[count($_tag_stack)-1], null, $this, $_block_repeat); while ($_block_repeat) { ob_start();'.Dwoo_Compiler::PHP_CLOSE;
}
public static function postProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $content)
{
return $content . $params['postOut'];
}
}
+50
View File
@@ -0,0 +1,50 @@
<?php
/**
* Strips the spaces at the beginning and end of each line and also the line breaks
* <pre>
* * mode : sets the content being stripped, available mode are 'default' or 'js'
* for javascript, which strips the comments to prevent syntax errors
* </pre>
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Plugin_strip extends Dwoo_Block_Plugin implements Dwoo_ICompilable_Block
{
public function init($mode = "default")
{
}
public static function preProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $type)
{
return '';
}
public static function postProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $content)
{
$params = $compiler->getCompiledParams($params);
$mode = trim($params['mode'], '"\'');
switch ($mode) {
case 'js':
case 'javascript':
$content = preg_replace('#(?<!:)//\s[^\r\n]*|/\*.*?\*/#','', $content);
case 'default':
default:
}
$content = preg_replace(array("/\n/","/\r/",'/(<\?(?:php)?|<%)\s*/'), array('','','$1 '), preg_replace('#^\s*(.+?)\s*$#m', '$1', $content));
return $content;
}
}
@@ -0,0 +1,94 @@
<?php
/**
* Formats a string to the given format, you can wrap lines at a certain
* length and indent them
* <pre>
* * wrap : maximum line length
* * wrap_char : the character(s) to use to break the line
* * wrap_cut : if true, the words that are longer than $wrap are cut instead of overflowing
* * indent : amount of $indent_char to insert before every line
* * indent_char : character(s) to insert before every line
* * indent_first : amount of additional $indent_char to insert before the first line of each paragraphs
* * style : some predefined formatting styles that set up every required variables, can be "email" or "html"
* * assign : if set, the formatted text is assigned to that variable instead of being output
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Plugin_textformat extends Dwoo_Block_Plugin
{
protected $wrap;
protected $wrapChar;
protected $wrapCut;
protected $indent;
protected $indChar;
protected $indFirst;
protected $assign;
public function init($wrap=80, $wrap_char="\r\n", $wrap_cut=false, $indent=0, $indent_char=" ", $indent_first=0, $style="", $assign="")
{
if ($indent_char === 'tab') {
$indent_char = "\t";
}
switch($style) {
case 'email':
$wrap = 72;
$indent_first = 0;
break;
case 'html':
$wrap_char = '<br />';
$indent_char = $indent_char == "\t" ? '&nbsp;&nbsp;&nbsp;&nbsp;':'&nbsp;';
break;
}
$this->wrap = (int) $wrap;
$this->wrapChar = (string) $wrap_char;
$this->wrapCut = (bool) $wrap_cut;
$this->indent = (int) $indent;
$this->indChar = (string) $indent_char;
$this->indFirst = (int) $indent_first + $this->indent;
$this->assign = (string) $assign;
}
public function process()
{
// gets paragraphs
$pgs = explode("\n", str_replace(array("\r\n", "\r"), "\n", $this->buffer));
while (list($i,) = each($pgs)) {
if (empty($pgs[$i])) {
continue;
}
// removes line breaks and extensive white space
$pgs[$i] = preg_replace(array('#\s+#', '#^\s*(.+?)\s*$#m'), array(' ', '$1'), str_replace("\n", '', $pgs[$i]));
// wordwraps + indents lines
$pgs[$i] = str_repeat($this->indChar, $this->indFirst) .
wordwrap(
$pgs[$i],
max($this->wrap - $this->indent, 1),
$this->wrapChar . str_repeat($this->indChar, $this->indent),
$this->wrapCut
);
}
if ($this->assign !== '') {
$this->dwoo->assignInScope(implode($this->wrapChar . $this->wrapChar, $pgs), $this->assign);
} else {
return implode($this->wrapChar . $this->wrapChar, $pgs);
}
}
}
@@ -0,0 +1,32 @@
<?php
/**
* Internal plugin used to wrap the template output, do not use in your templates as it will break them
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
final class Dwoo_Plugin_topLevelBlock extends Dwoo_Block_Plugin implements Dwoo_ICompilable_Block
{
public function init()
{
}
public static function preProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $type)
{
return 'ob_start(); /* template body */ '.Dwoo_Compiler::PHP_CLOSE;
}
public static function postProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $content)
{
return $content . Dwoo_Compiler::PHP_OPEN.' /* end template body */'."\n".'return $this->buffer . ob_get_clean();';
}
}
+76
View File
@@ -0,0 +1,76 @@
<?php
/**
* Moves the scope down into the provided variable, allowing you to use shorter
* variable names if you repeatedly access values into a single array
*
* The with block won't display anything at all if the provided scope is empty,
* so in effect it acts as {if $var}*content*{/if}
* <pre>
* * var : the variable name to move into
* </pre>
* Example :
*
* instead of the following :
*
* <code>
* {if $long.boring.prefix}
* {$long.boring.prefix.val} - {$long.boring.prefix.secondVal} - {$long.boring.prefix.thirdVal}
* {/if}
* </code>
*
* you can use :
*
* <code>
* {with $long.boring.prefix}
* {$val} - {$secondVal} - {$thirdVal}
* {/with}
* </code>
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Plugin_with extends Dwoo_Block_Plugin implements Dwoo_ICompilable_Block, Dwoo_IElseable
{
protected static $cnt=0;
public function init($var)
{
}
public static function preProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $type)
{
return '';
}
public static function postProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $content)
{
$rparams = $compiler->getRealParams($params);
$cparams = $compiler->getCompiledParams($params);
$compiler->setScope($rparams['var']);
$pre = Dwoo_Compiler::PHP_OPEN. 'if ('.$cparams['var'].')'."\n{\n".
'$_with'.(self::$cnt).' = $this->setScope("'.$rparams['var'].'");'.
"\n/* -- start with output */\n".Dwoo_Compiler::PHP_CLOSE;
$post = Dwoo_Compiler::PHP_OPEN. "\n/* -- end with output */\n".
'$this->setScope($_with'.(self::$cnt++).', true);'.
"\n}\n".Dwoo_Compiler::PHP_CLOSE;
if (isset($params['hasElse'])) {
$post .= $params['hasElse'];
}
return $pre . $content . $post;
}
}
@@ -0,0 +1,43 @@
<?php
/**
* This plugin serves as a {else} block specifically for the {with} plugin.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Plugin_withelse extends Dwoo_Block_Plugin implements Dwoo_ICompilable_Block
{
public function init()
{
}
public static function preProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $type)
{
$with =& $compiler->findBlock('with', true);
$params['initialized'] = true;
$compiler->injectBlock($type, $params);
return '';
}
public static function postProcessing(Dwoo_Compiler $compiler, array $params, $prepend, $append, $content)
{
if (!isset($params['initialized'])) {
return '';
}
$block =& $compiler->getCurrentBlock();
$block['params']['hasElse'] = Dwoo_Compiler::PHP_OPEN."else {\n".Dwoo_Compiler::PHP_CLOSE . $content . Dwoo_Compiler::PHP_OPEN."\n}".Dwoo_Compiler::PHP_CLOSE;
return '';
}
}
@@ -0,0 +1,175 @@
<?php
/**
* Formats any html output (must be valid xml where every tag opened is closed)
* using a single tab for indenting. 'pre' and other whitespace sensitive
* tags should not be affected.
*
* It is not recommended to use this on every template if you render multiple
* templates per page, you should only use it once on the main page template so that
* everything is formatted in one pass.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Filter_html_format extends Dwoo_Filter
{
/**
* tab count to auto-indent the source
*
* @var int
*/
protected static $tabCount = -1;
/**
* stores the additional data (following a tag) of the last call to open/close/singleTag
*
* @var string
*/
protected static $lastCallAdd = '';
/**
* formats the input using the singleTag/closeTag/openTag functions
*
* It is auto indenting the whole code, excluding <textarea>, <code> and <pre> tags that must be kept intact.
* Those tags must however contain only htmlentities-escaped text for everything to work properly.
* Inline tags are presented on a single line with their content
*
* @param Dwoo $dwoo the dwoo instance rendering this
* @param string $input the xhtml to format
* @return string formatted xhtml
*/
public function process($input)
{
self::$tabCount = -1;
// auto indent all but textareas & pre (or we have weird tabs inside)
$input = preg_replace_callback("#(<[^>]+>)(\s*)([^<]*)#", array('self', 'tagDispatcher'), $input);
return $input;
}
/**
* helper function for format()'s preg_replace call
*
* @param array $input array of matches (1=>tag, 2=>whitespace(optional), 3=>additional non-html content)
* @return string the indented tag
*/
protected static function tagDispatcher($input)
{
// textarea, pre, code tags and comments are to be left alone to avoid any non-wanted whitespace inside them so it just outputs them as they were
if (substr($input[1],0,9) == "<textarea" || substr($input[1],0,4) == "<pre" || substr($input[1],0,5) == "<code" || substr($input[1],0,4) == "<!--" || substr($input[1],0,9) == "<![CDATA[") {
return $input[1] . $input[3];
}
// closing textarea, code and pre tags and self-closed tags (i.e. <br />) are printed as singleTags because we didn't use openTag for the formers and the latter is a single tag
if (substr($input[1],0,10) == "</textarea" || substr($input[1],0,5) == "</pre" || substr($input[1],0,6) == "</code" || substr($input[1],-2) == "/>") {
return self::singleTag($input[1],$input[3],$input[2]);
}
// it's the closing tag
if ($input[0][1]=="/"){
return self::closeTag($input[1],$input[3],$input[2]);
}
// opening tag
return self::openTag($input[1],$input[3],$input[2]);
}
/**
* returns an open tag and adds a tab into the auto indenting
*
* @param string $tag content of the tag
* @param string $add additional data (anything before the following tag)
* @param string $whitespace white space between the tag and the additional data
* @return string
*/
protected static function openTag($tag,$add,$whitespace)
{
$tabs = str_pad('',self::$tabCount++,"\t");
if (preg_match('#^<(a|label|option|textarea|h1|h2|h3|h4|h5|h6|strong|b|em|i|abbr|acronym|cite|span|sub|sup|u|s|title)(?: [^>]*|)>#', $tag)) {
// if it's one of those tag it's inline so it does not require a leading line break
$result = $tag . $whitespace . str_replace("\n","\n".$tabs,$add);
} elseif (substr($tag,0,9) == '<!DOCTYPE') {
// it's the doctype declaration so no line break here either
$result = $tabs . $tag;
} else {
// normal block tag
$result = "\n".$tabs . $tag;
if (!empty($add)) {
$result .= "\n".$tabs."\t".str_replace("\n","\n\t".$tabs,$add);
}
}
self::$lastCallAdd = $add;
return $result;
}
/**
* returns a closing tag and removes a tab from the auto indenting
*
* @param string $tag content of the tag
* @param string $add additional data (anything before the following tag)
* @param string $whitespace white space between the tag and the additional data
* @return string
*/
protected static function closeTag($tag,$add,$whitespace)
{
$tabs = str_pad('',--self::$tabCount,"\t");
// if it's one of those tag it's inline so it does not require a leading line break
if (preg_match('#^</(a|label|option|textarea|h1|h2|h3|h4|h5|h6|strong|b|em|i|abbr|acronym|cite|span|sub|sup|u|s|title)>#', $tag)) {
$result = $tag . $whitespace . str_replace("\n","\n".$tabs,$add);
} else {
$result = "\n".$tabs.$tag;
if (!empty($add)) {
$result .= "\n".$tabs."\t".str_replace("\n","\n\t".$tabs,$add);
}
}
self::$lastCallAdd = $add;
return $result;
}
/**
* returns a single tag with auto indenting
*
* @param string $tag content of the tag
* @param string $add additional data (anything before the following tag)
* @return string
*/
protected static function singleTag($tag,$add,$whitespace)
{
$tabs = str_pad('',self::$tabCount,"\t");
// if it's img, br it's inline so it does not require a leading line break
// if it's a closing textarea, code or pre tag, it does not require a leading line break either or it creates whitespace at the end of those blocks
if (preg_match('#^<(img|br|/textarea|/pre|/code)(?: [^>]*|)>#', $tag)) {
$result = $tag.$whitespace;
if (!empty($add)) {
$result .= str_replace("\n","\n".$tabs,$add);
}
} else {
$result = "\n".$tabs.$tag;
if (!empty($add)) {
$result .= "\n".$tabs.str_replace("\n","\n".$tabs,$add);
}
}
self::$lastCallAdd = $add;
return $result;
}
}
@@ -0,0 +1,23 @@
<?php
/**
* Assigns a value to a variable
* <pre>
* * value : the value that you want to save
* * var : the variable name (without the leading $)
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_assign_compile(Dwoo_Compiler $compiler, $value, $var)
{
return '$this->assignInScope('.$value.', '.$var.')';
}
@@ -0,0 +1,41 @@
<?php
/**
* Capitalizes the first letter of each word
* <pre>
* * value : the string to capitalize
* * numwords : if true, the words containing numbers are capitalized as well
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_capitalize(Dwoo $dwoo, $value, $numwords=false)
{
if ($numwords || preg_match('#^[^0-9]+$#',$value))
{
if ($dwoo->getCharset() === 'iso-8859-1') {
return ucwords((string) $value);
}
return mb_convert_case((string) $value,MB_CASE_TITLE, $dwoo->getCharset());
} else {
$bits = explode(' ', (string) $value);
$out = '';
while (list(,$v) = each($bits)) {
if (preg_match('#^[^0-9]+$#', $v)) {
$out .= ' '.mb_convert_case($v, MB_CASE_TITLE, $dwoo->getCharset());
} else {
$out .= ' '.$v;
}
}
return substr($out, 1);
}
}
@@ -0,0 +1,22 @@
<?php
/**
* Concatenates any number of variables or strings fed into it
* <pre>
* * rest : two or more strings that will be merged into one
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_cat_compile(Dwoo_Compiler $compiler, $value, array $rest)
{
return '('.$value.').('.implode(').(', $rest).')';
}
@@ -0,0 +1,27 @@
<?php
/**
* Counts the characters in a string
* <pre>
* * value : the string to process
* * count_spaces : if true, the white-space characters are counted as well
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_count_characters_compile(Dwoo_Compiler $compiler, $value, $count_spaces=false)
{
if ($count_spaces==='false') {
return 'preg_match_all(\'#[^\s\pZ]#u\', '.$value.', $tmp)';
} else {
return 'mb_strlen('.$value.', $this->charset)';
}
}
@@ -0,0 +1,22 @@
<?php
/**
* Counts the paragraphs in a string
* <pre>
* * value : the string to process
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_count_paragraphs_compile(Dwoo_Compiler $compiler, $value)
{
return '(preg_match_all(\'#[\r\n]+#\', '.$value.', $tmp)+1)';
}
@@ -0,0 +1,22 @@
<?php
/**
* Counts the sentences in a string
* <pre>
* * value : the string to process
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_count_sentences_compile(Dwoo_Compiler $compiler, $value)
{
return "preg_match_all('#[\w\pL]\.(?![\w\pL])#u', $value, \$tmp)";
}
@@ -0,0 +1,22 @@
<?php
/**
* Counts the words in a string
* <pre>
* * value : the string to process
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_count_words_compile(Dwoo_Compiler $compiler, $value)
{
return 'preg_match_all(strcasecmp($this->charset, \'utf-8\')===0 ? \'#[\w\pL]+#u\' : \'#\w+#\', '.$value.', $tmp)';
}
@@ -0,0 +1,76 @@
<?php
/**
* Initiates a counter that is incremented every time you call it
* <pre>
* * name : the counter name, define it if you want to have multiple concurrent counters
* * start : the start value, if it's set, it will reset the counter to this value, defaults to 1
* * skip : the value to add to the counter at each call, defaults to 1
* * direction : "up" (default) or "down" to define whether the counter increments or decrements
* * print : if false, the counter will not output the current count, defaults to true
* * assign : if set, the counter is saved into the given variable and does not output anything, overriding the print parameter
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Plugin_counter extends Dwoo_Plugin
{
protected $counters = array();
public function process($name = 'default', $start = null, $skip = null, $direction = null, $print = null, $assign = null)
{
// init counter
if (!isset($this->counters[$name])) {
$this->counters[$name] = array
(
'count' => $start===null ? 1 : (int) $start,
'skip' => $skip===null ? 1 : (int) $skip,
'print' => $print===null ? true : (bool) $print,
'assign' => $assign===null ? null : (string) $assign,
'direction' => strtolower($direction)==='down' ? -1 : 1,
);
}
// increment
else
{
// override setting if present
if ($skip !== null) {
$this->counters[$name]['skip'] = (int) $skip;
}
if ($direction !== null) {
$this->counters[$name]['direction'] = strtolower($direction)==='down' ? -1 : 1;
}
if ($print !== null) {
$this->counters[$name]['print'] = (bool) $print;
}
if ($assign !== null) {
$this->counters[$name]['assign'] = (string) $assign;
}
if ($start !== null) {
$this->counters[$name]['count'] = (int) $start;
} else {
$this->counters[$name]['count'] += ($this->counters[$name]['skip'] * $this->counters[$name]['direction']);
}
}
$out = $this->counters[$name]['count'];
if ($this->counters[$name]['assign'] !== null) {
$this->dwoo->assignInScope($out, $this->counters[$name]['assign']);
} elseif ($this->counters[$name]['print'] === true) {
return $out;
}
}
}
@@ -0,0 +1,69 @@
<?php
/**
* Cycles between several values and returns one of them on each call
* <pre>
* * name : the cycler name, specify if you need to have multiple concurrent cycles running
* * values : an array of values or a string of values delimited by $delimiter
* * print : if false, the pointer will go to the next one but not print anything
* * advance : if false, the pointer will not advance to the next value
* * delimiter : the delimiter used to split values if they are provided as a string
* * assign : if set, the value is saved in that variable instead of being output
* * reset : if true, the pointer is reset to the first value
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.1
* @date 2008-12-24
* @package Dwoo
*/
class Dwoo_Plugin_cycle extends Dwoo_Plugin
{
protected $cycles = array();
public function process($name = 'default', $values = null, $print = true, $advance = true, $delimiter = ',', $assign = null, $reset = false)
{
if ($values !== null) {
if (is_string($values)) {
$values = explode($delimiter, $values);
}
if (!isset($this->cycles[$name]) || $this->cycles[$name]['values'] !== $values) {
$this->cycles[$name]['index'] = 0;
}
$this->cycles[$name]['values'] = array_values($values);
} elseif (isset($this->cycles[$name])) {
$values = $this->cycles[$name]['values'];
}
if ($reset) {
$this->cycles[$name]['index'] = 0;
}
if ($print) {
$out = $values[$this->cycles[$name]['index']];
} else {
$out = null;
}
if ($advance) {
if ($this->cycles[$name]['index'] >= count($values)-1) {
$this->cycles[$name]['index'] = 0;
} else {
$this->cycles[$name]['index']++;
}
}
if ($assign !== null) {
$this->dwoo->assignInScope($out, $assign);
} else {
return $out;
}
}
}
@@ -0,0 +1,54 @@
<?php
/**
* Formats a date
* <pre>
* * value : the date, as a unix timestamp, mysql datetime or whatever strtotime() can parse
* * format : output format, see {@link http://php.net/strftime} for details
* * default : a default timestamp value, if the first one is empty
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.1
* @date 2008-12-24
* @package Dwoo
*/
function Dwoo_Plugin_date_format(Dwoo $dwoo, $value, $format='%b %e, %Y', $default=null)
{
if (!empty($value)) {
// convert if it's not a valid unix timestamp
if (preg_match('#^-?\d{1,10}$#', $value)===0) {
$value = strtotime($value);
}
} elseif (!empty($default)) {
// convert if it's not a valid unix timestamp
if (preg_match('#^-?\d{1,10}$#', $default)===0) {
$value = strtotime($default);
} else {
$value = $default;
}
} else {
return '';
}
// Credits for that windows compat block to Monte Ohrt who made smarty's date_format plugin
if (DIRECTORY_SEPARATOR == '\\') {
$_win_from = array('%D', '%h', '%n', '%r', '%R', '%t', '%T');
$_win_to = array('%m/%d/%y', '%b', "\n", '%I:%M:%S %p', '%H:%M', "\t", '%H:%M:%S');
if (strpos($format, '%e') !== false) {
$_win_from[] = '%e';
$_win_to[] = sprintf('%\' 2d', date('j', $value));
}
if (strpos($format, '%l') !== false) {
$_win_from[] = '%l';
$_win_to[] = sprintf('%\' 2d', date('h', $value));
}
$format = str_replace($_win_from, $_win_to, $format);
}
return strftime($format, $value);
}
@@ -0,0 +1,23 @@
<?php
/**
* Returns a variable or a default value if it's empty
* <pre>
* * value : the variable to check
* * default : fallback value if the first one is empty
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_default_compile(Dwoo_Compiler $compiler, $value, $default='')
{
return '(($tmp = '.$value.')===null||$tmp===\'\' ? '.$default.' : $tmp)';
}
+173
View File
@@ -0,0 +1,173 @@
<?php
/**
* Dumps values of the given variable, or the entire data if nothing provided
* <pre>
* * var : the variable to display
* * show_methods : if set to true, the public methods of any object encountered are also displayed
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Plugin_dump extends Dwoo_Plugin
{
protected $outputObjects;
protected $outputMethods;
public function process($var = '$', $show_methods = false)
{
$this->outputMethods = $show_methods;
if ($var === '$') {
$var = $this->dwoo->getData();
$out = '<div style="background:#aaa; padding:5px; margin:5px; color:#000;">data';
} else {
$out = '<div style="background:#aaa; padding:5px; margin:5px; color:#000;">dump';
}
$this->outputObjects = array();
if (!is_array($var)) {
if (is_object($var)) {
return $this->exportObj('', $var);
} else {
return $this->exportVar('', $var);
}
}
$scope = $this->dwoo->getScope();
if ($var === $scope) {
$out .= ' (current scope): <div style="background:#ccc;">';
} else {
$out .= ':<div style="padding-left:20px;">';
}
$out .= $this->export($var, $scope);
return $out .'</div></div>';
}
protected function export($var, $scope)
{
$out = '';
foreach ($var as $i=>$v) {
if (is_array($v) || (is_object($v) && $v instanceof Iterator)) {
$out .= $i.' ('.(is_array($v) ? 'array':'object: '.get_class($v)).')';
if ($v===$scope) {
$out .= ' (current scope):<div style="background:#ccc;padding-left:20px;">'.$this->export($v, $scope).'</div>';
} else {
$out .= ':<div style="padding-left:20px;">'.$this->export($v, $scope).'</div>';
}
} elseif (is_object($v)) {
$out .= $this->exportObj($i.' (object: '.get_class($v).'):', $v);
} else {
$out .= $this->exportVar($i.' = ', $v);
}
}
return $out;
}
protected function exportVar($i, $v)
{
if (is_string($v) || is_bool($v) || is_numeric($v)) {
return $i.htmlentities(var_export($v, true)).'<br />';
} elseif (is_null($v)) {
return $i.'null<br />';
} elseif (is_resource($v)) {
return $i.'resource('.get_resource_type($v).')<br />';
} else {
return $i.htmlentities(var_export($v, true)).'<br />';
}
}
protected function exportObj($i, $obj)
{
if (array_search($obj, $this->outputObjects, true) !== false) {
return $i . ' [recursion, skipped]<br />';
}
$this->outputObjects[] = $obj;
$list = (array) $obj;
$protectedLength = strlen(get_class($obj)) + 2;
$out = array();
if ($this->outputMethods) {
$ref = new ReflectionObject($obj);
foreach ($ref->getMethods() as $method) {
if (!$method->isPublic()) {
continue;
}
if (empty($out['method'])) {
$out['method'] = '';
}
$params = array();
foreach ($method->getParameters() as $param) {
$params[] = ($param->isPassedByReference() ? '&':'') . '$'.$param->getName() . ($param->isOptional() ? ' = '.var_export($param->getDefaultValue(), true) : '');
}
$out['method'] .= '(method) ' . $method->getName() .'('.implode(', ', $params).')<br />';
}
}
foreach ($list as $attributeName => $attributeValue) {
if(property_exists($obj, $attributeName)) {
$key = 'public';
} elseif(substr($attributeName, 0, 3) === "\0*\0") {
$key = 'protected';
$attributeName = substr($attributeName, 3);
} else {
$key = 'private';
$attributeName = substr($attributeName, $protectedLength);
}
if (empty($out[$key])) {
$out[$key] = '';
}
$out[$key] .= '('.$key.') ';
if (is_array($attributeValue)) {
$out[$key] .= $attributeName.' (array):<br />
<div style="padding-left:20px;">'.$this->export($attributeValue, false).'</div>';
} elseif (is_object($attributeValue)) {
$out[$key] .= $this->exportObj($attributeName.' (object: '.get_class($attributeValue).'):', $attributeValue);
} else {
$out[$key] .= $this->exportVar($attributeName.' = ', $attributeValue);
}
}
$return = $i . '<br /><div style="padding-left:20px;">';
if (!empty($out['method'])) {
$return .= $out['method'];
}
if (!empty($out['public'])) {
$return .= $out['public'];
}
if (!empty($out['protected'])) {
$return .= $out['protected'];
}
if (!empty($out['private'])) {
$return .= $out['private'];
}
return $return . '</div>';
}
}
@@ -0,0 +1,20 @@
<?php
/**
* Returns the correct end of line character(s) for the current operating system
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_eol_compile(Dwoo_Compiler $compiler)
{
return 'PHP_EOL';
}
@@ -0,0 +1,61 @@
<?php
/**
* Applies various escaping schemes on the given string
* <pre>
* * value : the string to process
* * format : escaping format to use, valid formats are : html, htmlall, url, urlpathinfo, quotes, hex, hexentity, javascript and mail
* * charset : character set to use for the conversion (applies to some formats only), defaults to the current Dwoo charset
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_escape(Dwoo $dwoo, $value='', $format='html', $charset=null)
{
if ($charset === null) {
$charset = $dwoo->getCharset();
}
switch($format)
{
case 'html':
return htmlspecialchars((string) $value, ENT_QUOTES, $charset);
case 'htmlall':
return htmlentities((string) $value, ENT_QUOTES, $charset);
case 'url':
return rawurlencode((string) $value);
case 'urlpathinfo':
return str_replace('%2F', '/', rawurlencode((string) $value));
case 'quotes':
return preg_replace("#(?<!\\\\)'#", "\\'", (string) $value);
case 'hex':
$out = '';
$cnt = strlen((string) $value);
for ($i=0; $i < $cnt; $i++) {
$out .= '%' . bin2hex((string) $value[$i]);
}
return $out;
case 'hexentity':
$out = '';
$cnt = strlen((string) $value);
for ($i=0; $i < $cnt; $i++)
$out .= '&#x' . bin2hex((string) $value[$i]) . ';';
return $out;
case 'javascript':
return strtr((string) $value, array('\\'=>'\\\\',"'"=>"\\'",'"'=>'\\"',"\r"=>'\\r',"\n"=>'\\n','</'=>'<\/'));
case 'mail':
return str_replace(array('@', '.'), array('&nbsp;(AT)&nbsp;', '&nbsp;(DOT)&nbsp;'), (string) $value);
default:
return $dwoo->triggerError('Escape\'s format argument must be one of : html, htmlall, url, urlpathinfo, hex, hexentity, javascript or mail, "'.$format.'" given.', E_USER_WARNING);
}
}
@@ -0,0 +1,41 @@
<?php
/**
* Evaluates the given string as if it was a template
*
* Although this plugin is kind of optimized and will
* not recompile your string each time, it is still not
* a good practice to use it. If you want to have templates
* stored in a database or something you should probably use
* the Dwoo_Template_String class or make another class that
* extends it
* <pre>
* * var : the string to use as a template
* * assign : if set, the output of the template will be saved in this variable instead of being output
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_eval(Dwoo $dwoo, $var, $assign = null)
{
if ($var == '') {
return;
}
$tpl = new Dwoo_Template_String($var);
$out = $dwoo->get($tpl, $dwoo->readVar('_parent'));
if ($assign !== null) {
$dwoo->assignInScope($out, $assign);
} else {
return $out;
}
}
@@ -0,0 +1,126 @@
<?php
/**
* Extends another template, read more about template inheritance at {@link http://wiki.dwoo.org/index.php/TemplateInheritance}
* <pre>
* * file : the template to extend
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
class Dwoo_Plugin_extends extends Dwoo_Plugin implements Dwoo_ICompilable
{
protected static $childSource;
protected static $l;
protected static $r;
protected static $lastReplacement;
public static function compile(Dwoo_Compiler $compiler, $file)
{
list($l, $r) = $compiler->getDelimiters();
self::$l = preg_quote($l,'/');
self::$r = preg_quote($r,'/');
if ($compiler->getLooseOpeningHandling()) {
self::$l .= '\s*';
self::$r = '\s*'.self::$r;
}
$inheritanceTree = array(array('source'=>$compiler->getTemplateSource()));
$curPath = dirname($compiler->getDwoo()->getTemplate()->getResourceIdentifier()) . DIRECTORY_SEPARATOR;
$curTpl = $compiler->getDwoo()->getTemplate();
while (!empty($file)) {
if ($file === '""' || $file === "''" || (substr($file, 0, 1) !== '"' && substr($file, 0, 1) !== '\'')) {
throw new Dwoo_Compilation_Exception($compiler, 'Extends : The file name must be a non-empty string');
return;
}
if (preg_match('#^["\']([a-z]{2,}):(.*?)["\']$#i', $file, $m)) {
// resource:identifier given, extract them
$resource = $m[1];
$identifier = $m[2];
} else {
// get the current template's resource
$resource = $curTpl->getResourceName();
$identifier = substr($file, 1, -1);
}
try {
$parent = $compiler->getDwoo()->templateFactory($resource, $identifier, null, null, null, $curTpl);
} catch (Dwoo_Security_Exception $e) {
throw new Dwoo_Compilation_Exception($compiler, 'Extends : Security restriction : '.$e->getMessage());
} catch (Dwoo_Exception $e) {
throw new Dwoo_Compilation_Exception($compiler, 'Extends : '.$e->getMessage());
}
if ($parent === null) {
throw new Dwoo_Compilation_Exception($compiler, 'Extends : Resource "'.$resource.':'.$identifier.'" not found.');
} elseif ($parent === false) {
throw new Dwoo_Compilation_Exception($compiler, 'Extends : Resource "'.$resource.'" does not support extends.');
}
$curTpl = $parent;
$newParent = array('source'=>$parent->getSource(), 'resource'=>$resource, 'identifier'=>$parent->getResourceIdentifier(), 'uid'=>$parent->getUid());
if (array_search($newParent, $inheritanceTree, true) !== false) {
throw new Dwoo_Compilation_Exception($compiler, 'Extends : Recursive template inheritance detected');
}
$inheritanceTree[] = $newParent;
if (preg_match('/^'.self::$l.'extends\s+(?:file=)?\s*(\S+?|(["\']).+?\2)'.self::$r.'/i', $parent->getSource(), $match)) {
$curPath = dirname($identifier) . DIRECTORY_SEPARATOR;
$file = (substr($match[1], 0, 1) !== '"' && substr($match[1], 0, 1) !== '"') ? '"'.str_replace('"', '\\"', $match[1]).'"' : $match[1];
} else {
$file = false;
}
}
while (true) {
$parent = array_pop($inheritanceTree);
$child = end($inheritanceTree);
self::$childSource = $child['source'];
self::$lastReplacement = count($inheritanceTree) === 1;
if (!isset($newSource)) {
$newSource = $parent['source'];
}
$newSource = preg_replace_callback('/'.self::$l.'block (["\']?)(.+?)\1'.self::$r.'(?:\r?\n?)(.*?)(?:\r?\n?)'.self::$l.'\/block'.self::$r.'/is', array('Dwoo_Plugin_extends', 'replaceBlock'), $newSource);
$newSource = $l.'do extendsCheck("'.$parent['resource'].':'.$parent['identifier'].'" "'.str_replace('"', '\\"', $parent['uid']).'")'.$r.$newSource;
if (self::$lastReplacement) {
break;
}
}
$compiler->setTemplateSource($newSource);
$compiler->setPointer(0);
}
protected static function replaceBlock(array $matches)
{
if (preg_match('/'.self::$l.'block (["\']?)'.preg_quote($matches[2],'/').'\1'.self::$r.'(?:\r?\n?)(.*?)(?:\r?\n?)'.self::$l.'\/block'.self::$r.'/is', self::$childSource, $override)) {
$l = stripslashes(self::$l);
$r = stripslashes(self::$r);
if (self::$lastReplacement) {
return preg_replace('/'.self::$l.'\$dwoo\.parent'.self::$r.'/is', $matches[3], $override[2]);
} else {
return $l.'block '.$matches[1].$matches[2].$matches[1].$r.preg_replace('/'.self::$l.'\$dwoo\.parent'.self::$r.'/is', $matches[3], $override[2]).$l.'/block'.$r;
}
} else {
if (self::$lastReplacement) {
return $matches[3];
} else {
return $matches[0];
}
}
}
}
@@ -0,0 +1,34 @@
<?php
/**
* Checks whether an extended file has been modified, and if so recompiles the current template. This is for internal use only, do not use.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_extendsCheck_compile(Dwoo_Compiler $compiler, $file, $uid)
{
preg_match('#^["\']([a-z]{2,}):(.*?)["\']$#i', $file, $m);
$resource = $m[1];
$identifier = $m[2];
return '// checking for modification in '.$resource.':'.$identifier.'
try {
$tpl = $this->templateFactory("'.$resource.'", "'.$identifier.'");
} catch (Dwoo_Exception $e) {
$this->triggerError(\'Extends : Resource <em>'.$resource.'</em> was not added to Dwoo, can not include <em>'.$identifier.'</em>\', E_USER_WARNING);
}
if ($tpl === null)
$this->triggerError(\'Extends : Resource "'.$resource.':'.$identifier.'" was not found.\', E_USER_WARNING);
elseif ($tpl === false)
$this->triggerError(\'Extends : Resource "'.$resource.'" does not support extends.\', E_USER_WARNING);
if ($tpl->getUid() != "'.substr($uid, 1, -1).'") { ob_end_clean(); return false; }';
}
@@ -0,0 +1,51 @@
<?php
/**
* Reads a file
* <pre>
* * file : path or URI of the file to read (however reading from another website is not recommended for performance reasons)
* * assign : if set, the file will be saved in this variable instead of being output
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_fetch(Dwoo $dwoo, $file, $assign = null)
{
if ($file === '') {
return;
}
if ($policy = $dwoo->getSecurityPolicy()) {
while (true) {
if (preg_match('{^([a-z]+?)://}i', $file)) {
return $dwoo->triggerError('The security policy prevents you to read files from external sources.', E_USER_WARNING);
}
$file = realpath($file);
$dirs = $policy->getAllowedDirectories();
foreach ($dirs as $dir=>$dummy) {
if (strpos($file, $dir) === 0) {
break 2;
}
}
return $dwoo->triggerError('The security policy prevents you to read <em>'.$file.'</em>', E_USER_WARNING);
}
}
$file = str_replace(array("\t", "\n", "\r"), array('\\t', '\\n', '\\r'), $file);
$out = file_get_contents($file);
if ($assign !== null) {
$dwoo->assignInScope($out, $assign);
} else {
return $out;
}
}
@@ -0,0 +1,74 @@
<?php
/**
* Inserts another template into the current one
* <pre>
* * file : the resource name of the template
* * cache_time : cache length in seconds
* * cache_id : cache identifier for the included template
* * compile_id : compilation identifier for the included template
* * data : data to feed into the included template, it can be any array and will default to $_root (the current data)
* * assign : if set, the output of the included template will be saved in this variable instead of being output
* * rest : any additional parameter/value provided will be added to the data array
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_include(Dwoo $dwoo, $file, $cache_time = null, $cache_id = null, $compile_id = null, $data = '_root', $assign = null, array $rest = array())
{
if ($file === '') {
return;
}
if (preg_match('#^([a-z]{2,}):(.*)$#i', $file, $m)) {
// resource:identifier given, extract them
$resource = $m[1];
$identifier = $m[2];
} else {
// get the current template's resource
$resource = $dwoo->getTemplate()->getResourceName();
$identifier = $file;
}
try {
$include = $dwoo->templateFactory($resource, $identifier, $cache_time, $cache_id, $compile_id);
} catch (Dwoo_Security_Exception $e) {
return $dwoo->triggerError('Include : Security restriction : '.$e->getMessage(), E_USER_WARNING);
} catch (Dwoo_Exception $e) {
return $dwoo->triggerError('Include : '.$e->getMessage(), E_USER_WARNING);
}
if ($include === null) {
return $dwoo->triggerError('Include : Resource "'.$resource.':'.$identifier.'" not found.', E_USER_WARNING);
} elseif ($include === false) {
return $dwoo->triggerError('Include : Resource "'.$resource.'" does not support includes.', E_USER_WARNING);
}
if ($dwoo->isArray($data)) {
$vars = $data;
} elseif ($dwoo->isArray($cache_time)) {
$vars = $cache_time;
} else {
$vars = $dwoo->readVar($data);
}
if (count($rest)) {
$vars = $rest + $vars;
}
$out = $dwoo->get($include, $vars);
if ($assign !== null) {
$dwoo->assignInScope($out, $assign);
} else {
return $out;
}
}
@@ -0,0 +1,24 @@
<?php
/**
* Indents every line of a text by the given amount of characters
* <pre>
* * value : the string to indent
* * by : how many characters should be inserted before each line
* * char : the character(s) to insert
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_indent_compile(Dwoo_Compiler $compiler, $value, $by=4, $char=' ')
{
return "preg_replace('#^#m', '".str_repeat(substr($char, 1, -1), trim($by, '"\''))."', $value)";
}
@@ -0,0 +1,22 @@
<?php
/**
* Checks whether a variable is not null
* <pre>
* * var : variable to check
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_isset_compile(Dwoo_Compiler $compiler, $var)
{
return '('.$var.' !== null)';
}
@@ -0,0 +1,22 @@
<?php
/**
* Makes the input string lower cased
* <pre>
* * value : the string to process
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_lower_compile(Dwoo_Compiler $compiler, $value)
{
return 'mb_strtolower((string) '.$value.', $this->charset)';
}
@@ -0,0 +1,117 @@
<?php
/**
* Outputs a mailto link with optional spam-proof (okay probably not) encoding
* <pre>
* * address : target email address
* * text : display text to show for the link, defaults to the address if not provided
* * subject : the email subject
* * encode : one of the available encoding (none, js, jscharcode or hex)
* * cc : address(es) to carbon copy, comma separated
* * bcc : address(es) to blind carbon copy, comma separated
* * newsgroups : newsgroup(s) to post to, comma separated
* * followupto : address(es) to follow up, comma separated
* * extra : additional attributes to add to the &lt;a&gt; tag
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_mailto(Dwoo $dwoo, $address, $text=null, $subject=null, $encode=null, $cc=null, $bcc=null, $newsgroups=null, $followupto=null, $extra=null)
{
if (empty($address)) {
return '';
}
if (empty($text)) {
$text = $address;
}
// build address string
$address .= '?';
if (!empty($subject)) {
$address .= 'subject='.rawurlencode($subject).'&';
}
if (!empty($cc)) {
$address .= 'cc='.rawurlencode($cc).'&';
}
if (!empty($bcc)) {
$address .= 'bcc='.rawurlencode($bcc).'&';
}
if (!empty($newsgroup)) {
$address .= 'newsgroups='.rawurlencode($newsgroups).'&';
}
if (!empty($followupto)) {
$address .= 'followupto='.rawurlencode($followupto).'&';
}
$address = rtrim($address, '?&');
// output
switch($encode)
{
case 'none':
case null:
return '<a href="mailto:'.$address.'" '.$extra.'>'.$text.'</a>';
case 'js':
case 'javascript':
$str = 'document.write(\'<a href="mailto:'.$address.'" '.$extra.'>'.$text.'</a>\');';
$len = strlen($str);
$out = '';
for ($i=0; $i<$len; $i++) {
$out .= '%'.bin2hex($str[$i]);
}
return '<script type="text/javascript">eval(unescape(\''.$out.'\'));</script>';
break;
case 'javascript_charcode':
case 'js_charcode':
case 'jscharcode':
case 'jschar':
$str = '<a href="mailto:'.$address.'" '.$extra.'>'.$text.'</a>';
$len = strlen($str);
$out = '<script type="text/javascript">'."\n<!--\ndocument.write(String.fromCharCode(";
for ($i=0; $i<$len; $i++) {
$out .= ord($str[$i]).',';
}
return rtrim($out, ',') . "));\n-->\n</script>\n";
break;
case 'hex':
if (strpos($address, '?') !== false) {
return $dwoo->triggerError('Mailto: Hex encoding is not possible with extra attributes, use one of : <em>js, jscharcode or none</em>.', E_USER_WARNING);
}
$out = '<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;';
$len = strlen($address);
for ($i=0; $i<$len; $i++) {
if (preg_match('#\w#', $address[$i])) {
$out .= '%'.bin2hex($address[$i]);
} else {
$out .= $address[$i];
}
}
$out .= '" '.$extra.'>';
$len = strlen($text);
for ($i=0; $i<$len; $i++) {
$out .= '&#x'.bin2hex($text[$i]);
}
return $out.'</a>';
default:
return $dwoo->triggerError('Mailto: <em>encode</em> argument is invalid, it must be one of : <em>none (= no value), js, js_charcode or hex</em>', E_USER_WARNING);
}
}
+130
View File
@@ -0,0 +1,130 @@
<?php
/**
* Computes a mathematical equation
* <pre>
* * equation : the equation to compute, it can include normal variables with $foo or special math variables without the dollar sign
* * format : output format, see {@link http://php.net/sprintf} for details
* * assign : if set, the output is assigned into the given variable name instead of being output
* * rest : all math specific variables that you use must be defined, see the example
* </pre>
* Example :
*
* <code>
* {$c=2}
* {math "(a+b)*$c/4" a=3 b=5}
*
* output is : 4 ( = (3+5)*2/4)
* </code>
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_math_compile(Dwoo_Compiler $compiler, $equation, $format='', $assign='', array $rest=array())
{
/**
* Holds the allowed function, characters, operators and constants
*/
$allowed = array
(
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'+', '-', '/', '*', '.', ' ', '<<', '>>', '%', '&', '^', '|', '~',
'abs(', 'ceil(', 'floor(', 'exp(', 'log10(',
'cos(', 'sin(', 'sqrt(', 'tan(',
'M_PI', 'INF', 'M_E',
);
/**
* Holds the functions that can accept multiple arguments
*/
$funcs = array
(
'round(', 'log(', 'pow(',
'max(', 'min(', 'rand(',
);
$equation = $equationSrc = str_ireplace(array('pi', 'M_PI()', 'inf', ' e '), array('M_PI', 'M_PI', 'INF', ' M_E '), $equation);
$delim = $equation[0];
$open = $delim.'.';
$close = '.'.$delim;
$equation = substr($equation, 1, -1);
$out = '';
$ptr = 1;
$allowcomma = 0;
while (strlen($equation) > 0) {
$substr = substr($equation, 0, $ptr);
if (array_search($substr, $allowed) !== false) {
// allowed string
$out.=$substr;
$equation = substr($equation, $ptr);
$ptr = 0;
} elseif (array_search($substr, $funcs) !== false) {
// allowed func
$out.=$substr;
$equation = substr($equation, $ptr);
$ptr = 0;
$allowcomma++;
if ($allowcomma === 1) {
$allowed[] = ',';
}
} elseif (isset($rest[$substr])) {
// variable
$out.=$rest[$substr];
$equation = substr($equation, $ptr);
$ptr = 0;
} elseif ($substr === $open) {
// pre-replaced variable
preg_match('#.*\((?:[^()]*?|(?R))\)'.str_replace('.', '\\.', $close).'#', substr($equation, 2), $m);
if (empty($m)) {
preg_match('#.*?'.str_replace('.', '\\.', $close).'#', substr($equation, 2), $m);
}
$out.=substr($m[0], 0, -2);
$equation = substr($equation, strlen($m[0])+2);
$ptr = 0;
} elseif ($substr==='(') {
// opening parenthesis
if ($allowcomma>0) {
$allowcomma++;
}
$out.=$substr;
$equation = substr($equation, $ptr);
$ptr = 0;
} elseif ($substr===')') {
// closing parenthesis
if ($allowcomma>0) {
$allowcomma--;
if ($allowcomma===0) {
array_pop($allowed);
}
}
$out.=$substr;
$equation = substr($equation, $ptr);
$ptr = 0;
} elseif ($ptr >= strlen($equation)) {
// parse error if we've consumed the entire equation without finding anything valid
throw new Dwoo_Compilation_Exception($compiler, 'Math : Syntax error or variable undefined in equation '.$equationSrc.' at '.$substr);
return;
} else {
// nothing special, advance
$ptr++;
}
}
if ($format !== '\'\'') {
$out = 'sprintf('.$format.', '.$out.')';
}
if ($assign !== '\'\'') {
return '($this->assignInScope('.$out.', '.$assign.'))';
}
return '('.$out.')';
}
@@ -0,0 +1,22 @@
<?php
/**
* Converts line breaks into <br /> tags
* <pre>
* * value : the string to process
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_nl2br_compile(Dwoo_Compiler $compiler, $value)
{
return 'nl2br((string) '.$value.')';
}
@@ -0,0 +1,38 @@
<?php
/**
* Replaces the search string by the replace string using regular expressions
* <pre>
* * value : the string to search into
* * search : the string to search for, must be a complete regular expression including delimiters
* * replace : the string to use as a replacement, must be a complete regular expression including delimiters
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_regex_replace(Dwoo $dwoo, $value, $search, $replace)
{
$search = (array) $search;
$cnt = count($search);
for ($i = 0; $i < $cnt; $i++) {
// Credits for this to Monte Ohrt who made smarty's regex_replace modifier
if (($pos = strpos($search[$i], "\0")) !== false) {
$search[$i] = substr($search[$i], 0, $pos);
}
if (preg_match('#[a-z\s]+$#is', $search[$i], $m) && (strpos($m[0], 'e') !== false)) {
$search[$i] = substr($search[$i], 0, -strlen($m[0])) . str_replace(array('e', ' '), '', $m[0]);
}
}
return preg_replace($search, $replace, $value);
}
@@ -0,0 +1,28 @@
<?php
/**
* Replaces the search string by the replace string
* <pre>
* * value : the string to search into
* * search : the string to search for
* * replace : the string to use as a replacement
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_replace_compile(Dwoo_Compiler $compiler, $value, $search, $replace, $case_sensitive = true)
{
if ($case_sensitive == 'false' || (bool)$case_sensitive === false) {
return 'str_ireplace('.$search.', '.$replace.', '.$value.')';
} else {
return 'str_replace('.$search.', '.$replace.', '.$value.')';
}
}
@@ -0,0 +1,34 @@
<?php
/**
* Reverses a string or an array
* <pre>
* * value : the string or array to reverse
* * preserve_keys : if value is an array and this is true, then the array keys are left intact
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_reverse(Dwoo $dwoo, $value, $preserve_keys=false)
{
if (is_array($value)) {
return array_reverse($value, $preserve_keys);
} elseif(($charset=$dwoo->getCharset()) === 'iso-8859-1') {
return strrev((string) $value);
} else {
$strlen = mb_strlen($value);
$out = '';
while ($strlen--) {
$out .= mb_substr($value, $strlen, 1, $charset);
}
return $out;
}
}
@@ -0,0 +1,22 @@
<?php
/**
* Marks the variable as safe and removes the auto-escape function, only useful if you turned auto-escaping on
* <pre>
* * var : the variable to pass through untouched
* </pre>
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_safe_compile(Dwoo_Compiler $compiler, $var)
{
return preg_replace('#\(is_string\(\$tmp=(.+?)\) \? htmlspecialchars\(\$tmp, ENT_QUOTES, \$this->charset\) : \$tmp\)#', '$1', $var);
}
Loaded 100 of 316 files, more files were not shown because too many files have changed in this diff. Show more