diff --git a/composer.json b/composer.json index c00697e..16afd74 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,8 @@ "nulib/tests": "^7.4", "ext-posix": "*", "ext-pcntl": "*", - "ext-curl": "*" + "ext-curl": "*", + "ext-sqlite3": "*" }, "autoload": { "psr-4": { diff --git a/php/src/db/sqlite/_query_base.php b/php/src/db/sqlite/_query_base.php index 9545077..84bd8ff 100644 --- a/php/src/db/sqlite/_query_base.php +++ b/php/src/db/sqlite/_query_base.php @@ -3,6 +3,7 @@ namespace nulib\db\sqlite; use nulib\db\_private\_base; use nulib\db\_private\Tbindings; +use nulib\output\msg; use nulib\ValueException; use SQLite3; use SQLite3Stmt; @@ -35,10 +36,10 @@ class _query_base extends _base { } } - const DEBUG_QUERIES = false; + const DEBUG_QUERIES = true; function useStmt(SQLite3 $db, ?SQLite3Stmt &$stmt=null, ?string &$sql=null): bool { - if (static::DEBUG_QUERIES) error_log($this->sql); #XXX + if (static::DEBUG_QUERIES) msg::info($this->sql); #XXX if ($this->bindings !== null) { /** @var SQLite3Stmt $stmt */ $stmt = SqliteException::check($db, $db->prepare($this->sql)); diff --git a/php/src/php/time/DateTime.php b/php/src/php/time/DateTime.php index 9238b97..4c050d8 100644 --- a/php/src/php/time/DateTime.php +++ b/php/src/php/time/DateTime.php @@ -4,6 +4,7 @@ namespace nulib\php\time; use DateTimeInterface; use DateTimeZone; use InvalidArgumentException; +use nulib\php\func; /** * Class DateTime: une date et une heure @@ -34,30 +35,98 @@ class DateTime extends \DateTime { const DMYHIS_PATTERN = '/^(\d+)\/(\d+)(?:\/(\d+))? +(\d+)[h:.](\d+)(?:[:.](\d+))?$/'; const YMDHISZ_PATTERN = '/^((?:\d{2})?\d{2})(\d{2})(\d{2})[tT](\d{2})(\d{2})(\d{2})?([zZ])?$/'; + + protected static function get_value(array $datetime, ?string $key, ?string $k, ?int $index) { + $value = null; + if ($value === null && $key !== null) $value = $datetime[$key] ?? null; + if ($value === null && $k !== null) $value = $datetime[$k] ?? null; + if ($value === null && $index !== null) $value = $datetime[$index] ?? null; + return $value; + } + + private static function parse_int(array $datetime, ?string $key, ?string $k, ?int $index, ?int &$part, bool $required=true, ?int $default=null): bool { + $part = null; + $value = self::get_value($datetime, $key, $k, $index); + if ($value === null) { + if ($required && $default === null) return false; + $part = $default; + return true; + } + if (is_numeric($value)) { + $part = intval($value); + return true; + } + return false; + } + + private static function parse_str(array $datetime, ?string $key, ?string $k, ?int $index, ?string &$part, bool $required = true, ?string $default=null): bool { + $part = null; + $value = self::get_value($datetime, $key, $k, $index); + if ($value === null) { + if ($required && $default === null) return false; + $part = $default; + return true; + } + if (is_string($value)) { + $part = $value; + return true; + } + return false; + } + + protected static function parse_array(array $datetime): ?array { + if (!self::parse_int($datetime, "year", "Y", 0, $year)) return null; + if (!self::parse_int($datetime, "month", "m", 1, $month)) return null; + if (!self::parse_int($datetime, "day", "d", 2, $day)) return null; + self::parse_int($datetime, "hour", "H", 3, $hour, false); + self::parse_int($datetime, "minute", "M", 4, $minute, false); + self::parse_int($datetime, "second", "S", 5, $second, false); + self::parse_str($datetime, "tz", null, 6, $tz, false); + return [$year, $month, $day, $hour, $minute, $second, $tz]; + } + static function isa($datetime): bool { if ($datetime === null) return false; if ($datetime instanceof DateTimeInterface) return true; - if (!is_int($datetime) && !is_string($datetime)) return false; - return preg_match(self::DMY_PATTERN, $datetime) || - preg_match(self::YMD_PATTERN, $datetime) || - preg_match(self::DMYHIS_PATTERN, $datetime) || - preg_match(self::YMDHISZ_PATTERN, $datetime); + if (is_int($datetime)) return true; + if (is_string($datetime)) { + return preg_match(self::DMY_PATTERN, $datetime) || + preg_match(self::YMD_PATTERN, $datetime) || + preg_match(self::DMYHIS_PATTERN, $datetime) || + preg_match(self::YMDHISZ_PATTERN, $datetime); + } + if (is_array($datetime)) { + return self::parse_array($datetime) !== null; + } + return false; } static function isa_datetime($datetime, bool $frOnly=false): bool { if ($datetime === null) return false; if ($datetime instanceof DateTimeInterface) return true; - if (!is_int($datetime) && !is_string($datetime)) return false; - return preg_match(self::DMYHIS_PATTERN, $datetime) || - (!$frOnly && preg_match(self::YMDHISZ_PATTERN, $datetime)); + if (is_int($datetime)) return true; + if (is_string($datetime)) { + return preg_match(self::DMYHIS_PATTERN, $datetime) || + (!$frOnly && preg_match(self::YMDHISZ_PATTERN, $datetime)); + } + if (is_array($datetime)) { + return self::parse_array($datetime) !== null; + } + return false; } static function isa_date($date, bool $frOnly=false): bool { if ($date === null) return false; if ($date instanceof DateTimeInterface) return true; - if (!is_int($date) && !is_string($date)) return false; - return preg_match(self::DMY_PATTERN, $date) || - (!$frOnly && preg_match(self::YMD_PATTERN, $date)); + if (is_int($date)) return true; + if (is_string($date)) { + return preg_match(self::DMY_PATTERN, $date) || + (!$frOnly && preg_match(self::YMD_PATTERN, $date)); + } + if (is_array($date)) { + return self::parse_array($date) !== null; + } + return false; } static function _YmdHMSZ_format(\DateTime $datetime): string { @@ -148,9 +217,7 @@ class DateTime extends \DateTime { } elseif (is_int($datetime)) { parent::__construct("now", $timezone); $this->setTimestamp($datetime); - } elseif (!is_string($datetime)) { - throw new InvalidArgumentException("datetime must be a string or an instance of DateTimeInterface"); - } else { + } elseif (is_string($datetime)) { $Y = $H = $Z = null; if (preg_match(self::DMY_PATTERN, $datetime, $ms)) { $Y = $ms[3] ?? null; @@ -190,6 +257,18 @@ class DateTime extends \DateTime { if ($Z !== null) $timezone = new DateTimeZone("UTC"); } parent::__construct($datetime, $timezone); + } elseif (is_array($datetime) && ($datetime = self::parse_array($datetime)) !== null) { + [$Y, $m, $d, $H, $M, $S, $tz] = $datetime; + if ($H === null && $M === null && $S === null) { + $datetime = sprintf("%04d-%02d-%02d", $Y, $m, $d); + } else { + $datetime = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $Y, $m, $d, $H ?? 0, $M ?? 0, $S ?? 0); + } + if ($tz === "Z" || $tz === "z") $tz = "UTC"; + $timezone = $tz !== null? new DateTimeZone($tz): null; + parent::__construct($datetime, $timezone); + } else { + throw new InvalidArgumentException("datetime must be a string or an instance of DateTimeInterface"); } }