Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better Datetime handling #317

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@
*.log
test/*.db
*.swp
vendor/*
composer.lock
5 changes: 4 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
install: composer install --prefer-source --dev

before_script:
- echo 'extension = "memcache.so"' >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
- mysql -e 'CREATE DATABASE phpar_test;'
Expand All @@ -12,5 +14,6 @@ language: php
php:
- 5.3
- 5.4
- 5.5

script: phpunit -c phpunit.xml test/
script: vendor/bin/phpunit -c phpunit.xml test/
4 changes: 2 additions & 2 deletions ActiveRecord.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
require __DIR__.'/lib/Table.php';
require __DIR__.'/lib/ConnectionManager.php';
require __DIR__.'/lib/Connection.php';
require __DIR__.'/lib/Serialization.php';
require __DIR__.'/lib/SQLBuilder.php';
require __DIR__.'/lib/Reflections.php';
require __DIR__.'/lib/Inflector.php';
Expand Down Expand Up @@ -45,5 +46,4 @@ function activerecord_autoload($class_name)

if (file_exists($file))
require_once $file;
}
?>
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# PHP ActiveRecord - Version 1.0 #

[![Build Status](https://travis-ci.org/kla/php-activerecord.png?branch=master)](https://travis-ci.org/kla/php-activerecord)
[![Build Status](https://travis-ci.org/jpfuentes2/php-activerecord.png?branch=master)](https://travis-ci.org/jpfuentes2/php-activerecord)

by

Expand Down
5 changes: 5 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "3.7.*",
"pear/pear_exception": "1.0.*@dev",
"pear/Log": "dev-master"
},
"autoload": {
"files": [ "ActiveRecord.php" ]
}
Expand Down
3 changes: 1 addition & 2 deletions lib/Cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,4 @@ private static function get_namespace()
{
return (isset(static::$options['namespace']) && strlen(static::$options['namespace']) > 0) ? (static::$options['namespace'] . "::") : "";
}
}
?>
}
3 changes: 1 addition & 2 deletions lib/CallBack.php
Original file line number Diff line number Diff line change
Expand Up @@ -248,5 +248,4 @@ public function register($name, $closure_or_method_name=null, $options=array())
else
$this->registry[$name][] = $closure_or_method_name;
}
}
?>
}
66 changes: 60 additions & 6 deletions lib/Column.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ class Column
'date' => self::DATE,
'time' => self::TIME,

'int' => self::INTEGER,
'tinyint' => self::INTEGER,
'smallint' => self::INTEGER,
'mediumint' => self::INTEGER,
'int' => self::INTEGER,
'bigint' => self::INTEGER,

'float' => self::DECIMAL,
Expand Down Expand Up @@ -102,22 +102,64 @@ class Column
*/
public $sequence;

/**
* Cast a value to an integer type safely
*
* This will attempt to cast a value to an integer,
* unless its detected that the casting will cause
* the number to overflow or lose precision, in which
* case the number will be returned as a string, so
* that large integers (BIGINTS, unsigned INTS, etc)
* can still be stored without error
*
* This would ideally be done with bcmath or gmp, but
* requiring a new PHP extension for a bug-fix is a
* little ridiculous
*
* @param mixed $value The value to cast
* @return int|string type-casted value
*/
public static function castIntegerSafely($value)
{
if (is_int($value))
return $value;

// Its just a decimal number
elseif (is_numeric($value) && floor($value) != $value)
return (int) $value;

// If adding 0 to a string causes a float conversion,
// we have a number over PHP_INT_MAX
elseif (is_string($value) && is_float($value + 0))
return (string) $value;

// If a float was passed and its greater than PHP_INT_MAX
// (which could be wrong due to floating point precision)
// We'll also check for equal to (>=) in case the precision
// loss creates an overflow on casting
elseif (is_float($value) && $value >= PHP_INT_MAX)
return number_format($value, 0, '', '');

return (int) $value;
}

/**
* Casts a value to the column's type.
*
* @param mixed $value The value to cast
* @param Connection $connection The Connection this column belongs to
* @param boolean $db_format Flag of whether to cast value from the database format
* @return mixed type-casted value
*/
public function cast($value, $connection)
public function cast($value, $connection, $db_format = false)
{
if ($value === null)
return null;

switch ($this->type)
{
case self::STRING: return (string)$value;
case self::INTEGER: return (int)$value;
case self::INTEGER: return static::castIntegerSafely($value);
case self::DECIMAL: return (double)$value;
case self::DATETIME:
case self::DATE:
Expand All @@ -129,8 +171,21 @@ public function cast($value, $connection)

if ($value instanceof \DateTime)
return new DateTime($value->format('Y-m-d H:i:s T'));

return $connection->string_to_datetime($value);
if($db_format)
{
return $connection->string_to_datetime($value);
}
else
{
try
{
return new DateTime($value);
}
catch(\Exception $e)
{
return null;
}
}
}
return $value;
}
Expand All @@ -152,4 +207,3 @@ public function map_raw_type()
return $this->type;
}
}
?>
31 changes: 29 additions & 2 deletions lib/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ class Config extends Singleton
*/
private $date_format = \DateTime::ISO8601;

