Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
103b878
stanning on Inflector
shmax Sep 2, 2023
d611de8
stanning on Inflector
shmax Sep 2, 2023
15cda29
stanning on Table
shmax Sep 2, 2023
9e1bb67
fix column
shmax Sep 3, 2023
857d979
clean up date stuff
shmax Sep 3, 2023
54043de
some serializer linting
shmax Sep 3, 2023
f48ca2a
fixer
shmax Sep 3, 2023
514bb8f
fix warning
shmax Sep 3, 2023
c54b783
Merge branch 'master' into phpstan-7
shmax Sep 3, 2023
126acac
stanning for Serialization
shmax Sep 3, 2023
e6e86a5
Merge remote-tracking branch 'origin/master' into phpstan-7
shmax Sep 4, 2023
1822822
more stanning
shmax Sep 4, 2023
362e3df
wip
shmax Sep 4, 2023
e274d12
fix test
shmax Sep 4, 2023
55b6f9b
remove pointless reference
shmax Sep 4, 2023
66c8c27
stanning for Relationships
shmax Sep 4, 2023
a16a4f3
linting
shmax Sep 4, 2023
d913a61
linting
shmax Sep 4, 2023
4a05680
uses of get_primary_key
shmax Sep 4, 2023
3328a21
simplify camelize
shmax Sep 4, 2023
6ef0dd1
merge methods
shmax Sep 4, 2023
2f9d1c9
remove class option
shmax Sep 4, 2023
6c2f3ff
stanning on dynamic extension
shmax Sep 4, 2023
b0de19d
start on Connection
shmax Sep 4, 2023
6e8bd60
fix squeeze
shmax Sep 4, 2023
5208fac
linting
shmax Sep 4, 2023
bd5491a
stanning for Cache
shmax Sep 4, 2023
3b055a8
stanning for Callback
shmax Sep 4, 2023
ad81af3
fix column
shmax Sep 4, 2023
6f162ff
linting
shmax Sep 4, 2023
9c8d4ca
better fix for Column
shmax Sep 4, 2023
2708b93
finish model
shmax Sep 4, 2023
1bbd1bd
linting
shmax Sep 4, 2023
41efd77
linting
shmax Sep 4, 2023
c6abfad
linting
shmax Sep 4, 2023
beaf06d
fix tests
shmax Sep 4, 2023
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
4 changes: 2 additions & 2 deletions lib/Adapter/MysqlAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public function query_for_tables(): \PDOStatement
public function create_column(array $column): Column
{
$c = new Column();
$c->inflected_name = Inflector::instance()->variablize($column['field']);
$c->inflected_name = Inflector::variablize($column['field']);
$c->name = $column['field'];
$c->nullable = ('YES' === $column['null'] ? true : false);
$c->pk = ('PRI' === $column['key'] ? true : false);
Expand Down Expand Up @@ -84,7 +84,7 @@ public function accepts_limit_and_order_for_update_and_delete(): bool
}

