<?php
namespace Spot\Adapter;
/**
* Abstract Adapter
*
* @package Spot
* @link http://spot.os.ly
*/
abstract class AdapterAbstract
{
// Format for date columns, formatted for PHP's date() function
protected $_format_date;
protected $_format_time;
protected $_format_datetime;
// Connection details
protected $_connection;
protected $_dsn;
protected $_dsnParts;
protected $_options;
/**
* @param mixed $dsn DSN string or pre-existing Mongo object
* @param array $options
*/
public function __construct($dsn, array $options = array())
{
$this->_dsn = $dsn;
if(is_string($dsn)) {
// Parse DSN string
$this->_dsnParts = self::parseDSN($dsn);
} elseif(is_array($dsn)) {
// Array of keys => values
$this->_dsnParts = $dsn;
} elseif(null === $dsn) {
// No DSN string given
$this->_dsnParts = array();
}
$this->_options = $options;
}
/**
* Get database format
*
* @return string Date format for PHP's date() function
*/
public function dateFormat()
{
return $this->_format_date;
}
/**
* Get database time format
*
* @return string Time format for PHP's date() function
*/
public function timeFormat()
{
return $this->_format_time;
}
/**
* Get database format
*
* @return string DateTime format for PHP's date() function
*/
public function dateTimeFormat()
{
return $this->_format_datetime;
}
/**
* Get date
*
* @return object DateTime
*/
public function date($format = null)
{
if(null === $format) {
$format = $this->dateFormat();
}
return $this->dateTimeObject($format . ' ' . $this->timeFormat());
}
/**
* Get database time format
*
* @return object DateTime
*/
public function time($format = null)
{
if(null === $format) {
$format = $this->timeFormat();
}
return $this->dateTimeObject($this->dateFormat() . ' ' . $format);
}
/**
* Get datetime
*
* @return object DateTIme
*/
public function dateTime($format = null)
{
if(null === $format) {
$format = $this->dateTimeFormat();
}
return $this->dateTimeObject($format);
}
/**
* Turn formstted date into timestamp
* Also handles input timestamps
*
* @return DateTime object
*/
protected function dateTimeObject($format)
{
// Already a timestamp?
if(is_int($format) || is_float($format)) { // @link http://www.php.net/manual/en/function.is-int.php#97006
$dt = new \DateTime();
$dt->setTimestamp($format); // Timestamps must be prefixed with '@' symbol
} else {
$dt = new \DateTime();
$dt->format($format);
}
return $dt;
}
/**
* Taken from PHPUnit 3.4:
* @link http://github.com/sebastianbergmann/phpunit/blob/3.4/PHPUnit/Util/PDO.php
*
* Returns the Data Source Name as a structure containing the various parts of the DSN.
*
* Additional keys can be added by appending a URI query string to the
* end of the DSN.
*
* The format of the supplied DSN is in its fullest form:
* <code>
* adapter(dbsyntax)://username:hide@address.com+host/database?option=8&another=true
* </code>
*
* Most variations are allowed:
* <code>
* adapter://username:hide@address.com+host:110//usr/db_file.db?mode=0644
* adapter://username:hide@address.com/database_name
* adapter://username:hide@address.com
* adapter://hide@address.com
* adapter://host/database
* adapter://host
* adapter(dbsyntax)
* adapter
* </code>
*
* This function is 'borrowed' from PEAR /DB.php .
*
* @param string $dsn Data Source Name to be parsed
*
* @return array an associative array with the following keys:
* + adapter: Database backend used in PHP (mysql, odbc etc.)
* + dbsyntax: Database used with regards to SQL syntax etc.
* + protocol: Communication protocol to use (tcp, unix etc.)
* + host: Host specification (hostname[:port])
* + database: Database to use on the DBMS server
* + username: User name for login
* + password: Password for login
*/
public static function parseDSN( $dsn )
{
if ( $dsn == 'sqlite::memory:' )
{
$dsn = 'sqlite://:memory:';
}
$parsed = array(
'adapter' => FALSE,
'dbsyntax' => FALSE,
'username' => FALSE,
'password' => FALSE,
'protocol' => FALSE,
'host' => FALSE,
'port' => FALSE,
'socket' => FALSE,
'database' => FALSE,
);
if ( is_array( $dsn ) )
{
$dsn = array_merge( $parsed, $dsn );
if ( !$dsn['dbsyntax'] )
{
$dsn['dbsyntax'] = $dsn['adapter'];
}
return $dsn;
}
// Find phptype and dbsyntax
if ( ( $pos = strpos( $dsn, '://' ) ) !== FALSE )
{
$str = substr( $dsn, 0, $pos );
$dsn = substr( $dsn, $pos + 3 );
}
else
{
$str = $dsn;
$dsn = NULL;
}
// Get phptype and dbsyntax
// $str => phptype(dbsyntax)
if ( preg_match( '|^(.+?)\((.*?)\)$|', $str, $arr ) )
{
$parsed['adapter'] = $arr[1];
$parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2];
}
else
{
$parsed['adapter'] = $str;
$parsed['dbsyntax'] = $str;
}
if ( !count( $dsn ) )
{
return $parsed;
}
// Get (if found): username and password
// $dsn => username:hide@address.com+host/database
if ( ( $at = strrpos( (string) $dsn, '@' ) ) !== FALSE )
{
$str = substr( $dsn, 0, $at );
$dsn = substr( $dsn, $at + 1 );
if ( ( $pos = strpos( $str, ':' ) ) !== FALSE )
{
$parsed['username'] = rawurldecode( substr( $str, 0, $pos ) );
$parsed['password'] = rawurldecode( substr( $str, $pos + 1 ) );
}
else
{
$parsed['username'] = rawurldecode( $str );
}
}
// Find protocol and host
if ( preg_match( '|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match ) )
{
// $dsn => proto(proto_opts)/database
$proto = $match[1];
$proto_opts = $match[2] ? $match[2] : FALSE;
$dsn = $match[3];
}
else
{
// $dsn => protocol+host/database (old format)
if ( strpos( $dsn, '+' ) !== FALSE )
{
list( $proto, $dsn ) = explode( '+', $dsn, 2 );
}
if ( strpos( $dsn, '/' ) !== FALSE )
{
list( $proto_opts, $dsn ) = explode( '/', $dsn, 2 );
}
else
{
$proto_opts = $dsn;
$dsn = NULL;
}
}
// process the different protocol options
$parsed['protocol'] = ( !empty( $proto ) ) ? $proto : 'tcp';
$proto_opts = rawurldecode( $proto_opts );
if ( $parsed['protocol'] == 'tcp' )
{
if ( strpos( $proto_opts, ':' ) !== FALSE )
{
list( $parsed['host'], $parsed['port'] ) = explode( ':', $proto_opts );
}
else
{
$parsed['host'] = $proto_opts;
}
}
elseif ( $parsed['protocol'] == 'unix' )
{
$parsed['socket'] = $proto_opts;
}
// Get dabase if any
// $dsn => database
if ( $dsn )
{
if ( ( $pos = strpos( $dsn, '?' ) ) === FALSE )
{
// /database
$parsed['database'] = rawurldecode( $dsn );
}
else
{
// /database?param1=value1¶m2=value2
$parsed['database'] = rawurldecode( substr( $dsn, 0, $pos ) );
$dsn = substr( $dsn, $pos + 1 );
if ( strpos( $dsn, '&') !== FALSE )
{
$opts = explode( '&', $dsn );
}
else
{ // database?param1=value1
$opts = array( $dsn );
}
foreach ( $opts as $opt )
{
list( $key, $value ) = explode( '=', $opt );
if ( !isset( $parsed[$key] ) )
{
// don't allow params overwrite
$parsed[$key] = rawurldecode( $value );
}
}
}
}
return $parsed;
}
}