Browse Source

* Move migration class to SQL/
* Get framework in place for migration up/down (reversible change is still not handled)
* Make namespace class searching better by using strpos instead of substr

Nathaniel van Diepen 7 years ago
parent
commit
9e10a83d52

+ 1 - 1
App/controller.abstract.class.php

@@ -8,7 +8,7 @@
 		public abstract static function handle(Router $router);
 		public static function controllers(){
 			return array_filter(get_declared_classes(), function($class){
-				return substr($class, 0, 11) == "Controller\\";
+				return 0 === strpos($class, "Controller\\");
 			});
 		}
 		public static function handle_all(Router $router){

+ 97 - 0
SQL/migration.abstract.class.php

@@ -0,0 +1,97 @@
+<?php
+	namespace Juju\SQL;
+	require_once(realpath(dirname(__DIR__).'/sql.class.php'));
+	use Juju\{SQL, Settings};
+
+	abstract class Migration {
+		public abstract static function up();
+		public abstract static function down();
+		public abstract static function change();
+
+		const MIGRATE_UP = 'up';
+		const MIGRATE_DOWN = 'down';
+		private static $sql;
+
+		final public static function version(){
+			$name = get_called_class();
+			return substr($name, strrpos($name, '\\') + 1);
+		}
+		final public static function version_table(){
+			if(!class_exists("Juju\\Settings")){
+				throw new \Exception("Settings not loaded");
+			}
+			return Settings::get('db.versions');
+		}
+		final public static function installed(){
+			return self::$sql->query(
+				"select count(1) count ".
+				"from `".self::version_table()."` ".
+				"where version = ?",
+				's',
+				static::version()
+			)->assoc_result['count'] == 1;
+		}
+		final public static function migrations(){
+			$migrations = array_filter(get_declared_classes(), function($class){
+				return 0 === strpos($class, "Migration\\");
+			});
+			sort($migrations);
+			return $migrations;
+		}
+		final public static function migrate(string $direction, int $amount = 1){
+			if($amount < 1){
+				throw new \Exception("Migration amount must be a positive integer");
+			}
+			$table = self::version_table();
+			$sql = self::$sql;
+			if(count($sql->query("show tables like '{$table}'")->assoc_results) == 0){
+				$sql->query("CREATE TABLE `{$table}` (version varchar(100) NOT NULL, primary key (version))")->execute();
+			}
+			switch($direction){
+				case self::MIGRATE_UP:
+					foreach(self::migrations() as $migration){
+						if(!$migration::installed()){
+							$migration::up();
+							$sql->query(
+								"insert into `{$table}` set version = ?",
+								's',
+								$migration::version()
+							)->execute();
+							if(--$amount == 0){
+								break;
+							}
+						}
+					}
+				break;
+				case self::MIGRATE_DOWN:
+					foreach(array_reverse(self::migrations()) as $migration){
+						if($migration::installed()){
+							$migration::down();
+							$sql->query(
+								"delete from `{$table}` where version = ?",
+								's',
+								$migration::version()
+							)->execute();
+							if(--$amount == 0){
+								break;
+							}
+						}
+					}
+				break;
+				default:
+					throw new \Exception("Invalid migration direction '{$direction}'");
+			}
+		}
+		final public static function migrate_all(string $direction){
+			self::migrate($direction, count(self::migrations()));
+		}
+		final public static function bind(string $dsn){
+			self::$sql = SQL::FromDSN($dsn);
+		}
+		final public static function release(){
+			$sql = self::$sql;
+			unset($sql);
+			self::$sql = null;
+		}
+	}
+?>

+ 0 - 7
migration.abstract.class.php

@@ -1,7 +0,0 @@
-<?php
-	namespace Juju;
-
-	abstract class Migration {
-
-	}
-?>

+ 1 - 1
orm.abstract.class.php

@@ -285,7 +285,7 @@
 		}
 		public static function models(){
 			array_filter(get_declared_classes(), function($class){
-				return substr($class, 0, 5) == "Model\\";
+				return 0 === strpos($class, "Model\\");
 			});
 		}
 		// Instance Api