diff --git a/migrations/v0.1/2021_05_30_000000_wrap_migration_beta_path.php b/migrations/v1.0/2021_05_31_000000_rename_beta_migrations.php
similarity index 80%
rename from migrations/v0.1/2021_05_30_000000_wrap_migration_beta_path.php
rename to migrations/v1.0/2021_05_31_000000_rename_beta_migrations.php
index 70ed8452d..129ce79ed 100644
--- a/migrations/v0.1/2021_05_30_000000_wrap_migration_beta_path.php
+++ b/migrations/v1.0/2021_05_31_000000_rename_beta_migrations.php
@@ -22,7 +22,7 @@ return [
$db = $schema->getConnection();
$db->table('migrations')
- ->where('permission', 'LIKE', 'viewForum')
- ->update(['permission' => $db->raw("REPLACE(migration, 'v0.1/', '')")]);
+ ->whereNull('extension')
+ ->update(['migration' => $db->raw("REPLACE('v0.1/', '')")]);
}
];
diff --git a/migrations/v1.0/create_discussions_table.php b/migrations/v1.0/create_discussions_table.php
new file mode 100644
index 000000000..13d2a9ef1
--- /dev/null
+++ b/migrations/v1.0/create_discussions_table.php
@@ -0,0 +1,48 @@
+ function (Builder $schema) {
+ $schema->create('discussions', function (Blueprint $table) {
+ $table->increments('id');
+ $table->string('title', 200);
+ $table->unsignedInteger('comments_count')->default(0);
+ $table->unsignedInteger('participants_count')->default(0);
+ $table->unsignedInteger('post_number_index')->default(0);
+
+ $table->dateTime('created_at');
+ $table->foreignIdFor(User::class, 'user_id')->nullable();
+ $table->foreignIdFor(Post::class, 'first_post_id')->nullable();
+
+ $table->dateTime('last_posted_at')->nullable();
+ $table->foreignIdFor(User::class, 'last_posted_user_id')->nullable();
+ $table->foreignIdFor(Post::class, 'last_post_id')->nullable();
+ $table->unsignedInteger('last_post_number')->nullable();
+
+ $table->dateTime('hidden_at')->nullable();
+ $table->foreignIdFor(User::class, 'hidden_user_id')->nullable();
+
+ $table->string('slug', 200);
+ $table->boolean('is_private')->default(0);
+ });
+
+ $connection = $schema->getConnection();
+ $prefix = $connection->getTablePrefix();
+ $connection->statement('ALTER TABLE '.$prefix.'discussions ADD FULLTEXT title (title)');
+ },
+
+ 'down' => function (Builder $schema) {
+ $schema->drop('discussions');
+ },
+];
diff --git a/migrations/v1.0/create_posts_table.php b/migrations/v1.0/create_posts_table.php
new file mode 100644
index 000000000..2ff73d617
--- /dev/null
+++ b/migrations/v1.0/create_posts_table.php
@@ -0,0 +1,48 @@
+ function (Builder $schema) {
+ $schema->create('posts', function (Blueprint $table) {
+ $table->increments('id');
+ $table->foreignIdFor(Discussion::class, 'discussion_id');
+ $table->unsignedInteger('number')->nullable();
+
+ $table->dateTime('created_at');
+ $table->foreignIdFor(User::class, 'user_id')->nullable();
+ $table->string('type', 100)->nullable();
+ $table->mediumText('content')->nullable();
+
+ $table->dateTime('edited_at')->nullable();
+ $table->foreignIdFor(User::class, 'edited_user_id')->nullable();
+ $table->dateTime('hidden_at')->nullable();
+ $table->foreignIdFor(User::class, 'hidden_user_id')->nullable();
+
+ $table->string('ip_address', 45)->nullable();
+ $table->boolean('is_private');
+
+ $table->unique(['discussion_id', 'number']);
+ });
+
+ $connection = $schema->getConnection();
+ $prefix = $connection->getTablePrefix();
+ $connection->statement('ALTER TABLE '.$prefix.'posts ADD FULLTEXT content (content)');
+ },
+
+ 'down' => function (Builder $schema) {
+ $schema->drop('posts');
+ }
+];
diff --git a/migrations/v1.0/create_settings_table.php b/migrations/v1.0/create_settings_table.php
new file mode 100644
index 000000000..e7ed5857f
--- /dev/null
+++ b/migrations/v1.0/create_settings_table.php
@@ -0,0 +1,19 @@
+string('key', 100)->primary();
+ $table->binary('value')->nullable();
+ }
+);
diff --git a/migrations/v1.0/create_users_table.php b/migrations/v1.0/create_users_table.php
new file mode 100644
index 000000000..8c91a2a88
--- /dev/null
+++ b/migrations/v1.0/create_users_table.php
@@ -0,0 +1,35 @@
+increments('id');
+ $table->string('username', 100)->unique();
+ $table->string('email', 150)->unique();
+ $table->boolean('is_email_confirmed')->default(0);
+ $table->string('password', 100);
+ $table->string('avatar_url', 100)->nullable();
+ $table->text('preferences')->nullable();
+ $table->dateTime('join_time')->nullable();
+ $table->dateTime('last_seen_time')->nullable();
+ $table->dateTime('read_time')->nullable();
+ $table->dateTime('notification_read_time')->nullable();
+ $table->integer('discussions_count')->unsigned()->default(0);
+ $table->integer('comments_count')->unsigned()->default(0);
+
+ $table->index('joined_at');
+ $table->index('last_seen_at');
+ $table->index('discussion_count');
+ $table->index('comment_count');
+ }
+);
diff --git a/src/Database/MigrationSourceRepository.php b/src/Database/MigrationSourceRepository.php
index 228dad138..02a322661 100644
--- a/src/Database/MigrationSourceRepository.php
+++ b/src/Database/MigrationSourceRepository.php
@@ -12,6 +12,7 @@ namespace Flarum\Database;
use Flarum\Extension\Extension;
use Flarum\Foundation\Application;
use Illuminate\Database\ConnectionInterface;
+use Illuminate\Support\Str;
class MigrationSourceRepository
{
@@ -25,31 +26,32 @@ class MigrationSourceRepository
public function flarum(): array
{
if (! $this->databaseVersion()) {
- return $this->install();
+ return $this->wrap($this->install());
}
- return $this->upgrade();
+ return $this->wrap($this->upgrade());
}
- public function extension(Extension $extension): ?array
+ public function extension(Extension $extension): array
{
if (! $extension->hasMigrations()) {
return [];
}
- return $extension->getMigrations();
+ return $this->wrap(glob($extension->getPath().'/migrations/*_*.php'));
}
protected function install(): array
{
// We read every file from the latest major/minor version migrations directory.
// Including the create_
_table statements.
- $files = glob(__DIR__.'/../../migrations/'.$this->installedVersion(true).'/[0-9_]{15}_*.php');
+ $files = glob(__DIR__.'/../../migrations/'.$this->installedVersion(true).'/[0-9_]**.php');
// Sort by timestamp.
sort($files);
- $create = glob(__DIR__.'/../../migrations/'.$this->installedVersion(true).'/create_*.php');
+ // Read and prepend the create__table statements.
+ $create = glob(__DIR__.'/../../migrations/'.$this->installedVersion(true).'/create_*_table.php');
return array_merge($create, $files);
}
@@ -59,26 +61,28 @@ class MigrationSourceRepository
$files = [];
$add = false;
- $directories = glob(__DIR__.'/../../migrations/', GLOB_ONLYDIR);
+ $directories = glob(__DIR__.'/../../migrations/*', GLOB_ONLYDIR);
sort($directories, SORT_NATURAL);
// Upgrade
// Loop over all version migrations directory until we find the version that is currently active.
foreach ($directories as $directory) {
+ $directoryVersion = substr(basename($directory), 1);
+
// We have found the directory matching the version database version. Start adding files.
- if (substr($directory, 1) === $this->databaseVersion(true)) {
+ if ($directoryVersion === $this->databaseVersion(true)) {
$add = true;
}
if ($add) {
// Selectively add files, but only include those matching the format YYYY_MM_DD_HHIISS_.php
// This excludes the create__table.
- $files = array_merge($files, glob(__DIR__."/../../migrations/$directory/[0-9_]{15}_*.php"));
+ $files = array_merge($files, glob(realpath($directory) . "/[0-9_]**.php"));
}
// Once we found the version that is installed, we can quit.
// Theoretically this should never be necessary, it could just loop over all remaining ones.
- if (substr($directory, 1) === $this->installedVersion(true)) {
+ if ($directoryVersion === $this->installedVersion(true)) {
break;
}
}
@@ -89,6 +93,15 @@ class MigrationSourceRepository
return $files;
}
+ protected function shortVersion(string $version): string
+ {
+ if (preg_match('~(?^[0-9]+\.[0-9]+)~', $version, $m)) {
+ return $m['version'];
+ }
+
+ return $version;
+ }
+
protected function installedVersion(bool $short = false): string
{
$version = Application::VERSION;
@@ -100,15 +113,6 @@ class MigrationSourceRepository
return $version;
}
- protected function shortVersion(string $version): string
- {
- if (preg_match('~(?^[0-9]+\.[0-9]+)~', $version, $m)) {
- return $m['version'];
- }
-
- return $version;
- }
-
protected function databaseVersion(bool $short = false): ?string
{
$version = $this->connection->getSchemaBuilder()->hasTable('settings')
@@ -121,4 +125,16 @@ class MigrationSourceRepository
return $version;
}
+
+ protected function wrap(array $migrations): array
+ {
+ return collect($migrations)
+ ->mapWithKeys(function (string $path) {
+ $path = realpath($path);
+ $path = Str::after($path, 'migrations/');
+ $basename = Str::before($path, '.php');
+ return [$path => $basename];
+ })
+ ->toArray();
+ }
}
diff --git a/src/Database/Migrator.php b/src/Database/Migrator.php
index 96a2678fb..ccce54a30 100644
--- a/src/Database/Migrator.php
+++ b/src/Database/Migrator.php
@@ -11,7 +11,6 @@ namespace Flarum\Database;
use Exception;
use Flarum\Extension\Extension;
-use Flarum\Foundation\Application;
use Illuminate\Database\ConnectionInterface;
use Illuminate\Database\Schema\Builder;
use Illuminate\Filesystem\Filesystem;
@@ -79,13 +78,13 @@ class Migrator
/**
* Run the outstanding migrations at a given path.
*
- * @param string $path
- * @param Extension $extension
+ * @param string $path
+ * @param Extension|null $extension
* @return void
*/
- public function run($path, Extension $extension = null)
+ public function run(string $path, Extension $extension = null)
{
- $files = $this->getMigrationFiles($path, $extension);
+ $files = $this->getMigrationFiles($extension);
$ran = $this->repository->getRan($extension ? $extension->getId() : null);
@@ -97,12 +96,12 @@ class Migrator
/**
* Run an array of migrations.
*
- * @param string $path
- * @param array $migrations
- * @param Extension $extension
+ * @param string $path
+ * @param array $migrations
+ * @param Extension|null $extension
* @return void
*/
- public function runMigrationList($path, $migrations, Extension $extension = null)
+ public function runMigrationList(string $path, array $migrations, Extension $extension = null)
{
// First we will just make sure that there are any migrations to run. If there
// aren't, we will just make a note of it to the developer so they're aware
@@ -124,13 +123,13 @@ class Migrator
/**
* Run "up" a migration instance.
*
- * @param string $path
- * @param string $file
- * @param string $path
- * @param Extension $extension
+ * @param string $path
+ * @param string $file
+ * @param Extension|null $extension
* @return void
+ * @throws Exception
*/
- protected function runUp($path, $file, Extension $extension = null)
+ protected function runUp(string $path, string $file, Extension $extension = null)
{
$migration = $this->resolve($path, $file);
@@ -209,14 +208,9 @@ class Migrator
}
}
- public function getMigrationFiles(string $path, Extension $extension = null): array
+ public function getMigrationFiles(Extension $extension = null): array
{
- $files = $extension ? $this->source->extension($extension) : $this->source->flarum();
- dd($files);
-
- return array_map(function ($file) {
- return str_replace('.php', '', basename($file));
- }, $files);
+ return $extension ? $this->source->extension($extension) : $this->source->flarum();
}
/**
diff --git a/src/Extension/Extension.php b/src/Extension/Extension.php
index 0700ce5ba..7bfe9f405 100644
--- a/src/Extension/Extension.php
+++ b/src/Extension/Extension.php
@@ -9,6 +9,8 @@
namespace Flarum\Extension;
+use Flarum\Database\MigrationSourceRepository;
+use Flarum\Database\Migrator;
use Flarum\Extend\LifecycleInterface;
use Flarum\Extension\Exception\ExtensionBootError;
use Illuminate\Contracts\Container\Container;
@@ -458,15 +460,17 @@ class Extension implements Arrayable
}
}
- /**
- * Retrieves the list of migrations of this extension.
- *
- * @return array
- * @internal
- */
- public function getMigrations(): array
+ public function migrate(Migrator $migrator, string $direction)
{
- return glob($this->path.'/migrations/*_*.php');
+ if (! $this->hasMigrations()) {
+ return;
+ }
+
+ if ($direction == 'up') {
+ return $migrator->run($this->getPath().'/migrations', $this);
+ } else {
+ return $migrator->reset($this->getPath().'/migrations', $this);
+ }
}
/**