소스 검색

updated dibi to v4

CauseFX 4 년 전
부모
커밋
d70c4108d4
5개의 변경된 파일261개의 추가작업 그리고 405개의 파일을 삭제
  1. 1 1
      api/composer.json
  2. 14 15
      api/composer.lock
  3. 48 0
      api/vendor/dibi/dibi/appveyor.yml
  4. 198 262
      api/vendor/dibi/dibi/src/Dibi/Connection.php
  5. 0 127
      api/vendor/dibi/dibi/src/loader.php

+ 1 - 1
api/composer.json

@@ -1,6 +1,6 @@
 {
   "require": {
-    "dibi/dibi": "^3.2",
+    "dibi/dibi": "^4.2",
     "lcobucci/jwt": "3.3.1",
     "composer/semver": "^1.4",
     "phpmailer/phpmailer": "^6.2",

+ 14 - 15
api/composer.lock

@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "a9cfe24cec195b73c109643bc90dc450",
+    "content-hash": "db7f63e80bb05dd9f7e63091879075a6",
     "packages": [
         {
             "name": "adldap2/adldap2",
@@ -208,47 +208,46 @@
         },
         {
             "name": "dibi/dibi",
-            "version": "v3.2.4",
+            "version": "v4.2.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/dg/dibi.git",
-                "reference": "d571460a6f8fa1334a04f7aaa1551bb0f12c2266"
+                "reference": "73e16eb1a322599e8cdf350adcfdbc15eaf16577"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/dg/dibi/zipball/d571460a6f8fa1334a04f7aaa1551bb0f12c2266",
-                "reference": "d571460a6f8fa1334a04f7aaa1551bb0f12c2266",
+                "url": "https://api.github.com/repos/dg/dibi/zipball/73e16eb1a322599e8cdf350adcfdbc15eaf16577",
+                "reference": "73e16eb1a322599e8cdf350adcfdbc15eaf16577",
                 "shasum": ""
             },
             "require": {
-                "php": ">=5.4.4"
+                "php": ">=7.2"
             },
             "replace": {
                 "dg/dibi": "*"
             },
             "require-dev": {
-                "nette/tester": "~1.7",
+                "nette/di": "^3.0",
+                "nette/tester": "~2.0",
+                "phpstan/phpstan": "^0.12",
                 "tracy/tracy": "~2.2"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "3.2-dev"
+                    "dev-master": "4.2-dev"
                 }
             },
             "autoload": {
                 "classmap": [
                     "src/"
-                ],
-                "files": [
-                    "src/loader.php"
                 ]
             },
             "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "BSD-3-Clause",
-                "GPL-2.0",
-                "GPL-3.0"
+                "GPL-2.0-only",
+                "GPL-3.0-only"
             ],
             "authors": [
                 {
@@ -273,9 +272,9 @@
             ],
             "support": {
                 "issues": "https://github.com/dg/dibi/issues",
-                "source": "https://github.com/dg/dibi/tree/v3.2.4"
+                "source": "https://github.com/dg/dibi/tree/v4.2.3"
             },
-            "time": "2020-03-26T03:05:01+00:00"
+            "time": "2021-07-23T08:49:27+00:00"
         },
         {
             "name": "doctrine/annotations",

+ 48 - 0
api/vendor/dibi/dibi/appveyor.yml

@@ -0,0 +1,48 @@
+build: off
+cache:
+    - c:\php7 -> appveyor.yml
+    - '%LOCALAPPDATA%\Composer\files -> appveyor.yml'
+
+clone_folder: c:\projects\dibi
+
+services:
+    - mssql2012sp1
+#    - mssql2014
+    - mysql
+
+init:
+    - SET PATH=c:\php7;%PATH%
+    - SET ANSICON=121x90 (121x90)
+
+install:
+    # Install PHP 7.2
+    - IF EXIST c:\php7 (SET PHP=0) ELSE (SET PHP=1)
+    - IF %PHP%==1 mkdir c:\php7
+    - IF %PHP%==1 cd c:\php7
+    - IF %PHP%==1 curl https://windows.php.net/downloads/releases/archives/php-7.2.18-Win32-VC15-x64.zip --output php.zip
+    - IF %PHP%==1 7z x php.zip >nul
+    - IF %PHP%==1 echo extension_dir=ext >> php.ini
+    - IF %PHP%==1 echo extension=php_openssl.dll >> php.ini
+    - IF %PHP%==1 curl https://github.com/microsoft/msphpsql/releases/download/v5.8.0/Windows-7.2.zip -L --output sqlsrv.zip
+    - IF %PHP%==1 7z x sqlsrv.zip >nul
+    - IF %PHP%==1 copy Windows-7.2\x64\php_sqlsrv_72_ts.dll ext\php_sqlsrv_ts.dll
+    - IF %PHP%==1 del /Q *.zip
+
+    # Install Microsoft Access Database Engine x64
+    - IF %PHP%==1 curl https://download.microsoft.com/download/2/4/3/24375141-E08D-4803-AB0E-10F2E3A07AAA/AccessDatabaseEngine_X64.exe --output AccessDatabaseEngine_X64.exe
+    - cmd /c start /wait AccessDatabaseEngine_X64.exe /passive
+
+    # Install Nette Tester
+    - cd c:\projects\dibi
+    - appveyor DownloadFile https://getcomposer.org/composer.phar
+    - php composer.phar install --prefer-dist --no-interaction --no-progress
+
+    # Create databases.ini
+    - copy tests\databases.appveyor.ini tests\databases.ini
+
+test_script:
+    - vendor\bin\tester tests -s -p c:\php7\php -c tests\php-win.ini
+
+on_failure:
+    # Print *.actual content
+    - for /r %%x in (*.actual) do ( type "%%x" )

+ 198 - 262
api/vendor/dibi/dibi/src/Dibi/Connection.php

@@ -5,6 +5,8 @@
  * Copyright (c) 2005 David Grudl (https://davidgrudl.com)
  */
 
+declare(strict_types=1);
+
 namespace Dibi;
 
 use Traversable;
@@ -16,109 +18,92 @@ use Traversable;
  * @property-read int $affectedRows
  * @property-read int $insertId
  */
-class Connection
+class Connection implements IConnection
 {
 	use Strict;
 
 	/** @var array of function (Event $event); Occurs after query is executed */
-	public $onEvent;
+	public $onEvent = [];
 
 	/** @var array  Current connection configuration */
 	private $config;
 
-	/** @var Driver */
+	/** @var string[]  resultset formats */
+	private $formats;
+
+	/** @var Driver|null */
 	private $driver;
 
 	/** @var Translator|null */
 	private $translator;
 
-	/** @var bool  Is connected? */
-	private $connected = false;
-
 	/** @var HashMap Substitutes for identifiers */
 	private $substitutes;
 
+	private $transactionDepth = 0;
+
 
 	/**
 	 * Connection options: (see driver-specific options too)
 	 *   - lazy (bool) => if true, connection will be established only when required
 	 *   - result (array) => result set options
-	 *       - formatDateTime => date-time format (if empty, DateTime objects will be returned)
-	 *   - profiler (array or bool)
+	 *       - normalize => normalizes result fields (default: true)
+	 *       - formatDateTime => date-time format
+	 *           empty for decoding as Dibi\DateTime (default)
+	 *           "..." formatted according to given format, see https://www.php.net/manual/en/datetime.format.php
+	 *           "native" for leaving value as is
+	 *       - formatTimeInterval => time-interval format
+	 *           empty for decoding as DateInterval (default)
+	 *           "..." formatted according to given format, see https://www.php.net/manual/en/dateinterval.format.php
+	 *           "native" for leaving value as is
+	 *       - formatJson => json format
+	 *           "array" for decoding json as an array (default)
+	 *           "object" for decoding json as \stdClass
+	 *           "native" for leaving value as is
+	 *   - profiler (array)
 	 *       - run (bool) => enable profiler?
 	 *       - file => file to log
+	 *       - errorsOnly (bool) => log only errors
 	 *   - substitutes (array) => map of driver specific substitutes (under development)
-	 * @param  mixed   connection parameters
-	 * @param  string  connection name
+	 *   - onConnect (array) => list of SQL queries to execute (by Connection::query()) after connection is established
 	 * @throws Exception
 	 */
-	public function __construct($config, $name = null)
+	public function __construct(array $config, string $name = null)
 	{
-		if (is_string($config)) {
-			parse_str($config, $config);
-
-		} elseif ($config instanceof Traversable) {
-			$tmp = [];
-			foreach ($config as $key => $val) {
-				$tmp[$key] = $val instanceof Traversable ? iterator_to_array($val) : $val;
-			}
-			$config = $tmp;
-
-		} elseif (!is_array($config)) {
-			throw new \InvalidArgumentException('Configuration must be array, string or object.');
-		}
-
 		Helpers::alias($config, 'username', 'user');
 		Helpers::alias($config, 'password', 'pass');
 		Helpers::alias($config, 'host', 'hostname');
 		Helpers::alias($config, 'result|formatDate', 'resultDate');
 		Helpers::alias($config, 'result|formatDateTime', 'resultDateTime');
-
-		if (!isset($config['driver'])) {
-			$config['driver'] = \dibi::$defaultDriver;
-		}
-
-		if ($config['driver'] instanceof Driver) {
-			$this->driver = $config['driver'];
-			$config['driver'] = get_class($this->driver);
-		} elseif (is_subclass_of($config['driver'], 'Dibi\Driver')) {
-			$this->driver = new $config['driver'];
-		} else {
-			$class = preg_replace(['#\W#', '#sql#'], ['_', 'Sql'], ucfirst(strtolower($config['driver'])));
-			$class = "Dibi\\Drivers\\{$class}Driver";
-			if (!class_exists($class)) {
-				throw new Exception("Unable to create instance of dibi driver '$class'.");
-			}
-			$this->driver = new $class;
-		}
-
+		$config['driver'] = $config['driver'] ?? 'mysqli';
 		$config['name'] = $name;
 		$this->config = $config;
 
-		// profiler
-		$profilerCfg = &$config['profiler'];
-		if (is_scalar($profilerCfg)) {
-			$profilerCfg = ['run' => (bool) $profilerCfg];
-		}
-		if (!empty($profilerCfg['run'])) {
-			$filter = isset($profilerCfg['filter']) ? $profilerCfg['filter'] : Event::QUERY;
-
-			if (isset($profilerCfg['file'])) {
-				$this->onEvent[] = [new Loggers\FileLogger($profilerCfg['file'], $filter), 'logEvent'];
-			}
+		$this->formats = [
+			Type::DATE => $this->config['result']['formatDate'],
+			Type::DATETIME => $this->config['result']['formatDateTime'],
+			Type::JSON => $this->config['result']['formatJson'] ?? 'array',
+			Type::TIME_INTERVAL => $this->config['result']['formatTimeInterval'] ?? null,
+		];
 
-			if (Loggers\FirePhpLogger::isAvailable()) {
-				$this->onEvent[] = [new Loggers\FirePhpLogger($filter), 'logEvent'];
-			}
+		// profiler
+		if (isset($config['profiler']['file']) && (!isset($config['profiler']['run']) || $config['profiler']['run'])) {
+			$filter = $config['profiler']['filter'] ?? Event::QUERY;
+			$errorsOnly = $config['profiler']['errorsOnly'] ?? false;
+			$this->onEvent[] = [new Loggers\FileLogger($config['profiler']['file'], $filter, $errorsOnly), 'logEvent'];
 		}
 
-		$this->substitutes = new HashMap(function ($expr) { return ":$expr:"; });
+		$this->substitutes = new HashMap(function (string $expr) { return ":$expr:"; });
 		if (!empty($config['substitutes'])) {
 			foreach ($config['substitutes'] as $key => $value) {
 				$this->substitutes->$key = $value;
 			}
 		}
 
+		if (isset($config['onConnect']) && !is_array($config['onConnect'])) {
+			throw new \InvalidArgumentException("Configuration option 'onConnect' must be array.");
+		}
+
 		if (empty($config['lazy'])) {
 			$this->connect();
 		}
@@ -127,11 +112,10 @@ class Connection
 
 	/**
 	 * Automatically frees the resources allocated for this result set.
-	 * @return void
 	 */
 	public function __destruct()
 	{
-		if ($this->connected && $this->driver->getResource()) {
+		if ($this->driver && $this->driver->getResource()) {
 			$this->disconnect();
 		}
 	}
@@ -139,19 +123,40 @@ class Connection
 
 	/**
 	 * Connects to a database.
-	 * @return void
 	 */
-	final public function connect()
+	final public function connect(): void
 	{
+		if ($this->config['driver'] instanceof Driver) {
+			$this->driver = $this->config['driver'];
+			$this->translator = new Translator($this);
+			return;
+
+		} elseif (is_subclass_of($this->config['driver'], Driver::class)) {
+			$class = $this->config['driver'];
+
+		} else {
+			$class = preg_replace(['#\W#', '#sql#'], ['_', 'Sql'], ucfirst(strtolower($this->config['driver'])));
+			$class = "Dibi\\Drivers\\{$class}Driver";
+			if (!class_exists($class)) {
+				throw new Exception("Unable to create instance of Dibi driver '$class'.");
+			}
+		}
+
 		$event = $this->onEvent ? new Event($this, Event::CONNECT) : null;
 		try {
-			$this->driver->connect($this->config);
-			$this->connected = true;
+			$this->driver = new $class($this->config);
+			$this->translator = new Translator($this);
+
 			if ($event) {
 				$this->onEvent($event->done());
 			}
+			if (isset($this->config['onConnect'])) {
+				foreach ($this->config['onConnect'] as $sql) {
+					$this->query($sql);
+				}
+			}
 
-		} catch (Exception $e) {
+		} catch (DriverException $e) {
 			if ($event) {
 				$this->onEvent($event->done($e));
 			}
@@ -162,61 +167,44 @@ class Connection
 
 	/**
 	 * Disconnects from a database.
-	 * @return void
 	 */
-	final public function disconnect()
+	final public function disconnect(): void
 	{
-		$this->driver->disconnect();
-		$this->connected = false;
+		if ($this->driver) {
+			$this->driver->disconnect();
+			$this->driver = $this->translator = null;
+		}
 	}
 
 
 	/**
 	 * Returns true when connection was established.
-	 * @return bool
 	 */
-	final public function isConnected()
+	final public function isConnected(): bool
 	{
-		return $this->connected;
+		return (bool) $this->driver;
 	}
 
 
 	/**
 	 * Returns configuration variable. If no $key is passed, returns the entire array.
 	 * @see self::__construct
-	 * @param  string
-	 * @param  mixed  default value to use if key not found
 	 * @return mixed
 	 */
-	final public function getConfig($key = null, $default = null)
+	final public function getConfig(string $key = null, $default = null)
 	{
-		if ($key === null) {
-			return $this->config;
-
-		} elseif (isset($this->config[$key])) {
-			return $this->config[$key];
-
-		} else {
-			return $default;
-		}
-	}
-
-
-	/** @deprecated */
-	public static function alias(&$config, $key, $alias)
-	{
-		trigger_error(__METHOD__ . '() is deprecated, use Helpers::alias().', E_USER_DEPRECATED);
-		Helpers::alias($config, $key, $alias);
+		return $key === null
+			? $this->config
+			: ($this->config[$key] ?? $default);
 	}
 
 
 	/**
 	 * Returns the driver and connects to a database in lazy mode.
-	 * @return Driver
 	 */
-	final public function getDriver()
+	final public function getDriver(): Driver
 	{
-		if (!$this->connected) {
+		if (!$this->driver) {
 			$this->connect();
 		}
 		return $this->driver;
@@ -225,40 +213,37 @@ class Connection
 
 	/**
 	 * Generates (translates) and executes SQL query.
-	 * @param  array|mixed      one or more arguments
-	 * @return Result|int   result set or number of affected rows
+	 * @param  mixed  ...$args
 	 * @throws Exception
 	 */
-	final public function query($args)
+	final public function query(...$args): Result
 	{
-		$args = func_get_args();
-		return $this->nativeQuery($this->translateArgs($args));
+		return $this->nativeQuery($this->translate(...$args));
 	}
 
 
 	/**
 	 * Generates SQL query.
-	 * @param  array|mixed      one or more arguments
-	 * @return string
+	 * @param  mixed  ...$args
 	 * @throws Exception
 	 */
-	final public function translate($args)
+	final public function translate(...$args): string
 	{
-		$args = func_get_args();
-		return $this->translateArgs($args);
+		if (!$this->driver) {
+			$this->connect();
+		}
+		return (clone $this->translator)->translate($args);
 	}
 
 
 	/**
 	 * Generates and prints SQL query.
-	 * @param  array|mixed  one or more arguments
-	 * @return bool
+	 * @param  mixed  ...$args
 	 */
-	final public function test($args)
+	final public function test(...$args): bool
 	{
-		$args = func_get_args();
 		try {
-			Helpers::dump($this->translateArgs($args));
+			Helpers::dump($this->translate(...$args));
 			return true;
 
 		} catch (Exception $e) {
@@ -274,44 +259,22 @@ class Connection
 
 	/**
 	 * Generates (translates) and returns SQL query as DataSource.
-	 * @param  array|mixed      one or more arguments
-	 * @return DataSource
+	 * @param  mixed  ...$args
 	 * @throws Exception
 	 */
-	final public function dataSource($args)
-	{
-		$args = func_get_args();
-		return new DataSource($this->translateArgs($args), $this);
-	}
-
-
-	/**
-	 * Generates SQL query.
-	 * @param  array
-	 * @return string
-	 */
-	protected function translateArgs($args)
+	final public function dataSource(...$args): DataSource
 	{
-		if (!$this->connected) {
-			$this->connect();
-		}
-		if (!$this->translator) {
-			$this->translator = new Translator($this);
-		}
-		$translator = clone $this->translator;
-		return $translator->translate($args);
+		return new DataSource($this->translate(...$args), $this);
 	}
 
 
 	/**
 	 * Executes the SQL query.
-	 * @param  string           SQL statement.
-	 * @return Result|int   result set or number of affected rows
 	 * @throws Exception
 	 */
-	final public function nativeQuery($sql)
+	final public function nativeQuery(string $sql): Result
 	{
-		if (!$this->connected) {
+		if (!$this->driver) {
 			$this->connect();
 		}
 
@@ -320,19 +283,14 @@ class Connection
 		try {
 			$res = $this->driver->query($sql);
 
-		} catch (Exception $e) {
+		} catch (DriverException $e) {
 			if ($event) {
 				$this->onEvent($event->done($e));
 			}
 			throw $e;
 		}
 
-		if ($res) {
-			$res = $this->createResultSet($res);
-		} else {
-			$res = $this->driver->getAffectedRows();
-		}
-
+		$res = $this->createResultSet($res ?: new Drivers\NoDataResult(max(0, $this->driver->getAffectedRows())));
 		if ($event) {
 			$this->onEvent($event->done($res));
 		}
@@ -342,69 +300,48 @@ class Connection
 
 	/**
 	 * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
-	 * @return int  number of rows
 	 * @throws Exception
 	 */
-	public function getAffectedRows()
+	public function getAffectedRows(): int
 	{
-		if (!$this->connected) {
+		if (!$this->driver) {
 			$this->connect();
 		}
 		$rows = $this->driver->getAffectedRows();
-		if (!is_int($rows) || $rows < 0) {
+		if ($rows === null || $rows < 0) {
 			throw new Exception('Cannot retrieve number of affected rows.');
 		}
 		return $rows;
 	}
 
 
-	/**
-	 * @deprecated
-	 */
-	public function affectedRows()
-	{
-		trigger_error(__METHOD__ . '() is deprecated, use getAffectedRows()', E_USER_DEPRECATED);
-		return $this->getAffectedRows();
-	}
-
-
 	/**
 	 * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
-	 * @param  string     optional sequence name
-	 * @return int
 	 * @throws Exception
 	 */
-	public function getInsertId($sequence = null)
+	public function getInsertId(string $sequence = null): int
 	{
-		if (!$this->connected) {
+		if (!$this->driver) {
 			$this->connect();
 		}
 		$id = $this->driver->getInsertId($sequence);
-		if ($id < 1) {
+		if ($id === null) {
 			throw new Exception('Cannot retrieve last generated ID.');
 		}
-		return Helpers::intVal($id);
-	}
-
-
-	/**
-	 * @deprecated
-	 */
-	public function insertId($sequence = null)
-	{
-		trigger_error(__METHOD__ . '() is deprecated, use getInsertId()', E_USER_DEPRECATED);
-		return $this->getInsertId($sequence);
+		return $id;
 	}
 
 
 	/**
 	 * Begins a transaction (if supported).
-	 * @param  string  optional savepoint name
-	 * @return void
 	 */
-	public function begin($savepoint = null)
+	public function begin(string $savepoint = null): void
 	{
-		if (!$this->connected) {
+		if ($this->transactionDepth !== 0) {
+			throw new \LogicException(__METHOD__ . '() call is forbidden inside a transaction() callback');
+		}
+
+		if (!$this->driver) {
 			$this->connect();
 		}
 		$event = $this->onEvent ? new Event($this, Event::BEGIN, $savepoint) : null;
@@ -414,7 +351,7 @@ class Connection
 				$this->onEvent($event->done());
 			}
 
-		} catch (Exception $e) {
+		} catch (DriverException $e) {
 			if ($event) {
 				$this->onEvent($event->done($e));
 			}
@@ -425,12 +362,14 @@ class Connection
 
 	/**
 	 * Commits statements in a transaction.
-	 * @param  string  optional savepoint name
-	 * @return void
 	 */
-	public function commit($savepoint = null)
+	public function commit(string $savepoint = null): void
 	{
-		if (!$this->connected) {
+		if ($this->transactionDepth !== 0) {
+			throw new \LogicException(__METHOD__ . '() call is forbidden inside a transaction() callback');
+		}
+
+		if (!$this->driver) {
 			$this->connect();
 		}
 		$event = $this->onEvent ? new Event($this, Event::COMMIT, $savepoint) : null;
@@ -440,7 +379,7 @@ class Connection
 				$this->onEvent($event->done());
 			}
 
-		} catch (Exception $e) {
+		} catch (DriverException $e) {
 			if ($event) {
 				$this->onEvent($event->done($e));
 			}
@@ -451,12 +390,14 @@ class Connection
 
 	/**
 	 * Rollback changes in a transaction.
-	 * @param  string  optional savepoint name
-	 * @return void
 	 */
-	public function rollback($savepoint = null)
+	public function rollback(string $savepoint = null): void
 	{
-		if (!$this->connected) {
+		if ($this->transactionDepth !== 0) {
+			throw new \LogicException(__METHOD__ . '() call is forbidden inside a transaction() callback');
+		}
+
+		if (!$this->driver) {
 			$this->connect();
 		}
 		$event = $this->onEvent ? new Event($this, Event::ROLLBACK, $savepoint) : null;
@@ -466,7 +407,7 @@ class Connection
 				$this->onEvent($event->done());
 			}
 
-		} catch (Exception $e) {
+		} catch (DriverException $e) {
 			if ($event) {
 				$this->onEvent($event->done($e));
 			}
@@ -475,78 +416,80 @@ class Connection
 	}
 
 
+	/**
+	 * @return mixed
+	 */
+	public function transaction(callable $callback)
+	{
+		if ($this->transactionDepth === 0) {
+			$this->begin();
+		}
+
+		$this->transactionDepth++;
+		try {
+			$res = $callback($this);
+		} catch (\Throwable $e) {
+			$this->transactionDepth--;
+			if ($this->transactionDepth === 0) {
+				$this->rollback();
+			}
+			throw $e;
+		}
+
+		$this->transactionDepth--;
+		if ($this->transactionDepth === 0) {
+			$this->commit();
+		}
+
+		return $res;
+	}
+
+
 	/**
 	 * Result set factory.
-	 * @param  ResultDriver
-	 * @return Result
 	 */
-	public function createResultSet(ResultDriver $resultDriver)
+	public function createResultSet(ResultDriver $resultDriver): Result
 	{
-		$res = new Result($resultDriver);
-		return $res->setFormat(Type::DATE, $this->config['result']['formatDate'])
-			->setFormat(Type::DATETIME, $this->config['result']['formatDateTime']);
+		return (new Result($resultDriver, $this->config['result']['normalize'] ?? true))
+			->setFormats($this->formats);
 	}
 
 
 	/********************* fluent SQL builders ****************d*g**/
 
 
-	/**
-	 * @return Fluent
-	 */
-	public function command()
+	public function command(): Fluent
 	{
 		return new Fluent($this);
 	}
 
 
-	/**
-	 * @param  mixed    column name
-	 * @return Fluent
-	 */
-	public function select($args)
+	public function select(...$args): Fluent
 	{
-		$args = func_get_args();
-		return $this->command()->__call('select', $args);
+		return $this->command()->select(...$args);
 	}
 
 
 	/**
-	 * @param  string   table
-	 * @param  array
-	 * @return Fluent
+	 * @param  string|string[]  $table
 	 */
-	public function update($table, $args)
+	public function update($table, iterable $args): Fluent
 	{
-		if (!(is_array($args) || $args instanceof Traversable)) {
-			throw new \InvalidArgumentException('Arguments must be array or Traversable.');
-		}
 		return $this->command()->update('%n', $table)->set($args);
 	}
 
 
-	/**
-	 * @param  string   table
-	 * @param  array
-	 * @return Fluent
-	 */
-	public function insert($table, $args)
+	public function insert(string $table, iterable $args): Fluent
 	{
 		if ($args instanceof Traversable) {
 			$args = iterator_to_array($args);
-		} elseif (!is_array($args)) {
-			throw new \InvalidArgumentException('Arguments must be array or Traversable.');
 		}
 		return $this->command()->insert()
 			->into('%n', $table, '(%n)', array_keys($args))->values('%l', $args);
 	}
 
 
-	/**
-	 * @param  string   table
-	 * @return Fluent
-	 */
-	public function delete($table)
+	public function delete(string $table): Fluent
 	{
 		return $this->command()->delete()->from('%n', $table);
 	}
@@ -557,9 +500,8 @@ class Connection
 
 	/**
 	 * Returns substitution hashmap.
-	 * @return HashMap
 	 */
-	public function getSubstitutes()
+	public function getSubstitutes(): HashMap
 	{
 		return $this->substitutes;
 	}
@@ -567,13 +509,12 @@ class Connection
 
 	/**
 	 * Provides substitution.
-	 * @return string
 	 */
-	public function substitute($value)
+	public function substitute(string $value): string
 	{
 		return strpos($value, ':') === false
 			? $value
-			: preg_replace_callback('#:([^:\s]*):#', function ($m) { return $this->substitutes->{$m[1]}; }, $value);
+			: preg_replace_callback('#:([^:\s]*):#', function (array $m) { return $this->substitutes->{$m[1]}; }, $value);
 	}
 
 
@@ -582,75 +523,71 @@ class Connection
 
 	/**
 	 * Executes SQL query and fetch result - shortcut for query() & fetch().
-	 * @param  array|mixed    one or more arguments
-	 * @return Row|false
+	 * @param  mixed  ...$args
 	 * @throws Exception
 	 */
-	public function fetch($args)
+	public function fetch(...$args): ?Row
 	{
-		$args = func_get_args();
 		return $this->query($args)->fetch();
 	}
 
 
 	/**
 	 * Executes SQL query and fetch results - shortcut for query() & fetchAll().
-	 * @param  array|mixed    one or more arguments
+	 * @param  mixed  ...$args
 	 * @return Row[]|array[]
 	 * @throws Exception
 	 */
-	public function fetchAll($args)
+	public function fetchAll(...$args): array
 	{
-		$args = func_get_args();
 		return $this->query($args)->fetchAll();
 	}
 
 
 	/**
 	 * Executes SQL query and fetch first column - shortcut for query() & fetchSingle().
-	 * @param  array|mixed    one or more arguments
+	 * @param  mixed  ...$args
 	 * @return mixed
 	 * @throws Exception
 	 */
-	public function fetchSingle($args)
+	public function fetchSingle(...$args)
 	{
-		$args = func_get_args();
 		return $this->query($args)->fetchSingle();
 	}
 
 
 	/**
 	 * Executes SQL query and fetch pairs - shortcut for query() & fetchPairs().
-	 * @param  array|mixed    one or more arguments
-	 * @return array
+	 * @param  mixed  ...$args
 	 * @throws Exception
 	 */
-	public function fetchPairs($args)
+	public function fetchPairs(...$args): array
 	{
-		$args = func_get_args();
 		return $this->query($args)->fetchPairs();
 	}
 
 
-	/**
-	 * @return Literal
-	 */
-	public static function literal($value)
+	public static function literal(string $value): Literal
 	{
 		return new Literal($value);
 	}
 
 
+	public static function expression(...$args): Expression
+	{
+		return new Expression(...$args);
+	}
+
+
 	/********************* misc ****************d*g**/
 
 
 	/**
 	 * Import SQL dump from file.
-	 * @param  string  filename
-	 * @param  callable  function (int $count, ?float $percent): void
+	 * @param  callable  $onProgress  function (int $count, ?float $percent): void
 	 * @return int  count of sql commands
 	 */
-	public function loadFile($file, callable $onProgress = null)
+	public function loadFile(string $file, callable $onProgress = null): int
 	{
 		return Helpers::loadFromFile($this, $file, $onProgress);
 	}
@@ -658,14 +595,13 @@ class Connection
 
 	/**
 	 * Gets a information about the current database.
-	 * @return Reflection\Database
 	 */
-	public function getDatabaseInfo()
+	public function getDatabaseInfo(): Reflection\Database
 	{
-		if (!$this->connected) {
+		if (!$this->driver) {
 			$this->connect();
 		}
-		return new Reflection\Database($this->driver->getReflector(), isset($this->config['database']) ? $this->config['database'] : null);
+		return new Reflection\Database($this->driver->getReflector(), $this->config['database'] ?? null);
 	}
 
 
@@ -674,7 +610,7 @@ class Connection
 	 */
 	public function __wakeup()
 	{
-		throw new NotSupportedException('You cannot serialize or unserialize ' . get_class($this) . ' instances.');
+		throw new NotSupportedException('You cannot serialize or unserialize ' . static::class . ' instances.');
 	}
 
 
@@ -683,14 +619,14 @@ class Connection
 	 */
 	public function __sleep()
 	{
-		throw new NotSupportedException('You cannot serialize or unserialize ' . get_class($this) . ' instances.');
+		throw new NotSupportedException('You cannot serialize or unserialize ' . static::class . ' instances.');
 	}
 
 
-	protected function onEvent($arg)
+	protected function onEvent($arg): void
 	{
-		foreach ($this->onEvent ?: [] as $handler) {
-			call_user_func($handler, $arg);
+		foreach ($this->onEvent as $handler) {
+			$handler($arg);
 		}
 	}
 }

+ 0 - 127
api/vendor/dibi/dibi/src/loader.php

@@ -1,127 +0,0 @@
-<?php
-
-/**
- * This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
- * Copyright (c) 2005 David Grudl (https://davidgrudl.com)
- */
-
-
-if (PHP_VERSION_ID < 50404) {
-	throw new Exception('Dibi requires PHP 5.4.4 or newer.');
-}
-
-
-spl_autoload_register(function ($class) {
-	static $map = [
-		'dibi' => 'dibi.php',
-		'Dibi\Bridges\Nette\DibiExtension22' => 'Bridges/Nette/DibiExtension22.php',
-		'Dibi\Bridges\Tracy\Panel' => 'Bridges/Tracy/Panel.php',
-		'Dibi\Connection' => 'Connection.php',
-		'Dibi\ConstraintViolationException' => 'exceptions.php',
-		'Dibi\DataSource' => 'DataSource.php',
-		'Dibi\DateTime' => 'DateTime.php',
-		'Dibi\Driver' => 'interfaces.php',
-		'Dibi\DriverException' => 'exceptions.php',
-		'Dibi\Drivers\FirebirdDriver' => 'Drivers/FirebirdDriver.php',
-		'Dibi\Drivers\MsSqlDriver' => 'Drivers/MsSqlDriver.php',
-		'Dibi\Drivers\MsSqlReflector' => 'Drivers/MsSqlReflector.php',
-		'Dibi\Drivers\MySqlDriver' => 'Drivers/MySqlDriver.php',
-		'Dibi\Drivers\MySqlReflector' => 'Drivers/MySqlReflector.php',
-		'Dibi\Drivers\MySqliDriver' => 'Drivers/MySqliDriver.php',
-		'Dibi\Drivers\OdbcDriver' => 'Drivers/OdbcDriver.php',
-		'Dibi\Drivers\OracleDriver' => 'Drivers/OracleDriver.php',
-		'Dibi\Drivers\PdoDriver' => 'Drivers/PdoDriver.php',
-		'Dibi\Drivers\PostgreDriver' => 'Drivers/PostgreDriver.php',
-		'Dibi\Drivers\Sqlite3Driver' => 'Drivers/Sqlite3Driver.php',
-		'Dibi\Drivers\SqliteReflector' => 'Drivers/SqliteReflector.php',
-		'Dibi\Drivers\SqlsrvDriver' => 'Drivers/SqlsrvDriver.php',
-		'Dibi\Drivers\SqlsrvReflector' => 'Drivers/SqlsrvReflector.php',
-		'Dibi\Event' => 'Event.php',
-		'Dibi\Exception' => 'exceptions.php',
-		'Dibi\Expression' => 'Expression.php',
-		'Dibi\Fluent' => 'Fluent.php',
-		'Dibi\ForeignKeyConstraintViolationException' => 'exceptions.php',
-		'Dibi\HashMap' => 'HashMap.php',
-		'Dibi\HashMapBase' => 'HashMap.php',
-		'Dibi\Helpers' => 'Helpers.php',
-		'Dibi\IDataSource' => 'interfaces.php',
-		'Dibi\Literal' => 'Literal.php',
-		'Dibi\Loggers\FileLogger' => 'Loggers/FileLogger.php',
-		'Dibi\Loggers\FirePhpLogger' => 'Loggers/FirePhpLogger.php',
-		'Dibi\NotImplementedException' => 'exceptions.php',
-		'Dibi\NotNullConstraintViolationException' => 'exceptions.php',
-		'Dibi\NotSupportedException' => 'exceptions.php',
-		'Dibi\PcreException' => 'exceptions.php',
-		'Dibi\ProcedureException' => 'exceptions.php',
-		'Dibi\Reflection\Column' => 'Reflection/Column.php',
-		'Dibi\Reflection\Database' => 'Reflection/Database.php',
-		'Dibi\Reflection\ForeignKey' => 'Reflection/ForeignKey.php',
-		'Dibi\Reflection\Index' => 'Reflection/Index.php',
-		'Dibi\Reflection\Result' => 'Reflection/Result.php',
-		'Dibi\Reflection\Table' => 'Reflection/Table.php',
-		'Dibi\Reflector' => 'interfaces.php',
-		'Dibi\Result' => 'Result.php',
-		'Dibi\ResultDriver' => 'interfaces.php',
-		'Dibi\ResultIterator' => 'ResultIterator.php',
-		'Dibi\Row' => 'Row.php',
-		'Dibi\Strict' => 'Strict.php',
-		'Dibi\Translator' => 'Translator.php',
-		'Dibi\Type' => 'Type.php',
-		'Dibi\UniqueConstraintViolationException' => 'exceptions.php',
-	], $old2new = [
-		'DibiColumnInfo' => 'Dibi\Reflection\Column',
-		'DibiConnection' => 'Dibi\Connection',
-		'DibiDatabaseInfo' => 'Dibi\Reflection\Database',
-		'DibiDataSource' => 'Dibi\DataSource',
-		'DibiDateTime' => 'Dibi\DateTime',
-		'DibiDriverException' => 'Dibi\DriverException',
-		'DibiEvent' => 'Dibi\Event',
-		'DibiException' => 'Dibi\Exception',
-		'DibiFileLogger' => 'Dibi\Loggers\FileLogger',
-		'DibiFirebirdDriver' => 'Dibi\Drivers\FirebirdDriver',
-		'DibiFirePhpLogger' => 'Dibi\Loggers\FirePhpLogger',
-		'DibiFluent' => 'Dibi\Fluent',
-		'DibiForeignKeyInfo' => 'Dibi\Reflection\ForeignKey',
-		'DibiHashMap' => 'Dibi\HashMap',
-		'DibiHashMapBase' => 'Dibi\HashMapBase',
-		'DibiIndexInfo' => 'Dibi\Reflection\Index',
-		'DibiLiteral' => 'Dibi\Literal',
-		'DibiMsSql2005Driver' => 'Dibi\Drivers\SqlsrvDriver',
-		'DibiMsSql2005Reflector' => 'Dibi\Drivers\SqlsrvReflector',
-		'DibiMsSqlDriver' => 'Dibi\Drivers\MsSqlDriver',
-		'DibiMsSqlReflector' => 'Dibi\Drivers\MsSqlReflector',
-		'DibiMySqlDriver' => 'Dibi\Drivers\MySqlDriver',
-		'DibiMySqliDriver' => 'Dibi\Drivers\MySqliDriver',
-		'DibiMySqlReflector' => 'Dibi\Drivers\MySqlReflector',
-		'DibiNotImplementedException' => 'Dibi\NotImplementedException',
-		'DibiNotSupportedException' => 'Dibi\NotSupportedException',
-		'DibiOdbcDriver' => 'Dibi\Drivers\OdbcDriver',
-		'DibiOracleDriver' => 'Dibi\Drivers\OracleDriver',
-		'DibiPcreException' => 'Dibi\PcreException',
-		'DibiPdoDriver' => 'Dibi\Drivers\PdoDriver',
-		'DibiPostgreDriver' => 'Dibi\Drivers\PostgreDriver',
-		'DibiProcedureException' => 'Dibi\ProcedureException',
-		'DibiResult' => 'Dibi\Result',
-		'DibiResultInfo' => 'Dibi\Reflection\Result',
-		'DibiResultIterator' => 'Dibi\ResultIterator',
-		'DibiRow' => 'Dibi\Row',
-		'DibiSqlite3Driver' => 'Dibi\Drivers\Sqlite3Driver',
-		'DibiSqliteReflector' => 'Dibi\Drivers\SqliteReflector',
-		'DibiTableInfo' => 'Dibi\Reflection\Table',
-		'DibiTranslator' => 'Dibi\Translator',
-		'IDataSource' => 'Dibi\IDataSource',
-		'IDibiDriver' => 'Dibi\Driver',
-		'IDibiReflector' => 'Dibi\Reflector',
-		'IDibiResultDriver' => 'Dibi\ResultDriver',
-		'Dibi\Drivers\MsSql2005Driver' => 'Dibi\Drivers\SqlsrvDriver',
-		'Dibi\Drivers\MsSql2005Reflector' => 'Dibi\Drivers\SqlsrvReflector',
-	];
-	if (isset($map[$class])) {
-		require __DIR__ . '/Dibi/' . $map[$class];
-	} elseif (isset($old2new[$class])) {
-		$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
-		$location = isset($trace[1]['file']) ? 'used in ' . $trace[1]['file'] . ':' . $trace[1]['line'] : '';
-		trigger_error("Class $class $location has been renamed to {$old2new[$class]}.", E_USER_DEPRECATED);
-		class_alias($old2new[$class], $class);
-	}
-});