%PDF- %PDF-
Direktori : /www/varak.net/losik.varak.net/vendor/dibi/dibi/src/Dibi/ |
Current File : //www/varak.net/losik.varak.net/vendor/dibi/dibi/src/Dibi/Helpers.php |
<?php /** * This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com) * Copyright (c) 2005 David Grudl (https://davidgrudl.com) */ declare(strict_types=1); namespace Dibi; class Helpers { use Strict; /** @var HashMap */ private static $types; /** * Prints out a syntax highlighted version of the SQL command or Result. * @param string|Result $sql */ public static function dump($sql = null, bool $return = false): ?string { ob_start(); if ($sql instanceof Result && PHP_SAPI === 'cli') { $hasColors = (substr((string) getenv('TERM'), 0, 5) === 'xterm'); $maxLen = 0; foreach ($sql as $i => $row) { if ($i === 0) { foreach ($row as $col => $foo) { $len = mb_strlen($col); $maxLen = max($len, $maxLen); } } echo $hasColors ? "\033[1;37m#row: $i\033[0m\n" : "#row: $i\n"; foreach ($row as $col => $val) { $spaces = $maxLen - mb_strlen($col) + 2; echo "$col" . str_repeat(' ', $spaces) . "$val\n"; } echo "\n"; } echo empty($row) ? "empty result set\n\n" : "\n"; } elseif ($sql instanceof Result) { foreach ($sql as $i => $row) { if ($i === 0) { echo "\n<table class=\"dump\">\n<thead>\n\t<tr>\n\t\t<th>#row</th>\n"; foreach ($row as $col => $foo) { echo "\t\t<th>" . htmlspecialchars((string) $col) . "</th>\n"; } echo "\t</tr>\n</thead>\n<tbody>\n"; } echo "\t<tr>\n\t\t<th>", $i, "</th>\n"; foreach ($row as $col) { echo "\t\t<td>", htmlspecialchars((string) $col), "</td>\n"; } echo "\t</tr>\n"; } echo empty($row) ? '<p><em>empty result set</em></p>' : "</tbody>\n</table>\n"; } else { if ($sql === null) { $sql = \dibi::$sql; } static $keywords1 = 'SELECT|(?:ON\s+DUPLICATE\s+KEY)?UPDATE|INSERT(?:\s+INTO)?|REPLACE(?:\s+INTO)?|DELETE|CALL|UNION|FROM|WHERE|HAVING|GROUP\s+BY|ORDER\s+BY|LIMIT|OFFSET|FETCH\s+NEXT|SET|VALUES|LEFT\s+JOIN|INNER\s+JOIN|TRUNCATE|START\s+TRANSACTION|BEGIN|COMMIT|ROLLBACK(?:\s+TO\s+SAVEPOINT)?|(?:RELEASE\s+)?SAVEPOINT'; static $keywords2 = 'ALL|DISTINCT|DISTINCTROW|IGNORE|AS|USING|ON|AND|OR|IN|IS|NOT|NULL|LIKE|RLIKE|REGEXP|TRUE|FALSE'; // insert new lines $sql = " $sql "; $sql = preg_replace("#(?<=[\\s,(])($keywords1)(?=[\\s,)])#i", "\n\$1", $sql); // reduce spaces $sql = preg_replace('#[ \t]{2,}#', ' ', $sql); $sql = wordwrap($sql, 100); $sql = preg_replace("#([ \t]*\r?\n){2,}#", "\n", $sql); // syntax highlight $highlighter = "#(/\\*.+?\\*/)|(\\*\\*.+?\\*\\*)|(?<=[\\s,(])($keywords1)(?=[\\s,)])|(?<=[\\s,(=])($keywords2)(?=[\\s,)=])#is"; if (PHP_SAPI === 'cli') { if (substr((string) getenv('TERM'), 0, 5) === 'xterm') { $sql = preg_replace_callback($highlighter, function (array $m) { if (!empty($m[1])) { // comment return "\033[1;30m" . $m[1] . "\033[0m"; } elseif (!empty($m[2])) { // error return "\033[1;31m" . $m[2] . "\033[0m"; } elseif (!empty($m[3])) { // most important keywords return "\033[1;34m" . $m[3] . "\033[0m"; } elseif (!empty($m[4])) { // other keywords return "\033[1;32m" . $m[4] . "\033[0m"; } }, $sql); } echo trim($sql) . "\n\n"; } else { $sql = htmlspecialchars($sql); $sql = preg_replace_callback($highlighter, function (array $m) { if (!empty($m[1])) { // comment return '<em style="color:gray">' . $m[1] . '</em>'; } elseif (!empty($m[2])) { // error return '<strong style="color:red">' . $m[2] . '</strong>'; } elseif (!empty($m[3])) { // most important keywords return '<strong style="color:blue">' . $m[3] . '</strong>'; } elseif (!empty($m[4])) { // other keywords return '<strong style="color:green">' . $m[4] . '</strong>'; } }, $sql); echo '<pre class="dump">', trim($sql), "</pre>\n\n"; } } if ($return) { return ob_get_clean(); } else { ob_end_flush(); return null; } } /** * Finds the best suggestion. * @internal */ public static function getSuggestion(array $items, string $value): ?string { $best = null; $min = (strlen($value) / 4 + 1) * 10 + .1; $items = array_map('strval', $items); foreach (array_unique($items) as $item) { if (($len = levenshtein($item, $value, 10, 11, 10)) > 0 && $len < $min) { $min = $len; $best = $item; } } return $best; } /** @internal */ public static function escape(Driver $driver, $value, string $type): string { static $types = [ Type::TEXT => 'text', Type::BINARY => 'binary', Type::BOOL => 'bool', Type::DATE => 'date', Type::DATETIME => 'datetime', \dibi::IDENTIFIER => 'identifier', ]; if (isset($types[$type])) { return $driver->{'escape' . $types[$type]}($value); } else { throw new \InvalidArgumentException('Unsupported type.'); } } /** * Heuristic type detection. * @internal */ public static function detectType(string $type): ?string { static $patterns = [ '^_' => Type::TEXT, // PostgreSQL arrays 'RANGE$' => Type::TEXT, // PostgreSQL range types 'BYTEA|BLOB|BIN' => Type::BINARY, 'TEXT|CHAR|POINT|INTERVAL|STRING' => Type::TEXT, 'YEAR|BYTE|COUNTER|SERIAL|INT|LONG|SHORT|^TINY$' => Type::INTEGER, 'CURRENCY|REAL|MONEY|FLOAT|DOUBLE|DECIMAL|NUMERIC|NUMBER' => Type::FLOAT, '^TIME$' => Type::TIME, 'TIME' => Type::DATETIME, // DATETIME, TIMESTAMP 'DATE' => Type::DATE, 'BOOL' => Type::BOOL, 'JSON' => Type::JSON, ]; foreach ($patterns as $s => $val) { if (preg_match("#$s#i", $type)) { return $val; } } return null; } /** @internal */ public static function getTypeCache(): HashMap { if (self::$types === null) { self::$types = new HashMap([self::class, 'detectType']); } return self::$types; } /** * Apply configuration alias or default values. */ public static function alias(array &$config, string $key, string $alias): void { $foo = &$config; foreach (explode('|', $key) as $key) { $foo = &$foo[$key]; } if (!isset($foo) && isset($config[$alias])) { $foo = $config[$alias]; unset($config[$alias]); } } /** * Import SQL dump from file. * @return int count of sql commands */ public static function loadFromFile(Connection $connection, string $file, ?callable $onProgress = null): int { @set_time_limit(0); // intentionally @ $handle = @fopen($file, 'r'); // intentionally @ if (!$handle) { throw new \RuntimeException("Cannot open file '$file'."); } $stat = fstat($handle); $count = $size = 0; $delimiter = ';'; $sql = ''; $driver = $connection->getDriver(); while (($s = fgets($handle)) !== false) { $size += strlen($s); if (strtoupper(substr($s, 0, 10)) === 'DELIMITER ') { $delimiter = trim(substr($s, 10)); } elseif (substr($ts = rtrim($s), -strlen($delimiter)) === $delimiter) { $sql .= substr($ts, 0, -strlen($delimiter)); $driver->query($sql); $sql = ''; $count++; if ($onProgress) { $onProgress($count, isset($stat['size']) ? $size * 100 / $stat['size'] : null); } } else { $sql .= $s; } } if (rtrim($sql) !== '') { $driver->query($sql); $count++; if ($onProgress) { $onProgress($count, isset($stat['size']) ? 100 : null); } } fclose($handle); return $count; } /** @internal */ public static function false2Null($val) { return $val === false ? null : $val; } /** @internal */ public static function intVal($value): int { if (is_int($value)) { return $value; } elseif (is_string($value) && preg_match('#-?\d++\z#A', $value)) { if (is_float($value * 1)) { throw new Exception("Number $value is greater than integer."); } return (int) $value; } else { throw new Exception("Expected number, '$value' given."); } } }