Skip to content

Commit

Permalink
Merge pull request #4 from coenjacobs/pair-logger-table
Browse files Browse the repository at this point in the history
Logger table is only being setup if DatabaseLogger is used
  • Loading branch information
coenjacobs authored Feb 5, 2019
2 parents cf2c5ff + 2b6e1e7 commit 5b4afd4
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 166 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ Worker classes are the classes responsible for actually performing the queries y

## Loggers

Loggers take care of registering the migrations that have been run already. This is to ensure that no migrations are being run more than once. By default, there is a database based Logger available, in the `CoenJacobs\Migrator\Loggers\DatabaseLogger` class. This class actually uses the aforementioned `$wpdb` based Worker, in order to log the migration data into a specific database table. You can provide your own implementation of the Logger class, as long as they implement the `CoenJacobs\Migrator\Contracts\Logger` interface.
Loggers take care of registering the migrations that have been run already. This is to ensure that no migrations are being run more than once. By default, there is a database based Logger available, in the `CoenJacobs\Migrator\Loggers\DatabaseLogger` class. This class actually uses the aforementioned `$wpdb` based Worker, in order to log the migration data into a specific database table. This database table is being created, using the table name you've provided as the first contructor argument.

You can provide your own implementation of the Logger class, as long as they implement the `CoenJacobs\Migrator\Contracts\Logger` interface.

## Migration structure

Expand Down Expand Up @@ -77,7 +79,8 @@ use CoenJacobs\Migrator\Loggers\DatabaseLogger;
use CoenJacobs\Migrator\Workers\WpdbWorker;

