PDO::CASE_NATURAL, PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL, PDO::ATTR_STRINGIFY_FETCHES => false ]; public function getDsn(Config $config) { $dsn = "{$config->db}:"; $parts = []; foreach (['host', 'dbname', 'port'] as $part) { if (! empty($config->$part)) { $parts[] = "{$part}={$config->$part}"; } } return $dsn . implode(';', $parts); } public function getOptions(Config $config) { if (is_array($config->options)) { return $config->options + $this->options; } return $this->options; } public function setClientTimezone(Connection $db) { } public function quoteIdentifier($identifiers) { if (is_string($identifiers)) { $identifiers = explode('.', $identifiers); } foreach ($identifiers as $i => $identifier) { if ($identifier === '*') { continue; } $identifiers[$i] = $this->quoteCharacter[0] . str_replace($this->quoteCharacter[0], $this->escapeCharacter, $identifier) . $this->quoteCharacter[1]; } return implode('.', $identifiers); } public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder) { $queryBuilder->on(QueryBuilder::ON_ASSEMBLE_SELECT, function (Select $select): void { if ($select->hasOrderBy()) { foreach ($select->getOrderBy() as list($_, $direction)) { switch (strtolower($direction ?? '')) { case '': case 'asc': case 'desc': break; default: throw new UnexpectedValueException( sprintf('Invalid direction "%s" in ORDER BY', $direction) ); } } } }); } protected function getTimezoneOffset() { $tz = new DateTimeZone(date_default_timezone_get()); $offset = $tz->getOffset(new DateTime()); $prefix = $offset >= 0 ? '+' : '-'; $offset = abs($offset); $hours = (int) floor($offset / 3600); $minutes = (int) floor(($offset % 3600) / 60); return sprintf('%s%d:%02d', $prefix, $hours, $minutes); } }