Skip to content

Commit

Permalink
Merge v3 into v4 (#40)
Browse files Browse the repository at this point in the history
  • Loading branch information
roxblnfk authored Oct 14, 2022
2 parents 9b55393 + 971e641 commit 7af465e
Show file tree
Hide file tree
Showing 19 changed files with 179 additions and 59 deletions.
14 changes: 14 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# editorconfig.org

root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true

[*.yml]
indent_size = 2
6 changes: 4 additions & 2 deletions .github/workflows/ci-mssql.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
on:
- pull_request
- push
push:
branches:
- '4.*'
pull_request: null

name: ci-mssql

Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/ci-mysql.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
on:
- pull_request
- push
push:
branches:
- '4.*'
pull_request: null

name: ci-mysql

Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/ci-pgsql.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
on:
- pull_request
- push
push:
branches:
- '4.*'
pull_request: null

name: ci-pgsql

Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name: build

on: [push, pull_request]
on:
push:
branches:
- '4.*'
pull_request: null

jobs:
test:
Expand Down
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
.env
.coveralls.yml
composer.lock
vendor/
/vendor
tests/runtime/*
build/logs/*
build/
*.db
clover.xml
clover.json
clover.json
.phpunit.result.cache

11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ composer require cycle/migrations ^4.0
use Cycle\Migrations;
use Cycle\Database;
use Cycle\Database\Config;

$dbal = new Database\DatabaseManager(new Config\DatabaseConfig([
'default' => 'default',
'databases' => [
Expand All @@ -35,16 +36,22 @@ $dbal = new Database\DatabaseManager(new Config\DatabaseConfig([
),
]
]));

$config = new Migrations\Config\MigrationConfig([
'directory' => __DIR__ . '/../migrations/', // where to store migrations
'table' => 'migrations' // database table to store migration status
'safe' => true // When set to true no confirmation will be requested on migration run.
'vendorDirectories' => [ // Where to look for vendor package migrations
__DIR__ . '/../vendor/vendorName/packageName/migrations/'
],
'table' => 'migrations' // database table to store migration status
'safe' => true // When set to true no confirmation will be requested on migration run.
]);

$migrator = new Migrations\Migrator(
$config,
$dbal,
new Migrations\FileRepository($config)
);

// Init migration table
$migrator->configure();
```
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"license": "MIT",
"require": {
"php": ">=8.1",
"cycle/database": "^2.0",
"cycle/database": "^2.2",
"spiral/core": "^3.0",
"spiral/files": "^3.0",
"spiral/tokenizer": "^3.0",
Expand All @@ -14,7 +14,7 @@
"require-dev": {
"phpunit/phpunit": "^9.5",
"mockery/mockery": "^1.5",
"spiral/framework": "3.0.x-dev"
"vimeo/psalm": "dev-master"
},
"autoload": {
"psr-4": {
Expand Down
26 changes: 11 additions & 15 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php"
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" bootstrap="tests/bootstrap.php"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
verbose="false"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
stopOnError="false">

stopOnFailure="true"
stopOnError="true"
>
<coverage>
<include>
<directory>src/</directory>
</include>
</coverage>
<testsuites>
<testsuite name="Cycle Database Migrations">
<directory>./tests/</directory>
</testsuite>
</testsuites>

<filter>
<whitelist>
<directory>src/</directory>
</whitelist>
</filter>
</phpunit>
</phpunit>
21 changes: 21 additions & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0"?>
<psalm
errorLevel="4"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
>
<projectFiles>
<directory name="src" />
<ignoreFiles>
<directory name="vendor" />
</ignoreFiles>
</projectFiles>
<issueHandlers>
<UndefinedAttributeClass>
<errorLevel type="suppress">
<referencedClass name="JetBrains\PhpStorm\ExpectedValues" />
</errorLevel>
</UndefinedAttributeClass>
</issueHandlers>
</psalm>
1 change: 1 addition & 0 deletions src/Capsule.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
*/
final class Capsule implements CapsuleInterface
{
/** @var array<non-empty-string, AbstractTable> */
private array $schemas = [];

public function __construct(private DatabaseInterface $database)
Expand Down
2 changes: 2 additions & 0 deletions src/CapsuleInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public function getTable(string $table): TableInterface;
/**
* Get schema associated with given database and table.
*
* @param non-empty-string $table
*
* @throws ContextException
*/
public function getSchema(string $table): AbstractTable;
Expand Down
8 changes: 8 additions & 0 deletions src/Config/MigrationConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ public function getDirectory(): string
return $this->config['directory'] ?? '';
}

/**
* Vendor migrations directories.
*/
public function getVendorDirectories(): array
{
return (array) ($this->config['vendorDirectories'] ?? []);
}

/**
* Table to store list of executed migrations.
*/
Expand Down
61 changes: 41 additions & 20 deletions src/FileRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

namespace Cycle\Migrations;

use DateTimeInterface;
use Doctrine\Inflector\Inflector;
use Doctrine\Inflector\Rules\English\InflectorFactory;
use Spiral\Core\Container;
use Spiral\Core\FactoryInterface;
use Spiral\Files\Files;
Expand All @@ -15,6 +17,14 @@

/**
* Stores migrations as files.
*
* @psalm-type TFileArray = array{
* filename: non-empty-string,
* class: class-string,
* created: DateTimeInterface|null,
* chunk: string,
* name: non-empty-string
* }
*/
final class FileRepository implements RepositoryInterface
{
Expand All @@ -33,20 +43,17 @@ public function __construct(private MigrationConfig $config, FactoryInterface $f
{
$this->files = new Files();
$this->factory = $factory ?? new Container();
$this->inflector = (new \Doctrine\Inflector\Rules\English\InflectorFactory())->build();
$this->inflector = (new InflectorFactory())->build();
}

/**
* {@inheritdoc}
*/
public function getMigrations(): array
{
$timestamps = [];
$chunks = [];
$migrations = [];

foreach ($this->getFiles() as $f) {
if (!class_exists($f['class'], false)) {
foreach ($this->getFilesIterator() as $f) {
if (! \class_exists($f['class'], false)) {
//Attempting to load migration class (we can not relay on autoloading here)
require_once($f['filename']);
}
Expand All @@ -59,23 +66,20 @@ public function getMigrations(): array
$migrations[] = $migration->withState(new State($f['name'], $f['created']));
}

array_multisort($timestamps, $chunks, SORT_ASC | SORT_NATURAL, $migrations);
\array_multisort($timestamps, $chunks, SORT_ASC | SORT_NATURAL, $migrations);

return $migrations;
}

/**
* {@inheritdoc}
*/
public function registerMigration(string $name, string $class, string $body = null): string
{
if (empty($body) && !class_exists($class)) {
if (empty($body) && ! \class_exists($class)) {
throw new RepositoryException(
"Unable to register migration '{$class}', representing class does not exists"
);
}

$currentTimeStamp = date(self::TIMESTAMP_FORMAT);
$currentTimeStamp = \date(self::TIMESTAMP_FORMAT);
$inflectedName = $this->inflector->tableize($name);

foreach ($this->getMigrations() as $migration) {
Expand Down Expand Up @@ -108,16 +112,33 @@ public function registerMigration(string $name, string $class, string $body = nu
return $filename;
}

/**
* @return \Generator<int, TFileArray>
*/
private function getFilesIterator(): \Generator
{
foreach (
\array_merge(
[$this->config->getDirectory()],
$this->config->getVendorDirectories()
) as $directory
) {
yield from $this->getFiles($directory);
}
}

/**
* Internal method to fetch all migration filenames.
*
* @return \Generator<int, TFileArray>
*/
private function getFiles(): \Generator
private function getFiles(string $directory): \Generator
{
foreach ($this->files->getFiles($this->config->getDirectory(), '*.php') as $filename) {
foreach ($this->files->getFiles($directory, '*.php') as $filename) {
$reflection = new ReflectionFile($filename);
$definition = explode('_', basename($filename));
$definition = \explode('_', \basename($filename));

if (count($definition) < 3) {
if (\count($definition) < 3) {
throw new RepositoryException("Invalid migration filename '{$filename}'");
}

Expand All @@ -131,10 +152,10 @@ private function getFiles(): \Generator
'class' => $reflection->getClasses()[0],
'created' => $created,
'chunk' => $definition[1],
'name' => str_replace(
'name' => \str_replace(
'.php',
'',
implode('_', array_slice($definition, 2))
\implode('_', \array_slice($definition, 2))
),
];
}
Expand All @@ -147,9 +168,9 @@ private function createFilename(string $name): string
{
$name = $this->inflector->tableize($name);

$filename = sprintf(
$filename = \sprintf(
self::FILENAME_FORMAT,
date(self::TIMESTAMP_FORMAT),
\date(self::TIMESTAMP_FORMAT),
$this->chunkID++,
$name
);
Expand Down
6 changes: 3 additions & 3 deletions src/Migration.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ abstract class Migration implements MigrationInterface
protected const DATABASE = null;

private ?State $state = null;
private CapsuleInterface $capsule;
private ?CapsuleInterface $capsule = null;

/**
* {@inheritdoc}
Expand Down Expand Up @@ -66,7 +66,7 @@ public function getState(): State
*/
protected function database(): DatabaseInterface
{
if (empty($this->capsule)) {
if ($this->capsule === null) {
throw new MigrationException('Unable to get database, no capsule are set');
}

Expand All @@ -78,7 +78,7 @@ protected function database(): DatabaseInterface
*/
protected function table(string $table): TableBlueprint
{
if (empty($this->capsule)) {
if ($this->capsule === null) {
throw new MigrationException('Unable to get table blueprint, no capsule are set');
}

Expand Down
Loading

0 comments on commit 7af465e

Please sign in to comment.