$worker = new WpdbWorker();
$migrator = new Handler($worker, new DatabaseLogger());
$logger = new DatabaseLogger('migrations_table_name');
$handler = new Handler($worker, $logger);
```

After that, the Handler is ready to accept new migrations to be added, before they can be run. You pass the class as a string of the class name, where the class itself again implements the `CoenJacobs\Migrator\Contracts\Migration` interface:
Expand Down
3 changes: 2 additions & 1 deletion phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
backupGlobals="false"
bootstrap="vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
Expand All @@ -9,7 +10,7 @@
>
<testsuites>
<testsuite name="unit">
<directory suffix=".php">./tests/unit/</directory>
<directory suffix=".php">./tests/Unit/</directory>
</testsuite>
</testsuites>
</phpunit>
9 changes: 0 additions & 9 deletions src/Exceptions/ReservedNameException.php

This file was deleted.

48 changes: 1 addition & 47 deletions src/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
use CoenJacobs\Migrator\Contracts\Logger;
use CoenJacobs\Migrator\Contracts\Worker;
use CoenJacobs\Migrator\Contracts\Migration;
use CoenJacobs\Migrator\Exceptions\ReservedNameException;
use CoenJacobs\Migrator\Migrations\CreateMigrationsTable;

class Handler
{
Expand All @@ -31,41 +29,14 @@ public function __construct(Worker $worker, Logger $logger)
$this->worker = $worker;
$this->logger = $logger;
$this->logger->setWorker($this->worker);

$this->setupCoreMigrations();
}

private function setupCoreMigrations()
{
$this->add('core', CreateMigrationsTable::class);

// From here on, the 'core' index as $plugin_key is a reserved name and
// can't be used by anyone else.
$this->reservedNames = [
'core'
];
}

/**
* @param string $pluginKey
* @return bool
*/
public function isReservedName($pluginKey)
{
return in_array($pluginKey, $this->reservedNames);
}

/**
* @param string $pluginKey
* @param $migrationClassName
* @throws ReservedNameException
*/
public function add($pluginKey, $migrationClassName)
{
if ($this->isReservedName($pluginKey)) {
throw new ReservedNameException($pluginKey . ' is a reserved name and can not be used by implementations.');
}

$this->migrations[ $pluginKey ][] = $migrationClassName;
}

Expand All @@ -74,29 +45,17 @@ public function add($pluginKey, $migrationClassName)
* Core migrations will always be run first to setup base tables for logging.
*
* @param string $pluginKey
* @throws ReservedNameException
*/
public function up($pluginKey)
{
if ($this->isReservedName($pluginKey)) {
throw new ReservedNameException($pluginKey . ' is a reserved name and can not be used by implementations.');
}

if (! isset($this->migrations[ $pluginKey ])) {
return;
}

$runMigrations = $this->logger->getLoggedMigrations(['core', $pluginKey]);
$runMigrations = $this->logger->getLoggedMigrations([$pluginKey]);

$migrationsToRun = [];

// Add core migrations first
foreach ($this->migrations[ 'core' ] as $migrationClass) {
if (! in_array($migrationClass::id(), $runMigrations)) {
$migrationsToRun['core'][] = new $migrationClass($this->worker);
}
}

// Add added migrations for $pluginKey second
foreach ($this->migrations[ $pluginKey ] as $migrationClass) {
if (! in_array($migrationClass::id(), $runMigrations)) {
Expand All @@ -112,14 +71,9 @@ public function up($pluginKey)
* Core migrations will not be reversed since they can still be used by another plugin.
*
* @param string $pluginKey
* @throws ReservedNameException
*/
public function down($pluginKey)
{
if ($this->isReservedName($pluginKey)) {
throw new ReservedNameException($pluginKey . ' is a reserved name and can not be used by implementations.');
}

if (! isset($this->migrations[ $pluginKey ])) {
return;
}
Expand Down
84 changes: 53 additions & 31 deletions src/Loggers/DatabaseLogger.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,59 @@
namespace CoenJacobs\Migrator\Loggers;

use CoenJacobs\Migrator\Contracts\Migration;
use CoenJacobs\Migrator\Migrations\CreateMigrationsTable;

class DatabaseLogger extends BaseLogger
{
/** @var string */
protected $tableName;

/** @var bool */
protected $setup = false;

public function __construct($tableName)
{
$this->tableName = $tableName;
}

public function init()
{
if (!$this->isTableSetup()) {
$migration = new CreateMigrationsTable($this->worker);
$migration->setTableName($this->tableName);
$migration->up();

$this->setup = true;
}
}

public function add($plugin_key, Migration $migration, $batch)
{
$this->init();
$id = $migration->id();
$tableName = $this->worker->getPrefix() . 'migrator_migrations';

$batch = intval($batch);

$query = "INSERT INTO $tableName (migration, plugin_key, batch)
$query = "INSERT INTO $this->tableName (migration, plugin_key, batch)
VALUES ('$id', '$plugin_key', '$batch')";
$this->worker->query($query);
}

public function remove($plugin_key, Migration $migration)
{
$this->init();
$id = $migration->id();
$tableName = $this->worker->getPrefix() . 'migrator_migrations';
$query = "DELETE FROM $tableName (migration, plugin_key)
$query = "DELETE FROM $this->tableName (migration, plugin_key)
VALUES ('$id', '$plugin_key')";
$this->worker->query($query);
}

public function getLoggedMigrations($plugin_keys)
{
$databaseName = $this->worker->getDatabaseName();
$tableName = $this->worker->getPrefix() . 'migrator_migrations';
$this->init();

// Check if table exists before we try to query it
$query = "SELECT count(*)
FROM information_schema.TABLES
WHERE (TABLE_SCHEMA = '$databaseName') AND (TABLE_NAME = '$tableName')";

$result = $this->worker->getResults($query);

if (empty($result) || $result[0]->{"count(*)"} == 0) {
return [];
}

$query = 'SELECT migration FROM '.$tableName.'
WHERE plugin_key IN ("'. implode('","', $plugin_keys) .'")';
$query = 'SELECT migration FROM ' . $this->tableName . '
WHERE plugin_key IN ("' . implode('","', $plugin_keys) . '")';

$results = $this->worker->getResults($query);

Expand All @@ -53,33 +64,44 @@ public function getLoggedMigrations($plugin_keys)
foreach ($results as $result) {
$migrations[] = $result->migration;
}

return $migrations;
}

public function getHighestBatchNumber()
{
$this->init();

$query = 'SELECT MAX(batch) AS batch FROM ' . $this->tableName . ';';
$results = $this->worker->getResults($query);

if (empty($results)) {
return 0;
}

return array_pop($results)->batch;
}

protected function isTableSetup()
{
if ($this->setup === true) {
return true;
}

$databaseName = $this->worker->getDatabaseName();
$tableName = $this->worker->getPrefix() . 'migrator_migrations';

// Check if table exists before we try to query it
$query = "SELECT count(*)
FROM information_schema.TABLES
WHERE (TABLE_SCHEMA = '$databaseName') AND (TABLE_NAME = '$tableName')";
WHERE (TABLE_SCHEMA = '$databaseName') AND (TABLE_NAME = '$this->tableName')";

$result = $this->worker->getResults($query);

if (empty($result) || $result[0]->{"count(*)"} == 0) {
return 0;
}

$tableName = $this->worker->getPrefix() . 'migrator_migrations';
$query = 'SELECT MAX(batch) AS batch FROM '.$tableName.';';
$results = $this->worker->getResults($query);

if (empty($results)) {
return 0;
return false;
}

return array_pop($results)->batch;
$this->setup = true;
return true;
}
}
16 changes: 10 additions & 6 deletions src/Migrations/CreateMigrationsTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,22 @@

class CreateMigrationsTable extends BaseMigration
{
/** @var string */
protected $tableName;

public static function id()
{
return 'migrator-1-migrations-table';
}

public function up()
public function setTableName($tableName)
{
$tableName = $this->worker->getPrefix() . 'migrator_migrations';
$this->tableName = $tableName;
}

$query = "CREATE TABLE $tableName (
public function up()
{
$query = "CREATE TABLE $this->tableName (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
migration VARCHAR(255) NOT NULL,
plugin_key VARCHAR(255) NOT NULL,
Expand All @@ -24,9 +30,7 @@ public function up()

public function down()
{
$tableName = $this->worker->getPrefix() . 'migrator_migrations';

$query = "DROP TABLE $tableName";
$query = "DROP TABLE $this->tableName";
$this->worker->query($query);
}
}
Loading

0 comments on commit 5b4afd4

Please sign in to comment.