summaryrefslogtreecommitdiffstats
path: root/vendor/gipfl/db-migration/src/Migrations.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gipfl/db-migration/src/Migrations.php')
-rw-r--r--vendor/gipfl/db-migration/src/Migrations.php299
1 files changed, 299 insertions, 0 deletions
diff --git a/vendor/gipfl/db-migration/src/Migrations.php b/vendor/gipfl/db-migration/src/Migrations.php
new file mode 100644
index 0000000..2f85aa4
--- /dev/null
+++ b/vendor/gipfl/db-migration/src/Migrations.php
@@ -0,0 +1,299 @@
+<?php
+
+namespace gipfl\DbMigration;
+
+use DirectoryIterator;
+use Exception;
+use gipfl\ZfDb\Adapter\Exception\AdapterException;
+use gipfl\ZfDb\Adapter\Adapter as Db;
+use gipfl\ZfDb\Adapter\Pdo\Mysql;
+use gipfl\ZfDb\Adapter\Pdo\Pgsql;
+use InvalidArgumentException;
+use Zend_Db_Adapter_Pdo_Abstract as ZfDb;
+use Zend_Db_Adapter_Pdo_Mysql as ZfMysql;
+use Zend_Db_Adapter_Pdo_Pgsql as ZfPgsql;
+
+class Migrations
+{
+ const DB_TYPE_MYSQL = 'mysql';
+
+ const DB_TYPE_POSTGRESQL = 'pgsql';
+
+ /** @var Db */
+ protected $db;
+
+ /** @var string mysql or pgsql */
+ protected $dbType;
+
+ /** @var string */
+ protected $schemaDirectory;
+
+ /** @var string */
+ protected $tableName;
+
+ /**
+ * Migrations constructor.
+ *
+ * @param Db|ZfDb $db
+ * @param string $schemaDirectory
+ * @param string $tableName
+ */
+ public function __construct($db, $schemaDirectory, $tableName = 'schema_migration')
+ {
+ if (! ($db instanceof Db || $db instanceof ZfDb)) {
+ throw new InvalidArgumentException('$db must be an valid Zend_Db PDO adapter');
+ }
+ $this->db = $db;
+ if ($db instanceof Mysql || $db instanceof ZfMysql) {
+ $this->dbType = self::DB_TYPE_MYSQL;
+ } elseif ($db instanceof Pgsql || $db instanceof ZfPgsql) {
+ $this->dbType = self::DB_TYPE_POSTGRESQL;
+ } else {
+ throw new InvalidArgumentException(sprintf(
+ 'Migrations are currently supported for MySQL and PostgreSQL only, got %s',
+ get_class($db)
+ ));
+ }
+ $this->tableName = (string) $tableName;
+ $this->schemaDirectory = (string) $schemaDirectory;
+ }
+
+ /**
+ * Still unused
+ *
+ * @throws AdapterException|\Zend_Db_Adapter_Exception
+ */
+ protected function createMigrationsTable()
+ {
+ if ($this->dbType === self::DB_TYPE_POSTGRESQL) {
+ $create = /** @lang text */
+ <<<SQL
+
+CREATE TABLE {$this->tableName} (
+ schema_version SMALLINT NOT NULL,
+ migration_time TIMESTAMP WITH TIME ZONE NOT NULL,
+ PRIMARY KEY (schema_version)
+);
+
+SQL;
+ } else {
+ $create = /** @lang text */
+ <<<SQL
+CREATE TABLE {$this->tableName} (
+ schema_version SMALLINT UNSIGNED NOT NULL,
+ migration_time DATETIME NOT NULL,
+ PRIMARY KEY (schema_version)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_bin;
+SQL;
+ }
+ $this->db->exec($create);
+ }
+
+ /**
+ * @return int
+ */
+ public function getLastMigrationNumber()
+ {
+ try {
+ $query = $this->db->select()->from(
+ ['m' => $this->getTableName()],
+ ['schema_version' => 'MAX(schema_version)']
+ );
+
+ return (int) $this->db->fetchOne($query);
+ } catch (Exception $e) {
+ return 0;
+ }
+ }
+
+ /**
+ * @return string
+ */
+ protected function getTableName()
+ {
+ return $this->tableName;
+ }
+
+ /**
+ * @return bool
+ */
+ public function hasAnyTable()
+ {
+ return count($this->db->listTables()) > 0;
+ }
+
+ /**
+ * @return bool
+ */
+ public function hasTable($tableName)
+ {
+ return in_array($tableName, $this->db->listTables());
+ }
+
+ /**
+ * @return bool
+ */
+ public function hasMigrationsTable()
+ {
+ return $this->hasTable($this->tableName);
+ }
+
+ /**
+ * @return bool
+ */
+ public function hasSchema()
+ {
+ return $this->listPendingMigrations() !== [0];
+ }
+
+ /**
+ * @return bool
+ */
+ public function hasPendingMigrations()
+ {
+ return $this->countPendingMigrations() > 0;
+ }
+
+ /**
+ * @return int
+ */
+ public function countPendingMigrations()
+ {
+ return count($this->listPendingMigrations());
+ }
+
+ /**
+ * @return Migration[]
+ */
+ public function getPendingMigrations()
+ {
+ $migrations = array();
+ foreach ($this->listPendingMigrations() as $version) {
+ $migrations[] = new Migration(
+ $version,
+ $this->loadMigrationFile($version)
+ );
+ }
+
+ return $migrations;
+ }
+
+ /**
+ * @return $this
+ */
+ public function applyPendingMigrations()
+ {
+ foreach ($this->getPendingMigrations() as $migration) {
+ $migration->apply($this->db);
+ }
+
+ return $this;
+ }
+
+ /**
+ * @return int[]
+ */
+ public function listPendingMigrations()
+ {
+ $lastMigration = $this->getLastMigrationNumber();
+ if ($lastMigration === 0) {
+ return [0];
+ }
+
+ return $this->listMigrationsAfter($this->getLastMigrationNumber());
+ }
+
+ /**
+ * @return int[]
+ */
+ public function listAllMigrations()
+ {
+ $dir = $this->getMigrationsDirectory();
+ $versions = [];
+
+ if (! is_readable($dir)) {
+ return $versions;
+ }
+
+ foreach (new DirectoryIterator($dir) as $file) {
+ if ($file->isDot()) {
+ continue;
+ }
+
+ $filename = $file->getFilename();
+ if (preg_match('/^upgrade_(\d+)\.sql$/', $filename, $match)) {
+ $versions[] = (int) $match[1];
+ }
+ }
+
+ sort($versions);
+
+ return $versions;
+ }
+
+ /**
+ * @param $version
+ * @return false|string
+ */
+ public function loadMigrationFile($version)
+ {
+ if ($version === 0) {
+ $filename = $this->getFullSchemaFile();
+ } else {
+ $filename = sprintf(
+ '%s/upgrade_%d.sql',
+ $this->getMigrationsDirectory(),
+ $version
+ );
+ }
+
+ return file_get_contents($filename);
+ }
+
+ /**
+ * @param $version
+ * @return int[]
+ */
+ protected function listMigrationsAfter($version)
+ {
+ $filtered = [];
+ foreach ($this->listAllMigrations() as $available) {
+ if ($available > $version) {
+ $filtered[] = $available;
+ }
+ }
+
+ return $filtered;
+ }
+
+ /**
+ * @param ?string $subDirectory
+ * @return string
+ */
+ public function getSchemaDirectory($subDirectory = null)
+ {
+ if ($subDirectory === null) {
+ return $this->schemaDirectory;
+ } else {
+ return $this->schemaDirectory . '/' . ltrim($subDirectory, '/');
+ }
+ }
+
+ /**
+ * @return string
+ */
+ public function getMigrationsDirectory()
+ {
+ return $this->getSchemaDirectory($this->dbType . '-migrations');
+ }
+
+ /**
+ * @return string
+ */
+ protected function getFullSchemaFile()
+ {
+ return $this->getSchemaDirectory(
+ $this->dbType. '.sql'
+ );
+ }
+}