/**
* The current timezone to use by default in databases.
* Used for databases that can't store timezone info.(MySQL)
*
* @var DateTimeZone
*/
private $default_timezone;

/**
* Allows config initialization using a closure.
*
Expand Down Expand Up @@ -280,6 +288,26 @@ public function set_date_format($format)
Serialization::$DATETIME_FORMAT = $format;
}

public function get_default_timezone()
{
if(!isset($this->default_timezone))
{
$this->default_timezone = new \DateTimeZone(date_default_timezone_get());
}
return $this->default_timezone;
}

public function set_default_timezone($timezone)
{
if($timezone instanceof \DateTimeZone)
{
$this->default_timezone = $timezone;
}
else
{
$this->default_timezone = new \DateTimeZone($timezone);
}
}
/**
* Sets the url for the cache server to enable query caching.
*
Expand All @@ -300,5 +328,4 @@ public function set_cache($url, $options=array())
{
Cache::initialize($url,$options);
}
};
?>
}
19 changes: 9 additions & 10 deletions lib/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -473,13 +473,15 @@ public function datetime_to_string($datetime)
*/
public function string_to_datetime($string)
{
$date = date_create($string);
$errors = \DateTime::getLastErrors();

if ($errors['warning_count'] > 0 || $errors['error_count'] > 0)
return null;

return new DateTime($date->format(static::$datetime_format));
try
{
$datetime = new DateTime($string);
}
catch(\Exception $e)
{
$datetime = null;
}
return $datetime;
}

/**
Expand Down Expand Up @@ -531,6 +533,3 @@ public function accepts_limit_and_order_for_update_and_delete()
}

}

;
?>
4 changes: 1 addition & 3 deletions lib/ConnectionManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,4 @@ public static function drop_connection($name=null)
if (isset(self::$connections[$name]))
unset(self::$connections[$name]);
}
}

?>
}
3 changes: 1 addition & 2 deletions lib/DateTime.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,5 +147,4 @@ public function setTimestamp($unixtimestamp)
$this->flag_dirty();
call_user_func_array(array($this,'parent::setTimestamp'),func_get_args());
}
}
?>
}
23 changes: 11 additions & 12 deletions lib/Exceptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
*
* @package ActiveRecord
*/
class ActiveRecordException extends \Exception {};
class ActiveRecordException extends \Exception {}

/**
* Thrown when a record cannot be found.
*
* @package ActiveRecord
*/
class RecordNotFound extends ActiveRecordException {};
class RecordNotFound extends ActiveRecordException {}

/**
* Thrown when there was an error performing a database operation.
Expand Down Expand Up @@ -44,28 +44,28 @@ public function __construct($adapter_or_string_or_mystery)
else
parent::__construct($adapter_or_string_or_mystery);
}
};
}

/**
* Thrown by {@link Model}.
*
* @package ActiveRecord
*/
class ModelException extends ActiveRecordException {};
class ModelException extends ActiveRecordException {}

/**
* Thrown by {@link Expressions}.
*
* @package ActiveRecord
*/
class ExpressionsException extends ActiveRecordException {};
class ExpressionsException extends ActiveRecordException {}

/**
* Thrown for configuration problems.
*
* @package ActiveRecord
*/
class ConfigException extends ActiveRecordException {};
class ConfigException extends ActiveRecordException {}

/**
* Thrown when attempting to access an invalid property on a {@link Model}.
Expand All @@ -91,7 +91,7 @@ public function __construct($class_name, $property_name)
$this->message = "Undefined property: {$class_name}->{$property_name} in {$this->file} on line {$this->line}";
parent::__construct();
}
};
}

/**
* Thrown when attempting to perform a write operation on a {@link Model} that is in read-only mode.
Expand All @@ -112,26 +112,25 @@ public function __construct($class_name, $method_name)
$this->message = "{$class_name}::{$method_name}() cannot be invoked because this model is set to read only";
parent::__construct();
}
};
}

/**
* Thrown for validations exceptions.
*
* @package ActiveRecord
*/
class ValidationsArgumentError extends ActiveRecordException {};
class ValidationsArgumentError extends ActiveRecordException {}

/**
* Thrown for relationship exceptions.
*
* @package ActiveRecord
*/
class RelationshipException extends ActiveRecordException {};
class RelationshipException extends ActiveRecordException {}

/**
* Thrown for has many thru exceptions.
*
* @package ActiveRecord
*/
class HasManyThroughAssociationException extends RelationshipException {};
?>
class HasManyThroughAssociationException extends RelationshipException {}
Loading