/**
* @return array<string, array<string, mixed>>
* @return array<string, string|array<string, mixed>>
*/
public function native_database_types(): array
{
Expand Down
2 changes: 1 addition & 1 deletion lib/Adapter/PgsqlAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public function query_for_tables(): \PDOStatement
public function create_column(array $column): Column
{
$c = new Column();
$c->inflected_name = Inflector::instance()->variablize($column['field']);
$c->inflected_name = Inflector::variablize($column['field']);
$c->name = $column['field'];
$c->nullable = ($column['not_nullable'] ? false : true);
$c->pk = ($column['pk'] ? true : false);
Expand Down
16 changes: 8 additions & 8 deletions lib/Adapter/SqliteAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@
*/
class SqliteAdapter extends Connection
{
public static $datetime_format = 'Y-m-d H:i:s';
public static string $datetime_format = 'Y-m-d H:i:s';

protected function __construct(\stdClass $info)
protected function __construct(array $info)
{
if (!file_exists($info->host)) {
throw new ConnectionException("Could not find sqlite db: $info->host");
if (!file_exists($info['host'])) {
throw new ConnectionException('Could not find sqlite db: ' . $info['host']);
}
$this->connection = new \PDO("sqlite:$info->host", null, null, static::$PDO_OPTIONS);
$this->connection = new \PDO('sqlite:' . $info['host'], null, null, static::$PDO_OPTIONS);
}

public function limit(string $sql, int $offset = 0, int $limit = 0)
Expand All @@ -49,10 +49,10 @@ public function query_for_tables(): \PDOStatement
public function create_column(array $column): Column
{
$c = new Column();
$c->inflected_name = Inflector::instance()->variablize($column['name']);
$c->inflected_name = Inflector::variablize($column['name']);
$c->name = $column['name'];
$c->nullable = $column['notnull'] ? false : true;
$c->pk = $column['pk'] ? true : false;
$c->nullable = !$column['notnull'];
$c->pk = (bool) $column['pk'];
$c->auto_increment = in_array(
strtoupper($column['type']),
['INT', 'INTEGER']
Expand Down
18 changes: 10 additions & 8 deletions lib/Cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,16 @@ public static function initialize(string $url = '', array $options = []): void
{
if ($url) {
$url = parse_url($url);
$file = ucwords(Inflector::instance()->camelize($url['scheme']));
assert(is_array($url));
$file = ucwords(Inflector::camelize($url['scheme'] ?? ''));
$class = "ActiveRecord\\$file";
require_once __DIR__ . "/cache/$file.php";
static::$adapter = new $class($url);

$cache = new $class($url);

assert($cache instanceof Memcache);

static::$adapter = $cache;
} else {
static::$adapter = null;
}
Expand Down Expand Up @@ -85,7 +91,7 @@ public static function get(string $key, \Closure $closure, int $expire = null):
$key = static::get_namespace() . $key;

if (!($value = static::$adapter->read($key))) {
static::$adapter->write($key, $value = $closure(), $expire ?? static::$options['expire']);
static::$adapter->write($key, $value = $closure(), $expire ?? static::$options['expire'] ?? 0);
}

return $value;
Expand All @@ -97,13 +103,9 @@ public static function set(string $key, mixed $var, int $expire = null): void
return;
}

if (is_null($expire)) {
$expire = static::$options['expire'];
}

$key = static::get_namespace() . $key;

static::$adapter->write($key, $var, $expire);
static::$adapter->write($key, $var, $expire ?? static::$options['expire'] ?? 0);
}

public static function delete(string $key): void
Expand Down
4 changes: 2 additions & 2 deletions lib/CallBack.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class CallBack
/**
* Holds data for registered callbacks.
*
* @var array<string, CallBack>
* @var array<string, array<\Closure|string>>
*/
private array $registry = [];

Expand Down Expand Up @@ -141,7 +141,7 @@ public function __construct(string $model_class_name)
*
* @param $name string Name of a callback (see {@link VALID_CALLBACKS $VALID_CALLBACKS})
*
* @return array<CallBack> array of callbacks or null if invalid callback name
* @return array<\Closure|string> array of callbacks or empty array if invalid callback name
*/
public function get_callbacks(string $name): array
{
Expand Down
2 changes: 1 addition & 1 deletion lib/Column.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ public static function castIntegerSafely($value): string|int
}

// It's just a decimal number
elseif (is_numeric($value) && floor($value) != $value) {
elseif (is_float($value) && floor($value) != $value) {
return (int) $value;
}

Expand Down
135 changes: 69 additions & 66 deletions lib/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,20 @@
use ActiveRecord\Exception\DatabaseException;
use Closure;
use PDO;
use Psr\Log\LoggerInterface;

/**
* The base class for database connection adapters.
*
* @package ActiveRecord
* @phpstan-type ConnectionInfo array{
* protocol: string,
* host: string,
* db: string|null,
* user: string|null,
* pass: string|null,
* port?: int|null,
* charset?: string|null
* }
*/
abstract class Connection
{
Expand All @@ -42,22 +51,16 @@ abstract class Connection
public string $last_query;
/**
* Switch for logging.
*
* @var bool
*/
private $logging = false;
private bool $logging = false;
/**
* Contains a Logger object that must implement a log() method.
*
* @var object
*/
private $logger;
private LoggerInterface $logger;
/**
* The name of the protocol that is used.
*
* @var string
*/
public $protocol;
public string $protocol;
/**
* Database's date format
*
Expand All @@ -66,10 +69,8 @@ abstract class Connection
public static $date_format = 'Y-m-d';
/**
* Database's datetime format
*
* @var string
*/
public static $datetime_format = 'Y-m-d H:i:s';
public static string $datetime_format = 'Y-m-d H:i:s';
/**
* Default PDO options to set for each connection.
*
Expand Down Expand Up @@ -126,16 +127,17 @@ public static function instance(string $connection_string_or_connection_name = n
throw new DatabaseException('Empty connection string');
}
$info = static::parse_connection_url($connection_string);
$fqclass = static::load_adapter_class($info->protocol);
$fqclass = static::load_adapter_class($info['protocol']);

try {
$connection = new $fqclass($info);
$connection->protocol = $info->protocol;
assert($connection instanceof Connection);
$connection->protocol = $info['protocol'];
$connection->logging = $config->get_logging();
$connection->logger = $connection->logging ? $config->get_logger() : null;

if (isset($info->charset)) {
$connection->set_encoding($info->charset);
if (isset($info['charset'])) {
$connection->set_encoding($info['charset']);
}
} catch (\PDOException $e) {
throw new DatabaseException($e);
Expand All @@ -162,6 +164,8 @@ protected static function load_adapter_class(string $adapter)
}
require_once $source;

assert(class_exists($fqclass));

return $fqclass;
}

Expand All @@ -186,26 +190,26 @@ protected static function load_adapter_class(string $adapter)
*
* @param string $connection_url A connection URL
*
* @return object the parsed URL as an object
* @return ConnectionInfo
*/
public static function parse_connection_url(string $connection_url)
public static function parse_connection_url(string $connection_url): array
{
$url = @parse_url($connection_url);

if (!isset($url['host'])) {
throw new DatabaseException('Database host must be specified in the connection string. If you want to specify an absolute filename, use e.g. sqlite://unix(/path/to/file)');
}
$info = new \stdClass();
$info->protocol = $url['scheme'];
$info->host = $url['host'];
$info->db = isset($url['path']) ? substr($url['path'], 1) : null;
$info->user = isset($url['user']) ? $url['user'] : null;
$info->pass = isset($url['pass']) ? $url['pass'] : null;
$host = $url['host'];
$db = isset($url['path']) ? substr($url['path'], 1) : null;
$user = $url['user'] ?? null;
$pass = $url['pass'] ?? null;
$protocol = $url['scheme'] ?? null;
$charset = null;

$allow_blank_db = ('sqlite' == $info->protocol);
$allow_blank_db = ('sqlite' == $protocol);

if ('unix(' == $info->host) {
$socket_database = $info->host . '/' . $info->db;
if ('unix(' == $host) {
$socket_database = $host . '/' . $db;

if ($allow_blank_db) {
$unix_regex = '/^unix\((.+)\)\/?().*$/';
Expand All @@ -214,29 +218,25 @@ public static function parse_connection_url(string $connection_url)
}

if (preg_match_all($unix_regex, $socket_database, $matches) > 0) {
$info->host = $matches[1][0];
$info->db = $matches[2][0];
$host = $matches[1][0];
$db = $matches[2][0];
}
} elseif ('windows(' == substr($info->host, 0, 8)) {
$info->host = urldecode(substr($info->host, 8) . '/' . substr($info->db, 0, -1));
$info->db = null;
}

if ($allow_blank_db && $info->db) {
$info->host .= '/' . $info->db;
} elseif ('windows(' == substr($host, 0, 8)) {
$host = urldecode(substr($host, 8) . '/' . substr($db, 0, -1));
$db = null;
}

if (isset($url['port'])) {
$info->port = $url['port'];
if ($allow_blank_db && $db) {
$host .= '/' . $db;
}

if (false !== strpos($connection_url, 'decode=true')) {
if ($info->user) {
$info->user = urldecode($info->user);
if ($user) {
$user = urldecode($user);
}

if ($info->pass) {
$info->pass = urldecode($info->pass);
if ($pass) {
$pass = urldecode($pass);
}
}

Expand All @@ -245,33 +245,45 @@ public static function parse_connection_url(string $connection_url)
list($name, $value) = explode('=', $pair);

if ('charset' == $name) {
$info->charset = $value;
$charset = $value;
}
}
}

return $info;
assert(!is_null($protocol));

return [
'charset' => $charset,
'protocol' => $protocol,
'host' => $host,
'db' => $db,
'user' => $user,
'pass' => $pass,
'port' => $url['port'] ?? null
];
}

/**
* Class Connection is a singleton. Access it via instance().
*
* @param ConnectionInfo $info
*/
protected function __construct(\stdClass $info)
protected function __construct(array $info)
{
try {
// unix sockets start with a /
if ('/' != $info->host[0]) {
$host = "host=$info->host";
if ('/' != $info['host'][0]) {
$host = 'host=' . $info['host'];

if (isset($info->port)) {
$host .= ";port=$info->port";
if (isset($info['port'])) {
$host .= ';port=' . $info['port'];
}
} else {
$host = "unix_socket=$info->host";
$host = 'unix_socket=' . $info['host'];
}

$dsn = "$info->protocol:$host;dbname=$info->db";
$this->connection = new \PDO($dsn, $info->user, $info->pass, static::$PDO_OPTIONS);
$dsn = $info['protocol'] . ":$host;dbname=" . $info['db'];
$this->connection = new \PDO($dsn, $info['user'], $info['pass'], static::$PDO_OPTIONS);
} catch (\PDOException $e) {
throw new Exception\ConnectionException($e);
}
Expand Down Expand Up @@ -484,26 +496,15 @@ public function quote_name($string)
$string : static::$QUOTE_CHARACTER . $string . static::$QUOTE_CHARACTER;
}

/**
* Return a date time formatted into the database's date format.
*
* @param DateTime $datetime The DateTime object
*
* @return string
*/
public function date_to_string($datetime)
public function date_string(\DateTimeInterface $datetime): string
{
return $datetime->format(static::$date_format);
}

/**
* Return a date time formatted into the database's datetime format.
*
* @param DateTime $datetime The DateTime object
*
* @return string
*/
public function datetime_to_string(\DateTime $datetime)
public function datetime_string(\DateTimeInterface $datetime): string
{
return $datetime->format(static::$datetime_format);
}
Expand All @@ -524,6 +525,8 @@ public function string_to_datetime(string $string): ?DateTime
return null;
}

assert($date instanceof \DateTime);

$date_class = Config::instance()->get_date_class();

return $date_class::createFromFormat(
Expand Down
Loading